Skip to content

Discrete data

For many functions, discretization of the domain is straightforward. But if the function has singularities close to the domain of approximation, a continuum approach may be more robust.

The approximate function can take a vector of sample points as a domain. The given function is then evaluated only at those points, and the rational approximation is a fully discrete process that uses only the given data.

julia
using RationalFunctionApproximation, ComplexRegions
x = -1:0.01:1
f = x -> tanh(5 * (x - 0.2))
r = approximate(f, x)
Barycentric{Float64, Float64} rational of type (11, 11) constructed from 201 samples

You can alternatively provide just the discrete function values yourself. The domain is always given second:

julia
y = f.(x)
r = approximate(y, x)
Barycentric{Float64, Float64} rational of type (11, 11) constructed from 201 samples

As long as there are no singularities as close to the domain as the sample points are to one another, a basic discretization works well.

julia
I = unit_interval
println("nearest pole is $(minimum(dist(z, I) for z in poles(r))) away")
_, err = check(r);
println("max error on the given domain: ", maximum(abs, err))
nearest pole is 0.31415926535638594 away
[ Info: Max error is 2.24e-14
max error on the given domain: 2.2426505097428162e-14

But if the distance to a singularity is comparable to the sample spacing, the quality of the approximation may suffer. Even worse, the method may not be aware that it has failed.

julia
f = x -> tanh(400 * (x - 0.2))
r = approximate(f, x)
println("nearest pole is $(minimum(dist(z, I) for z in poles(r))) away")
_, err = check(r);
println("max error on the given domain: ", maximum(abs, err))
err = maximum(abs(f(x)- r(x)) for x in range(-1, 1, 3000))
println("max error on finer test points: ", err)
nearest pole is 0.004569419284272946 away
[ Info: Max error is 7.84e-14
max error on the given domain: 7.838174553853605e-14
max error on finer test points: 0.058457305710306495

In the continuous mode, the adaptive sampling of the domain attempts to ensure that the approximation is accurate everywhere.

julia
r = approximate(f, I; tol=1e-12)
err = maximum(abs(f(x)- r(x)) for x in range(-1, 1, 3000))
println("max error on finer test points: ", err)
Warning: Stopping with estimated error 1.698e-12 after 60 iterations
@ RationalFunctionApproximation ~/work/RationalFunctionApproximation.jl/RationalFunctionApproximation.jl/src/barycentric.jl:367
max error on finer test points: 1.938782467902911e-12