Skip to main content

An adaptive fast function approximator based on tree search

Project description

Baobzi

An adaptive fast function approximator based on tree search. Word salad aside, baobzi is a tool to convert very CPU intensive function calculations into relatively cheap ones (at the cost of memory). This is similar to functions like chebeval in MATLAB, but can be significantly faster since the order of the polynomial fit can be much much lower to meet similar tolerances. It also isn't constrained for use only in MATLAB.

Internally, baobzi represents your function by a grid of binary/quad/oct/N trees, where the leaves represent the function in some small sub-box of the function's domain with chebyshev polynomials. When you evaluate your function at a point with baobzi, it searches the tree for the box containing your point and evaluates using this approximant.

Example use cases

  • Build complicated or high computational cost function in higher level language. Build a baobzi function and use it as a drop in replacement to your function. Reap speed benefits.
  • Take prior function, export it, and use it in a higher performance language: production or prototype.
  • Your favorite scipy function not supported in numba yet? Use baobzi instead of porting that function.

Limitations

  • Can use a lot of memory... especially on oscillatory or rapidly changing functions. If your function is periodic, fit your function on one period. Transform the function if necessary.
  • Not suited around singularities. Just don't do it. Use multiple baobzi objects around your singularity if necessary.
  • Doesn't do any bounds checking. It is up to the user to sanitize input.

Features

  • Relative language agnosticism. The library has a simple C interface, which is then bound to multiple languages (C/C++, Fortran, Python, Julia, MATLAB). This means you can make a heavy duty function in MATLAB, interpolate it there, and then call it from another language of your choice.
  • CPU dispatch -- baobzi will detect your CPU and run an optimized codepath based on that -- no intervention by the user.
  • No library dependencies. All code necessary to build baobzi is in baobzi. There is an optional static library supported for building C/C++ codes where you don't want to load in the shared baobzi object, but would rather throw it right in your binary. See Including in your CMake project.

Quick install

Python/Conda

There are currently no wheels, which means conda/pip have to do source builds of Baobzi (though this should change hopefully soon). To do with standard pip install, first, make sure you have a modern gcc/g++ in your path, and cmake >= 3.14.

# create a virtualenv, if you want
python3 -m venv --system-site-packages myenv
source myenv/bin/activate
pip install git+https://github.com/flatironinstitute/baobzi.git

python -c 'from baobzi import Baobzi'

If you use conda, you can install gcc, g++, and cmake via the conda-forge repo, and then use pip to install baobzi.

conda create -y -n baobzi -c conda-forge gcc gxx cmake numpy
conda activate baobzi
pip install git+https://github.com/flatironinstitute/baobzi.git

python -c 'from baobzi import Baobzi'

Building/testing

Baobzi's only dependencies are cmake >= 3.14, and a C/C++17 compiler (gcc only really, currently). I get the best performance out of g++-11 right now. While there is a header only library for C++, it can be quite finicky. Therefore, for optimal performance, I currently suggest using the C shared/static library interface with gcc rather than the C++ header directly. See examples/C/baobzi_timing.c for an example. On my Xeon Gold 6128 using one core, this example gets roughly 20M evals/s on a simple 2D example, and 3M evals/s on a simple 3D example.

# At FI -- module load gcc cmake matlab
export BAOBZI_ROOT=$HOME/local/baobzi
git clone --recursive https://github.com/flatironinstitute/baobzi.git
cd baobzi
mkdir build
cd build
# Don't supply -march!!! Builds with CPU dispatch
cmake -DBAOBZI_BUILD_MATLAB=True -DCMAKE_INSTALL_PREFIX=$BAOBZI_ROOT ..
make -j $((2*$(nproc)))
make install

Input parameters

