treeweave 0.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,62 @@
1
+ # bindings/python — nanobind extension linking treeweave_c_static + a pytest
2
+ # CTest. Added by cmake/treeweave_bindings.cmake when TREEWEAVE_BUILD_PYTHON=ON.
3
+ # The pip/scikit-build wheel build reaches this same file: pyproject sets
4
+ # cmake.source-dir = "../../" and configures the root with TREEWEAVE_BUILD_PYTHON=ON.
5
+
6
+ # Development.SABIModule (optional) lets nanobind emit a CPython stable-ABI
7
+ # (abi3) extension on 3.12+, which is what the wheel build ships.
8
+ find_package(
9
+ Python
10
+ 3.9
11
+ QUIET
12
+ COMPONENTS Interpreter Development.Module
13
+ OPTIONAL_COMPONENTS Development.SABIModule
14
+ )
15
+ if(NOT Python_FOUND)
16
+ message(
17
+ STATUS
18
+ "treeweave[python]: Python 3.9+ (Development.Module) not found — skipping."
19
+ )
20
+ return()
21
+ endif()
22
+
23
+ # Shared module definition (also used by the pip wheel build) — locates nanobind
24
+ # (interpreter or FetchContent) and defines the `_treeweave` target.
25
+ include("${CMAKE_CURRENT_SOURCE_DIR}/treeweave_python.cmake")
26
+ treeweave_add_python_module(treeweave::treeweave_c_static)
27
+
28
+ # Install the extension into the wheel's `treeweave/` package. Scoped to its own
29
+ # component so the scikit-build-core wheel build installs ONLY this
30
+ # (install.components = ["python_ext"] in pyproject.toml) and never drags in the
31
+ # C++ dev tree (headers / libtreeweave_c / CMake config).
32
+ install(TARGETS _treeweave LIBRARY DESTINATION treeweave COMPONENT python_ext)
33
+
34
+ # Assemble an importable package *in the build tree* — never write the .so (or
35
+ # copy .py) into the source tree. Layout: <build>/python-pkg/treeweave/.
36
+ set(_treeweave_pypkg "${CMAKE_BINARY_DIR}/python-pkg")
37
+ set_target_properties(
38
+ _treeweave
39
+ PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${_treeweave_pypkg}/treeweave"
40
+ )
41
+ # Stage the pure-Python sources next to the extension (re-copied on reconfigure
42
+ # if they change, via the configure_file input dependency).
43
+ file(GLOB _treeweave_py "${CMAKE_CURRENT_SOURCE_DIR}/treeweave/*.py")
44
+ foreach(_f IN LISTS _treeweave_py)
45
+ get_filename_component(_n "${_f}" NAME)
46
+ configure_file("${_f}" "${_treeweave_pypkg}/treeweave/${_n}" COPYONLY)
47
+ endforeach()
48
+
49
+ add_test(
50
+ NAME python_treeweave
51
+ COMMAND
52
+ "${Python_EXECUTABLE}" -m pytest -q "${CMAKE_CURRENT_SOURCE_DIR}/tests"
53
+ )
54
+ set_tests_properties(
55
+ python_treeweave
56
+ PROPERTIES ENVIRONMENT "PYTHONPATH=${_treeweave_pypkg}"
57
+ )
58
+ message(
59
+ STATUS
60
+ "treeweave[python]: extension + pytest 'python_treeweave' registered "
61
+ "(build-tree package at ${_treeweave_pypkg})."
62
+ )
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: treeweave
3
+ Version: 0.0.0
4
+ Summary: Python bindings for the treeweave piecewise-polynomial approximator
5
+ License-Expression: BSD-3-Clause
6
+ Requires-Python: >=3.9
7
+ Requires-Dist: numpy
8
+ Provides-Extra: test
9
+ Requires-Dist: pytest; extra == "test"
10
+ Description-Content-Type: text/markdown
11
+
12
+ # treeweave Python bindings
13
+
14
+ Python (nanobind) wrapper for the [treeweave](../../README.md) piecewise-polynomial
15
+ function approximator.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install scikit-build-core nanobind numpy
21
+ pip install . # regular install
22
+ # or for development:
23
+ pip install -e . --no-build-isolation
24
+ ```
25
+
26
+ ## Quick start
27
+
28
+ ```python
29
+ import math
30
+ import numpy as np
31
+ import treeweave
32
+
33
+ # Fit exp(x) on [0, 1] to 1e-10 relative tolerance.
34
+ def func(x):
35
+ return math.exp(x[0]) # x is a (dim,) ndarray
36
+
37
+ approx = treeweave.fit(func, 0.0, 1.0, tol=1e-10) # dim & out_dim inferred
38
+
39
+ # Scalar eval
40
+ print(approx(0.5)) # ≈ exp(0.5)
41
+
42
+ # Batch eval
43
+ xs = np.linspace(0, 1, 1000)
44
+ ys = approx(xs) # shape (1000,)
45
+ ys = approx(xs, sorted=True) # 1-D ascending fast path
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `treeweave.fit(f, a, b, tol, *, dim=None, out_dim=None, dtype="f64", ...)`
51
+
52
+ Fits callable `f` and returns a callable `TreeweaveFunction`.
53
+
54
+ - `a`, `b`: domain corners (scalars for 1D, length-`dim` lists otherwise).
55
+ - `tol`: approximation tolerance (drives adaptive tree refinement).
56
+ - `dim`: input dimension; inferred from `len(a)` (scalar corners ⇒ 1) when omitted.
57
+ - `out_dim`: number of output components; inferred by probing `f` once at the
58
+ box midpoint (`np.asarray(f(mid)).size`, scalar ⇒ 1) when omitted.
59
+ - `dtype`: `"f64"` (default) or `"f32"`.
60
+
61
+ The C ABI auto-selects a register-optimal leaf polynomial degree per detected CPU; accuracy is controlled entirely by `tol`.
62
+
63
+ ### `TreeweaveFunction`
64
+
65
+ The fitted object is **called** — there are no named eval methods. A point
66
+ gives a point result; a batch gives a batch result; two optional keyword flags
67
+ select alternate batch modes.
68
+
69
+ | Call / property | Description |
70
+ |---|---|
71
+ | `fn(x)` | Evaluate. Point: scalar (`dim==1`) or `(dim,)` → scalar / `(out_dim,)`. Batch: `(N,)` (`dim==1`) or `(N, dim)` → `(N,)` / `(N, out_dim)` |
72
+ | `fn(x, sorted=True)` | 1-D ascending-batch fast path (requires `dim == 1`) |
73
+ | `fn(x, transposed=True)` | Batch returning `(out_dim, N)` (requires `out_dim > 1`) |
74
+ | `.dim` | Input dimensionality |
75
+ | `.out_dim` | Output dimensionality |
76
+ | `.dtype` | `"f64"` or `"f32"` |
77
+ | `.memory_usage` | Bytes used by the approximation |
78
+ | `.print_stats()` | Print internal tree statistics |
79
+
80
+ A point whose length `!= dim`, a batch whose column count `!= dim`,
81
+ `sorted=True` with `dim != 1`, or `transposed=True` with `out_dim == 1` each
82
+ raise `ValueError` rather than silently mis-shaping the result.
83
+
84
+ ## Running tests
85
+
86
+ ```bash
87
+ pip install pytest
88
+ pytest tests/ -q
89
+ ```
@@ -0,0 +1,78 @@
1
+ # treeweave Python bindings
2
+
3
+ Python (nanobind) wrapper for the [treeweave](../../README.md) piecewise-polynomial
4
+ function approximator.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install scikit-build-core nanobind numpy
10
+ pip install . # regular install
11
+ # or for development:
12
+ pip install -e . --no-build-isolation
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```python
18
+ import math
19
+ import numpy as np
20
+ import treeweave
21
+
22
+ # Fit exp(x) on [0, 1] to 1e-10 relative tolerance.
23
+ def func(x):
24
+ return math.exp(x[0]) # x is a (dim,) ndarray
25
+
26
+ approx = treeweave.fit(func, 0.0, 1.0, tol=1e-10) # dim & out_dim inferred
27
+
28
+ # Scalar eval
29
+ print(approx(0.5)) # ≈ exp(0.5)
30
+
31
+ # Batch eval
32
+ xs = np.linspace(0, 1, 1000)
33
+ ys = approx(xs) # shape (1000,)
34
+ ys = approx(xs, sorted=True) # 1-D ascending fast path
35
+ ```
36
+
37
+ ## API
38
+
39
+ ### `treeweave.fit(f, a, b, tol, *, dim=None, out_dim=None, dtype="f64", ...)`
40
+
41
+ Fits callable `f` and returns a callable `TreeweaveFunction`.
42
+
43
+ - `a`, `b`: domain corners (scalars for 1D, length-`dim` lists otherwise).
44
+ - `tol`: approximation tolerance (drives adaptive tree refinement).
45
+ - `dim`: input dimension; inferred from `len(a)` (scalar corners ⇒ 1) when omitted.
46
+ - `out_dim`: number of output components; inferred by probing `f` once at the
47
+ box midpoint (`np.asarray(f(mid)).size`, scalar ⇒ 1) when omitted.
48
+ - `dtype`: `"f64"` (default) or `"f32"`.
49
+
50
+ The C ABI auto-selects a register-optimal leaf polynomial degree per detected CPU; accuracy is controlled entirely by `tol`.
51
+
52
+ ### `TreeweaveFunction`
53
+
54
+ The fitted object is **called** — there are no named eval methods. A point
55
+ gives a point result; a batch gives a batch result; two optional keyword flags
56
+ select alternate batch modes.
57
+
58
+ | Call / property | Description |
59
+ |---|---|
60
+ | `fn(x)` | Evaluate. Point: scalar (`dim==1`) or `(dim,)` → scalar / `(out_dim,)`. Batch: `(N,)` (`dim==1`) or `(N, dim)` → `(N,)` / `(N, out_dim)` |
61
+ | `fn(x, sorted=True)` | 1-D ascending-batch fast path (requires `dim == 1`) |
62
+ | `fn(x, transposed=True)` | Batch returning `(out_dim, N)` (requires `out_dim > 1`) |
63
+ | `.dim` | Input dimensionality |
64
+ | `.out_dim` | Output dimensionality |
65
+ | `.dtype` | `"f64"` or `"f32"` |
66
+ | `.memory_usage` | Bytes used by the approximation |
67
+ | `.print_stats()` | Print internal tree statistics |
68
+
69
+ A point whose length `!= dim`, a batch whose column count `!= dim`,
70
+ `sorted=True` with `dim != 1`, or `transposed=True` with `out_dim == 1` each
71
+ raise `ValueError` rather than silently mis-shaping the result.
72
+
73
+ ## Running tests
74
+
75
+ ```bash
76
+ pip install pytest
77
+ pytest tests/ -q
78
+ ```
@@ -0,0 +1,78 @@
1
+ [build-system]
2
+ requires = ["scikit-build-core>=0.10", "nanobind>=2.0"]
3
+ build-backend = "scikit_build_core.build"
4
+
5
+ [project]
6
+ name = "treeweave"
7
+ description = "Python bindings for the treeweave piecewise-polynomial approximator"
8
+ readme = "README.md"
9
+ license = "BSD-3-Clause"
10
+ requires-python = ">=3.9"
11
+ dependencies = ["numpy"]
12
+ # Single-sourced from the root VERSION file via the regex provider below (the
13
+ # same file the root CMakeLists project() reads), so the wheel metadata, the C++
14
+ # core, and any future bump never drift apart.
15
+ dynamic = ["version"]
16
+
17
+ [project.optional-dependencies]
18
+ test = ["pytest"]
19
+
20
+ [tool.scikit-build]
21
+ minimum-version = "0.10"
22
+ cmake.build-type = "Release"
23
+ # The Python package lives here in bindings/python, but the C++ core it links
24
+ # is the whole repo. Point scikit-build-core at the root CMakeLists (built
25
+ # with TREEWEAVE_BUILD_PYTHON=ON) so the wheel is self-contained — the same trick
26
+ # finufft uses. cibuildwheel copies the repo root into the build container, so
27
+ # "../../" resolves there too.
28
+ cmake.source-dir = "../../"
29
+ build.targets = ["_treeweave"]
30
+ # Install ONLY the extension component into the wheel (the install() rule in
31
+ # cmake/treeweave_bindings.cmake tags _treeweave with COMPONENT python_ext); without
32
+ # this the root install would also stage the C++ headers / libtreeweave_c / CMake
33
+ # config into the wheel.
34
+ install.components = ["python_ext"]
35
+ # The pure-Python package (treeweave/*.py) sits next to this pyproject.
36
+ wheel.packages = ["treeweave"]
37
+ # One abi3 wheel (CPython stable ABI) serves 3.12+; the nanobind module is
38
+ # built STABLE_ABI (see treeweave_python.cmake). 3.9–3.11 get version-specific
39
+ # wheels from the per-version cibuildwheel runs.
40
+ wheel.py-api = "cp312"
41
+
42
+ [tool.scikit-build.cmake.define]
43
+ TREEWEAVE_BUILD_PYTHON = "ON"
44
+ TREEWEAVE_BUILD_TESTS = "OFF"
45
+ TREEWEAVE_BUILD_EXAMPLES = "OFF"
46
+ # A stray warning on the wheel builder's compiler must never break `pip install`.
47
+ TREEWEAVE_WARNINGS_AS_ERRORS = "OFF"
48
+
49
+ [tool.scikit-build.metadata.version]
50
+ provider = "scikit_build_core.metadata.regex"
51
+ input = "../../VERSION"
52
+ regex = '''(?P<value>[0-9]+\.[0-9]+\.[0-9]+)'''
53
+
54
+ # The sdist is rooted at the repo (cmake.source-dir); drop everything the wheel
55
+ # build doesn't need so it stays small and the build context is lean.
56
+ [tool.scikit-build.sdist]
57
+ exclude = [
58
+ ".git*", ".github", "bench", "docs", "examples",
59
+ "bindings/julia", "bindings/matlab",
60
+ "build", "build*", "*.whl",
61
+ ]
62
+
63
+ [tool.cibuildwheel]
64
+ # abi3 wheel once (cp312, covers 3.12+) plus version-specific 3.9–3.11. PyPy
65
+ # and musllinux are out of scope for the C-ABI core.
66
+ build = "cp39-* cp310-* cp311-* cp312-*"
67
+ skip = "*-musllinux_* pp*"
68
+ build-frontend = "build"
69
+ # The C ABI is linked statically into _treeweave, so the only shared deps are the
70
+ # system C/C++ runtimes — nothing external to vendor. The repair step still
71
+ # runs (auditwheel/delocate) to stamp the platform tag. Per-arch baselines
72
+ # (TREEWEAVE_ARCH / TREEWEAVE_C_MULTIARCH) are injected by wheels.yml.
73
+ test-extras = ["test"]
74
+ test-command = "pytest {project}/bindings/python/tests"
75
+
76
+ [tool.cibuildwheel.linux]
77
+ manylinux-x86_64-image = "manylinux_2_28"
78
+ manylinux-aarch64-image = "manylinux_2_28"