# ApproxFun.jl lets you do calculus on a function you never wrote down

> ApproxFun is a Julia package for approximating functions, where you build a Fun from an interval and then treat it as an object you can differentiate, integrate, add and take roots of, backed by a spectral method. It suits a numerical analyst working on differential equations, and the approximation is the point, since the function you are working with may have no closed form.

**JuliaApproximation/ApproxFun.jl** — Julia package for function approximation

- Repository: https://github.com/JuliaApproximation/ApproxFun.jl
- Website: http://juliaapproximation.github.io/ApproxFun.jl/
- Stars: 561 · Forks: 71
- Language: Julia
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/juliaapproximation-approxfun-jl

## A function becomes a value you can compute with

ApproxFun is a package for approximating functions, in a similar vein to the Matlab package Chebfun and the Mathematica package RHPackage. The idea is that you never write down the function, you point at an interval and a callback, and the package hands you back an object that behaves like a function.

```julia
using LinearAlgebra, SpecialFunctions, Plots, ApproxFun
x = Fun(identity,0..10)
f = sin(x^2)
g = cos(x)
```

Evaluating `f(.1)` returns a high accuracy approximation to `sin(0.01)`. All the algebraic manipulations of functions are supported and more.

That last clause is what makes the package more than a wrapper around a callback. The algebraic manipulations are the interesting part: you can add `f` and `g^2` together and compute the roots and extrema.

```julia
h = f + g^2
r = roots(h)
rp = roots(h')

plot(h; label="f + g^2")
scatter!(r, h.(r); label="roots")
scatter!(rp, h.(rp); label="extrema")
```

So the workflow is: define the function on an interval, compose it with itself and with other functions, then ask for the things you would otherwise have to find numerically, such as the zeros and the turning points. The `roots` and `roots(h')` calls do the work that a plotting script and a hand-rolled Newton iteration would otherwise do.

## Differentiation and integration come from overriding base functions

The mechanism behind the calculus operations is a design choice that is worth understanding, because it explains both the ergonomics and the limits of the package.

To find the extrema in the previous example, the prime operator was overridden for the differentiate function, and several other Julia base functions are overridden for the purposes of calculus. The documentation checks the result against a known identity, that the exponential is its own derivative, by evaluating the norm of the difference.

```julia
f = Fun(exp, -1..1)
norm(f-f')  # 4.4391656415701095e-14
```

Similarly, `cumsum` defines an indefinite integration operator, and the check is again a residual norm.

```julia
g = cumsum(f)
g = g + f(-1)
norm(f-g) # 3.4989733283850415e-15d
```

The residuals are small, which is the evidence the documentation offers that the operators do what they claim.

