Browse Source

math: move the Remez algorithm implementation to the core.

legacy
Sam Hocevar sam 13 years ago
parent
commit
48bf48a4e4
14 changed files with 165 additions and 173 deletions
  1. +2
    -2
      src/Makefile.am
  2. +2
    -2
      src/core.h
  3. +1
    -1
      src/eglapp.h
  4. +1
    -1
      src/image/image.h
  5. +1
    -1
      src/input.h
  6. +81
    -3
      src/lol/math/matrix.h
  7. +3
    -3
      src/lol/math/real.h
  8. +64
    -53
      src/lol/math/remez.h
  9. +1
    -1
      src/platform/nacl/naclapp.h
  10. +1
    -1
      src/platform/ps3/ps3app.h
  11. +1
    -1
      src/platform/sdl/sdlapp.h
  12. +1
    -1
      test/math/Makefile.am
  13. +0
    -97
      test/math/remez-matrix.h
  14. +6
    -6
      test/math/remez.cpp

+ 2
- 2
src/Makefile.am View File

@@ -2,7 +2,7 @@
noinst_LIBRARIES = liblol.a noinst_LIBRARIES = liblol.a


liblol_a_SOURCES = \ liblol_a_SOURCES = \
core.h matrix.cpp matrix.h tiler.cpp tiler.h dict.cpp dict.h \
core.h matrix.cpp real.cpp tiler.cpp tiler.h dict.cpp dict.h \
audio.cpp audio.h scene.cpp scene.h font.cpp font.h layer.cpp layer.h \ audio.cpp audio.h scene.cpp scene.h font.cpp font.h layer.cpp layer.h \
map.cpp map.h entity.cpp entity.h ticker.cpp ticker.h lolgl.h \ map.cpp map.h entity.cpp entity.h ticker.cpp ticker.h lolgl.h \
tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h log.cpp log.h \ tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h log.cpp log.h \
@@ -11,9 +11,9 @@ liblol_a_SOURCES = \
text.cpp text.h emitter.cpp emitter.h numeric.h hash.cpp hash.h \ text.cpp text.h emitter.cpp emitter.h numeric.h hash.cpp hash.h \
worldentity.cpp worldentity.h gradient.cpp gradient.h half.cpp half.h \ worldentity.cpp worldentity.h gradient.cpp gradient.h half.cpp half.h \
platform.cpp platform.h sprite.cpp sprite.h trig.cpp trig.h \ platform.cpp platform.h sprite.cpp sprite.h trig.cpp trig.h \
real.cpp real.h \
\ \
lol/unit.h \ lol/unit.h \
lol/math/matrix.h lol/math/real.h lol/math/remez.h \
\ \
application/application.cpp application/application.h \ application/application.cpp application/application.h \
eglapp.cpp eglapp.h \ eglapp.cpp eglapp.h \


+ 2
- 2
src/core.h View File

@@ -64,8 +64,8 @@ static inline int isnan(float f)
// Base types // Base types
#include "trig.h" #include "trig.h"
#include "half.h" #include "half.h"
#include "real.h"
#include "matrix.h"
#include "lol/math/real.h"
#include "lol/math/matrix.h"
#include "numeric.h" #include "numeric.h"
#include "timer.h" #include "timer.h"
#include "thread/thread.h" #include "thread/thread.h"


+ 1
- 1
src/eglapp.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_EGLAPP_H__ #if !defined __LOL_EGLAPP_H__
#define __LOL_EGLAPP_H__ #define __LOL_EGLAPP_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


+ 1
- 1
src/image/image.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_IMAGE_H__ #if !defined __LOL_IMAGE_H__
#define __LOL_IMAGE_H__ #define __LOL_IMAGE_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


+ 1
- 1
src/input.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_INPUT_H__ #if !defined __LOL_INPUT_H__
#define __LOL_INPUT_H__ #define __LOL_INPUT_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


src/matrix.h → src/lol/math/matrix.h View File

@@ -13,8 +13,8 @@
// ------------------ // ------------------
// //


