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.4.tar.gz (72.3 kB view details)

Uploaded Source

Built Distributions

baobzi-0.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded PyPy macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-cp311-cp311-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-cp310-cp310-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-cp39-cp39-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

baobzi-0.9.4-cp38-cp38-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

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

baobzi-0.9.4-cp37-cp37m-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

baobzi-0.9.4-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.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (809.8 kB view details)

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

baobzi-0.9.4-cp36-cp36m-macosx_10_9_x86_64.whl (682.9 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: baobzi-0.9.4.tar.gz
  • Upload date:
  • Size: 72.3 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.4.tar.gz
Algorithm Hash digest
SHA256 6e04ef70b60216d073ed82e8ddb47e761088a97689cd6d1cd89e8d5ce877552d
MD5 d173de0aac2272e1d0c23887eb9359ce
BLAKE2b-256 37d47ce8e331f64d8525e865c349fe99977ca93bbbcece251caf2335819a44f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4f80743576f554584807bb6ba4476d185529cfe3668ec794c0f4fe360d834df5
MD5 3ede6b57ecaac9fe0ebee83933449f75
BLAKE2b-256 804f20fd835ad46e67b032a05af118e085b32587043956ef934de504438285fb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0c66baa1b1dd3b6f58fba58a2628f40deda093026e96663c28dbaf0b8ee5c2c8
MD5 cf06a6dc512bd09a9cc691e764dd5248
BLAKE2b-256 06e405030b2e6890d23705f9359f1eaea6e792d5e3458c26fe5dd9b22437fe6d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 51bedb367a4177ac54eff989a3d332d4fb0344e89cd41c4e17e93e881705b8e3
MD5 4cda840921a780fadbae92c461b63ecd
BLAKE2b-256 61b4de0a43bb2d7e8dd52ccafa97cde2d72baeec63f34960981ca0d66a054e23

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3901f5ae8ce7c91503d7a70eb8256d6c027596e325752a272fa704c02baa9c7c
MD5 5122d3652f7f117539e69cd1d3a342ec
BLAKE2b-256 06e7cd45ba6cb641ee3d5b0d258c6512cdcee69833a905fd828ceec9e3f23779

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2fb09399025b8afad9533dc65a2012af98faba584c203f71fd0608fd3ef4939e
MD5 09ef542dfd9cf7118592d63d2d5c0e23
BLAKE2b-256 b32c736af110a77befcd92bed1946523179ba60da7777657a3289eacdc098e20

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 88b65e5092e8f554ea8acec12f0eeebaa14f0fa382f84ceafe8e49212dcff6a3
MD5 9ee67cf4bcfd75b3c7ddcf824d0ea757
BLAKE2b-256 d28e4f68e5c84ca0a781aac7492d6a0a92ab0d86187ffe48bcfc121404c4bb72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 c847388571401683a464316bad4e145c79d5782ce839d8f920726a956d74d218
MD5 9eae323a62657a1969f7923d69f2cdf8
BLAKE2b-256 698222fbd1f4ed09fbd19b87d3642474951bbbd6f99f517d856a1baf0cdab31b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 881b6d2ffaa099354e17ac4aa419cbb066d7da8d23957eec6318e5ac2b0348e9
MD5 463a25ae93068295a5529807f45d171c
BLAKE2b-256 dd03824e0e6ef859681a23b1096c0fd4f719f51a728174c113a1005cb38bb991

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 65a12c61071a58b7d3e5e004fe974cb4c7f8561ed94bea807d628033ed2fde66
MD5 b4550ce63d4c512c0b2f10060473d871
BLAKE2b-256 f2f32b04b6c086abdc462208ab64ce0814687bfe760cf34303d9503c06a567cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 851fbbab4c531a4d8b8b073be86852ec09ca85c5e57532b528c690c26b6a486e
MD5 223ab6ad6119ca4fe6cedfcce6e784bf
BLAKE2b-256 4553918cb0d3141f87a87c6e814b50ebd275805b9659b5c3199d4ce2cfad2215

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c3814b473f41b783fd55c2024f002d1f9a0975b0ade8e7f600a7e8d149d6769a
MD5 543ae1d75bc3d63dd2bd3c7e1edeb6bf
BLAKE2b-256 fa26840952c382dee117197b761317df7b079ec09df038a7e13e690d4039c143

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 65abc5b9e0fa10d968de38ba175f9bc36de7183419b3cb25fb8f02242ea8b210
MD5 b7fe81e4c275ea30083e98694e1cef9e
BLAKE2b-256 8253b43fc48054ab3658bf02afaa7ac26549870241daef1c3c70e01cbd96716a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 67d19e6ac1e8794d449fc7183de2e5a4628898bfbcd3af2082a6f2db7939a25c
MD5 f29c6c2d79ac8954353804c38872161e
BLAKE2b-256 acf419843243666c2543033b0169fb352ebb316fd7c7b353c78bb8c71f4c492a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0a8ab50f00bacfb47d085714cea67e8f5dd735f6e75059844484962efe5ef7bb
MD5 7be78adfb5789e053d0c51d30df86c8e
BLAKE2b-256 f33cee544203f842423228419ff4a94fdea784f9e55297504bfc848e3e1f9616

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4d0414eef17431e224b35dbee9bf28b421ec1be3035b8999d972a4d80345ca23
MD5 2e5d0a684bd855e975c292b268f26402
BLAKE2b-256 1ae743fe3933f015f5c7bae7d63939dff0f0ea60e1e228fc98dfa615df0671b9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 97ceefd6acc2e67a6e7219083e9f3366dbd34e93397be05428a8545ddb15e695
MD5 2088f1215d61c4d0c556a0f50f721b24
BLAKE2b-256 bf160e369dbe08fd1b6faee61313febfba96080f6321a3cd1602c46b600f3eb7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 645a010fa2e17f965af57b1e969a725ce3b32098d2dab48cc3efff9dd600a9c6
MD5 20c5610c3686cd7768507e4c109b73d2
BLAKE2b-256 0ae79dd1d49923887c637c775d02a3b56f01e679e4e7e01fa24bffbaa241a3ff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5eac34cc6cb3dda7c0b70176276a66fb4878fc731db7905b864555b166d559e2
MD5 122fd3c6c1d69c643768f67220ec4ec9
BLAKE2b-256 3cef3381499f510edaf186106592ffed59a2de5c2f88114d9da7ac8136d7ccf6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 3f3923db65e35633c0685171e07948b23a8d617df2dbb54f5fd7c9cd06ba8f7b
MD5 80ad5f20bc339aa6a6ad1d9f032dd903
BLAKE2b-256 b3ba81bf59cde11eb13b4b82e980e4da23ca228645d106f016e3c088728bd6eb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 96b7ffd009df6f1a5c3a6643d9f534ae8d93ee0e79198dca0672d2384cfe91cd
MD5 58f00ade35fa7d849df3a306aed7f565
BLAKE2b-256 b062659198347c23d0b1b9884dd688720ad0aad5720107bcd06f97ed5cd6fe45

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5c10d427301c74403b96a0611cabc4c16234a9a6ab23f8700d70061ef7ea6e3e
MD5 eaa93fd998d69ffa6c9bc78d09db2b46
BLAKE2b-256 5d947bff8c1825f5079a60ce4bb002d86825d1d99c83358c58fe430d978dce4f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 917663de63fd8993eab1b081a46b95ea37d0eada6dae680db7eedb021b16f5de
MD5 ea53b4dc8747cc541d248a714d8da5a9
BLAKE2b-256 f575ea3bf42c51f768966287dab6d4c1e4d0c46b59cb16a349e2cdfe51612ebd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 808616fc3b566be4bb983061ea0acb7cce2694c05cfa3b5ab2e4d42701c22fbe
MD5 9525b5aab8b5df1e274c760b6677572d
BLAKE2b-256 2cc897f2b26c1e86c669ee11bd4c152e82d330cf52a37f8e8d44369284c8c562

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for baobzi-0.9.4-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0109183f1ab1f6753b3b9f348576011b16d06f8b56fd0ecfce3d0ead036a399a
MD5 136d42fcc68eb57a702912a9cacdae6e
BLAKE2b-256 f3569a28e91f1eba7479b2d44c5b9c2ecc1163d91d29e1682ece83f03035ebe4

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