Baobzi only has a few input parameters, but they can greatly impact the performance and are worth playing with for your specific function.

  • func: Function you want to be approximated

  • dim: Number of independent variables to your function.

  • order: Polynomial order used to represent a chunk of your function. Higher order is slower, especially in higher dimensions. An evaluation, ignoring search/cache issues, takes O(ORDER^DIM) time. Search isn't free though, and baobzi typically needs fewer subdivisions for higher orders, so your function might be faster and use less memory if you use a higher order.

  • data: This parameter is only relevant to C/C++/Fortran. If the function you're fitting takes parameters, pack that somehow, and data is simply a pointer to that packed info. See examples.

  • tol: The maximum desired relative error between your function and the approximant. It is impossible to guarantee that all function evaluations will meet this tolerance, so it's important to test the results on the domain you're interested in to ensure that results are to your satisfaction.

  • minimum_leaf_fraction: Baobzi internally is represented by a tree. However, to speed up tree lookups, that tree is divided into subtrees that start at some depth. That depth, by default, is one above the first level to have a "leaf." A leaf is a terminal box where the function evaluation happens (other nodes just contain pointers to their children). This scheme can adversely impact performance in some cases though (such as cases where only one node on a level is a leaf). This parameter sets a requirement that baobzi keeps subdividing entire levels when the fraction of leaves on a given level is less than this threshold.

    An easy way to think about this is if the parameter is 0.0, then baobzi will never make a leaf node a parent node, and the tree will be as small as possible (but not necessarily well balanced). If the parameter is 1.0, then baobzi will ensure that the final depth of the tree is entirely filled with leaves. This tree is perfectly balanced, and therefore exactly a uniform grid. Anything between will vary between these two extremes. This parameter can EXTREMELY impact performance, especially on 1D trees.

  • split_multi_eval: When evaluating a vector of points, baobzi can currently use one of two strategies which can dramatically impact performance, depending on the tree and computer. The default is to split the evaluation of the points into two stages, one where the boxes are calculated in one pass, and then the points are evaluated with them in a second. This tends to help when there are a large number of nodes, as it increases the chance of a cache hit by not ever loading in extra evaluation data. However it requires making a temporary data structure to hold this, which costs time/memory.

    The second is to just brute force evaluate the points as they appear in the target order. This typically works very well in 1D, for small trees, but otherwise has poor performance.

    Setting this parameter to 1 uses the typically faster 'split' model, while setting it to 0 will use the direct model.

Running with...

All examples require your project know where the baobzi shared object is located. In the example above, it's located in either the $BAOBZI_ROOT/lib or $BAOBZI_ROOT/lib64 directory, depending on your system.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$BAOBZI_ROOT/lib
export LIBRARY_PATH=$LIBRARY_PATH:$BAOBZI_ROOT/lib
export C_INCLUDE_PATH=$C_INCLUDE_PATH:$BAOBZI_ROOT/include
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$BAOBZI_ROOT/include
export PYTHONPATH=$PYTHONPATH:$BAOBZI_ROOT/share/baobzi/python
export JULIA_LOAD_PATH=JULIA_LOAD_PATH:$BAOBZI_ROOT/share/baobzi/julia
export MATLABPATH=$MATLABPATH:$BAOBZI_ROOT/share/baobzi/matlab

C

A more complicated example than below: examples/C/baobzi_timing.c

// test_baobzi.c
#include <baobzi.h>
#include <stdio.h>

double testfunc(const double *x, const void *data) { return x[0] * x[1]; }

int main(int argc, char *argv[]) {
    baobzi_input_t input = {
        .func = testfunc,
        .data = NULL,
        .dim = 2,
        .order = 6,
        .tol = 1E-10,
        .minimum_leaf_fraction = 0.0,
        .split_multi_eval = 0
    };

    const double hl[2] = {1.0, 1.0};
    const double center[2] = {0.0, 0.0};
    const double x[2] = {0.25, 0.25};

    baobzi_t func_approx = baobzi_init(&input, center, hl);
    printf("%g\n", baobzi_eval(func_approx, x));
    baobzi_save(func_approx, "func_approx.baobzi");
    func_approx = baobzi_free(func_approx);

    func_approx = baobzi_restore("func_approx.baobzi");
    printf("%g\n", baobzi_eval(func_approx, x));
    return 0;
}
gcc -o test_baobzi.c -lbaobzi
./test_baobzi

C++

A more complicated example than below: examples/c++/baobzi_timing.cpp

// test_baobzi.cpp
#include <baobzi.hpp>
#include <cstdio>

double testfunc(const double *x) { return x[0] * x[1]; }

