Discrete vs. continuous mode

The original AAA algorithm (Nakatsukasa, Sète, Trefethen 2018) works with a fixed set of points on the domain of approximation. The aaa method can work with this type of data:

using RationalFunctionApproximation, ComplexRegions
x = -1:0.01:1
f = x -> tanh(5 * (x - 0.2))
r = aaa(x, f.(x))
Barycentric function with 12 nodes and values:
    1.0=>0.999329,  -1.0=>-0.999988,  0.46=>0.861723,  …  0.74=>0.991007

As long as there are no singularities as close to the domain as the sample points are to one another, this fully discrete approach should be fine:

I = unit_interval
println("nearest pole is $(minimum(dist(z, I) for z in poles(r))) away")
xx = -1:0.0005:1
println("error = $(maximum(abs, @. f(xx) - r(xx) ))")
nearest pole is 0.31415926535544925 away
error = 2.8310687127941492e-14

But if the distance to a singularity is comparable to the sample spacing, the quality of the approximation may suffer:

f = x -> tanh(500 * (x - 0.2))
r = aaa(x, f.(x))
println("nearest pole is $(minimum(dist(z, I) for z in poles(r))) away")
println("error = $(maximum(abs, @. f(xx) - r(xx) ))")
nearest pole is 0.004340949411054289 away
error = 0.13277905425418834

In the continuous mode (Driscoll, Nakatsukasa, Trefethen) used by the approximate method, the samples are refined adaptively to try to ensure that the approximation is accurate everywhere:

r = approximate(f, I)
println("error = $(maximum(abs, @. f(xx) - r(xx) ))")
error = 9.274803147718558e-13