solving.legacy
@@ -16,7 +16,7 @@ pi_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ | |||||
pi_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | pi_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ | ||||
pi_DEPENDENCIES = $(top_builddir)/src/liblol.a | pi_DEPENDENCIES = $(top_builddir)/src/liblol.a | ||||
remez_SOURCES = remez.cpp | |||||
remez_SOURCES = remez.cpp remez-matrix.h remez-solver.h | |||||
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,0 +1,95 @@ | |||||
// | |||||
// 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 | |||||
{ | |||||
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__ */ | |||||
@@ -0,0 +1,295 @@ | |||||
// | |||||
// 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_SOLVER_H__ | |||||
#define __REMEZ_SOLVER_H__ | |||||
template<int ORDER> class RemezSolver | |||||
{ | |||||
public: | |||||
typedef real RealFunc(real const &x); | |||||
RemezSolver() | |||||
{ | |||||
ChebyInit(); | |||||
} | |||||
void Run(RealFunc *func, RealFunc *error, int steps) | |||||
{ | |||||
m_func = func; | |||||
m_error = error; | |||||
Init(); | |||||
ChebyCoeff(); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%14.12gx^%i", j && (bn[j] >= real::R_0) ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
for (int n = 0; n < steps; n++) | |||||
{ | |||||
FindError(); | |||||
Step(); | |||||
ChebyCoeff(); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%14.12gx^%i", j && (bn[j] >= real::R_0) ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
FindZeroes(); | |||||
} | |||||
FindError(); | |||||
Step(); | |||||
ChebyCoeff(); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%14.12gx^%i", j && (bn[j] >= real::R_0) ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
} | |||||
/* Fill the Chebyshev tables */ | |||||
void ChebyInit() | |||||
{ | |||||
memset(cheby, 0, sizeof(cheby)); | |||||
cheby[0][0] = 1; | |||||
cheby[1][1] = 1; | |||||
for (int i = 2; i < ORDER + 1; i++) | |||||
{ | |||||
cheby[i][0] = -cheby[i - 2][0]; | |||||
for (int j = 1; j < ORDER + 1; j++) | |||||
cheby[i][j] = 2 * cheby[i - 1][j - 1] - cheby[i - 2][j]; | |||||
} | |||||
} | |||||
void ChebyCoeff() | |||||
{ | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
bn[i] = 0; | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
if (cheby[j][i]) | |||||
bn[i] += coeff[j] * (real)cheby[j][i]; | |||||
} | |||||
} | |||||
real ChebyEval(real const &x) | |||||
{ | |||||
real ret = 0.0, xn = 1.0; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
real mul = 0; | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
if (cheby[j][i]) | |||||
mul += coeff[j] * (real)cheby[j][i]; | |||||
ret += mul * xn; | |||||
xn *= x; | |||||
} | |||||
return ret; | |||||
} | |||||
void Init() | |||||
{ | |||||
/* Pick up x_i where error will be 0 and compute f(x_i) */ | |||||
real fxn[ORDER + 1]; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
zeroes[i] = (real)(2 * i - ORDER) / (real)(ORDER + 1); | |||||
fxn[i] = m_func(zeroes[i]); | |||||
} | |||||
/* We build a matrix of Chebishev evaluations: row i contains the | |||||
* evaluations of x_i for polynomial order n = 0, 1, ... */ | |||||
Matrix<ORDER + 1> mat; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
/* Compute the powers of x_i */ | |||||
real powers[ORDER + 1]; | |||||
powers[0] = 1.0; | |||||
for (int n = 1; n < ORDER + 1; n++) | |||||
powers[n] = powers[n - 1] * zeroes[i]; | |||||
/* Compute the Chebishev evaluations at x_i */ | |||||
for (int n = 0; n < ORDER + 1; n++) | |||||
{ | |||||
real sum = 0.0; | |||||
for (int k = 0; k < ORDER + 1; k++) | |||||
if (cheby[n][k]) | |||||
sum += (real)cheby[n][k] * powers[k]; | |||||
mat.m[i][n] = sum; | |||||
} | |||||
} | |||||
/* Solve the system */ | |||||
mat = mat.inv(); | |||||
/* Compute interpolation coefficients */ | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
{ | |||||
coeff[j] = 0; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
coeff[j] += mat.m[j][i] * fxn[i]; | |||||
} | |||||
} | |||||
void FindZeroes() | |||||
{ | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
real a = control[i]; | |||||
real ea = ChebyEval(a) - m_func(a); | |||||
real b = control[i + 1]; | |||||
real eb = ChebyEval(b) - m_func(b); | |||||
while (fabs(a - b) > (real)1e-140) | |||||
{ | |||||
real c = (a + b) * (real)0.5; | |||||
real ec = ChebyEval(c) - m_func(c); | |||||
if ((ea < (real)0 && ec < (real)0) | |||||
|| (ea > (real)0 && ec > (real)0)) | |||||
{ | |||||
a = c; | |||||
ea = ec; | |||||
} | |||||
else | |||||
{ | |||||
b = c; | |||||
eb = ec; | |||||
} | |||||
} | |||||
zeroes[i] = a; | |||||
} | |||||
} | |||||
void FindError() | |||||
{ | |||||
real final = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
{ | |||||
real a = -1, b = 1; | |||||
if (i > 0) | |||||
a = zeroes[i - 1]; | |||||
if (i < ORDER + 1) | |||||
b = zeroes[i]; | |||||
printf("Error for [%g..%g]: ", (double)a, (double)b); | |||||
for (;;) | |||||
{ | |||||
real c = a, delta = (b - a) / (real)10.0; | |||||
real maxerror = 0; | |||||
int best = -1; | |||||
for (int k = 0; k <= 10; k++) | |||||
{ | |||||
real e = fabs(ChebyEval(c) - m_func(c)); | |||||
if (e > maxerror) | |||||
{ | |||||
maxerror = e; | |||||
best = k; | |||||
} | |||||
c += delta; | |||||
} | |||||
if (best == 0) | |||||
best = 1; | |||||
if (best == 10) | |||||
best = 9; | |||||
b = a + (real)(best + 1) * delta; | |||||
a = a + (real)(best - 1) * delta; | |||||
if (b - a < (real)1e-15) | |||||
{ | |||||
if (maxerror > final) | |||||
final = maxerror; | |||||
control[i] = (a + b) * (real)0.5; | |||||
printf("%g (at %g)\n", (double)maxerror, (double)control[i]); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
printf("Final error: %g\n", (double)final); | |||||
} | |||||
void Step() | |||||
{ | |||||
/* Pick up x_i where error will be 0 and compute f(x_i) */ | |||||
real fxn[ORDER + 2]; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
fxn[i] = m_func(control[i]); | |||||
/* We build a matrix of Chebishev evaluations: row i contains the | |||||
* evaluations of x_i for polynomial order n = 0, 1, ... */ | |||||
Matrix<ORDER + 2> mat; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
{ | |||||
/* Compute the powers of x_i */ | |||||
real powers[ORDER + 1]; | |||||
powers[0] = 1.0; | |||||
for (int n = 1; n < ORDER + 1; n++) | |||||
powers[n] = powers[n - 1] * control[i]; | |||||
/* Compute the Chebishev evaluations at x_i */ | |||||
for (int n = 0; n < ORDER + 1; n++) | |||||
{ | |||||
real sum = 0.0; | |||||
for (int k = 0; k < ORDER + 1; k++) | |||||
if (cheby[n][k]) | |||||
sum += (real)cheby[n][k] * powers[k]; | |||||
mat.m[i][n] = sum; | |||||
} | |||||
if (i & 1) | |||||
mat.m[i][ORDER + 1] = fabs(m_error(control[i])); | |||||
else | |||||
mat.m[i][ORDER + 1] = -fabs(m_error(control[i])); | |||||
} | |||||
/* Solve the system */ | |||||
mat = mat.inv(); | |||||
/* Compute interpolation coefficients */ | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
{ | |||||
coeff[j] = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
coeff[j] += mat.m[j][i] * fxn[i]; | |||||
} | |||||
/* Compute the error */ | |||||
real error = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
error += mat.m[ORDER + 1][i] * fxn[i]; | |||||
} | |||||
int cheby[ORDER + 1][ORDER + 1]; | |||||
/* ORDER + 1 chebyshev coefficients and 1 error value */ | |||||
real coeff[ORDER + 2]; | |||||
/* ORDER + 1 zeroes of the error function */ | |||||
real zeroes[ORDER + 1]; | |||||
/* ORDER + 2 control points */ | |||||
real control[ORDER + 2]; | |||||
real bn[ORDER + 1]; | |||||
private: | |||||
RealFunc *m_func; | |||||
RealFunc *m_error; | |||||
}; | |||||
#endif /* __REMEZ_SOLVER_H__ */ | |||||
@@ -20,367 +20,25 @@ | |||||
using namespace lol; | using namespace lol; | ||||
using namespace std; | using namespace std; | ||||
/* The order of the approximation we're looking for */ | |||||
static int const ORDER = 4; | |||||
#include "remez-matrix.h" | |||||
#include "remez-solver.h" | |||||
/* The function we want to approximate */ | /* The function we want to approximate */ | ||||
static real myfun(real const &x) | static real myfun(real const &x) | ||||
{ | { | ||||
return exp(x); | return exp(x); | ||||
//if (!x) | |||||
// return real::R_PI_2; | |||||
//return sin(x * real::R_PI_2) / x; | |||||
} | } | ||||
static real myerror(real const &x) | static real myerror(real const &x) | ||||
{ | { | ||||
return myfun(x); | return myfun(x); | ||||
//return real::R_1; | |||||
} | |||||
/* Naive matrix inversion */ | |||||
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; | |||||
} | |||||
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 | |||||
{ | |||||
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]; | |||||
}; | |||||
static int cheby[ORDER + 1][ORDER + 1]; | |||||
/* Fill the Chebyshev tables */ | |||||
static void cheby_init() | |||||
{ | |||||
memset(cheby, 0, sizeof(cheby)); | |||||
cheby[0][0] = 1; | |||||
cheby[1][1] = 1; | |||||
for (int i = 2; i < ORDER + 1; i++) | |||||
{ | |||||
cheby[i][0] = -cheby[i - 2][0]; | |||||
for (int j = 1; j < ORDER + 1; j++) | |||||
cheby[i][j] = 2 * cheby[i - 1][j - 1] - cheby[i - 2][j]; | |||||
} | |||||
} | |||||
static void cheby_coeff(real *coeff, real *bn) | |||||
{ | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
bn[i] = 0; | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
if (cheby[j][i]) | |||||
bn[i] += coeff[j] * (real)cheby[j][i]; | |||||
} | |||||
} | |||||
static real cheby_eval(real *coeff, real const &x) | |||||
{ | |||||
real ret = 0.0, xn = 1.0; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
real mul = 0; | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
if (cheby[j][i]) | |||||
mul += coeff[j] * (real)cheby[j][i]; | |||||
ret += mul * xn; | |||||
xn *= x; | |||||
} | |||||
return ret; | |||||
} | |||||
static void remez_init(real *coeff, real *zeroes) | |||||
{ | |||||
/* Pick up x_i where error will be 0 and compute f(x_i) */ | |||||
real fxn[ORDER + 1]; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
zeroes[i] = (real)(2 * i - ORDER) / (real)(ORDER + 1); | |||||
fxn[i] = myfun(zeroes[i]); | |||||
} | |||||
/* We build a matrix of Chebishev evaluations: row i contains the | |||||
* evaluations of x_i for polynomial order n = 0, 1, ... */ | |||||
Matrix<ORDER + 1> mat; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
/* Compute the powers of x_i */ | |||||
real powers[ORDER + 1]; | |||||
powers[0] = 1.0; | |||||
for (int n = 1; n < ORDER + 1; n++) | |||||
powers[n] = powers[n - 1] * zeroes[i]; | |||||
/* Compute the Chebishev evaluations at x_i */ | |||||
for (int n = 0; n < ORDER + 1; n++) | |||||
{ | |||||
real sum = 0.0; | |||||
for (int k = 0; k < ORDER + 1; k++) | |||||
if (cheby[n][k]) | |||||
sum += (real)cheby[n][k] * powers[k]; | |||||
mat.m[i][n] = sum; | |||||
} | |||||
} | |||||
/* Solve the system */ | |||||
mat = mat.inv(); | |||||
/* Compute interpolation coefficients */ | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
{ | |||||
coeff[j] = 0; | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
coeff[j] += mat.m[j][i] * fxn[i]; | |||||
} | |||||
} | |||||
static void remez_findzeroes(real *coeff, real *zeroes, real *control) | |||||
{ | |||||
for (int i = 0; i < ORDER + 1; i++) | |||||
{ | |||||
real a = control[i]; | |||||
real ea = cheby_eval(coeff, a) - myfun(a); | |||||
real b = control[i + 1]; | |||||
real eb = cheby_eval(coeff, b) - myfun(b); | |||||
while (fabs(a - b) > (real)1e-140) | |||||
{ | |||||
real c = (a + b) * (real)0.5; | |||||
real ec = cheby_eval(coeff, c) - myfun(c); | |||||
if ((ea < (real)0 && ec < (real)0) | |||||
|| (ea > (real)0 && ec > (real)0)) | |||||
{ | |||||
a = c; | |||||
ea = ec; | |||||
} | |||||
else | |||||
{ | |||||
b = c; | |||||
eb = ec; | |||||
} | |||||
} | |||||
zeroes[i] = a; | |||||
} | |||||
} | |||||
static void remez_finderror(real *coeff, real *zeroes, real *control) | |||||
{ | |||||
real final = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
{ | |||||
real a = -1, b = 1; | |||||
if (i > 0) | |||||
a = zeroes[i - 1]; | |||||
if (i < ORDER + 1) | |||||
b = zeroes[i]; | |||||
printf("Error for [%g..%g]: ", (double)a, (double)b); | |||||
for (;;) | |||||
{ | |||||
real c = a, delta = (b - a) / (real)10.0; | |||||
real maxerror = 0; | |||||
int best = -1; | |||||
for (int k = 0; k <= 10; k++) | |||||
{ | |||||
real e = fabs(cheby_eval(coeff, c) - myfun(c)); | |||||
if (e > maxerror) | |||||
{ | |||||
maxerror = e; | |||||
best = k; | |||||
} | |||||
c += delta; | |||||
} | |||||
if (best == 0) | |||||
best = 1; | |||||
if (best == 10) | |||||
best = 9; | |||||
b = a + (real)(best + 1) * delta; | |||||
a = a + (real)(best - 1) * delta; | |||||
if (b - a < (real)1e-15) | |||||
{ | |||||
if (maxerror > final) | |||||
final = maxerror; | |||||
control[i] = (a + b) * (real)0.5; | |||||
printf("%g (at %g)\n", (double)maxerror, (double)control[i]); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
printf("Final error: %g\n", (double)final); | |||||
} | |||||
static void remez_step(real *coeff, real *control) | |||||
{ | |||||
/* Pick up x_i where error will be 0 and compute f(x_i) */ | |||||
real fxn[ORDER + 2]; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
fxn[i] = myfun(control[i]); | |||||
/* We build a matrix of Chebishev evaluations: row i contains the | |||||
* evaluations of x_i for polynomial order n = 0, 1, ... */ | |||||
Matrix<ORDER + 2> mat; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
{ | |||||
/* Compute the powers of x_i */ | |||||
real powers[ORDER + 1]; | |||||
powers[0] = 1.0; | |||||
for (int n = 1; n < ORDER + 1; n++) | |||||
powers[n] = powers[n - 1] * control[i]; | |||||
/* Compute the Chebishev evaluations at x_i */ | |||||
for (int n = 0; n < ORDER + 1; n++) | |||||
{ | |||||
real sum = 0.0; | |||||
for (int k = 0; k < ORDER + 1; k++) | |||||
if (cheby[n][k]) | |||||
sum += (real)cheby[n][k] * powers[k]; | |||||
mat.m[i][n] = sum; | |||||
} | |||||
if (i & 1) | |||||
mat.m[i][ORDER + 1] = fabs(myerror(control[i])); | |||||
else | |||||
mat.m[i][ORDER + 1] = -fabs(myerror(control[i])); | |||||
} | |||||
/* Solve the system */ | |||||
mat = mat.inv(); | |||||
/* Compute interpolation coefficients */ | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
{ | |||||
coeff[j] = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
coeff[j] += mat.m[j][i] * fxn[i]; | |||||
} | |||||
/* Compute the error */ | |||||
real error = 0; | |||||
for (int i = 0; i < ORDER + 2; i++) | |||||
error += mat.m[ORDER + 1][i] * fxn[i]; | |||||
} | } | ||||
int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
{ | { | ||||
cheby_init(); | |||||
/* ORDER + 1 chebyshev coefficients and 1 error value */ | |||||
real coeff[ORDER + 2]; | |||||
/* ORDER + 1 zeroes of the error function */ | |||||
real zeroes[ORDER + 1]; | |||||
/* ORDER + 2 control points */ | |||||
real control[ORDER + 2]; | |||||
real bn[ORDER + 1]; | |||||
remez_init(coeff, zeroes); | |||||
cheby_coeff(coeff, bn); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%12.10gx^%i", j ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
for (int n = 0; n < 200; n++) | |||||
{ | |||||
remez_finderror(coeff, zeroes, control); | |||||
remez_step(coeff, control); | |||||
cheby_coeff(coeff, bn); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%12.10gx^%i", j ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
remez_findzeroes(coeff, zeroes, control); | |||||
} | |||||
remez_finderror(coeff, zeroes, control); | |||||
remez_step(coeff, control); | |||||
RemezSolver<4> solver; | |||||
cheby_coeff(coeff, bn); | |||||
for (int j = 0; j < ORDER + 1; j++) | |||||
printf("%s%12.10gx^%i", j ? "+" : "", (double)bn[j], j); | |||||
printf("\n"); | |||||
solver.Run(myfun, myerror, 10); | |||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
} | } | ||||