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:
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
+