rsys

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

commit b3e0f88729935b489486f6e78e11fcf54e4e3829
parent 4c90efffccc66b478237a89962c41bf90e58190d
Author: vaplv <vaplv@free.fr>
Date:   Fri,  1 Jul 2016 15:00:00 +0200

Make the floatX and floatXY types generic to the data type

Diffstat:
Mcmake/CMakeLists.txt | 4++--
Msrc/float2.h | 5+++--
Msrc/float22.h | 7++++---
Msrc/float3.h | 7++++---
Msrc/float33.h | 7++++---
Msrc/float4.h | 5+++--
Msrc/float44.h | 7++++---
Dsrc/floatX.h | 335-------------------------------------------------------------------------------
Dsrc/floatXY.h | 326-------------------------------------------------------------------------------
Asrc/realX.h | 389+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/realXY.h | 350+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 763 insertions(+), 679 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -78,11 +78,11 @@ set(RSYS_FILES_INC_API dynamic_array_uint.h dynamic_array_size_t.h dynamic_array_str.h - floatX.h + realX.h float2.h float3.h float4.h - floatXY.h + realXY.h float22.h float33.h float44.h diff --git a/src/float2.h b/src/float2.h @@ -17,8 +17,9 @@ #define FLOAT2_H /* Generate common floatX funcs */ -#define FLOATX_DIMENSION__ 2 -#include "floatX.h" +#define REALX_DIMENSION__ 2 +#define REAL_TYPE__ float +#include "realX.h" static FINLINE float f2_cross(const float a[2], const float b[2]) diff --git a/src/float22.h b/src/float22.h @@ -19,9 +19,10 @@ #include "float2.h" /* Generate common floatXY funcs */ -#define FLOATX_DIMENSION__ 2 -#define FLOATY_DIMENSION__ 2 -#include "floatXY.h" +#define REALX_DIMENSION__ 2 +#define REALY_DIMENSION__ 2 +#define REAL_TYPE__ float +#include "realXY.h" /* Specific float22 funcs */ static FINLINE float* diff --git a/src/float3.h b/src/float3.h @@ -16,9 +16,10 @@ #ifndef FLOAT3_H #define FLOAT3_H -/* Generate common floatX funcs */ -#define FLOATX_DIMENSION__ 3 -#include "floatX.h" +/* Generate common realX funcs */ +#define REALX_DIMENSION__ 3 +#define REAL_TYPE__ float +#include "realX.h" static FINLINE float* f3_cross(float dst[3], const float a[3], const float b[3]) diff --git a/src/float33.h b/src/float33.h @@ -20,9 +20,10 @@ #include <math.h> /* Generate common floatXY funcs */ -#define FLOATX_DIMENSION__ 3 -#define FLOATY_DIMENSION__ 3 -#include "floatXY.h" +#define REALX_DIMENSION__ 3 +#define REALY_DIMENSION__ 3 +#define REAL_TYPE__ float +#include "realXY.h" /* Specific float33 funcs */ static FINLINE float* diff --git a/src/float4.h b/src/float4.h @@ -17,8 +17,9 @@ #define FLOAT4_H /* Generate common floatX funcs */ -#define FLOATX_DIMENSION__ 4 -#include "floatX.h" +#define REALX_DIMENSION__ 4 +#define REAL_TYPE__ float +#include "realX.h" #endif /* FLOAT4_H */ diff --git a/src/float44.h b/src/float44.h @@ -20,9 +20,10 @@ #include "float4.h" /* Generate common floatXY funcs */ -#define FLOATX_DIMENSION__ 4 -#define FLOATY_DIMENSION__ 4 -#include "floatXY.h" +#define REALX_DIMENSION__ 4 +#define REALY_DIMENSION__ 4 +#define REAL_TYPE__ float +#include "realXY.h" /* Specific float44 funcs*/ static FINLINE float* diff --git a/src/floatX.h b/src/floatX.h @@ -1,335 +0,0 @@ -/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr) - * - * The RSys library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The RSys library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ - -/* - * 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 definition -#endif - -#include "math.h" -#include "rsys.h" -#include <math.h> - -#ifdef COMPILER_GCC - #pragma GCC push_options - #pragma GCC optimize("unroll-loops") -#endif - -STATIC_ASSERT(FLOATX_DIMENSION__ > 1, Unexpected_value); - -#define FLOATX_FUNC__(Func) \ - CONCAT(CONCAT(CONCAT(f, FLOATX_DIMENSION__), _), Func) - -/* Helper macro */ -#define SIZEOF_FLOATX__ sizeof(float[FLOATX_DIMENSION__]) - -#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); - ASSERT(!MEM_AREA_OVERLAP(dst, SIZEOF_FLOATX__, src, SIZEOF_FLOATX__)); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - dst[i] = src[i]; - return dst; -} - -static FINLINE float* -FLOATX_FUNC__(set)(float* dst, const float* src) -{ - ASSERT(dst && src); - if(!MEM_AREA_OVERLAP(dst, SIZEOF_FLOATX__, src, SIZEOF_FLOATX__)) { - return FLOATX_FUNC__(set__)(dst, src); - } else { - float tmp[FLOATX_DIMENSION__]; - return FLOATX_FUNC__(set__)(dst, FLOATX_FUNC__(set__)(tmp, src)); - } -} - -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 tmp[FLOATX_DIMENSION__]; - 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__) - tmp[i] = a[i] * rcp_len; - FLOATX_FUNC__(set__)(dst, tmp); - return len; -} - -static FINLINE char -FLOATX_FUNC__(is_normalized)(const float* a) -{ - return eq_epsf(FLOATX_FUNC__(len)(a), 1.f, 1.e-6f); -} - -static FINLINE float* -FLOATX_FUNC__(add)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] + b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(addf)(float* dst, const float* a, const float f) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] + f; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(sub)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] - b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(subf)(float* dst, const float* a, const float f) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] - f; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(mul)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] * b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(mulf)(float* dst, const float* a, const float f) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] * f; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(div)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] / b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(divf)(float* dst, const float* a, const float f) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] / f; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(minus)(float* dst, const float* a) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = -a[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -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 { - float tmp[FLOATX_DIMENSION__]; - int i; - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = from[i] + t * (to[i] - from[i]); - FLOATX_FUNC__(set__)(dst, tmp); - } - 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_epsf(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) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] > b[i] ? a[i] : b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATX_FUNC__(min)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__]; - int i; - ASSERT(dst && a && b); - FOR_EACH(i, 0, FLOATX_DIMENSION__) - tmp[i] = a[i] < b[i] ? a[i] : b[i]; - return FLOATX_FUNC__(set__)(dst, tmp); -} - -#undef FLOATX_DIMENSION__ -#undef FLOATX_FUNC__ - -#ifdef COMPILER_GCC - #pragma GCC pop_options -#endif - diff --git a/src/floatXY.h b/src/floatXY.h @@ -1,326 +0,0 @@ -/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr) - * - * The RSys library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The RSys library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ - -/* - * 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" - -#ifdef COMPILER_GCC - #pragma GCC push_options - #pragma GCC optimize("unroll-loops") -#endif - -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) - -/* Helper macro */ -#define SIZEOF_FLOATXY__ sizeof(float[FLOATX_DIMENSION__*FLOATY_DIMENSION__]) - -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); - ASSERT(!MEM_AREA_OVERLAP(dst, SIZEOF_FLOATXY__, src, SIZEOF_FLOATXY__)); - 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)(float* dst, const float* src) -{ - ASSERT(dst && src); - if(!MEM_AREA_OVERLAP(dst, SIZEOF_FLOATXY__, src, SIZEOF_FLOATXY__)) { - return FLOATXY_FUNC__(set__)(dst, src); - } else { - float tmp[FLOATX_DIMENSION__*FLOATY_DIMENSION__]; - return FLOATXY_FUNC__(set__)(dst, FLOATXY_FUNC__(set__)(tmp, src)); - } -} - -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) -{ - float tmp[FLOATX_DIMENSION__*FLOATY_DIMENSION__]; - int i; - FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) - tmp[i] = a[i] + b[i]; - return FLOATXY_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATXY_FUNC__(sub)(float* dst, const float* a, const float* b) -{ - float tmp[FLOATX_DIMENSION__*FLOATY_DIMENSION__]; - int i; - FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) - tmp[i] = a[i] - b[i]; - return FLOATXY_FUNC__(set__)(dst, tmp); -} - -static FINLINE float* -FLOATXY_FUNC__(minus)(float* dst, const float* a) -{ - float tmp[FLOATX_DIMENSION__*FLOATY_DIMENSION__]; - int i; - FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) - tmp[i] = -a[i]; - return FLOATXY_FUNC__(set__)(dst, tmp); -} - -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) -{ - float tmp[FLOATX_DIMENSION__*FLOATY_DIMENSION__]; - int i; - ASSERT(dst && mat); - FOR_EACH(i, 0, FLOATX_DIMENSION__ * FLOATY_DIMENSION__) - tmp[i] = mat[i] * b; - return FLOATXY_FUNC__(set__)(dst, tmp);; -} - -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; - }} - return FLOATXY_FUNC__(set__)(dst, tmp); -} - -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; - }} - return FLOATXY_FUNC__(set__)(dst, tmp); -} -#endif /* FLOATX_DIMENSION__ == FLOATY_DIMENSION__ */ - -#undef FLOATX_FUNC__ -#undef FLOATXY_FUNC__ -#undef FLOATX_DIMENSION__ -#undef FLOATY_DIMENSION__ -#undef SIZEOF_FLOATXY__ - -#ifdef COMPILER_GCC - #pragma GCC pop_options -#endif - diff --git a/src/realX.h b/src/realX.h @@ -0,0 +1,389 @@ +/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr) + * + * The RSys library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The RSys library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ + +/* + * Internal header used to generate funcs on REAL_TYPE__ vector of X dimensions + */ +#if !defined(REALX_DIMENSION__) || !defined(REAL_TYPE__) + #error Missing arguments +#endif + +#if defined(REALX_FUNC__) \ + || defined(REAL_LETTER__) \ + || defined(REAL_EPSILON__) \ + || defined(SIZEOF_REALX__) + #error Unexpected macro definition +#endif + +#include "math.h" +#include "rsys.h" +#include <math.h> + +#ifdef COMPILER_GCC + #pragma GCC push_options + #pragma GCC optimize("unroll-loops") +#endif + +STATIC_ASSERT(REALX_DIMENSION__ > 1, Unexpected_value); + +/* Define the epsilon for each real type */ +#define REAL_EPSILON_double 1.e-8 +#define REAL_EPSILON_float 1.e-6f +#define REAL_EPSILON__ CONCAT(REAL_EPSILON_, REAL_TYPE__) + +/* Define the suffix/prefix letter for each real type */ +#define REAL_LETTER_float f +#define REAL_LETTER_double d +#define REAL_LETTER__ CONCAT(REAL_LETTER_, REAL_TYPE__) + +#define REALX_FUNC__(Func) \ + CONCAT(CONCAT(CONCAT(REAL_LETTER__, REALX_DIMENSION__), _), Func) + +/* Helper macro */ +#define SIZEOF_REALX__ sizeof(REAL_TYPE__[REALX_DIMENSION__]) + +#if REALX_DIMENSION__ <= 4 +static FINLINE REAL_TYPE__* +CONCAT(REAL_LETTER__, REALX_DIMENSION__) + (REAL_TYPE__* dst + ,const REAL_TYPE__ x + ,const REAL_TYPE__ y +#if REALX_DIMENSION__ > 2 + ,const REAL_TYPE__ z +#endif +#if REALX_DIMENSION__ > 3 + ,const REAL_TYPE__ w +#endif + ) +{ + ASSERT(dst); + dst[0] = x; + dst[1] = y; +#if REALX_DIMENSION__ > 2 + dst[2] = z; +#endif +#if REALX_DIMENSION__ > 3 + dst[3] = w; +#endif + return dst; +} +#endif + +static FINLINE REAL_TYPE__* +REALX_FUNC__(splat)(REAL_TYPE__* dst, const REAL_TYPE__ val) +{ + int i; + ASSERT(dst); + FOR_EACH(i, 0, REALX_DIMENSION__) + dst[i] = val; + return dst; +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(set__)(REAL_TYPE__* dst, const REAL_TYPE__* src) +{ + int i; + ASSERT(dst && src); + ASSERT(!MEM_AREA_OVERLAP(dst, SIZEOF_REALX__, src, SIZEOF_REALX__)); + FOR_EACH(i, 0, REALX_DIMENSION__) + dst[i] = src[i]; + return dst; +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(set)(REAL_TYPE__* dst, const REAL_TYPE__* src) +{ + ASSERT(dst && src); + if(!MEM_AREA_OVERLAP(dst, SIZEOF_REALX__, src, SIZEOF_REALX__)) { + return REALX_FUNC__(set__)(dst, src); + } else { + REAL_TYPE__ tmp[REALX_DIMENSION__]; + return REALX_FUNC__(set__)(dst, REALX_FUNC__(set__)(tmp, src)); + } +} + +static FINLINE REAL_TYPE__ +REALX_FUNC__(dot)(const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + REAL_TYPE__ dot = 0; + int i; + ASSERT(a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + dot += a[i] * b[i]; + return dot; +} + +static FINLINE REAL_TYPE__ +REALX_FUNC__(len)(const REAL_TYPE__* a) +{ + ASSERT(a); + return (REAL_TYPE__)sqrt((double)REALX_FUNC__(dot)(a, a)); +} + +static FINLINE REAL_TYPE__ +REALX_FUNC__(normalize)(REAL_TYPE__* dst, const REAL_TYPE__* a) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + REAL_TYPE__ len, rcp_len; + int i; + ASSERT(dst && a); + + len = REALX_FUNC__(len)(a); + if(len == 0) + return len; + + rcp_len = 1.0f / len; + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] * rcp_len; + REALX_FUNC__(set__)(dst, tmp); + return len; +} + +static FINLINE char +REALX_FUNC__(is_normalized)(const REAL_TYPE__* a) +{ + return eq_epsf(REALX_FUNC__(len)(a), 1.0, REAL_EPSILON__); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(add) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] + b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(CONCAT(add, REAL_LETTER__)) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__ f) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] + f; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(sub) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] - b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(CONCAT(sub, REAL_LETTER__)) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__ f) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] - f; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(mul) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] * b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(CONCAT(mul, REAL_LETTER__)) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__ f) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] * f; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(div) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] / b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(CONCAT(div, REAL_LETTER__)) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__ f) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] / f; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(minus)(REAL_TYPE__* dst, const REAL_TYPE__* a) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = -a[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__ +REALX_FUNC__(sum)(const REAL_TYPE__* a) +{ + REAL_TYPE__ f = 0; + int i = 0; + ASSERT(a); + do { + f += a[i]; + ++i; + } while(i < REALX_DIMENSION__); + return f; +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(lerp) + (REAL_TYPE__* dst, + const REAL_TYPE__* from, + const REAL_TYPE__* to, + const REAL_TYPE__ t) +{ + ASSERT(dst && from && to); + if(t <= 0.f) { + REALX_FUNC__(set)(dst, from); + } else if(t >= 1) { + REALX_FUNC__(set)(dst, to); + } else { + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = from[i] + t * (to[i] - from[i]); + REALX_FUNC__(set__)(dst, tmp); + } + return dst; +} + +static FINLINE char +REALX_FUNC__(eq)(const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + int i = 0; + char is_eq = 1; + ASSERT(a && b); + do { + is_eq = a[i] == b[i]; + ++i; + } while(i < REALX_DIMENSION__ && is_eq); + return is_eq; +} + +static FINLINE char +REALX_FUNC__(eq_eps) + (const REAL_TYPE__* a, + const REAL_TYPE__* b, + const REAL_TYPE__ eps) +{ + int i = 0; + char is_eq = 1; + ASSERT(a && b); + do { + is_eq = eq_epsf(a[i], b[i], eps); + ++i; + } while(i < REALX_DIMENSION__ && is_eq); + return is_eq; +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(max) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] > b[i] ? a[i] : b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(min) + (REAL_TYPE__* dst, + const REAL_TYPE__* a, + const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int i; + ASSERT(dst && a && b); + FOR_EACH(i, 0, REALX_DIMENSION__) + tmp[i] = a[i] < b[i] ? a[i] : b[i]; + return REALX_FUNC__(set__)(dst, tmp); +} + +#undef REAL_TYPE__ +#undef REAL_LETTER__ +#undef REAL_LETTER__float +#undef REAL_LETTER_double +#undef REAL_EPSILON__ +#undef REAL_EPSILON_float +#undef REAL_EPSILON_double +#undef REALX_DIMENSION__ +#undef REALX_FUNC__ +#undef SIZEOF_REALX__ + +#ifdef COMPILER_GCC + #pragma GCC pop_options +#endif + diff --git a/src/realXY.h b/src/realXY.h @@ -0,0 +1,350 @@ +/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr) + * + * The RSys library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The RSys library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ + +/* + * Internal header used to generate funcs on column major REAL_TYPE__ matrix + * of X x Y dimensions + */ +#if !defined(REALX_DIMENSION__) \ + || !defined(REALY_DIMENSION__) \ + || !defined(REAL_TYPE__) + #error Missing arguments +#endif + +#if defined(REALXY_FUNC__) \ + || defined(REALX_FUNC__) \ + || defined(REALY_FUNC__) \ + || defined(REAL_EPSILON__) \ + || defined(REAL_LETTER__) \ + || defined(SIZEOF_REALXY__) + #error Unexpected macro defintion +#endif + +#include "math.h" +#include "rsys.h" + +#ifdef COMPILER_GCC + #pragma GCC push_options + #pragma GCC optimize("unroll-loops") +#endif + +STATIC_ASSERT + (REALX_DIMENSION__ > 1 && REALY_DIMENSION__ > 1, Unexpected_value); + +/* Define the epsilon for each real type */ +#define REAL_EPSILON_double 1.e-8 +#define REAL_EPSILON_float 1.e-6f +#define REAL_EPSILON__ CONCAT(REAL_EPSILON_, REAL_TYPE__) + +/* Define the suffix/prefix letter for each real type */ +#define REAL_LETTER_float f +#define REAL_LETTER_double d +#define REAL_LETTER__ CONCAT(REAL_LETTER_, REAL_TYPE__) + +#define REALXY_FUNC__(Func) \ + CONCAT(CONCAT(CONCAT(CONCAT \ + (REAL_LETTER__, REALX_DIMENSION__), REALY_DIMENSION__), _), Func) + +#define REALX_FUNC__(Func) \ + CONCAT(CONCAT(CONCAT(f, REALX_DIMENSION__), _), Func) +#define REALY_FUNC__(Func) \ + CONCAT(CONCAT(CONCAT(f, REALY_DIMENSION__), _), Func) + +/* Helper macro */ +#define SIZEOF_REALXY__ sizeof(REAL_TYPE__[REALX_DIMENSION__*REALY_DIMENSION__]) + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(splat)(REAL_TYPE__* dst, const REAL_TYPE__ val) +{ + int i = 0; + ASSERT(dst); + FOR_EACH(i, 0, REALX_DIMENSION__*REALY_DIMENSION__) { + dst[i] = val; + } + return dst; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(set__)(REAL_TYPE__* dst, const REAL_TYPE__* src) +{ + int x, y, i; + ASSERT(dst && src); + ASSERT(!MEM_AREA_OVERLAP(dst, SIZEOF_REALXY__, src, SIZEOF_REALXY__)); + i = 0; + FOR_EACH(x, 0, REALX_DIMENSION__) { + FOR_EACH(y, 0, REALY_DIMENSION__) { + dst[i] = src[i]; + ++i; + }} + return dst; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(set)(REAL_TYPE__* dst, const REAL_TYPE__* src) +{ + ASSERT(dst && src); + if(!MEM_AREA_OVERLAP(dst, SIZEOF_REALXY__, src, SIZEOF_REALXY__)) { + return REALXY_FUNC__(set__)(dst, src); + } else { + REAL_TYPE__ tmp[REALX_DIMENSION__*REALY_DIMENSION__]; + return REALXY_FUNC__(set__)(dst, REALXY_FUNC__(set__)(tmp, src)); + } +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(set_identity)(REAL_TYPE__* mat) +{ + int x, y, i; + ASSERT(mat); + i = 0; + FOR_EACH(x, 0, REALX_DIMENSION__) { + FOR_EACH(y, 0, REALY_DIMENSION__) { + mat[i] = x == y ? 1.f : 0.f; + ++i; + }} + return mat; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(set_row)(REAL_TYPE__* mat, const REAL_TYPE__* row, const int irow) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int x; + ASSERT(mat && row && irow < REALY_DIMENSION__ && irow >= 0); + + FOR_EACH(x, 0, REALX_DIMENSION__) + tmp[x] = row[x]; + FOR_EACH(x, 0, REALX_DIMENSION__) + mat[x * REALY_DIMENSION__ + irow] = tmp[x]; + return mat; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(set_col)(REAL_TYPE__* mat, const REAL_TYPE__* col, const int icol) +{ + REAL_TYPE__ tmp[REALY_DIMENSION__]; + int y; + ASSERT(mat && col && icol < REALX_DIMENSION__ && icol >= 0); + FOR_EACH(y, 0, REALY_DIMENSION__) + tmp[y] = col[y]; + REALX_FUNC__(set)(mat + (icol * REALY_DIMENSION__), tmp); + return mat; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(row)(REAL_TYPE__* row, const REAL_TYPE__* mat, const int irow) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int x; + ASSERT(row && mat && irow < REALY_DIMENSION__); + + FOR_EACH(x, 0, REALX_DIMENSION__) + tmp[x] = mat[x * REALY_DIMENSION__ + irow]; + FOR_EACH(x, 0, REALX_DIMENSION__) + row[x] = tmp[x]; + return row; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(col_ptr)(REAL_TYPE__* mat, const int icol) +{ + ASSERT(mat && icol < REALX_DIMENSION__); + return mat + (icol * REALY_DIMENSION__); +} + +static FINLINE const REAL_TYPE__* +REALXY_FUNC__(col_cptr)(const REAL_TYPE__* mat, const int icol) +{ + ASSERT(mat && icol < REALX_DIMENSION__); + return mat + (icol * REALY_DIMENSION__); +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(col)(REAL_TYPE__* col, const REAL_TYPE__* mat, const int icol) +{ + REAL_TYPE__ tmp[REALY_DIMENSION__]; + const REAL_TYPE__* col_ptr = REALXY_FUNC__(col_cptr)(mat, icol); + int x, y; + ASSERT(mat && icol < REALY_DIMENSION__); + + FOR_EACH(y, 0, REALY_DIMENSION__) + tmp[y] = col_ptr[y]; + FOR_EACH(x, 0, REALX_DIMENSION__) + col[x] = tmp[x]; + return col; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(add)(REAL_TYPE__* dst, const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__*REALY_DIMENSION__]; + int i; + FOR_EACH(i, 0, REALX_DIMENSION__ * REALY_DIMENSION__) + tmp[i] = a[i] + b[i]; + return REALXY_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(sub)(REAL_TYPE__* dst, const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__*REALY_DIMENSION__]; + int i; + FOR_EACH(i, 0, REALX_DIMENSION__ * REALY_DIMENSION__) + tmp[i] = a[i] - b[i]; + return REALXY_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(minus)(REAL_TYPE__* dst, const REAL_TYPE__* a) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__*REALY_DIMENSION__]; + int i; + FOR_EACH(i, 0, REALX_DIMENSION__ * REALY_DIMENSION__) + tmp[i] = -a[i]; + return REALXY_FUNC__(set__)(dst, tmp); +} + +static FINLINE char +REALXY_FUNC__(eq)(const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + char is_eq = 1; + int x = 0; + ASSERT(a && b); + + do { + const int i = x * REALY_DIMENSION__; + is_eq = REALX_FUNC__(eq)(a + i, b + i); + ++x; + } while(x < REALX_DIMENSION__ && is_eq); + return is_eq; +} + +static FINLINE char +REALXY_FUNC__(eq_eps)(const REAL_TYPE__* a, const REAL_TYPE__* b, const REAL_TYPE__ eps) +{ + char is_eq = 1; + int x = 0; + ASSERT(a && b); + + do { + const int i = x * REALY_DIMENSION__; + is_eq = REALX_FUNC__(eq_eps)(a + i, b + i, eps); + ++x; + } while(x < REALX_DIMENSION__ && is_eq); + return is_eq; +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(CONCAT(mulf, REALX_DIMENSION__)) + (REAL_TYPE__* dst, const REAL_TYPE__* mat, const REAL_TYPE__* vec) +{ + REAL_TYPE__ row[REALX_DIMENSION__]; + REAL_TYPE__ tmp[REALY_DIMENSION__]; + int y; + ASSERT(dst && mat && vec); + + FOR_EACH(y, 0, REALY_DIMENSION__) { + REALXY_FUNC__(row)(row, mat, y); + tmp[y] = REALX_FUNC__(dot)(row, vec); + } + return REALY_FUNC__(set)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(mul)(REAL_TYPE__* dst, const REAL_TYPE__* mat, const REAL_TYPE__ b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__*REALY_DIMENSION__]; + int i; + ASSERT(dst && mat); + FOR_EACH(i, 0, REALX_DIMENSION__ * REALY_DIMENSION__) + tmp[i] = mat[i] * b; + return REALXY_FUNC__(set__)(dst, tmp);; +} + +static FINLINE REAL_TYPE__* +REALX_FUNC__(CONCAT(CONCAT(mulf, REALX_DIMENSION__), REALY_DIMENSION__)) + (REAL_TYPE__* dst, const REAL_TYPE__* vec, const REAL_TYPE__* mat) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__]; + int x; + ASSERT(dst && vec && mat); + FOR_EACH(x, 0, REALX_DIMENSION__) { + const REAL_TYPE__* col = mat + (x * REALY_DIMENSION__); + tmp[x] = REALX_FUNC__(dot)(vec, col); + } + return REALX_FUNC__(set)(dst, tmp); +} + +#if REALX_DIMENSION__ == REALY_DIMENSION__ +static FINLINE REAL_TYPE__* +REALXY_FUNC__(transpose)(REAL_TYPE__* dst, const REAL_TYPE__* src) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__ * REALY_DIMENSION__]; + int x, y, i; + ASSERT(dst && src); + + i = 0; + FOR_EACH(x, 0, REALX_DIMENSION__) { + FOR_EACH(y, 0, REALY_DIMENSION__) { + tmp[y * REALY_DIMENSION__ + x] = src[i]; + ++i; + }} + return REALXY_FUNC__(set__)(dst, tmp); +} + +static FINLINE REAL_TYPE__* +REALXY_FUNC__(CONCAT(CONCAT(mulf, REALX_DIMENSION__), REALY_DIMENSION__)) + (REAL_TYPE__* dst, const REAL_TYPE__* a, const REAL_TYPE__* b) +{ + REAL_TYPE__ tmp[REALX_DIMENSION__ * REALY_DIMENSION__]; + REAL_TYPE__ a_trans[REALX_DIMENSION__ * REALY_DIMENSION__]; + int x, y, i; + + /* Transpose the a matrix */ + i = 0; + FOR_EACH(x, 0, REALX_DIMENSION__) { + FOR_EACH(y, 0, REALY_DIMENSION__) { + a_trans[y * REALY_DIMENSION__ + x] = a[i]; + ++i; + }} + /* Compute the a x b and store the result into tmp */ + i = 0; + FOR_EACH(x, 0, REALX_DIMENSION__) { + FOR_EACH(y, 0, REALY_DIMENSION__) { + tmp[i] = REALX_FUNC__(dot) + (a_trans + (y * REALY_DIMENSION__), b + (x * REALY_DIMENSION__)); + ++i; + }} + return REALXY_FUNC__(set__)(dst, tmp); +} +#endif /* REALX_DIMENSION__ == REALY_DIMENSION__ */ + +#undef REAL_EPSILON__ +#undef REAL_EPSILON_float +#undef REAL_EPSILON_double +#undef REAL_LETTER__ +#undef REAL_LETTER__float +#undef REAL_LETTER_double +#undef REALX_FUNC__ +#undef REALY_FUNC__ +#undef REALXY_FUNC__ +#undef REALX_DIMENSION__ +#undef REALY_DIMENSION__ +#undef SIZEOF_REALXY__ + +#ifdef COMPILER_GCC + #pragma GCC pop_options +#endif +