You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+42-64Lines changed: 42 additions & 64 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,9 @@ We created `numpycpp` to keep NumPy's familiar usage patterns while letting C++
15
15
16
16
`numpycpp` is a **header-only C++ library** implementing numpy's core API (`numpy.*`, `numpy.linalg.*`, `numpy.einsum`) with **bit-level precision alignment**. Raw pointer + size interface. Zero external dependencies — pure C++17 standard library.
17
17
18
-
All APIs are tested against Python numpy under strict bit-level comparison: every IEEE 754 float bit must match exactly. Where bit-exact parity is unattainable due to differing math library implementations (1‑ULP), it is documented explicitly.
18
+
All APIs are tested against Python numpy under strict bit-level comparison: every IEEE 754 float bit must match exactly (336 tests, float64 + float32).
19
+
20
+
**Bit-exact math** is achieved via an SVML bridge that resolves numpy's own transcendental functions (`__svml_exp8`, `__svml_sin8`, etc.) from the loaded `_multiarray_umath.so` at runtime. This guarantees that `exp`, `log`, `sin`, `cos`, `tan`, and all other transcendental functions produce the exact same bits as numpy. On platforms without AVX-512, the bridge falls back to `std::` (1‑ULP).
19
21
20
22
## Quick Start
21
23
@@ -78,97 +80,73 @@ Add `-Ipath/to/numpycpp` to your compiler flags and include the headers directly
78
80
### Testing
79
81
80
82
The test suite verifies **bit-level precision alignment** between every C++ function and Python numpy.
81
-
No tolerance, no `atol`/`rtol` — raw IEEE 754 bits must match exactly.
83
+
No tolerance, no `atol`/`rtol` — raw IEEE 754 bits must match exactly. 336 tests, float64 + float32.
82
84
83
85
```bash
84
86
cd tests
85
87
make # compile C++ test module
86
-
make test# run all tests (default: 337 tests, float64 + float32)
88
+
make test# run all 336 tests (silent mode: only failures print)
87
89
```
88
90
89
-
**API category filter** — limit tests to specific API groups via env var:
91
+
To run with verbose output:
90
92
91
93
```bash
92
-
# Run only creation + reduction APIs (zeros_like, sum, mean, etc.)
93
-
NUMPYCPP_TEST_APIS=creation,reduction make test
94
-
95
-
# Run only elementary math (sqrt, exp, sin, pow, etc.)
> **Why 1‑ULP?** The C++ standard library (`std::exp`, `std::log`, etc.) and numpy's underlying libm may use different polynomial approximations or rounding strategies, leading to a single-bit difference in the last place. This is inherent to the math library, not a bug in `numpycpp`.
> **SVML bridge**: On AVX-512 platforms, `numpycpp` resolves numpy's own SVML vector functions (`__svml_exp8`, `__svml_sin8`, etc.) from the loaded `_multiarray_umath.so` via `dlsym`. This guarantees bit-identical transcendental results. On non-AVX-512, `std::` fallbacks produce ≤ 1 ULP difference.
129
+
>
130
+
> **Reductions**: All reductions use numpy's pairwise summation algorithm (recursive split, 8-accumulator unrolled). This matches `np.sum` exactly. Dot products and norms build on pairwise_sum, not BLAS — matching `np.sum(a*b)` and `np.sqrt(np.sum(a*a))` respectively.
0 commit comments