Skip to content

Commit 47d85ec

Browse files
committed
updated ci and docs
1 parent b99c2d7 commit 47d85ec

5 files changed

Lines changed: 30 additions & 44 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CI for qf_math — tests, strict library build, 100% line coverage on src/qf_math.c,
2-
# and sync of an annotated git tag v<QF_MATH_VERSION> so the version appears under
3-
# the GitHub repo “Tags” / Releases sidebar when pushing to main.
2+
# and sync of an annotated git tag + GitHub Release for v<QF_MATH_VERSION> when
3+
# pushing to main.
44

55
name: CI
66

@@ -36,8 +36,10 @@ jobs:
3636
v=$(awk '/^#define QF_MATH_VERSION[[:space:]]/ {gsub(/"/,"",$3); print $3; exit}' src/qf_math.h)
3737
echo "value=$v" >> "$GITHUB_OUTPUT"
3838
39-
- name: Push tag v${{ steps.ver.outputs.value }} (main only, if missing)
39+
- name: Tag and release v${{ steps.ver.outputs.value }} (main only, if missing)
4040
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
41+
env:
42+
GH_TOKEN: ${{ github.token }}
4143
run: |
4244
set -euo pipefail
4345
TAG="v${{ steps.ver.outputs.value }}"
@@ -50,3 +52,6 @@ jobs:
5052
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
5153
git tag -a "$TAG" -m "qf_math ${{ steps.ver.outputs.value }}" "$GITHUB_SHA"
5254
git push origin "refs/tags/$TAG"
55+
gh release create "$TAG" --title "qf_math ${{ steps.ver.outputs.value }}" \
56+
--notes "Release ${{ steps.ver.outputs.value }} — see [README](https://github.com/${{ github.repository }}#readme) for API overview and [CHANGELOG commits](https://github.com/${{ github.repository }}/commits/$TAG)." \
57+
--verify-tag

README.md

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
**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.
1515

16-
[github.com/deftio/fr_math](github.com/deftio/fr_math) is the fixed point (pure integer) cousin of this library with identical apis.
16+
[fr_math](github.com/deftio/fr_math) is the fixed point (pure integer) cousin of this library with identical apis.
1717

1818
| | |
1919
|---|---|
@@ -24,7 +24,6 @@
2424

2525
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.
2626

27-
---
2827

2928
## Why use this?
3029

@@ -33,13 +32,11 @@ Version macros live in [`qf_math.h`](src/qf_math.h): `QF_MATH_VERSION` / `QF_MAT
3332
- **Explicit trade-offs**: worst-case errors are documented in headers (e.g. trig ~3e-5 class behavior vs libm doubles).
3433
- **No heap**, minimal stack depth in normal use, integer-friendly helpers (`QF_*` macros, BAM phase, fixed-radix bridges).
3534

36-
---
3735

3836
## FPU-less alternative: [`fr_math`](https://github.com/deftio/fr_math)
3937

4038
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.
4139

42-
---
4340

4441
## Repository layout
4542

@@ -57,7 +54,6 @@ build/ compiled binaries, CMake outputs, cloned deps (gitignored)
5754

5855
Everything that resembles an artifact—including vendored comparison libraries—stays under **`build/`** (for example `build/compare/third_party/`) so your tree stays clean.
5956

60-
---
6157

6258
## Build & test (host)
6359

@@ -78,7 +74,6 @@ make coverage-check # CI-style gate: 100% lines covered in src/qf_math.c
7874
make clean
7975
```
8076

81-
---
8277

8378
## Cross-compile code sizes (Docker)
8479

@@ -91,7 +86,6 @@ make docker-sizes-rebuild # force docker image rebuild first
9186

9287
Details: **[docker/README.md](docker/README.md)**.
9388

94-
---
9589

9690
## Comparisons vs other math stacks (`compare/`)
9791