int main(int argc, char *argv[]) {
    using baobzi::Baobzi;
    baobzi_input_t input = {
        .func = testfunc,
        .data = NULL,
        .dim = 2,
        .order = 6,
        .tol = 1E-10,
        .minimum_leaf_fraction = 0.0,
        .split_multi_eval = 0
    };

    const double hl[2] = {1.0, 1.0};
    const double center[2] = {0.0, 0.0};
    const double x[2] = {0.25, 0.25};
    {
        Baobzi func_approx(&input, center, hl);
        printf("%g\n", func_approx(x));
        func_approx.save("func_approx.baobzi");
    }

    Baobzi func_approx("func_approx.baobzi");
    printf("%g\n", func_approx(x));

    return 0;
}
g++ -o test_baobzi.cpp -lbaobzi

Python

examples/python/simple2d.py

# simple2d.py
from baobzi import Baobzi

def py_test_func(x):
    return x[0] * x[1]

center = [0.0, 0.0]
hl = [1.0, 1.0]
point = [0.25, 0.25]
tol = 1E-8
minimum_leaf_fraction = 0.0 # optional/default
split_multi_eval = 1 # optional/default

test = Baobzi(py_test_func, 2, 6, center, hl, 1E-8, minimum_leaf_fraction, split_multi_eval)
test.save('test.baobzi')
print(test(point))
del test

test2 = Baobzi(filename='test.baobzi')
print(test2(point))
del test2
python3 simple2d.py

Julia

examples/julia/simple2d.jl

# simple2d.jl
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]
hl = [0.5, 1.0]
test_point = [0.25, 0.25]
dim = 2
order = 6
tol = 1E-8
minimum_leaf_fraction = 0.0 # optional/default
split_multi_eval = 1 # optional/default
output_file = "simple2d.baobzi"

func_approx = baobzi.init(testfunc, dim, order, center, hl, tol, minimum_leaf_fraction, split_multi_eval)
println(baobzi.eval(func_approx, test_point) - testfunc(pointer(test_point)))

baobzi.save(func_approx, output_file)
baobzi.free(func_approx)

func_approx = baobzi.restore(output_file)
println(baobzi.eval(func_approx, test_point) - testfunc(pointer(test_point)))
julia simple2d.jl

MATLAB

MATLAB initialization does not work for anonymous functions. You must declare an actual function (in its own myfunc.m file).

%% testfun.m
function [y] = testfun(x)
  y = x(1) * x(2);
end
%% simple2d.m
dim = 2;
order = 6;
center = [0.0, 0.0];
hl = [1.0, 1.0];
tol = 1E-8;
func_approx = baobzi('new', 'testfun', dim, order, center, hl, tol);
display(func_approx.eval([0.25, 0.25]))
func_approx.save('simple2d.baobzi');
clear func_approx
func_approx = baobzi('restore', 'simple2d.baobzi');
display(func_approx.eval([0.25, 0.25]))
matlab -batch simple2d

Fortran

examples/fortran/fortran_example.f90

program main
  use baobzi
  implicit none
  real(kind=c_double) :: center(2), half_length(2), tol
  real(kind=c_double) :: x(2)
  real(kind=c_double), target :: scale_factor
  type(c_ptr) :: func_approx
  character(len=64) :: fname
  type(baobzi_input_t) :: input

  input%func = c_funloc(testfun)
  input%data = c_loc(scale_factor)
  input%dim = 2
  input%order = 6
  input%tol = 1E-8
  input%minimum_leaf_fraction = 0.0
  input%split_multi_eval = 0

  center(:) = 0.0
  half_length(:) = 1.0
  x(:) = 0.25

  fname = trim(adjustl('fortran.baobzi'))//char(0)

  func_approx = baobzi_init(input, center, half_length)
  print *, baobzi_eval(func_approx, x) - testfun(x, scale_factor)

  call baobzi_save(func_approx, fname)
  func_approx = baobzi_free(func_approx)

  func_approx = baobzi_restore(fname)
  print *, baobzi_eval(func_approx, x) - testfun(x, scale_factor)

