[](https://opensource.org/licenses/BSD-2-Clause) [](https://github.com/deftio/qf_math/actions/workflows/ci.yml) [](#coverage-gate) [](compare/README.md) [](src/qf_math.h) [](https://github.com/deftio/qf_math) [](https://registry.platformio.org/libraries/deftio/qf_math) [](https://github.com/deftio/qf_math) [](https://components.espressif.com/components/deftio/qf_math) # Quick Float Math (`qf_math`) **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. [fr_math](github.com/deftio/fr_math) is the fixed point (pure integer) cousin of this library with identical apis. | | | |---|---| | **Language** | C99 (`float` API, `qf` typedef), plus optional C++ header wrapper | | **Dependencies** | None at compile time for the library itself | | **License** | BSD-2-Clause — see `LICENSE.txt` | | **Layout** | `src/` library · `test/` unit tests · `build/` all binaries & fetched third-party sources | 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. ## Why use this? - **Deterministic building blocks** for motor control, graphics-lite, sensor fusion, LED/audio synthesis, and telemetry pipelines. - **Tight code size**: one translation unit with shared lookup tables (see `make size`). - **Explicit trade-offs**: worst-case errors are documented in headers (e.g. trig ~3e-5 class behavior vs libm doubles). - **No heap**, minimal stack depth in normal use, integer-friendly helpers (`QF_*` macros, BAM phase, fixed-radix bridges). ## FPU-less alternative: [`fr_math`](https://github.com/deftio/fr_math) 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. ## Repository layout ``` src/ qf_math.c, qf_math.h/.hpp — drop-in C library + C++ wrapper test/ qf_math_test.c — correctness vs libm on host docs/ Markdown documentation (algorithms, API, fr_math, integration) pages/ GitHub Pages site (compact HTML + CSS; deploy via Actions) examples/ optional demos — ESP-IDF (`esp32s3_benchmark`), LilyGO T-Display-S3 PlatformIO (`lilygo_t_display_s3_bench`), Raspberry Pi Pico 2 Arduino (`pico2_benchmark`) docker/ multi-arch toolchain image + cross size report (fr_math-style) compare/ matrices vs other math libs + benchmark harness (see below) tools/ extra shell helpers & qf_math vs libm micro-benchmark build/ compiled binaries, CMake outputs, cloned deps (gitignored) ``` Everything that resembles an artifact—including vendored comparison libraries—stays under **`build/`** (for example `build/compare/third_party/`) so your tree stays clean. ## Build & test (host) Requires a normal UNIX toolchain (`gcc` or `clang`) and `-lm` for **tests and benchmarks only** (references use `sinf`, `logf`, …). ### Coverage gate [`make coverage-check`](Makefile) (also run in CI) rebuilds tests with gcov and **fails unless every executable line in `src/qf_math.c` is covered**. Use `make coverage` for the same build plus a human-readable gcov summary without enforcing 100%. ```bash make help # targets make lib # build/qf_math.o make test # build & run unit tests make bench # qf_math vs libm speed/accuracy (single TU bench) make size # object size report make coverage # gcov summary (optional gcov install; non-failing) make coverage-check # CI-style gate: 100% lines covered in src/qf_math.c make clean ``` ## Cross-compile code sizes (Docker) 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`). ```bash make docker-sizes # same as ./docker/run.sh make docker-sizes-rebuild # force docker image rebuild first ``` Details: **[docker/README.md](docker/README.md)**. ## Comparisons vs other math stacks (`compare/`) Documentation tables live under **`compare/`** (`LIBRARIES.md` for platforms/representation/footprint guidance, `FUNCTION_MATRIX.md` for symbol coverage vs **libfixmath**, **fr_math**, **CMSIS-DSP**, **libm**, …). | Target | What it does | |--------|----------------| | `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/`. | | `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. | | `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-github-report` | Regenerates **[`compare/BENCHMARK_REPORT.md`](compare/BENCHMARK_REPORT.md)** for GitHub (embedded bench tables + sizes). | | `make compare-tests` | CMake-builds libfixmath `tests_ro64` under `build/compare/third_party/libfixmath-build` and runs it. | | `make compare-fr-tests` | Runs **fr_math**’s upstream `make test` against the shallow clone (`compare/run_fr_math_tests.sh`). | | `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. | | `make benchmark-crossplatform` | Rewrite **`compare/BENCHMARK_CROSSPLATFORM.md`** — Host \| MCU **Speed vs libm** ratios from the committed snapshots (no hardware). | **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. **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. **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. ## Packaging & integration ### PlatformIO Use `library.json` at the repo root: add this folder as a local library or publish following [PlatformIO library format](https://docs.platformio.org/en/latest/manifests/library-json/index.html). Headers resolve from `src/` (`#include "qf_math.h"` for C, `#include "qf_math.hpp"` for C++). ### Espressif ESP-IDF `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/`. Add as a dependency (path or git URL) per Espressif docs; then `#include "qf_math.h"` from application components. ## API overview Public surface is declared in `src/qf_math.h`: - **Macros**: clamps, interpolation, deg/rad/BAM, radix bridges (`QF_TO_FR`, …). - **Trig**: `qf_sin`, `qf_cos`, `qf_tan`, BAM-native variants, inverse trig. - **Log/exp/pow**: `qf_log2`, `qf_ln`, `qf_log10`, `qf_pow2`, `qf_exp`, `qf_pow10`, `qf_pow`. - **Length**: `qf_sqrt`, `qf_hypot`, `qf_hypot_fast2`, `qf_hypot_fast8` (piecewise-linear magnitude). - **Audio-ish**: LFSR noise, PWM/square/saw/triangle waves, `qf_adsr_*` envelope. Domain violations (`sqrt` of negative, `log` of non-positive) return `QF_DOMAIN_ERROR`. ## Documentation for automation | File | Purpose | |------|---------| | [`docs/`](docs/) | **Markdown documentation** — algorithms, API reference, fr_math relationship, integration guide | | [`pages/`](pages/) | **GitHub Pages** site (enable *Settings → Pages → GitHub Actions*; live at `https://deftio.github.io/qf_math/` after first deploy) | | [`compare/README.md`](compare/README.md) | Compare harness docs (`make compare`, sizes, upstream suites, GitHub report) | | [`compare/BENCHMARK_REPORT.md`](compare/BENCHMARK_REPORT.md) | Last checked-in **host benchmark + size snapshot** (run `make compare-github-report` to refresh) | | [`compare/BENCHMARK_CROSSPLATFORM.md`](compare/BENCHMARK_CROSSPLATFORM.md) | Host vs MCU **relative** ratios (`make benchmark-crossplatform`; refresh snapshots first) | | `llms.txt` | Compact index for LLM tooling / crawling | | `agents.md` | Conventions for coding agents working in this repo | ## Contributing & correctness - Prefer extending tests in `test/qf_math_test.c` when adjusting numerical behavior. - Keep binaries and fetched trees under `build/` only. - Match existing comment and license style in touched files. ## Credits Author: **M. A. Chatterjee** (`deftio` at `deftio` dot `com`). See `LICENSE.txt` for full BSD-2-Clause text. Third-party comparison tooling pulls **libfixmath** (MIT) and **fr_math** (BSD-2-Clause); neither is bundled in git—they populate only under `build/compare/third_party/` when you run comparison targets.
idf.py add-dependency "deftio/qf_math^1.0.0"