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
**qf_math** is a compact, dependency-free C99 library for **fast approximate math on IEEE-754 `float`**. It targets embedded firmware where you want predictable cost and small flash footprint: table-driven trig, logarithms, exponentials, `sqrt`, `hypot`, waveform helpers, and a floating-point ADSR envelope—without pulling in full libm semantics on platforms where that matters.
13
+
**qf_math** is a lightweight library for **fast approximate math on IEEE-754 `float`** — built for ARM Cortex-M, RISC-V, Xtensa/ESP32, and any 32-bit target. One translation unit, no heap, no dependencies, no FPU required (but benefits from one). Drop it into firmware for predictable-cost trig, log, exp, sqrt, hypot, waveforms, and ADSR — without pulling in full libm.
14
+
15
+
**[fr_math](https://github.com/deftio/fr_math)** is the **fixed-point (pure integer)** cousin with the same API family.
Peak error from identical benchmark grids. Both libraries use the same approximation strategies (BAM phase, sub-step interpolation, piecewise hypot) — the accuracy difference comes from float vs fixed-point arithmetic.
33
+
34
+
| Function | Metric | libm |**qf_math**|**fr_math**|
> **%FS** = % of full-scale (±1 output for trig). **rel %** = relative error vs `double` reference. **abs rad** = absolute radians. Bold = closer to libm. `libm` column is the `*f` reference (effectively 0 error at this precision).
49
+
50
+
51
+
## Speed vs libm — ESP32-S3 (with FPU)
52
+
53
+
Ratio of libm wall-clock time to library time for the same loop. **> 1.0** = faster than `sinf`/`sqrtf`/etc. on that platform. ESP32-S3 has a single-precision FPU, so both `qf_math` and `libm` use hardware float — the advantage comes from simpler approximations with fewer branches.
15
54
16
-
[fr_math](github.com/deftio/fr_math) is the fixed point (pure integer) cousin of this library with identical apis.
55
+
| Function |**qf_math**|**fr_math**| Notes |
56
+
|:---------|------------:|------------:|:------|
57
+
| sin (rad) |**4.30**× | 1.32× | qf_math: table + lerp; fr_math: integer table via float bridge |
58
+
| cos (rad) |**4.39**× | 0.90× ||
59
+
| tan (rad) |**3.56**× | 1.31× ||
60
+
| asin | 1.10× | 0.77× ||
61
+
| acos | 1.11× | 0.77× ||
62
+
| atan2 |**1.41**× | 0.70× ||
63
+
| sqrt | 1.07× | 0.08× | libm sqrtf is hard to beat (HW instruction on many cores) |
> **fr_math** numbers include **float↔fixed bridge overhead** — native `s32` / `fix16_t` calls in a pure-integer pipeline are faster. See [`compare/BENCHMARK_CROSSPLATFORM.md`](compare/BENCHMARK_CROSSPLATFORM.md) for full matrices including libfixmath, FastTrig, and ESP-DSP.
69
+
70
+
71
+
## Quick start
72
+
73
+
```c
74
+
#include"qf_math.h"
75
+
76
+
qf y = qf_sin(1.0f); /* radians */
77
+
qf len = qf_hypot(dx, dy);
78
+
qf dB = 20.0f * qf_log10(v / ref);
79
+
```
17
80
18
81
| | |
19
82
|---|---|
20
83
| **Language** | C99 (`float` API, `qf` typedef), plus optional C++ header wrapper |
21
84
| **Dependencies** | None at compile time for the library itself |
22
85
| **License** | BSD-2-Clause — see `LICENSE.txt` |
23
-
|**Layout**|`src/` library · `test/` unit tests · `build/` all binaries & fetched third-party sources |
24
86
25
87
Version macros live in [`qf_math.h`](src/qf_math.h): `QF_MATH_VERSION` / `QF_MATH_VERSION_HEX`. When you bump the version string, update the **Version** badge at the top of this README to match.
26
88
89
+
For releases, prefer the version/release helpers so manifests, docs, badges, pages, and generated reports stay in sync:
90
+
91
+
```bash
92
+
python3 tools/qf_version.py show --format markdown
93
+
python3 tools/qf_version.py update 1.0.2
94
+
make make-release VERSION=1.0.2
95
+
make make-release RELEASE_ARGS="--dry-run --skip-docker --skip-peer-tests"
96
+
```
97
+
27
98
28
99
## Why use this?
29
100
@@ -33,9 +104,19 @@ Version macros live in [`qf_math.h`](src/qf_math.h): `QF_MATH_VERSION` / `QF_MAT
33
104
-**No heap**, minimal stack depth in normal use, integer-friendly helpers (`QF_*` macros, BAM phase, fixed-radix bridges).
For targets **without a hardware FPU** (or when you want to avoid soft-float cost), use **[fr_math](https://github.com/deftio/fr_math)**—a **battle-tested** sister library that exposes the **same API** using **pure fixed-point** math, with **16-bit** platform support when that is a requirement.
117
+
Domain violations (`sqrt` of negative, `log` of non-positive) return `QF_DOMAIN_ERROR`.
118
+
119
+
Full reference: [`docs/API.md`](docs/API.md) — Algorithms: [`docs/ALGORITHMS.md`](docs/ALGORITHMS.md) — [Float math tradeoffs](https://deftio.github.io/qf_math/float-math-tradeoffs.html) (libm vs qf_math vs fixed-point vs DSP)
39
120
40
121
41
122
## Repository layout
@@ -45,15 +126,13 @@ src/ qf_math.c, qf_math.h/.hpp — drop-in C library + C++ wrapper
45
126
test/ qf_math_test.c — correctness vs libm on host
Everything that resembles an artifact—including vendored comparison libraries—stays under **`build/`** (for example `build/compare/third_party/`) so your tree stays clean.
56
-
57
136
58
137
## Build & test (host)
59
138
@@ -77,11 +156,11 @@ make clean
77
156
78
157
## Cross-compile code sizes (Docker)
79
158
80
-
Like **[fr_math](https://github.com/deftio/fr_math)**, this repo ships a **`docker/`** image (Ubuntu + common cross-compilers + Espressif Xtensa) to compile **`src/qf_math.c`** for several CPUs and emit **`.text`** sizes (`build/docker_size_table.md`).
159
+
Like **[fr_math](https://github.com/deftio/fr_math)**, this repo ships a **`docker/`** image (Ubuntu + common 32/64-bit cross-compilers + Espressif Xtensa) to compile **`src/qf_math.c`** for several CPUs and emit the source-of-truth size matrix (`build/docker_sizes.csv`).
81
160
82
161
```bash
83
-
make docker-sizes #same as ./docker/run.sh
84
-
make docker-sizes-rebuild #force docker image rebuild first
162
+
make docker-sizes #CSV + compact compare/README.md summary
163
+
make docker-sizes-rebuild #rebuild image, then CSV + summary
@@ -94,19 +173,12 @@ Documentation tables live under **`compare/`** (`LIBRARIES.md` for platforms/rep
94
173
| Target | What it does |
95
174
|--------|----------------|
96
175
|`make compare-deps`| Shallow-clones **[libfixmath](https://github.com/PetteriAimonen/libfixmath)** (MIT) and **[fr_math](https://github.com/deftio/fr_math)** into `build/compare/third_party/`. |
97
-
|`make compare` (alias `make compare-matrix`) | Builds `build/compare/benchmark_suite` — accuracy + wall-clock for **qf_math**, **libm**, **libfixmath** (float bridge), **fr_math** (Q16.16 bridge), and a **Taylor poly** baseline. |
98
-
|`make compare-report`| Prints a Markdown **size table** (`size(1)` totals) for `qf_math.o`, the libfixmath object subset, and `FR_math.o`. |
|`make compare-tests`| CMake-builds libfixmath `tests_ro64` under `build/compare/third_party/libfixmath-build` and runs it. |
101
-
|`make compare-fr-tests`| Runs **fr_math**’s upstream `make test` against the shallow clone (`compare/run_fr_math_tests.sh`). |
102
-
|`make mcu-benchmark-snapshot`| Flash MCU bench and rewrite **`compare/MCU_BENCHMARK_SNAPSHOT*.md`** via UART (**pio** / Arduino, **pyserial**). Supports LilyGO T-Display-S3, ESP32-S3, and Raspberry Pi Pico 2. |
103
-
|`make benchmark-crossplatform`| Rewrite **`compare/BENCHMARK_CROSSPLATFORM.md`** — Host \| MCU **Speed vs libm** ratios from the committed snapshots (no hardware). |
176
+
|`make compare`| Builds `build/compare/benchmark_suite` — accuracy + wall-clock for **qf_math**, **libm**, **libfixmath** (float bridge), **fr_math** (Q16.16 bridge), and a **Taylor poly** baseline. |
177
+
|`make compare-github-report`| Regenerates **[`compare/BENCHMARK_REPORT.md`](compare/BENCHMARK_REPORT.md)** for GitHub. |
178
+
|`make mcu-benchmark-snapshot`| Flash MCU bench and rewrite **`compare/MCU_BENCHMARK_SNAPSHOT*.md`** via UART. |
**Interpretation:** Desktop timings are *not* MCU timings. Bridged benchmarks include float↔fixed overhead that disappears when you stay natively in `fix16_t` / fixed-radix `s32`. The automated `s32` peer row is **fr_math**; other fast libraries are surveyed in [`compare/PEERS.md`](compare/PEERS.md) but are not wired into the reproducible host/ESP32-S3 harness yet. Use these numbers for intuition and regression tracking, not as a substitute for profiling on your silicon.
106
-
107
-
**On silicon:****[examples/lilygo_t_display_s3_bench](examples/lilygo_t_display_s3_bench/README.md)** (PlatformIO, **LilyGO T-Display-S3**), **[examples/esp32s3_benchmark](examples/esp32s3_benchmark/README.md)** (ESP-IDF), or **[examples/pico2_benchmark](examples/pico2_benchmark/)** (Arduino, **Raspberry Pi Pico 2** ARM / RISC-V) run the **same**[`benchmark_core.c`](compare/benchmark_core.c) loops so UART / USB serial captures wall-clock on real hardware.
108
-
109
-
**Host vs MCU (relative only):****[compare/BENCHMARK_CROSSPLATFORM.md](compare/BENCHMARK_CROSSPLATFORM.md)** merges **Speed vs libm** tables from [`compare/BENCHMARK_REPORT.md`](compare/BENCHMARK_REPORT.md) (POSIX snapshot) and the MCU snapshots (`MCU_BENCHMARK_SNAPSHOT*.md` — ESP32-S3, Pico 2 ARM, Pico 2 RISC-V); regenerate with **`make benchmark-crossplatform`** after refreshing those files.
181
+
**On silicon:****[examples/lilygo_t_display_s3_bench](examples/lilygo_t_display_s3_bench/README.md)** (PlatformIO), **[examples/esp32s3_benchmark](examples/esp32s3_benchmark/README.md)** (ESP-IDF), or **[examples/pico2_benchmark](examples/pico2_benchmark/)** (Arduino, Pico 2 ARM/RISC-V) run the **same**[`benchmark_core.c`](compare/benchmark_core.c) loops on real hardware.
110
182
111
183
112
184
## Packaging & integration
@@ -119,31 +191,16 @@ Use `library.json` at the repo root: add this folder as a local library or publi
119
191
120
192
`idf_component.yml` registers the component for the ESP-IDF Component Manager. `CMakeLists.txt` wraps `idf_component_register` for `src/qf_math.c` with include path `src/`.
121
193
122
-
Add as a dependency (path or git URL) per Espressif docs; then `#include "qf_math.h"` from application components.
|[`pages/`](pages/)|**GitHub Pages** site (enable *Settings → Pages → GitHub Actions*; live at `https://deftio.github.io/qf_math/` after first deploy) |
0 commit comments