contains
  function testfun (x, scale_factor) bind(c) result(y)
    use, intrinsic :: iso_c_binding
    implicit none
    real(kind=c_double), dimension(*) :: x
    real(kind=c_double) :: scale_factor
    real(kind=c_double) :: y

    y = scale_factor * x(1) * x(2)
  end function testfun

end program main
gfortran -o fortran_example -I$BAOBZI_ROOT/share/baobzi/fortran fortran_example.f90 -lbaobzi

Environment

Most control flow of Baobzi is handled through the input structure, but there is a single environment variable: BAOBZI_ARCH. This environment variable lets you manually set the instruction set used by the evaluation. There is usually no reason to use this, but in some cases, AVX2 will outperform AVX512, or you might want to do some testing on the impact of the instruction set. Valid values are (case-insensitive) GENERIC, AVX, AVX2, and AVX512.

Including in your CMake project

Here I've added a git submodule in extern/baobzi, and I build and link in the static library. You can also set the shared library on, and the static off, though you'll want to ensure the shared library gets installed with your project. Probably better to use the static. In this example, it added 23MB to my test executable size.

set(BAOBZI_BUILD_SHARED OFF CACHE BOOL "")
set(BAOBZI_BUILD_STATIC ON CACHE BOOL "")
set(BAOBZI_BUILD_EXAMPLES OFF CACHE BOOL "")
set(BAOBZI_BUILD_TESTS OFF CACHE BOOL "")
add_subdirectory(extern/baobzi)

add_executable(baobzi_test src/test.cpp)
target_include_directories(baobzi_test PUBLIC extern/baobzi/include)
target_link_libraries(baobzi_test PUBLIC baobzi_static)

Roadmap

See the issues or project tracker.

Known Issues. IMPORTANT PLEASE READ

  • No out of bounds handling at all. If you call out of bounds, your program could crash or worse. Only you can prevent segfaults (or even worse, wrong answers). Note that baobzi dimensions are defined on the semi-open interval [x0, x1). Calling on the upper boundaries will segfault or give wrong answers.
  • Baobzi can't handle singularities or otherwise pathological functions like sin(1/x). It will eat your memory and crash. I intend to handle these issues, but I want to work on an API that allows for more options to deal with them. That will take time.
    • Workaround: for now, just piecewise a bunch of baobzi functions to work around singularities. I hope to add an option to add exclusion domain, or a bunch of domains to fit and represent as a single function.
  • In one and two dimensions, baobzi will determine tolerance matching by looking at the values of certain chebyshev coefficients. This tends to underestimate the fit, resulting in better precision than you expected (though there are exceptions). In 3D, it uses a sampling technique. This effectively doubles the time to fit, but will give you a tolerance closer to the expected one. Start low, and move up until you find a fit that works for you. Eventually this will be an option in the API.
  • MATLAB initialization does not work for anonymous functions. You must declare an actual function (in its own myfunc.m file).
  • Doesn't do 4+ dimensions (though possible, I haven't worked out the fitting procedures yet). Probably don't want to go above 5 dimensions, since each node takes O(8 * ORDER^D) bytes of memory.

Why the name?

It's a cute version of baobab, or the tree of life, which is already a very popular project name. The baobab lives an extraordinarily long time, which this interpolator is designed to do. Plant it (it's a tree!), and use it again and again. That's about the extent of the metaphor -- try not to think about it too much.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

baobzi-0.9.6.tar.gz (72.4 kB view details)

Uploaded Source

Built Distributions

baobzi-0.9.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.6-cp311-cp311-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp311-cp311-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

baobzi-0.9.6-cp310-cp310-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp310-cp310-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

baobzi-0.9.6-cp39-cp39-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.9 musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp39-cp39-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

baobzi-0.9.6-cp38-cp38-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.8 musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp38-cp38-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

