Releases
Release highlights. For the full per-symbol change log, see release_notes.md in the repo.
v2.0.8 — 2026
Tangent accuracy rewrite and trig rounding fix.
- BAM-native tangent: new
fr_tan_bam(u16 bam)with 65-entry octant table (130 bytes). No 64-bit math.FR_TanI,FR_Tan,fr_tanare now thin wrappers. - Round-to-nearest fix: radian/degree trig wrappers now round instead of truncating when converting to BAM. Peak error drops from ~1.03% to 0.16% on the radian path, matching BAM-native accuracy.
- Conversion macro trimming:
FR_DEG2BAMandFR_RAD2BAMreduced to ~18–21 bits (from ~28 bits). Verified: no measurable accuracy impact. FR_TRIG_MINVALfixed: now-FR_TRIG_MAXVAL(was-FR_TRIG_MASK)
v2.0.7 — 2026
README restructure, accuracy table cleanup, expanded cross-compile support.
FR_CORE_ONLYconvenience define — single#definestrips both print helpers and wave generators- Accuracy table cleanup — removed LSB column (percent error is the user-facing metric)
- New cross-compile targets — RP2040 (Cortex-M0+), STM32 (Cortex-M4), 68HC11, MIPS32 added to Docker build
- Three-column size table — Lean / Core / Full for every target, sorted 8-bit → 64-bit
scripts/crossbuild_sizes.sh— consolidated script: Docker build, CSV + markdown output, doc patching- README reordered and cleaned up: accuracy table first, badges as standard markdown, concise build flavor descriptions
v2.0.6 — 2026
Accuracy improvements, lean-build options, library cleanup.
- FR_acos boundary fix — 12x better accuracy near ±1.0 via deferred quantization
- FR_atan2 rewrite — asin/acos + hypot_fast8, 0.41% peak error (was 20% in libfixmath)
- Lean build guards —
FR_NO_PRINT(~1.3 KB) andFR_NO_WAVES(~0.6 KB) for ROM-constrained targets - Removed FR_hypot_fast (4-segment) — FR_hypot_fast8 is strictly better; 4-seg was dead weight
- libfixmath comparison benchmark added to repo (
compare_lfm/)
v2.0.5 — 2026
Release pipeline fixes. Fixed squash-merge divergence handling and
on-master push/CI sequencing in tools/make_release.sh.
v2.0.4 — 2026
CI fix release. Fixed release.yml coverage step, release pipeline
auto-commits badge/version changes, removed conflicting auto-release
job from ci.yml.
v2.0.3 — 2026
CI and release pipeline cleanup. Guided release script
(tools/make_release.sh) that validates, merges, tags, and publishes
to PlatformIO and ESP-IDF in one flow.
v2.0.2 — 2026
Embedded library publishing support. No functional changes to the math library — adds Arduino, PlatformIO, and ESP-IDF package manager integration.
- Arduino Library Manager, PlatformIO Registry, and ESP-IDF Component Registry metadata files
- Reorganized examples with focused Arduino
.inosketches - Added
llms.txtandagents.mdfor AI coding agents - Tag-triggered release workflow (
.github/workflows/release.yml)
v2.0.1 — 2026
Precision and accuracy release. All changes are backward-compatible with v2.0.0 except where noted.
Trig output precision
fr_cos_bam/fr_sin_bamnow return s15.16 (was s0.15). Exact values at cardinal angles:cos(0°) = 65536,cos(90°) = 0.FR_TRIG_ONE = 65536.FR_TanI/fr_tanreturn s15.16 (was s16.15). Saturation is now±INT32_MAX.- All wrappers updated:
FR_Cos,FR_Sin,FR_CosI,FR_SinI,FR_TanI,FR_Tan.
Inverse trig now returns radians
FR_acos,FR_asin,FR_atangain anout_radixparameter and return radians at that radix (was degrees ass16).FR_atan2(y, x, out_radix)also returns radians.FR_BAM2RADmacro corrected (was off by a factor of 1024).
Rounding improvements
FR_FixMuls/FR_FixMulSat: add 0.5 LSB (+0x8000) before the>>16shift. Both now round to nearest instead of truncating.FR_sqrt/FR_hypot: the internalfr_isqrt64now rounds to nearest (remainder > root → +1). Worst-case error drops from <1 LSB to ≤ 0.5 LSB.
Improved exp / log accuracy
FR_pow2table expanded from 17 entries (16 segments) to 65 entries (64 segments, 260 bytes). Interpolation error drops by ~16×.FR_log2table expanded from 33 entries to 65 entries (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB at Q16.16.FR_MULK28macro added: multiplies any fixed-point value by a radix-28 constant using a 64-bit intermediate with round-to-nearest. ~9 decimal digits of precision.FR_EXPandFR_POW10now useFR_MULK28for the base conversion instead of shift-only macros. Much lower error.FR_lnandFR_log10also useFR_MULK28internally.FR_EXP_FASTandFR_POW10_FASTadded as shift-only alternatives for 8-bit targets where 64-bit multiply is expensive.- Four radix-28 constants added:
FR_kLOG2E_28,FR_krLOG2E_28,FR_kLOG2_10_28,FR_krLOG2_10_28.
New utility macros
FR_MIN,FR_MAX,FR_CLAMP— standard min/max/clamp.FR_DIV(x, xr, y, yr)— fixed-point division with 64-bit pre-scaling. Now rounds to nearest (≤ 0.5 LSB error) instead of truncating.FR_DIV_TRUNCpreserves the old truncating behavior for backward compatibility.FR_DIV32is the 32-bit-only truncating path.FR_MOD(x, xr, y, yr)— fixed-point modulus.
Infrastructure
- Docker cross-compile size report (9 targets).
sync_version.shrewrite —FR_MATH_VERSION_HEXis the single source of truth for version numbers.- CI auto-release job, Dependabot config.
- Documentation audit: 14 errors fixed across header, source, markdown, and HTML docs.
Breaking changes from v2.0.0
| Change | v2.0.0 | v2.0.1 |
|---|---|---|
| sin/cos return type | s16 (s0.15) | s32 (s15.16) |
| sin/cos 1.0 value | 32767 | 65536 (exact) |
| tan return format | s16.15 (radix 15) | s15.16 (radix 16) |
| tan saturation | ±(32767 << 15) | ±INT32_MAX |
| FR_acos/asin signature | (input, radix) → s16 degrees | (input, radix, out_radix) → s32 radians |
| FR_atan signature | (input, radix) → s16 degrees | (input, radix, out_radix) → s32 radians |
| FR_atan2 signature | (y, x) → s16 degrees | (y, x, out_radix) → s32 radians |
| FR_BAM2RAD | off by 1024× (bug) | correct |
| FR_DIV rounding | truncates toward zero | rounds to nearest (use FR_DIV_TRUNC for old behavior) |
v2.0.0 — 2026
The first major revision in more than twenty years. v2 is a bug-fix, precision, and feature release with a full test suite and 99% line coverage.
64-bit safety
v1 defined s32 as signed long, which is
64 bits on LP64 platforms (Linux x64, macOS arm64). Every
fixed-point path that assumed s32 was exactly 32 bits
silently produced wrong results on desktop hosts. v2 migrates all
typedefs to <stdint.h>
(int8_t…int32_t). C99 is now
mandatory.
Numerical fixes
FR_FixMulSat/FR_FixMuls: rewritten on anint64_tfast path with explicit saturation; v1 had an algebraic bug in the sign-combination logic.FR_log2/FR_ln/FR_log10: new leading-bit-position + 33-entry mantissa table with linear interpolation. v1 returned wrong values for non-power-of-2 inputs.FR_pow2/FR_EXP/FR_POW10: corrected floor-toward-−∞ integer-part extraction. v1 gave wrong answers for negative non-integer inputs.FR_atan2: v1 was a placeholder that returned garbage. v2 is a correct octant-reduced arctan with max error ≤ 1°. The vestigialradixargument was dropped.FR_atan,FR_Tan,FR_TanI: wiring and overflow fixes.FR_printNumD/F/H: fixed undefined behavior onINT_MINand a broken fraction extraction in the v1 code.FR_DEG2RAD/FR_RAD2DEG: macro bodies were swapped in v1. v2 fixes them and adds missing parentheses.
New functionality
- Radian-native trig:
fr_sin,fr_cos,fr_tan,fr_sin_bam,fr_cos_bam,fr_sin_deg,fr_cos_deg. Uses a new 129-entry quadrant cosine table with round-to-nearest linear interpolation. Max error ≤ 1 LSB of s0.15 (~3e−5). - BAM macros:
FR_DEG2BAM,FR_BAM2DEG,FR_RAD2BAM,FR_BAM2RAD. BAM (16 bits per full circle) is the natural integer representation for phase accumulators and gives zero quantization at the wraparound. - Square root and hypot:
FR_sqrtuses a digit-by-digit integer isqrt onint64_t;FR_hypotcomputessqrt(x² + y²)with no intermediate overflow across the fulls32range. - Wave generator family:
fr_wave_sqr,fr_wave_pwm,fr_wave_tri,fr_wave_saw,fr_wave_tri_morph,fr_wave_noise. All are stateless and take au16BAM phase. Suitable for embedded audio, LFOs, and control signals. - ADSR envelope generator: linear-segment attack/decay/sustain/release with s1.30 internal state so very long durations at high sample rates still have non-zero per-sample increments.
- Compile-time table size:
-DFR_TRIG_TABLE_BITS=8doubles table precision at the cost of a larger (257-entry) table. Default is 7 / 129 entries.
New documentation
- API Reference — complete per-symbol reference with inputs, outputs, radix handling, and worst-case error.
CONTRIBUTING.md— PR expectations, portability rules, commit format.tools/interp_analysis.html— interactive Chart.js comparison of seven interpolation methods on the trig table.- This documentation site (the one you’re reading).
Breaking changes
FR_NUM(i, f, r)→FR_NUM(i, f, d, r). The v1 form was broken (it ignoredfentirely), so any caller was already getting wrong results.FR_atan2(y, x, radix)→FR_atan2(y, x). Theradixparameter was vestigial.FR_RESULTand theFR_E_*codes are gone.inv()returnsbool;add()/sub()/setrotate()returnvoid. Math functions use named sentinelsFR_DOMAIN_ERROR,FR_OVERFLOW_POS,FR_OVERFLOW_NEG.FR_SQUAREandFR_FIXMUL32uremoved — useFR_FixMuls/FR_FixMulSat, which now have anint64_tfast path and work at any radix.FR_NO_INT64andFR_NO_STDINTbuild flags removed. Every modern C99 toolchain ships<stdint.h>and 64-bit arithmetic.
Test suite
v2 ships with a full test suite covering 99% of library
source lines, plus a characterization suite (test_tdd.cpp)
that pins numerical behavior to bit-exact reference values.
v1.0.3 — 2025
Test-coverage release. Overall line coverage went from 4% to 72%
with four new test files
(test_comprehensive.c,
test_overflow_saturation.c,
test_full_coverage.c,
test_2d_complete.cpp). Added a GitHub Actions CI with
multi-platform (Linux, macOS) and multi-compiler (gcc, clang)
matrices, cross-compilation for ARM and RISC-V, and 32-bit
compatibility testing.
Also fixed a broken FR_atan implementation, corrected
FR_PI / FR_2PI / FR_E
declarations to use const, and fixed
XFormPtI test assumptions.
v1.02 — first public release
Basic fixed-point operations, 2D transforms, and integer-degree trigonometry. This is the version that shipped inside the original Palm Pilot Inkstorm application.
v1.01 — internal development
Naming conventions cleanup and an initial test framework. Never released publicly.
Timeline
FR_Math has been in continuous service since 2000, when it was written to run 2D graphics transforms on 16 MHz 68k Palm Pilots for Trumpetsoft’s Inkstorm. It has since been ported to ARM, x86, MIPS, RISC-V, and a menagerie of 8- and 16-bit embedded targets. The current release has a full test suite, a bit-exact numerical specification, and CI on every push.