# \[ANN\] ArnoldiVandermonde.jl

**URL:** <https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047>\
**Category:** Package Announcements\
**Created:** [May 8, 2026, 7:49pm UTC](https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047 "2026-05-08T19:49:11Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![tobydriscoll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobydriscoll/32/1843_2.png) [@tobydriscoll](https://discourse.julialang.org/u/tobydriscoll)\
**Post date:** [May 8, 2026, 7:49pm UTC](https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047/1 "2026-05-08T19:49:11Z")

</div>

I am pleased to announce version 0.1.0 of [ArnoldiVandermonde.jl](https://github.com/complexvariables/ArnoldiVandermonde.jl), a lightweight package to numerically orthogonalize polynomials on discrete point sets in the complex plane.

A monomial basis 1, x, x^2, \ldots is disastrously ill-conditioned unless your domain is the unit circle in \mathbf{C}. The Chebyshev (and other Jacobi) polynomials are famously well-conditioned for real intervals, but not as useful on most other domains. The Arnoldi–Vandermonde iteration uses the Arnoldi iteration (i.e., modified Gram–Schmidt) to numerically orthogonalize a polynomial basis as it is grown. This basis can be used to give stable, spectrally accurate L\_2 projections of smooth functions. See [Brubeck & Trefethen (2021)](https://doi.org/10.1137/19M130100X) for an introduction to the algorithm.

For instance:

```julia-repl
julia> using ArnoldiVandermonde
julia> f(x) = sin(exp(x));

julia> @time p = project(f, 0, 1)
  0.000195 seconds (684 allocations: 1.636 MiB)
Arnoldi polynomial of degree 17 on 65 nodes

julia> @time p = project(f, BigFloat(0), 1)
  7.304747 seconds (171.66 M allocations: 15.354 GiB, 10.02% gc time)
Arnoldi polynomial of degree 77 on 257 nodes

julia> maximum(abs(f(x) - p(x)) for x in range(BigFloat(0), 1, 10000)) |> Float64
3.0407129046474806e-72

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 8, 2026, 8:06pm UTC](https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047/2 "2026-05-08T20:06:50Z")

</div>

Great! Seems like it fully resolves this thread: [Julia analog to R's poly function, orthogonal polynomials by QR decomposition](https://discourse.julialang.org/t/julia-analog-to-rs-poly-function-orthogonal-polynomials-by-qr-decomposition/128640/)

How does it compare to the `ArnoldiFit` object in Polynomials.jl?

---

<div class="post-metadata">

**Author:** ![tobydriscoll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobydriscoll/32/1843_2.png) [@tobydriscoll](https://discourse.julialang.org/u/tobydriscoll)\
**Post date:** [May 8, 2026, 8:23pm UTC](https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047/3 "2026-05-08T20:23:16Z")

</div>

Good question!

```julia
f(x) = sin(exp(x));
x = range(0, 1, 800);

function test1(f, x, n)
   B = ArnoldiBasis(x, n)
   return B \ f
end

function test2(f, x, n)
   return fit(ArnoldiFit, x, f.(x), n)
end

```

```julia-repl
julia> @benchmark test1($f, $x, 16)
BenchmarkTools.Trial: 10000 samples with 1 evaluation per sample.
 Range (min … max): 114.875 μs … 22.270 ms ┊ GC (min … max): 0.00% … 99.25%
 Time (median): 135.208 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 170.619 μs ± 366.259 μs ┊ GC (mean ± σ): 20.17% ± 12.29%

  █▁                                                             
  ██▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▂▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ ▂
  115 μs Histogram: frequency by time 1.54 ms <

 Memory estimate: 631.92 KiB, allocs estimate: 53.

julia> @benchmark test2($f, $x, 16)
BenchmarkTools.Trial: 10000 samples with 1 evaluation per sample.
 Range (min … max): 164.667 μs … 20.761 ms ┊ GC (min … max): 0.00% … 98.29%
 Time (median): 340.375 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 475.733 μs ± 604.246 μs ┊ GC (mean ± σ): 30.12% ± 22.17%

  ▄▃▄██▆▃ ▂
  ███████▇▃▁▁▁▃▁▁▁▁▁▁▁▁▁▃▁▁▁▃▄▄▆▅▆▆▇▆▇▇█████████▇▇▇▇▇▇▇▆▇▇▆▆▆▇▆ █
  165 μs Histogram: log(frequency) by time 2.69 ms <

 Memory estimate: 3.16 MiB, allocs estimate: 1360.

```

For evaluation, I did a separate implementation for array inputs that pays off:

```julia
y = range(0, 1, 2000)
p1 = test1(f, x, 16)
p2 = test2(f, x, 16)

```

```julia-repl
julia> @benchmark $p1.($y)
BenchmarkTools.Trial: 10000 samples with 1 evaluation per sample.
 Range (min … max): 225.042 μs … 1.282 ms ┊ GC (min … max): 0.00% … 80.42%
 Time (median): 236.709 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 240.896 μs ± 28.685 μs ┊ GC (mean ± σ): 0.38% ± 2.70%

  ▁█                                                            
  ██▄▄▄▇▅▃▄▄▃▃▃▄▃▃▃▃▃▃▄▃▃▃▃▄▄▂▃▂▂▂▂▂▁▁▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
  225 μs Histogram: frequency by time 288 μs <

 Memory estimate: 16.06 KiB, allocs estimate: 3.

julia> @benchmark $p1($y)
BenchmarkTools.Trial: 10000 samples with 1 evaluation per sample.
 Range (min … max): 60.541 μs … 4.412 ms ┊ GC (min … max): 0.00% … 97.42%
 Time (median): 74.958 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 92.949 μs ± 183.744 μs ┊ GC (mean ± σ): 18.08% ± 9.45%

  ██                                                            
  ██▃▂▂▂▂▂▂▁▂▂▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▂▁▁▁▁▁▂ ▂
  60.5 μs Histogram: frequency by time 907 μs <

 Memory estimate: 304.14 KiB, allocs estimate: 6.

julia> p2 = test2(f, x, 16)
ArnoldiFit of degree 16

julia> @benchmark $p2.($y)
BenchmarkTools.Trial: 10000 samples with 1 evaluation per sample.
 Range (min … max): 174.583 μs … 4.799 ms ┊ GC (min … max): 0.00% … 95.91%
 Time (median): 181.458 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 246.001 μs ± 493.594 μs ┊ GC (mean ± σ): 24.63% ± 11.59%

  █ ▁
  ██▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▄▆▅▇▅ █
  175 μs Histogram: log(frequency) by time 4.06 ms <

 Memory estimate: 391.06 KiB, allocs estimate: 4003.

```

I’ll have to add a mention of `ArnoldiFit` to the readme; I completely forgot about it. But I need the basis as well as the polynomial for some other stuff I’m working on.

---

<div class="post-metadata">

**Author:** ![tobydriscoll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobydriscoll/32/1843_2.png) [@tobydriscoll](https://discourse.julialang.org/u/tobydriscoll)\
**Post date:** [May 8, 2026, 8:26pm UTC](https://discourse.julialang.org/t/ann-arnoldivandermonde-jl/137047/4 "2026-05-08T20:26:39Z")

</div>

The reference should be Brubeck, **Nakatsukasa** , and Trefethen (2021).
