Crate microcheby

Crate microcheby 

Source
Expand description

microcheby is a crate for computing and evaluating polynomial approximations of functions of one variable using using Chebyshev polynomials. The code is no_std compatible, does not depend on alloc and is optimized for resource constrained environments where every clock cycle counts. Optimizations include:

  • Clenshaw recursion for evaluating approximations.
  • Efficient loop free functions for evaluating low order approximations.
  • Even more efficient loop free evaluation if the range happens to be [-1, 1].
  • Approximation evaluation without divisions.

§Installing

Add the following line to your Cargo.toml file:

microcheby = "0.1"

To use microcheby in a no_std environment:

microcheby = { version = "0.1", default-features = false }

§Chebyshev approximation

Sufficiently well behaved functions can be expressed as an infinite weighted sum of so called Chebyshev polynomials of increasing order. Such a sum is known as a Chebyshev expansion. If the target function is smooth enough, the coefficients (weights) of the expansion will typically converge to zero quickly and only the first few terms are needed to get a good approximation. For a truncated expansion with n terms, an estimate of the approximation error is given by the magnitude of coefficient n+1.

For a more detailed introduction, see 5.8 Chebyshev Approximation in Numerical Recipes in C: The Art of Scientific Computing.

§Basic usage

use microcheby::ChebyshevExpansion;

// Compute a 6 term expansion approximating the square root of x on the interval [0.1, 1.0]
let sqrt_exp = ChebyshevExpansion::<6>::fit(0.1, 1.0, |x| x.sqrt());
// Get the approximated value at x=0.7
let value_approx = sqrt_exp.eval(0.7);
// Get the actual value at x=0.7
let value_actual = 0.7_f32.sqrt();
// Compute the approximation error
let error = value_actual - value_approx;
assert!(error.abs() < 0.0002);

§Precomputing and instantiating expansions

Computing expansion coefficients requires an accurate cosine function and potentially costly target function evaluations, so it is sometimes desirable to precompute the coefficients and then use them to instantiate the expansion.

use microcheby::ChebyshevExpansion;

// Compute a 6 term expansion approximating the square root of x on the interval [0.1, 1.0]
let sqrt_exp = ChebyshevExpansion::<6>::fit(0.1, 1.0, |x| x.sqrt());

// x_min, x_max and coeffs are needed to instantiate the expansion.
// You can either print them to the terminal like this or use the associated getters.
println!("{sqrt_exp}");

// Instantiate the expansion computed above using arguments copied from the terminal.
let exp = ChebyshevExpansion::new(
    0.1,
    1.0,
    [1.4066492, 0.32991815, -0.04125017, 0.010474294, -0.0032901317, 0.0010244437]
);
assert_eq!(sqrt_exp.x_min(), exp.x_min());
assert_eq!(sqrt_exp.x_max(), exp.x_max());
assert_eq!(sqrt_exp.coeffs(), exp.coeffs());

Expansions can also be instantiated statically at compile time.

use microcheby::ChebyshevExpansion;

// Compute a 6 term expansion approximating the square root of x on the interval [0.1, 1.0]
let sqrt_exp = ChebyshevExpansion::<6>::fit(0.1, 1.0, |x| x.sqrt());

// x_min, range_scale and coeffs_internal are needed to instantiate the expansion
// at compile time since floating point operations are not allowed in constant expressions.
// You can either print them to the terminal like this or get them using a debugger.
println!("{:?}", sqrt_exp);

// A statically allocated ChebyshevExpansion
const EXP:ChebyshevExpansion<6> = ChebyshevExpansion::const_new(
    0.1,
    4.4444447,
    [0.7033246, 0.32991815, -0.04125017, 0.010474294, -0.0032901317, 0.0010244437]
);
assert_eq!(sqrt_exp.x_min(), EXP.x_min());
assert_eq!(sqrt_exp.x_max(), EXP.x_max());
assert_eq!(sqrt_exp.coeffs(), EXP.coeffs());

Structs§

ChebyshevExpansion
An N term Chebyshev expansion. See 5.8 Chebyshev Approximation in Numerical Recipes in C: The Art of Scientific Computing.

Enums§

MatchBoundary
Boundary matching is the process of adding a linear term ax + b to the Chebyshev expansion to make the it match the original function exactly at x_min and/or x_max. This probably increases the approximation error, but can be useful when exact matches at x_min and/or x_max are more important than overall accuracy.