Listing 6. C code to determine optimal scale and offset for some approximation
const double Epsilon = 0.0001;
const double ThresholdError = 0.0001;
// Find values for A and B minimizing the maximal error given n and m
void FindAB( double n, double m, double &A, double &B )
{
double k0 = 0;
double k1 = 1;
double k;
double ErrorLeft, ErrorRight;
// Binary
search for optimal crossing point
do
{
k = (k0 + k1)/2.0;
A = ( pow( k, n/m ) - 1.0 ) / ( k - 1.0
);
B = 1.0 - A;
EvaluateMaxError( n, m, A, B, k, ErrorLeft, ErrorRight );
if(
ErrorLeft < ErrorRight )
k0 = k;
else
k1 = k;
} while( fabs( ErrorLeft - ErrorRight ) > ThresholdError
);
}
// Evaluate the maximal error to the left and right of the crossing point
// for given values of A and B
// The crossing point k is given to reduce computation
void EvaluateMaxError( double n, double m, double A, double B, double k,
double &ErrorLeft, double &ErrorRight )
{
double x;
double DerErr;
// Find
maximal point of the error function on the left of the crossing point
double x0 = 0;
double x1 = k;
do
{
x = (x0 + x1)/2.0;
DerErr
= DerError( x, n, m, A, B );
if( DerErr < 0 )
x0 = x;
else
x1 = x;
} while( fabs( x0-x1 ) > Epsilon );
// Evaluate
the error at that point
ErrorLeft = fabs( Error( x, n, m, A, B ) );
x0 = k;
x1 = 1;
// Find
maximal point of the error function on the right of the crossing point
do
{
x = (x0 + x1)/2.0;
DerErr
= DerError( x, n, m, A, B );
if( DerErr > 0 )
x0 = x;
else
x1 = x;
} while( fabs( x0-x1 ) > Epsilon );
// Evaluate
the error at that point
ErrorRight = fabs( Error( x, n, m, A, B ) );
}
// Evaluate the approximation function
double Approx( double x, double m, double A, double B )
{
if( x < -B/A )
return 0;
return pow( A * x + B, m );
}
// Evaluate the derivative of the approximation function
double DerApprox( double x, double m, double A, double B )
{
if( x < -B/A )
return 0;
return A*m*pow( A * x + B, m-1 );
}
// Evaluate the error function
double Error( double x, double n, double m, double A, double B )
{
return Approx( x, m, A, B ) - pow( x, n );
}
// Evaluate the derivative of the error function
double DerError( double x, double n, double m, double A, double B )
{
return DerApprox( x, m, A, B ) - n*pow( x, n-1 );
}