# Baobzi.jl

Wrapper library for Baobzi interpolator library

TLDR: Baobzi takes a function and represents adatively it as a tree of polynomial
interpolants. This is *very* fast and *very* accurate. Basically it allows you to precompute a
"heavy" function into a very good approximation of that function that can be orders of
magnitude faster. Operations on 1D functions are typically ~100-200 million evaluations per
second, depending on hardware. I.e. functions can often evaluate faster than some fancy
implementations of functions like `log`

, and can be orders of magnitude faster than special function evaluations.

Unfortunately, Baobzi is not a pure Julia implementation. The core library is written in `c++`

and has with `c`

bindings as a public API. Since `Baobzi`

needs to call the function you want
to approximate, this presents some limitations with Julia due to mutability and type
constraints. Basically you need to make your "callback" function C callable (`double myfunc(double* x))`

. That or generate the function object in another language and call it in
julia. This is probably best shown by example. All functions you want to fit need a signature
identical to the `testfunc`

below.

Simple 2d example for the function `z = x*y`

import Baobzi
function testfunc(xp::Ptr{Float64})::Cdouble
x = unsafe_load(xp, 1)
y = unsafe_load(xp, 2)
return x * y
end
center = [0.0, 0.0] # center of our function's rectangular domain
hl = [1.0, 1.0] # half widths of the functions rectangular domain
test_point = [0.25, 0.25] # just a point we want to evaluate at
dim = 2 # number of independent variables in our function (x, y)
order = 6 # order of polynomial fit
tol = 1E-10 # requested precision of fit
output_file = "simple2d.baobzi" # place to store the file
split_multi_eval = 0 # Whether to split evaluation into two steps or not. Has mild performance implications
# Fit our function
func_approx = Baobzi.init(testfunc, dim, order, center, hl, tol, 0)
# Print some stats about the fit procedure
Baobzi.stats(func_approx)
# Compare result
println(Baobzi.eval(func_approx, test_point) - testfunc(pointer(test_point)))
# Save our function and then delete it
Baobzi.save(func_approx, output_file)
Baobzi.free(func_approx)
# Restore function and compare
func_approx = Baobzi.restore(output_file)
println(Baobzi.eval(func_approx, test_point) - testfunc(pointer(test_point)))
# Evaluate function at many points in our domain
points = 2.0 * (rand(Float64, 2000000)) .- 1.0
z = Baobzi.eval_multi(func_approx, points)