Powerful interpolation routines with a simple calling interface.
You specify f(x), i.e. the function to use, and your error tolerance delta-y.
The Interpolator can fit a curve to a number of points of your choosing, and provides you with a "g(x)" style interface to the interpolant.
The Approximator can sample your function at a number of points and automatically construct a list of the sampled values, for use in interpolation. You choose the function f(x) and the interpolation method; the Approximator calls these as needed.
Interpolator and Approximator will work with
floats, doubles, the 2- and 3-vectors of my Vecpac library, and other types.
May be used standalone, or with Numerical Recipes™ interpolant routines (sold separately).
Purpose, Rationale
To make interpolation simple;
to capitalize on the power of C++, in order to present the user with a universal calling interface to interpolation routines, especially Numerical Recipes™ routines;
to adaptively fit curves.
Interpolator was written so that functions of one argument may be easily replaced by general-purpose interpolators.
Approximator was written to give computationally expensive functions an interface which calls the underlying expensive function as few times as possible, while still providing required levels of accuracy.
Caution
Don't try to build one of these at home! Testing it to perfection would take much more than $20 worth of your time.
Code Example
// Code to demonstrate the Approximator
// and the Piecewise Linear Interpolator class templates.
#include <math.h> // for exp()
#include "approximator.h" // for the Approximator template
#include "pw_linear_interpolator.h" // for the PWLinearInterpolator template
int
main()
{
// Construct a piecewise linear approximator to fit exp(x)
// over the range [-1, 3.5].
// Knots are placed no farther apart than 0.1 (in x);
// Between knots, the estimated deviation (in y) must be within 0.01:
Approximator<PWLinearInterpolator<double, double> > ax_pw_dd(exp, 0.1, 0.01);
// Now ask the Approximator to fit a curve over a range of x-values:
ax_pw_dd.extrapol_param = 0.5;
// (Must do this before mapping the range.
// This parameter will be explained later.)
ax_pw_dd.map_range(-1, 3.5);
// map_range() causes the Approximator to call your function and fit a curve.
// Call map_range() if you know in advance what range of x-values
// you wish to operate on.
// Note the effect of extrapol_param:
// extrapol_param pads the range slightly, so that every
// slight excursion/extrapolation outside the range won't cause f(x) to be called
// (which would change the curve fit).
// extrapol_param can limit or prevent disruptive re-fitting
// during crucial, sensitive phases of computation.
// (Re-fits change the curve shape and so are undesirable during operations like
// quadrature.)
// Set-up is now complete.
// In this example, we asked map_range() to map [-1, 3.5],
// but the extrapol_param of 0.5 widens this to [-1.5, 4.0].
// Later, when we use this approximator,
// as long as we choose x's inside [-1.5, 4.0], f() won't be called again,
// and the fit will remain constant; but
// any x outside [-1.5, 4.0] will cause new f() points to be sampled,
// causing the curve to be re-fit.
// In the example below, notice that we *will* go outside the range [-1.5, 4.0];
// but the Approximator handles this automatically, silently,
// without user intervention.
// f is approximated at 4.5 and printed without trouble. // Now use the Approximator to estimate values of exp().
// We print the estimated value, the true value, and the difference.
double x;
for (x = -1; x < 5; x += 0.5)
{
double y = exp(x),
y_star = ax_pw_dd(x);
double dy = y_star - y;
printf("ax_pw_dd(%5.2g) = ", x);
cout << y_star << "; exp(x) = " << y ;
cout << "; dy = " << dy << endl ;
}
putchar('\n');
printf("Number of function evaluations: %d\n", ax_pw_dd.nofun);
}
Output:
ax_pw_dd( -1) = 0.36803; exp(x) = 0.367879; dy = 0.000150654
ax_pw_dd( -0.5) = 0.606975; exp(x) = 0.606531; dy = 0.000444433
ax_pw_dd( 0) = 1.00097; exp(x) = 1; dy = 0.000971184
ax_pw_dd( 0.5) = 1.65058; exp(x) = 1.64872; dy = 0.00185698
ax_pw_dd( 1) = 2.72154; exp(x) = 2.71828; dy = 0.00326084
ax_pw_dd( 1.5) = 4.48703; exp(x) = 4.48169; dy = 0.00534431
ax_pw_dd( 2) = 7.39723; exp(x) = 7.38906; dy = 0.00817509
ax_pw_dd( 2.5) = 12.1861; exp(x) = 12.1825; dy = 0.00364754
ax_pw_dd( 3) = 20.0911; exp(x) = 20.0855; dy = 0.00557955
ax_pw_dd( 3.5) = 33.1213; exp(x) = 33.1155; dy = 0.00587866
ax_pw_dd( 4) = 54.5982; exp(x) = 54.5982; dy = 0
ax_pw_dd( 4.5) = 90.0171; exp(x) = 90.0171; dy = 1.42109e-14
Number of function evaluations: 259
// Granted, we could have called exp() directly,
// and the number of evaluations would have been much less.
// Then again, no one uses linear interpolators :^) .
// Here's a more realistic example, using the Piecewise Cubic Approximator:
~If customers are interested, add the examples for splines here, featuring the NR adaptor.
~How about a 3D example? 3D interpolators are working.
Pricing
Interpolator/Approximator is provided in three editions:
Copper Edition: Evaluation Copy -- comments removed; for demo purposes only (has one mysterious bug intentionally left in); no Numerical Recipes™ interface. (downloadable)
Silver Edition: Object Code Library. Template files. Templates instantiated for floats, doubles, and 3-vectors. Fully functional. Test suite included. (license $20)
Gold Edition: Source Code (license $100; terms to be announced)
The "Template Files" include:
Interpolator template
Interpolator instances:
Linear
Piecewise Linear
Spline*
Polynomial*
Interpolator3D template: May be used with any Interpolator instance as argument -- converts that interpolant into a function taking a scalar and returning a 3-vector.
Approximator template: May be used with any Interpolator or Interpolator3D instance as argument -- converts that interpolant into an adaptive curve fitter.
Specialized Approximator instances:
Piecewise Cubic
* Requires Numerical Recipes™ files in order to work. (3rd party -- sold separately)
Availability
As of August 23, 2001, Interpolator/Approximator demo code (Copper Edition) is available for Macintosh. (Download)
Silver Edition Macintosh code will be produced for customers who show an interest after evaluating the Copper Edition.
Code for other platforms is On Hold until a user expresses interest. Your e-mails will be most welcome.
If you are interested in purchasing or evaluating this product on a platform not listed above, please don't hesitate to send your encouragement to me at the e-mail address below -- I will work faster if I know you are waiting. Please mention which platform/OS you wish to work with.
Update for 2005: Due to the number of customers who expressed an interest but clearly never intended to pay, code for new platforms will only be produced for customers who pay in advance. Cheapskates and people-users can go write their own code.