#if !defined __LOL_MATRIX_H__
#define __LOL_MATRIX_H__
#if !defined __LOL_MATH_MATRIX_H__
#define __LOL_MATH_MATRIX_H__


#include <cmath> #include <cmath>
#if !defined __ANDROID__ #if !defined __ANDROID__
@@ -24,6 +24,9 @@
namespace lol namespace lol
{ {


class half;
class real;

#define VECTOR_TYPES(tname, suffix) \ #define VECTOR_TYPES(tname, suffix) \
template <typename T> struct tname; \ template <typename T> struct tname; \
typedef tname<half> f16##suffix; \ typedef tname<half> f16##suffix; \
@@ -587,7 +590,82 @@ template <typename T> struct Mat4
Vec4<T> v[4]; Vec4<T> v[4];
}; };


/*
* Arbitrarily-sized square matrices; for now this only supports
* naive inversion and is used for the Remez inversion method.
*/

template<int N, typename T> struct Mat
{
inline Mat<N, T>() {}

Mat(T x)
{
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
if (i == j)
m[i][j] = x;
else
m[i][j] = 0;
}

/* Naive matrix inversion */
Mat<N, T> inv() const
{
Mat a = *this, b((T)1);

/* Inversion method: iterate through all columns and make sure
* all the terms are 1 on the diagonal and 0 everywhere else */
for (int i = 0; i < N; i++)
{
/* If the expected coefficient is zero, add one of
* the other lines. The first we meet will do. */
if (!a.m[i][i])
{
for (int j = i + 1; j < N; j++)
{
if (!a.m[i][j])
continue;
/* Add row j to row i */
for (int n = 0; n < N; n++)
{
a.m[n][i] += a.m[n][j];
b.m[n][i] += b.m[n][j];
}
break;
}
}

/* Now we know the diagonal term is non-zero. Get its inverse
* and use that to nullify all other terms in the column */
T x = (T)1 / a.m[i][i];
for (int j = 0; j < N; j++)
{
if (j == i)
continue;
T mul = x * a.m[i][j];
for (int n = 0; n < N; n++)
{
a.m[n][j] -= mul * a.m[n][i];
b.m[n][j] -= mul * b.m[n][i];
}
}

/* Finally, ensure the diagonal term is 1 */
for (int n = 0; n < N; n++)
{
a.m[n][i] *= x;
b.m[n][i] *= x;
}
}

return b;
}

T m[N][N];
};

} /* namespace lol */ } /* namespace lol */


#endif // __LOL_MATRIX_H__
#endif // __LOL_MATH_MATRIX_H__



src/real.h → src/lol/math/real.h View File

@@ -13,8 +13,8 @@
// -------------- // --------------
// //


#if !defined __LOL_REAL_H__
#define __LOL_REAL_H__
#if !defined __LOL_MATH_REAL_H__
#define __LOL_MATH_REAL_H__


#include <stdint.h> #include <stdint.h>


@@ -147,5 +147,5 @@ private:


} /* namespace lol */ } /* namespace lol */


#endif // __LOL_REAL_H__
#endif // __LOL_MATH_REAL_H__



test/math/remez-solver.h → src/lol/math/remez.h View File

@@ -1,26 +1,34 @@
// //
// Lol Engine - Sample math program: Chebyshev polynomials
// Lol Engine
// //
// Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To // modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See // Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
// //


#if !defined __REMEZ_SOLVER_H__
#define __REMEZ_SOLVER_H__
//
// The Remez class
// ---------------
//

#if !defined __LOL_MATH_REMEZ_H__
#define __LOL_MATH_REMEZ_H__