baobzi-0.9.6-cp37-cp37m-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.7m musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp37-cp37m-macosx_10_9_x86_64.whl (683.2 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

baobzi-0.9.6-cp36-cp36m-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.6m musllinux: musl 1.1+ x86-64

baobzi-0.9.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (817.0 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64

baobzi-0.9.6-cp36-cp36m-macosx_10_9_x86_64.whl (683.3 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

Details for the file baobzi-0.9.6.tar.gz.

File metadata

  • Download URL: baobzi-0.9.6.tar.gz
  • Upload date:
  • Size: 72.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.16

File hashes

Hashes for baobzi-0.9.6.tar.gz
Algorithm Hash digest
SHA256 1df4ca86e7e68178e076aa82826c00fe2e518aabb9be270e3c0050684bf215d1
MD5 22825d2e1fc9fc7783aaf842c404e8eb
BLAKE2b-256 766ccd2ecf2db0a33c23765f0013f2949c98c8123fa21acbfe1fe4e1c69e6a1c

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 347fe9e72983f704c8386bf16df5869363dddaf950b3f506da310759ded51377
MD5 534eb830b7524b2fa893f8c736846065
BLAKE2b-256 d20cbc0d1065dc34681f1fb35038d75050f73689904c426cdf55a997a0c69af8

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d3359065e7ad54524e4fdb221dc08765c54a4a57a80e4bf7db20319137e0a44c
MD5 db0ff4f13e5081ebcd718db2ee853151
BLAKE2b-256 5cbe0fd60582ff81adb55181980cef856c0853278cbabf6bd5d45d8c78fa7f5c

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 65bc5605e733bc6629ca438715d97b21f29e1e180281f9b301abbef5579d74c3
MD5 682ef4e17f35dc056ca2a44e5a5ad190
BLAKE2b-256 6c8518c13ff0283f8cfe571a69818e3b56babf2cfc4df3f97f6f4a1d03900f8c

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f11ac2dc8661d619ee7ab1a926a3c9af76eadd2934cd951e86ef4d47001f6cbb
MD5 e5ab116a8baf6ed52adb3bd6f969af31
BLAKE2b-256 0e2664dcfcd6a965ba617d832851f16f43e957d23e6788d3192cc88082cb349b

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9b1a19e0b6589b6a7045da292256bad5577f85e6c6745842aaf70f47b6e8ba68
MD5 e2553cc0aa82f346b5964a43198677c6
BLAKE2b-256 f1bf3333518ac7acd5ce47be9d71b27d3b5fe1f91ed8b56957578bcdd8f9cfe9

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3a34e068b82da1ee93f8caaae597bfc870570c5c7ac56c37f5b101717a46cf9c
MD5 03589657e1a475f3f4af1509019356b6
BLAKE2b-256 93189a08750800ba3418e8205b1a42170e1e36a488c74b6c84ad1ae07655aad3

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 2cdf3509e81f5648aa633995b2058d4b25b55eff8e85fda194bf2a79de6e3093
MD5 654e748060dc9c451c4ab42bd014001c
BLAKE2b-256 7c638a877bb99a9ef334d7b4d5532473810a6abd7cb61bfbf9d8fd259808321c

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9eb9ec64eb495b32007aa40277a31312ad228e37dc9e6567daff2eca47bb559b
MD5 153764f87240979cab3c7423e12416d6
BLAKE2b-256 e1d919c30ed0598ee2a6fd485e72341cd054fd5e4be97f3e4bb73327f788edc7

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7b1d6b15c6e9b4aae0da6b51eb5548c7b89cd8b6c34ccdbff2c86dde34110a10
MD5 7c086324c078202ba04d18679424bbf8
BLAKE2b-256 00d2c4364dbe7618ba5aa72e63917fb6d56880ecb7dc33519e6796c50eed2751

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 b11915986e6991683710a769bc2dc69839f98f03aea950dd3f383c9bb4e7063c
MD5 a24e65f827ed107d43a4b13e0be18759
BLAKE2b-256 2faa20b5f6a9cd73750635f7d29a9781cf8859b3ba70573e345a416c3f9c0ce4

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5ef80f2c8bc22967cdfc7768ccb5c7582fce91f658868ab22a8539af1be87031
MD5 d9c104e9833f75e52360c39a11eb16c5
BLAKE2b-256 893c4221085a6c786afc660010b7e6a460c5eed72af69f1d6379f7273e3228d8

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 daa30bedfc24a12322b8daf0dbadef9dbd24ba4fac0f815398dd21d34539ac71
MD5 6adbdeb684bc63ea237e019243d4a2ca
BLAKE2b-256 d9835327894f0ff62bf18b8661fb74d67e15a4640791b72b309ec5834690a230

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp39-cp39-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 153fb973d96a403a885f1b21609e3eb45b53caa1784a2dea38e2733f8a869901
MD5 c6ca6f67a49996d2a405bb4dba9cb347
BLAKE2b-256 433444436de6c60b06269e67559ec06adac0965d220b635cd3425808a1083c0d

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 23ce607ea91e5935978be4358fe0d795fd02dd33f72bdfae2b9d69c0c2685fde
MD5 2df7ce0b3268e4d6a7464395f52c84cc
BLAKE2b-256 af839880dc727265acfb903b0a908696180e5d28a141e06005cbd840b27360aa

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 316d5b29d36d04a0dfee4fcd0f8ee79f7bbe054a950fe73bd7e33577212e57e8
MD5 0ae45e273c2b3c720300848e84fd7bf4
BLAKE2b-256 989b7ecaba80a873c6470d217cd42690f44c7ed6c3d17b9335d1936245c3b6b2

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp38-cp38-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 489f3f42c658b54cfdb02cc7a4a34dab565254d8a7ed643c883121b6072178ac
MD5 e06f0218912a014c81e59ad77d074556
BLAKE2b-256 717fb8ac410578ed791f4a1767742d4fce9744efaea573b96e8998b45afe0f72

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3b56a48575463810f26f3fdf17e65e3508141f3be71d6fdbfdf8f1e441571da1
MD5 2be981bbadecc45062b2503330ea2acc
BLAKE2b-256 1ce3072bae77ce6a16b5c4a199a95a156921c6694fe767cc345b24991870f5a9

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 00f96ee3453d680361c2650e0a7ded9978028ccc48d46d3adf8206ef10b20058
MD5 8575c93e36a55c52789a4c24e4641c00
BLAKE2b-256 68dfee6e0c28dd7f5d94d6e29b62f0e1c55a4248c4f710cf82a460ceaf1b3c65

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp37-cp37m-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 dad83f7359302848da696b78c023c942a40becdf5783c64f7cdbb8849c8f37e8
MD5 d844b953398a96021bc189002c707ba7
BLAKE2b-256 5a5cb57a889e3e7e1677387e78c98981a67221a58a7148d2b8d00b32b7a57353

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5277ba66451bbdb1a46ca8a6b252742930fb13cdc79e134aa0a8ee2afd0c965d
MD5 2c3a36a2d9e1af2958e9d33d8e05164c
BLAKE2b-256 a2ea5c4af3a42fd5fcd1ceed431c98f0dfc8ef6d123ad1f4b9b53de112975b4a

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8343b3cbd54e7789d171fa57080b111807994e66efd7836f32384304d40dfb98
MD5 065ff17b59dda2b6bdb929b4f353fadf
BLAKE2b-256 103bbdc8f594b69f143a8493262a23bc75774ec12ac84bf23a3c3278a1f32daf

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp36-cp36m-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 5e571a34da79e1be0a004d3dc4fe946eddcc5095e52070481bc701e4e3b7ffe7
MD5 f230500039be54c71c87c783e88a7666
BLAKE2b-256 64e5372bf99d306e95c1e3ad2a0817b7a5b05ffbc06ee9f46afc9d8a3ac2d63f

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e99593635b616d14515d2856e59da544f34e1882f43d1076c781a7b89213f7ee
MD5 8cc5e5eb7c6eefe892fb9ce1396a9efd
BLAKE2b-256 36dedb36f18db0c840b1baa412de88c4d6c000c68885dd6a8967333c0c48fc8f

See more details on using hashes here.

File details

Details for the file baobzi-0.9.6-cp36-cp36m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for baobzi-0.9.6-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 39e59bc5442b15c91132b662a4418f7a760c9af45ce64fc13633424c1cf7e787
MD5 0223b17d19a2d06dbc757541ad368508
BLAKE2b-256 2237ab80df88fefb193de5e9e8e601c920f6851a27ad7554971cee7233572113

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page