@@ -114,32 +108,19 @@ Documentation tables live under **`compare/`** (`LIBRARIES.md` for platforms/rep
114108

115109
**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.
116110

117-
---
118111

119112
## Packaging & integration
120113

121114
### PlatformIO
122115

123-
- **Manifest:** [`library.json`](library.json) (registry: [deftio/qf_math](https://registry.platformio.org/libraries/deftio/qf_math)).
124-
- **`lib_deps`:** `deftio/qf_math` or `https://github.com/deftio/qf_math.git`
125-
- **Lean subset** (smaller ROM, no `log10` / `pow10` / waves / ADSR): add to the env `build_flags = -DQF_MATH_LEAN`
126-
- **`export` exclude** in the manifest trims compare/tests/docs from the PIO-installed copy; clones via **git URL** still get the full repo (including **`examples/`**).
127-
- Sanity check locally: `pio pkg pack .` must succeed before publishing.
128-
129-
### Arduino Library Manager / Arduino IDE
130-
131-
- **Manifest:** [`library.properties`](library.properties) beside `library.json` (Arduino 2.x discovers `src/` layout).
132-
- Install from ZIP of the repo or symlink the folder under `Arduino/libraries/`; include `#include <qf_math.h>` (Arduino adds library `src/` to the include path).
116+
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++).
133117

134118
### Espressif ESP-IDF
135119

136-
- **Component Manager:** [`idf_component.yml`](idf_component.yml) + [`CMakeLists.txt`](CMakeLists.txt). Component tarball excludes bulky trees (`examples/`, `compare/`, …); **`src/`**, root **`CMakeLists.txt`**, **`LICENSE.txt`**, and **`README.md`** remain usable.
137-
- **Consumer projects:** `#include "qf_math.h"`; optional **`QF_MATH_LEAN`** via `target_compile_definitions` on your target or **`idf.py menuconfig`/CMake extra flags**.
138-
- **Warnings:** component build uses `-Wall -Wextra -Wshadow -Wconversion` **without** `-Werror` so toolchain/IDF updates are less likely to break downstream apps.
120+
`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/`.
139121

140-
Add as a dependency (path or git URL) per Espressif docs.
122+
Add as a dependency (path or git URL) per Espressif docs; then `#include "qf_math.h"` from application components.
141123

142-
---
143124

144125
## API overview
145126

@@ -153,7 +134,6 @@ Public surface is declared in `src/qf_math.h`:
153134

154135
Domain violations (`sqrt` of negative, `log` of non-positive) return `QF_DOMAIN_ERROR`.
155136

156-
---
157137

158138
## Documentation for automation
159139

@@ -167,15 +147,13 @@ Domain violations (`sqrt` of negative, `log` of non-positive) return `QF_DOMAIN_
167147
| `llms.txt` | Compact index for LLM tooling / crawling |
168148
| `agents.md` | Conventions for coding agents working in this repo |
169149

170-
---
171150

172151
## Contributing & correctness
173152

174153
- Prefer extending tests in `test/qf_math_test.c` when adjusting numerical behavior.
175154
- Keep binaries and fetched trees under `build/` only.
176155
- Match existing comment and license style in touched files.
177156

178-
---
179157

180158
## Credits
181159

pages/index.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ <h2>Accuracy &amp; speed sweep vs libm</h2>
2525
<p>This table is generated by <code>tools/qf_math_bench.c --html-table</code> (same grids as <code>make bench</code>). Numbers are from the machine that last ran <code>make docs-pages</code> or the GitHub Actions Pages deploy — <strong>not MCU timings</strong>.</p>
2626

2727
<!--QF_MATH_BENCH_TABLE_BEGIN-->
28-
<p class="qf-meta"><small>Generated UTC <strong>2026-05-08 03:36:06Z</strong> — 10000-sample grids, 100000 outer × 100-inner timing loops; error vs C <code>double</code>; libm = matching <code>*f</code> call. Compiler: <code>Apple LLVM 21.0.0 (clang-2100.0.123.102)</code>.</small></p>
28+
<p class="qf-meta"><small>Generated UTC <strong>2026-05-09 09:09:51Z</strong> — 10000-sample grids, 100000 outer × 100-inner timing loops; error vs C <code>double</code>; libm = matching <code>*f</code> call. Compiler: <code>Apple LLVM 21.0.0 (clang-2100.0.123.102)</code>.</small></p>
2929
<h3>Accuracy sweep vs libm (<code>float</code>)</h3>
3030
<table class="qf-table"><thead><tr><th scope="col">Function</th><th scope="col">Bench note</th><th scope="col">Max</th><th scope="col">Mean</th><th scope="col"><code>qf</code> ms</th><th scope="col">libm ms</th><th scope="col">libm ÷ qf</th></tr></thead>
3131
<tbody>
32-
<tr><td><code>qf_sin()</code></td><td>radians; ref = sin in double</td><td>0.009691% amp</td><td>0.003225% amp</td><td>49.31</td><td>21.57</td><td><strong>0.44</strong>×</td></tr>
33-
<tr><td><code>qf_cos()</code></td><td>radians; ref = cos in double</td><td>0.009733% amp</td><td>0.003226% amp</td><td>33.05</td><td>23.46</td><td><strong>0.71</strong>×</td></tr>
34-
<tr><td><code>qf_tan()</code></td><td>excludes inputs within 0.05 rad of poles</td><td>1.71% amp</td><td>0.04845% amp</td><td>61.59</td><td>29.32</td><td><strong>0.48</strong>×</td></tr>
35-
<tr><td><code>qf_acos()</code></td><td>domain [-1, 1]; radians out</td><td>0.007487% of pi</td><td>0.000372% of pi</td><td>76.82</td><td>22.90</td><td><strong>0.30</strong>×</td></tr>
36-
<tr><td><code>qf_atan2()</code></td><td>swept (y,x) magnitudes; ref = atan2 double</td><td>0.02969% of pi</td><td>0.006815% of pi</td><td>57.21</td><td>26.28</td><td><strong>0.46</strong>×</td></tr>
37-
<tr><td><code>qf_log2()</code></td><td>x in (0.001, 100]; absolute Δ vs double</td><td>4.353e-05 abs</td><td>1.615e-05 abs</td><td>16.40</td><td>23.07</td><td><strong>1.41</strong>×</td></tr>
38-
<tr><td><code>qf_ln()</code></td><td>x in (0.001, 100]; absolute Δ vs double</td><td>3.03e-05 abs</td><td>1.119e-05 abs</td><td>22.99</td><td>22.84</td><td><strong>0.99</strong>×</td></tr>
39-
<tr><td><code>qf_pow2()</code></td><td>relative vs double; libm ref = exp2f</td><td>0.001473% rel</td><td>0.0009778% rel</td><td>20.28</td><td>16.77</td><td><strong>0.83</strong>×</td></tr>
40-
<tr><td><code>qf_exp()</code></td><td>relative vs double on grid</td><td>0.001512% rel</td><td>0.0009779% rel</td><td>21.95</td><td>16.68</td><td><strong>0.76</strong>×</td></tr>
41-
<tr><td><code>qf_sqrt()</code></td><td>relative vs double</td><td>0.0004702% rel</td><td>0.0001786% rel</td><td>16.28</td><td>6.33</td><td><strong>0.39</strong>×</td></tr>
42-
<tr><td><code>qf_hypot()</code></td><td>relative vs double hypot</td><td>0.0004676% rel</td><td>0.0001906% rel</td><td>13.22</td><td>12.96</td><td><strong>0.98</strong>×</td></tr>
43-
<tr><td><code>qf_hypot_fast8()</code></td><td>qf piecewise-linear; timed vs hypotf reference</td><td>0.1372% rel</td><td>0.05112% rel</td><td>22.70</td><td>13.17</td><td><strong>0.58</strong>×</td></tr>
32+
<tr><td><code>qf_sin()</code></td><td>radians; ref = sin in double</td><td>0.001885% amp</td><td>0.0007992% amp</td><td>10.64</td><td>21.39</td><td><strong>2.01</strong>×</td></tr>
33+
<tr><td><code>qf_cos()</code></td><td>radians; ref = cos in double</td><td>0.001887% amp</td><td>0.0008006% amp</td><td>10.46</td><td>22.70</td><td><strong>2.17</strong>×</td></tr>
34+
<tr><td><code>qf_tan()</code></td><td>excludes inputs within 0.05 rad of poles</td><td>0.4535% amp</td><td>0.02151% amp</td><td>29.42</td><td>28.64</td><td><strong>0.97</strong>×</td></tr>
35+
<tr><td><code>qf_acos()</code></td><td>domain [-1, 1]; radians out</td><td>0.01482% of pi</td><td>0.002432% of pi</td><td>94.05</td><td>22.36</td><td><strong>0.24</strong>×</td></tr>
36+
<tr><td><code>qf_atan2()</code></td><td>swept (y,x) magnitudes; ref = atan2 double</td><td>0.04097% of pi</td><td>0.01276% of pi</td><td>28.63</td><td>25.71</td><td><strong>0.90</strong>×</td></tr>
37+
<tr><td><code>qf_log2()</code></td><td>x in (0.001, 100]; absolute Δ vs double</td><td>8.104e-07 abs</td><td>2.15e-07 abs</td><td>19.19</td><td>22.23</td><td><strong>1.16</strong>×</td></tr>
38+
<tr><td><code>qf_ln()</code></td><td>x in (0.001, 100]; absolute Δ vs double</td><td>6.235e-07 abs</td><td>1.676e-07 abs</td><td>25.55</td><td>22.30</td><td><strong>0.87</strong>×</td></tr>
39+
<tr><td><code>qf_pow2()</code></td><td>relative vs double; libm ref = exp2f</td><td>0.000322% rel</td><td>3.64e-05% rel</td><td>22.48</td><td>16.13</td><td><strong>0.72</strong>×</td></tr>
40+
<tr><td><code>qf_exp()</code></td><td>relative vs double on grid</td><td>0.0003402% rel</td><td>4.163e-05% rel</td><td>25.65</td><td>16.28</td><td><strong>0.63</strong>×</td></tr>
41+
<tr><td><code>qf_sqrt()</code></td><td>relative vs double</td><td>0.0004702% rel</td><td>0.0001786% rel</td><td>16.08</td><td>6.27</td><td><strong>0.39</strong>×</td></tr>
42+
<tr><td><code>qf_hypot()</code></td><td>relative vs double hypot</td><td>0.0004676% rel</td><td>0.0001906% rel</td><td>13.35</td><td>13.02</td><td><strong>0.98</strong>×</td></tr>
43+
<tr><td><code>qf_hypot_fast8()</code></td><td>qf piecewise-linear; timed vs hypotf reference</td><td>0.1372% rel</td><td>0.05112% rel</td><td>22.89</td><td>13.17</td><td><strong>0.58</strong>×</td></tr>
4444
</tbody></table>
4545
<p class="qf-footnote"><small><strong>Error column:</strong> <em>amp</em> = % of ±1 output (sin/cos/tan). <em>rel</em> = max relative error vs double × 100. <em>of pi</em> = absolute radian error as % of π (acos, atan2). <em>abs</em> = absolute Δ vs double on the grid (log2, ln). <strong>libm ÷ qf</strong> uses total loop time; &gt; 1 means qf_math was faster on this host (microbenchmark only; profile on your MCU).</small></p>
4646
<!--QF_MATH_BENCH_TABLE_END-->

tools/check_coverage.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ else
3636
fi
3737

3838
echo "--- gcov line summary (src/qf_math.c) ---"
39-
grep -v '^[[:space:]]*-:[[:space:]]*0:' "$GCOV_FILE" | grep '^[[:space:]]*[0-9]' | head -5 >/dev/null
40-
gcov -r "$GCOV_FILE" 2>/dev/null || true
4139

4240
if grep -q '#####:' "$GCOV_FILE"; then
4341
echo ""

tools/qf_math_bench.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
* All rights reserved. BSD-2-Clause — see qf_math.h for full text.
1111
*/
1212

13+
/* Enable clock_gettime / CLOCK_MONOTONIC on glibc with -std=c99 */
14+
#if !defined(_POSIX_C_SOURCE) && !defined(__APPLE__)
15+
#define _POSIX_C_SOURCE 199309L
16+
#endif
17+
1318
#include <stdio.h>
1419
#include <math.h>
1520
#include <stdint.h>

0 commit comments

Comments
 (0)