template<int ORDER> class RemezSolver
namespace lol
{

template<int ORDER, typename T> class RemezSolver
{ {
public: public:
typedef real RealFunc(real const &x);
typedef T RealFunc(T const &x);


RemezSolver() RemezSolver()
{ {
} }


void Run(real a, real b, RealFunc *func, RealFunc *weight, int steps)
void Run(T a, T b, RealFunc *func, RealFunc *weight, int steps)
{ {
m_func = func; m_func = func;
m_weight = weight; m_weight = weight;
@@ -49,15 +57,15 @@ public:
PrintPoly(); PrintPoly();
} }


real ChebyEval(real const &x)
T ChebyEval(T const &x)
{ {
real ret = 0.0, xn = 1.0;
T ret = 0.0, xn = 1.0;


for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
real mul = 0;
T mul = 0;
for (int j = 0; j < ORDER + 1; j++) for (int j = 0; j < ORDER + 1; j++)
mul += coeff[j] * (real)Cheby(j, i);
mul += coeff[j] * (T)Cheby(j, i);
ret += mul * xn; ret += mul * xn;
xn *= x; xn *= x;
} }
@@ -68,20 +76,20 @@ public:
void Init() void Init()
{ {
/* Pick up x_i where error will be 0 and compute f(x_i) */ /* Pick up x_i where error will be 0 and compute f(x_i) */
real fxn[ORDER + 1];
T fxn[ORDER + 1];
for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
zeroes[i] = (real)(2 * i - ORDER) / (real)(ORDER + 1);
zeroes[i] = (T)(2 * i - ORDER) / (T)(ORDER + 1);
fxn[i] = Value(zeroes[i]); fxn[i] = Value(zeroes[i]);
} }


/* We build a matrix of Chebishev evaluations: row i contains the /* We build a matrix of Chebishev evaluations: row i contains the
* evaluations of x_i for polynomial order n = 0, 1, ... */ * evaluations of x_i for polynomial order n = 0, 1, ... */
Matrix<ORDER + 1> mat;
lol::Mat<ORDER + 1, T> mat;
for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
/* Compute the powers of x_i */ /* Compute the powers of x_i */
real powers[ORDER + 1];
T powers[ORDER + 1];
powers[0] = 1.0; powers[0] = 1.0;
for (int n = 1; n < ORDER + 1; n++) for (int n = 1; n < ORDER + 1; n++)
powers[n] = powers[n - 1] * zeroes[i]; powers[n] = powers[n - 1] * zeroes[i];
@@ -89,9 +97,9 @@ public:
/* Compute the Chebishev evaluations at x_i */ /* Compute the Chebishev evaluations at x_i */
for (int n = 0; n < ORDER + 1; n++) for (int n = 0; n < ORDER + 1; n++)
{ {
real sum = 0.0;
T sum = 0.0;
for (int k = 0; k < ORDER + 1; k++) for (int k = 0; k < ORDER + 1; k++)
sum += (real)Cheby(n, k) * powers[k];
sum += (T)Cheby(n, k) * powers[k];
mat.m[i][n] = sum; mat.m[i][n] = sum;
} }
} }
@@ -115,21 +123,22 @@ public:
* place as the absolute error! */ * place as the absolute error! */
for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
struct { real value, error; } left, right, mid;
struct { T value, error; } left, right, mid;


left.value = control[i]; left.value = control[i];
left.error = ChebyEval(left.value) - Value(left.value); left.error = ChebyEval(left.value) - Value(left.value);
right.value = control[i + 1]; right.value = control[i + 1];
right.error = ChebyEval(right.value) - Value(right.value); right.error = ChebyEval(right.value) - Value(right.value);


static real limit = real::R_1 >> 500;
static T limit = (T)1 >> 500;
static T zero = (T)0;
while (fabs(left.value - right.value) > limit) while (fabs(left.value - right.value) > limit)
{ {
mid.value = (left.value + right.value) >> 1; mid.value = (left.value + right.value) >> 1;
mid.error = ChebyEval(mid.value) - Value(mid.value); mid.error = ChebyEval(mid.value) - Value(mid.value);


if ((left.error < real::R_0 && mid.error < real::R_0)
|| (left.error > real::R_0 && mid.error > real::R_0))
if ((left.error < zero && mid.error < zero)
|| (left.error > zero && mid.error > zero))
left = mid; left = mid;
else else
right = mid; right = mid;
@@ -146,11 +155,11 @@ public:
/* Find ORDER + 2 extrema of the error function. We need to /* Find ORDER + 2 extrema of the error function. We need to
* compute the relative error, since its extrema are at slightly * compute the relative error, since its extrema are at slightly
* different locations than the absolute error’s. */ * different locations than the absolute error’s. */
real final = 0;
T final = 0;


for (int i = 0; i < ORDER + 2; i++) for (int i = 0; i < ORDER + 2; i++)
{ {
real a = -1, b = 1;
T a = -1, b = 1;
if (i > 0) if (i > 0)
a = zeroes[i - 1]; a = zeroes[i - 1];
if (i < ORDER + 1) if (i < ORDER + 1)
@@ -158,14 +167,14 @@ public:


for (;;) for (;;)
{ {
real c = a, delta = (b - a) >> 3;
real maxerror = 0;
real maxweight = 0;
T c = a, delta = (b - a) >> 3;
T maxerror = 0;
T maxweight = 0;
int best = -1; int best = -1;
for (int k = 1; k <= 7; k++) for (int k = 1; k <= 7; k++)
{ {
real error = ChebyEval(c) - Value(c);
real weight = Weight(c);
T error = ChebyEval(c) - Value(c);
T weight = Weight(c);
if (fabs(error * maxweight) >= fabs(maxerror * weight)) if (fabs(error * maxweight) >= fabs(maxerror * weight))
{ {
maxerror = error; maxerror = error;
@@ -175,12 +184,12 @@ public:
c += delta; c += delta;
} }


b = a + (real)(best + 1) * delta;
a = a + (real)(best - 1) * delta;
b = a + (T)(best + 1) * delta;
a = a + (T)(best - 1) * delta;


if (b - a < (real)1e-18)
if (b - a < (T)1e-18)
{ {
real e = maxerror / maxweight;
T e = maxerror / maxweight;
if (e > final) if (e > final)
final = e; final = e;
control[i] = (a + b) >> 1; control[i] = (a + b) >> 1;
@@ -196,17 +205,17 @@ public:
void Step() void Step()
{ {
/* Pick up x_i where error will be 0 and compute f(x_i) */ /* Pick up x_i where error will be 0 and compute f(x_i) */
real fxn[ORDER + 2];
T fxn[ORDER + 2];
for (int i = 0; i < ORDER + 2; i++) for (int i = 0; i < ORDER + 2; i++)
fxn[i] = Value(control[i]); fxn[i] = Value(control[i]);


/* We build a matrix of Chebishev evaluations: row i contains the /* We build a matrix of Chebishev evaluations: row i contains the
* evaluations of x_i for polynomial order n = 0, 1, ... */ * evaluations of x_i for polynomial order n = 0, 1, ... */
Matrix<ORDER + 2> mat;
lol::Mat<ORDER + 2, T> mat;
for (int i = 0; i < ORDER + 2; i++) for (int i = 0; i < ORDER + 2; i++)
{ {
/* Compute the powers of x_i */ /* Compute the powers of x_i */
real powers[ORDER + 1];
T powers[ORDER + 1];
powers[0] = 1.0; powers[0] = 1.0;
for (int n = 1; n < ORDER + 1; n++) for (int n = 1; n < ORDER + 1; n++)
powers[n] = powers[n - 1] * control[i]; powers[n] = powers[n - 1] * control[i];
@@ -214,9 +223,9 @@ public:
/* Compute the Chebishev evaluations at x_i */ /* Compute the Chebishev evaluations at x_i */
for (int n = 0; n < ORDER + 1; n++) for (int n = 0; n < ORDER + 1; n++)
{ {
real sum = 0.0;
T sum = 0.0;
for (int k = 0; k < ORDER + 1; k++) for (int k = 0; k < ORDER + 1; k++)
sum += (real)Cheby(n, k) * powers[k];
sum += (T)Cheby(n, k) * powers[k];
mat.m[i][n] = sum; mat.m[i][n] = sum;
} }
if (i & 1) if (i & 1)
@@ -237,7 +246,7 @@ public:
} }


/* Compute the error */ /* Compute the error */
real error = 0;
T error = 0;
for (int i = 0; i < ORDER + 2; i++) for (int i = 0; i < ORDER + 2; i++)
error += mat.m[ORDER + 1][i] * fxn[i]; error += mat.m[ORDER + 1][i] * fxn[i];
} }
@@ -264,31 +273,31 @@ public:


/* Transform Chebyshev polynomial weights into powers of X^i /* Transform Chebyshev polynomial weights into powers of X^i
* in the [-1..1] range. */ * in the [-1..1] range. */
real bn[ORDER + 1];
T bn[ORDER + 1];


for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
bn[i] = 0; bn[i] = 0;
for (int j = 0; j < ORDER + 1; j++) for (int j = 0; j < ORDER + 1; j++)
bn[i] += coeff[j] * (real)Cheby(j, i);
bn[i] += coeff[j] * (T)Cheby(j, i);
} }


/* Transform a polynomial in the [-1..1] range into a polynomial /* Transform a polynomial in the [-1..1] range into a polynomial
* in the [a..b] range. */ * in the [a..b] range. */
real k1p[ORDER + 1], k2p[ORDER + 1];
real an[ORDER + 1];
T k1p[ORDER + 1], k2p[ORDER + 1];
T an[ORDER + 1];


for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
k1p[i] = i ? k1p[i - 1] * m_invk1 : real::R_1;
k2p[i] = i ? k2p[i - 1] * m_invk2 : real::R_1;
k1p[i] = i ? k1p[i - 1] * m_invk1 : (T)1;
k2p[i] = i ? k2p[i - 1] * m_invk2 : (T)1;
} }


for (int i = 0; i < ORDER + 1; i++) for (int i = 0; i < ORDER + 1; i++)
{ {
an[i] = 0; an[i] = 0;
for (int j = i; j < ORDER + 1; j++) for (int j = i; j < ORDER + 1; j++)
an[i] += (real)Comb(j, i) * k1p[j - i] * bn[j];
an[i] += (T)Comb(j, i) * k1p[j - i] * bn[j];
an[i] *= k2p[i]; an[i] *= k2p[i];
} }


@@ -297,33 +306,35 @@ public:
{ {
if (j) if (j)
printf("+"); printf("+");
printf("x^%i*", j);
printf("x**%i*", j);
an[j].print(40); an[j].print(40);
} }
printf("\n"); printf("\n");
} }


real Value(real const &x)
T Value(T const &x)
{ {
return m_func(x * m_k2 + m_k1); return m_func(x * m_k2 + m_k1);
} }


real Weight(real const &x)
T Weight(T const &x)
{ {
return m_weight(x * m_k2 + m_k1); return m_weight(x * m_k2 + m_k1);
} }


/* ORDER + 1 Chebyshev coefficients and 1 error value */ /* ORDER + 1 Chebyshev coefficients and 1 error value */
real coeff[ORDER + 2];
T coeff[ORDER + 2];
/* ORDER + 1 zeroes of the error function */ /* ORDER + 1 zeroes of the error function */
real zeroes[ORDER + 1];
T zeroes[ORDER + 1];
/* ORDER + 2 control points */ /* ORDER + 2 control points */
real control[ORDER + 2];
T control[ORDER + 2];


private: private:
RealFunc *m_func, *m_weight; RealFunc *m_func, *m_weight;
real m_k1, m_k2, m_invk1, m_invk2;
T m_k1, m_k2, m_invk1, m_invk2;
}; };


#endif /* __REMEZ_SOLVER_H__ */
} /* namespace lol */

#endif /* __LOL_MATH_REMEZ_H__ */



+ 1
- 1
src/platform/nacl/naclapp.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_NACLAPP_H__ #if !defined __LOL_NACLAPP_H__
#define __LOL_NACLAPP_H__ #define __LOL_NACLAPP_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


+ 1
- 1
src/platform/ps3/ps3app.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_PS3APP_H__ #if !defined __LOL_PS3APP_H__
#define __LOL_PS3APP_H__ #define __LOL_PS3APP_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


+ 1
- 1
src/platform/sdl/sdlapp.h View File

@@ -16,7 +16,7 @@
#if !defined __LOL_SDLAPP_H__ #if !defined __LOL_SDLAPP_H__
#define __LOL_SDLAPP_H__ #define __LOL_SDLAPP_H__


#include "matrix.h"
#include "lol/math/matrix.h"


namespace lol namespace lol
{ {


+ 1
- 1
test/math/Makefile.am View File

@@ -22,7 +22,7 @@ poly_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
poly_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ poly_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
poly_DEPENDENCIES = $(top_builddir)/src/liblol.a poly_DEPENDENCIES = $(top_builddir)/src/liblol.a


remez_SOURCES = remez.cpp remez-matrix.h remez-solver.h
remez_SOURCES = remez.cpp
remez_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ remez_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
remez_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ remez_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
remez_DEPENDENCIES = $(top_builddir)/src/liblol.a remez_DEPENDENCIES = $(top_builddir)/src/liblol.a


+ 0
- 97
test/math/remez-matrix.h View File

@@ -1,97 +0,0 @@
//
// Lol Engine - Sample math program: Chebyshev polynomials
//
// Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

#if !defined __REMEZ_MATRIX_H__
#define __REMEZ_MATRIX_H__

template<int N> struct Matrix
{
inline Matrix() {}

Matrix(real x)
{
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
if (i == j)
m[i][j] = x;
else
m[i][j] = 0;
}

/* Naive matrix inversion */
Matrix<N> inv() const
{
Matrix a = *this, b((real)1.0);

/* Inversion method: iterate through all columns and make sure
* all the terms are 1 on the diagonal and 0 everywhere else */
for (int i = 0; i < N; i++)
{
/* If the expected coefficient is zero, add one of
* the other lines. The first we meet will do. */
if ((double)a.m[i][i] == 0.0)
{
for (int j = i + 1; j < N; j++)
{
if ((double)a.m[i][j] == 0.0)
continue;
/* Add row j to row i */
for (int n = 0; n < N; n++)
{
a.m[n][i] += a.m[n][j];
b.m[n][i] += b.m[n][j];
}
break;
}
}

/* Now we know the diagonal term is non-zero. Get its inverse
* and use that to nullify all other terms in the column */
real x = (real)1.0 / a.m[i][i];
for (int j = 0; j < N; j++)
{
if (j == i)
continue;
real mul = x * a.m[i][j];
for (int n = 0; n < N; n++)
{
a.m[n][j] -= mul * a.m[n][i];
b.m[n][j] -= mul * b.m[n][i];
}
}

/* Finally, ensure the diagonal term is 1 */
for (int n = 0; n < N; n++)
{
a.m[n][i] *= x;
b.m[n][i] *= x;
}
}

return b;
}

void print() const
{
using std::printf;

for (int j = 0; j < N; j++)
{
for (int i = 0; i < N; i++)
printf("%9.5f ", (double)m[j][i]);
printf("\n");
}
}

real m[N][N];
};

#endif /* __REMEZ_MATRIX_H__ */


+ 6
- 6
test/math/remez.cpp View File

@@ -12,19 +12,19 @@
# include "config.h" # include "config.h"
#endif #endif


#include <cstring>
#include <cstdio> #include <cstdio>
#include <cstdlib>


#if USE_SDL && defined __APPLE__ #if USE_SDL && defined __APPLE__
# include <SDL_main.h> # include <SDL_main.h>
#endif #endif


#include "core.h"
#include "lol/math/real.h"
#include "lol/math/matrix.h"
#include "lol/math/remez.h"


using lol::real; using lol::real;

#include "remez-matrix.h"
#include "remez-solver.h"
using lol::RemezSolver;


/* The function we want to approximate */ /* The function we want to approximate */
real myfun(real const &y) real myfun(real const &y)
@@ -41,7 +41,7 @@ real myerr(real const &y)


int main(int argc, char **argv) int main(int argc, char **argv)
{ {
RemezSolver<2> solver;
RemezSolver<2, real> solver;
solver.Run(real::R_1 >> 400, real::R_PI_2 * real::R_PI_2, myfun, myerr, 40); solver.Run(real::R_1 >> 400, real::R_PI_2 * real::R_PI_2, myfun, myerr, 40);


return EXIT_SUCCESS; return EXIT_SUCCESS;


Loading…
Cancel
Save