Browse Source

lolremez: minor cosmetic changes and comments.

undefined
Sam Hocevar 10 years ago
parent
commit
364014c6e7
2 changed files with 59 additions and 51 deletions
  1. +58
    -50
      tools/lolremez/solver.cpp
  2. +1
    -1
      tools/lolremez/solver.h

+ 58
- 50
tools/lolremez/solver.cpp View File

@@ -69,6 +69,10 @@ void RemezSolver::Run(real a, real b,
PrintPoly();
}

/*
* This is basically the first Remez step: we solve a system of
* order N+1 and get a good initial polynomial estimate.
*/
void RemezSolver::Init()
{
/* m_order + 1 zeroes of the error function */
@@ -111,6 +115,54 @@ void RemezSolver::Init()
}
}

/*
* Every subsequent iteration of the Remez algorithm: we solve a system
* of order N+2 to both refine the estimate and compute the error.
*/
void RemezSolver::Step()
{
/* Pick up x_i where error will be 0 and compute f(x_i) */
array<real> fxn;
for (int i = 0; i < m_order + 2; i++)
fxn.Push(EvalFunc(m_control[i]));

/* We build a matrix of Chebishev evaluations: row i contains the
* evaluations of x_i for polynomial order n = 0, 1, ... */
LinearSystem<real> system(m_order + 2);
for (int n = 0; n < m_order + 1; n++)
{
auto p = polynomial<real>::chebyshev(n);
for (int i = 0; i < m_order + 2; i++)
system[i][n] = p.eval(m_control[i]);
}

/* The last line of the system is the oscillating error */
for (int i = 0; i < m_order + 2; i++)
{
real error = fabs(EvalWeight(m_control[i]));
system[i][m_order + 1] = (i & 1) ? error : -error;
}

/* Solve the system */
system = system.inverse();

/* Compute new polynomial estimate */
m_estimate = polynomial<real>();
for (int n = 0; n < m_order + 1; n++)
{
real weight = 0;
for (int i = 0; i < m_order + 2; i++)
weight += system[n][i] * fxn[i];

m_estimate += weight * polynomial<real>::chebyshev(n);
}

/* Compute the error (FIXME: unused?) */
real error = 0;
for (int i = 0; i < m_order + 2; i++)
error += system[m_order + 1][i] * fxn[i];
}

void RemezSolver::FindZeroes()
{
/* Find m_order + 1 zeroes of the error function. No need to
@@ -121,16 +173,16 @@ void RemezSolver::FindZeroes()
struct { real value, error; } left, right, mid;

left.value = m_control[i];
left.error = EvalCheby(left.value) - EvalFunc(left.value);
left.error = EvalEstimate(left.value) - EvalFunc(left.value);
right.value = m_control[i + 1];
right.error = EvalCheby(right.value) - EvalFunc(right.value);
right.error = EvalEstimate(right.value) - EvalFunc(right.value);

static real limit = ldexp((real)1, -500);
static real zero = (real)0;
while (fabs(left.value - right.value) > limit)
{
mid.value = (left.value + right.value) / 2;
mid.error = EvalCheby(mid.value) - EvalFunc(mid.value);
mid.error = EvalEstimate(mid.value) - EvalFunc(mid.value);

if ((left.error <= zero && mid.error <= zero)
|| (left.error >= zero && mid.error >= zero))
@@ -175,7 +227,7 @@ real RemezSolver::FindExtrema()
if (r == 0 || (k & 1))
{
++evals;
real error = fabs(EvalCheby(c) - EvalFunc(c));
real error = fabs(EvalEstimate(c) - EvalFunc(c));
real weight = fabs(EvalWeight(c));
/* if error/weight >= maxerror/maxweight */
if (error * maxweight >= maxerror * weight)
@@ -214,56 +266,12 @@ real RemezSolver::FindExtrema()
}

printf("Iterations: Rounds %d Evals %d\n", rounds, evals);
printf("Times: Cheby %f Func %f EvalWeight %f\n",
printf("Times: Estimate %f Func %f EvalWeight %f\n",
m_stats_cheby, m_stats_func, m_stats_weight);

return final;
}

void RemezSolver::Step()
{
/* Pick up x_i where error will be 0 and compute f(x_i) */
array<real> fxn;
for (int i = 0; i < m_order + 2; i++)
fxn.Push(EvalFunc(m_control[i]));

/* We build a matrix of Chebishev evaluations: row i contains the
* evaluations of x_i for polynomial order n = 0, 1, ... */
LinearSystem<real> system(m_order + 2);
for (int n = 0; n < m_order + 1; n++)
{
auto p = polynomial<real>::chebyshev(n);
for (int i = 0; i < m_order + 2; i++)
system[i][n] = p.eval(m_control[i]);
}

/* The last line of the system is the oscillating error */
for (int i = 0; i < m_order + 2; i++)
{
real error = fabs(EvalWeight(m_control[i]));
system[i][m_order + 1] = (i & 1) ? error : -error;
}

/* Solve the system */
system = system.inverse();

/* Compute new polynomial estimate */
m_estimate = polynomial<real>();
for (int n = 0; n < m_order + 1; n++)
{
real weight = 0;
for (int i = 0; i < m_order + 2; i++)
weight += system[n][i] * fxn[i];

m_estimate += weight * polynomial<real>::chebyshev(n);
}

/* Compute the error */
real error = 0;
for (int i = 0; i < m_order + 2; i++)
error += system[m_order + 1][i] * fxn[i];
}

void RemezSolver::PrintPoly()
{
using std::printf;
@@ -284,7 +292,7 @@ void RemezSolver::PrintPoly()
printf("\n\n");
}

real RemezSolver::EvalCheby(real const &x)
real RemezSolver::EvalEstimate(real const &x)
{
Timer t;
real ret = m_estimate.eval(x);


+ 1
- 1
tools/lolremez/solver.h View File

@@ -34,7 +34,7 @@ private:
void Step();
void PrintPoly();

lol::real EvalCheby(lol::real const &x);
lol::real EvalEstimate(lol::real const &x);
lol::real EvalFunc(lol::real const &x);
lol::real EvalWeight(lol::real const &x);



Loading…
Cancel
Save