The design consequence is that the package works by extending Julia's own vocabulary. `f'` is differentiation, `cumsum` is integration, and both fit into code that already reads like Julia. The alternative, a separate namespace of approximation functions, would be more explicit and less familiar, and it would not let you write `roots(h')` and have it mean the same thing as `roots` of the derivative.

Overriding base functions is also the package's main hazard. Code that treats a `Fun` as an ordinary array or function has to know that some operators behave differently for a `Fun` than for a vector.

## Special functions and differential operators are overridden too

The same extension mechanism covers the special functions, which is where the package earns its keep for the differential equation use case.

Algebraic and differential operations are also implemented where possible, and most of Julia's built-in functions, and special functions from SpecialFunctions.jl, are overridden to accept `Fun`s.

```julia
x = Fun()
f = erf(x)
g = besselj(3,exp(f))
h = airyai(10asin(f)+2g)
```

The error function, a Bessel function of the first kind, and the Airy function, composed with each other and with a sine and an exponential, all evaluated on an approximation rather than on a number. The composition `10asin(f)+2g` is the kind of expression that appears in a boundary value problem, and the package is designed so that it can be written directly.

The repository's examples directory shows the range of what is being solved, and the file names are a good index: ODE_IVP for initial value problems, ODE_BVP for boundary value problems, NonlinearBVP for nonlinear boundary value problems, PDE_Heat, PDE_Helmholtz and PDE_Poisson for partial differential equations, Sampling for inverse transform sampling, Periodic for periodic problems, Eigenvalue with several variants, and system_of_eqn for systems of equations.

That list is also the honest scope of the package. It is a numerical apparatus for a specific class of problem, not a general purpose symbolic system.

## The method behind the approximation

The references section explains where the numerics come from, and they are the spectral method literature rather than something specific to Julia.

The list includes Olver and Townsend, A fast and well-conditioned spectral method in SIAM Review, and their paper on the automatic solution of partial differential equations using a global spectral method in Journal of Computational Physics. There is also Olver and Townsend on fast inverse transform sampling in one and two dimensions, and Aurentz and Slevinsky on symmetrizing the ultraspherical spectral method for self-adjoint problems, arxiv:1903.08538.

So the approximation is a Chebyshev or ultraspherical spectral expansion, which is why the two Matlab and Mathematica predecessors named in the introduction, Chebfun and RHPackage, are the right comparison points. Spectral methods represent a function by its values at a small set of well-chosen points, which is why the package can differentiate and integrate by manipulating coefficients rather than by finite differences.

The Aurentz and Slevinsky paper on symmetrizing the ultraspherical method for self-adjoint problems is the one that matters for the eigenvalue and BVP examples, because self-adjointness is what lets the spectral method work cleanly on those problems.

The implementation detail that matters most in practice is that a `Fun` knows its interval. Every operation in the examples, `Fun(identity,0..10)`, `Fun(exp, -1..1)`, is tied to the domain, and the accuracy of the approximation is a property of that domain and the smoothness of the function on it.

## Installing it and running the first example

ApproxFun is a Julia package, so it is installed with the Julia package manager, from the Julia REPL or by adding it to a project environment.

ApproxFun is installed the way any Julia package is, and the documentation page carries a Quick Start section for it.

Once it is loaded, the first thing worth doing is the identity check, because it tells you whether the approximation is behaving on your machine without needing a plot.

```julia
f = Fun(exp, -1..1)
norm(f-f')  # 4.4391656415701095e-14
```

The result should be a small residual, and the documentation shows a value of 4.4391656415701095e-14 for that expression.

For anything involving plotting, the examples load Plots as well, and the package's own documentation contains examples of usage. The separate ApproxFunExamples repository contains many examples of using the package, in Jupyter notebooks and Julia scripts, and the documentation notes that this is independently maintained, so it might not always be in sync with the latest version of ApproxFun. The recommendation is to check the examples in the documentation first, as these will always be compatible with the latest version of the package.

That recommendation is worth taking literally. The examples repository is the kind of thing that ages quietly, while the documentation is regenerated with each release.

## The repository layout, and who the package is for

The top level of the repository shows a package with the standard Julia arrangement plus a few extras.

There is a src/ directory for the package source, an ext/ directory for Julia extension packages, test/ for the test suite, docs/ for the documentation, examples/ for the example scripts, and images/ for the figures used in the documentation. There is a Project.toml for the package metadata, a NEWS.md for the release history, and a CITATION.bib, which tells you the project expects to be cited in academic work and has made the citation file part of the repository.

The badges add a detail about how the package is checked. There is a CI badge, a codecov badge, a JuliaHub dependencies badge, a package evaluation badge pointing at the JuliaCI Nanosoldier report, and an Aqua QA badge, which is the Julia package quality assurance suite. A pkgeval badge pointing at a bad report is a slightly unusual thing to advertise, and reading it as a sign of what the maintainer values is fair: a package that publishes its own package quality report.

The intended user is a numerical analyst or a student working on differential equations in Julia, and the homepage is the documentation site at juliaapproximation.github.io, with separate stable and dev documentation builds.

The release history is steady rather than fast. The listed versions are v0.13.29 on 2026-10-01, v0.13.28 on 2025-01-28 and v0.13.27 on 2024-06-11, and the last push was on 2026-10-01. The version has been at 0.13 for a long time, and a package that overrides base functions is not something to expect a 1.0 stability guarantee from.

## Where the approximation is the wrong tool

The honest limits are about what the package does not promise and what it costs.

The first is that this is a numerical package, and the numbers in the documentation are residuals of a particular implementation on particular functions. The package is described in a similar vein to Chebfun and RHPackage, and it inherits their scope. If you need a certified error bound, a validated result or an interval answer, spectral approximation with a residual you print yourself is not that.

The second is the base function overriding. The package extends `f'`, `cumsum` and most of SpecialFunctions.jl to accept a `Fun`, which is what makes the code read naturally, and it also means that a `Fun` does not behave like an ordinary Julia function or array everywhere. Code that dispatches on type, or that relies on the plain behaviour of `cumsum` for a vector, has to account for it.

The third is scope. The examples directory is dominated by differential equations, which is the domain the method suits, and the package description does not claim to be a general approximation toolkit for arbitrary data fitting. If what you want is smoothing a noisy measured curve, or a spline through points, this is a much larger and more opinionated dependency than the job needs.

The alternative in the same direction is to write the numerical method yourself on a Chebyshev or ultraspherical grid, which is what the references describe, or to use a package aimed at a narrower problem such as solving one specific boundary value problem. ApproxFun earns its place when the same operator algebra has to work across several problems, and it costs more than it saves when you only need one.

## Conclusion

ApproxFun.jl fits a Julia user solving ordinary or partial differential equations who wants a working approximation of a function rather than a symbolic form, since the package gives differentiation, integration, roots and extrema as operations on an object. It does not fit a workload that needs certified error bounds or a closed form solution, because the package is built around numerical approximation. Before adopting it, read the documentation examples rather than the separate examples repository, since the documentation states that the repository is independently maintained and might not always be in sync with the latest version, and check the licence in LICENSE.md, because the project metadata does not classify it.

## FAQ

### What does ApproxFun.jl do?

It is a Julia package for approximating functions. You create a Fun from a callback and an interval, and the resulting object supports algebraic manipulation, differentiation, integration, and the computation of roots and extrema.

### How do I install ApproxFun.jl in Julia?

Use the Julia package manager, for example Pkg.add("ApproxFun") in the REPL, or add it to your project environment. The package then loads with using ApproxFun, and the documentation examples use LinearAlgebra, SpecialFunctions and Plots alongside it.

### How does ApproxFun implement differentiation and integration?

It overrides Julia base functions for the purposes of calculus, so the prime operator performs differentiation and cumsum defines an indefinite integration operator. The documentation checks these by evaluating the norm of the difference, for example norm(f-f') for the exponential as its own derivative.

### Where are the examples for ApproxFun.jl?

The package documentation contains examples of usage, including solving ordinary and partial differential equations. A separate ApproxFunExamples repository holds many examples as Jupyter notebooks and Julia scripts, but it is independently maintained and might not be in sync with the latest package version, so the documentation examples are the ones to check first.

## Sources

- [Issues](https://github.com/JuliaApproximation/ApproxFun.jl/issues)
- [JuliaApproximation/ApproxFun.jl on GitHub](https://github.com/JuliaApproximation/ApproxFun.jl)
- [Project website](http://juliaapproximation.github.io/ApproxFun.jl/)
- [README](https://github.com/JuliaApproximation/ApproxFun.jl/blob/master/README.md)
- [Releases](https://github.com/JuliaApproximation/ApproxFun.jl/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/juliaapproximation-approxfun-jl
