Skip to content

Releases: deftio/fr_math

FR_Math 2.0.8

05 May 02:51
9286efb

Choose a tag to compare

FR_Math Release Notes

Version 2.0.8 (2026)

Tangent accuracy rewrite and trig rounding fix.

BAM-native tangent table

  • New fr_tan_bam(u16 bam) function with a dedicated 65-entry octant
    lookup table (gFR_TAN_TAB_O in FR_trig_table.h, 130 bytes ROM).
    First octant uses direct table + lerp; second octant uses the
    reciprocal identity tan(x) = 1/tan(90-x) with one 32-bit division.
    No 64-bit intermediates anywhere in the tan path.
  • FR_TanI, FR_Tan, fr_tan are now thin wrappers over
    fr_tan_bam. The old sin/cos division implementation is removed.
  • Peak error: 0.17% (BAM), 0.60% (deg r7), 0.17% (rad r16).

Round-to-nearest fix for radian/degree wrappers

  • fr_cos, fr_sin, fr_tan, FR_Cos, FR_Sin, FR_Tan now add
    0.5 LSB (1 << (radix-1)) before the >> radix shift when converting
    from radians/degrees to BAM. This rounds to the nearest BAM value
    instead of truncating, eliminating a systematic 1-BAM rounding error
    that caused ~1% peak error near zero crossings.
  • Radian-path sin/cos/tan now match BAM-native accuracy (0.16-0.17%
    peak, was ~1.03%).

Conversion macro trimming

  • FR_DEG2BAM: 10 terms (~28 bits) reduced to 7 terms (~18 bits)
  • FR_RAD2BAM: 9 terms (~27 bits) reduced to 7 terms (~21 bits)
  • FR_DEG2RAD: 3 terms (~13 bits) extended to 5 terms (~17 bits)
  • 18 bits of precision gives 4 bits of headroom over the 14-bit
    effective BAM resolution of the trig tables. Verified: reverting to
    the old full-precision macros changes sin/cos peak error by <0.04%.

Other

  • FR_TRIG_MINVAL fixed: was -FR_TRIG_MASK (-65535), now
    -FR_TRIG_MAXVAL (-2147483647) to properly pair with FR_TRIG_MAXVAL
    for tan saturation clamping.
  • Accuracy table in all docs now shows separate BAM/deg/rad rows for
    sin/cos and tan, matching the TDD characterization report.
  • fr_tan_bam added to function listings across README, docs, HTML
    pages, and llms.txt.

Version 2.0.7 (2026)

README restructure, accuracy table cleanup, and expanded cross-compile support.

New: FR_CORE_ONLY convenience define

A single #define FR_CORE_ONLY before including FR_math.h (or -DFR_CORE_ONLY
on the command line) now strips both print helpers and wave generators in one step.
It expands to FR_NO_PRINT + FR_NO_WAVES internally.

Accuracy table cleanup

The LSB column has been removed from the accuracy table output. Percent error
is the metric that matters to callers; LSB error is an implementation detail
that varies with the chosen radix.

Expanded cross-compile targets

  • RP2040 (Cortex-M0+) and STM32 (Cortex-M4) added as named targets
    in the Docker cross-build
  • 68HC11 and MIPS32 toolchains added to the Docker image
  • Size table now shows three columns: Lean, Core, and Full
  • Consolidated scripts/crossbuild_sizes.sh — single script runs Docker,
    builds all targets, writes CSV + markdown, and patches doc files
    (replaces crossbuild-docker.sh, size_report.sh, update_sizes.sh)
  • Size table sorted by architecture width (8-bit → 64-bit)

README restructure

Sections reordered: accuracy table moved above the size table to lead with
the library's primary selling point. Badges cleaned up from Quikdown HTML to
standard markdown syntax. Build flavor descriptions made more concise.


Version 2.0.6 (2026)

Accuracy improvements, lean-build options, and library cleanup.

Accuracy & algorithms

  • FR_acos boundary fix: deferred quantization computes 1-x at the
    caller's radix instead of r15, giving 12x better accuracy near ±1.0
    (max LSB error 512.6 → 42.3)
  • FR_atan2 rewrite: uses asin/acos + hypot_fast8 with octant
    switching for well-conditioned results everywhere (0.41% peak vs
    20% for libfixmath)

Lean build options

Two new compile-time #define guards strip optional subsystems for
ROM-constrained targets:

Define Removes Savings
FR_NO_PRINT FR_printNumF/D/H, FR_numstr ~1.3 KB
FR_NO_WAVES fr_wave_*, fr_adsr_*, FR_HZ2BAM_INC ~0.6 KB

With both guards the core math library compiles to ~3.5 KB on x86-64
(clang -Os), roughly 2.6 KB on Thumb-2.

Removed

  • FR_hypot_fast (4-segment) deleted — FR_hypot_fast8 (8-segment)
    is strictly better in both accuracy (0.10% vs 0.34%) and is used
    internally by FR_atan2. The 4-segment variant was dead weight.

Other

  • libfixmath comparison benchmark (compare_lfm/) added to repo
  • Documentation updated across all markdown and HTML pages

Version 2.0.5 (2026)

Release pipeline fixes. No functional changes to the math library.

  • Fixed tools/make_release.sh failing after squash-merge: local master
    diverges from origin (squash creates a new commit), so git pull --ff-only fails. Now detects divergence and resets to origin/master.
  • Fixed on-master release path: script now pushes master to origin and
    waits for CI before tagging (previously skipped both, causing tags to
    point at commits not yet on the remote).
  • Release pipeline auto-commits pipeline-generated changes (badge
    updates, version sync) instead of failing on a dirty working tree.
    Unexpected dirty files still block the release.

Version 2.0.4 (2026)

CI fix release. No functional changes to the math library.

  • Fixed release.yml coverage step failing due to stale gcov invocation
  • Removed conflicting auto-release job from ci.yml (replaced by
    tag-triggered release.yml)
  • Documentation updated: release_management.md, docs/building.md,
    and pages/guide/building.html now accurately describe the guided
    release pipeline

Version 2.0.3 (2026)

CI and release pipeline cleanup. No functional changes to the math
library itself.

Release pipeline

  • New guided release script tools/make_release.sh (ported from xelp):
    validates, opens PR, waits for CI, merges, tags, waits for GitHub
    Release, then publishes to PlatformIO and ESP-IDF registries
  • Removed old scripts/make_release.sh (validation-only, manual merge)
  • All doc/page references updated to tools/make_release.sh
  • Cleaned up stale branches

Version 2.0.2 (2026)

Embedded library publishing support. No functional changes to the
math library itself — this release adds package manager integration
and improves example organization.

Library publishing

  • Added library.properties for Arduino Library Manager
  • Added library.json for PlatformIO Registry
  • Added idf_component.yml + CMakeLists.txt for ESP-IDF Component Registry
  • Added keywords.txt for Arduino IDE syntax highlighting
  • Added .github/workflows/release.yml for tag-triggered release validation

Examples reorganized

  • New focused Arduino sketches: basic-math, trig-functions, wave-generators
  • Moved FR_Math_Example1.cpp to examples/posix-example/
  • Removed symlinks from examples/arduino_smoke/ (Arduino forbids symlinks)
  • Added examples/README.md

Documentation

  • Added llms.txt — machine-readable API summary for AI coding agents
  • Added agents.md — coding agent conventions and contribution guide
  • Added dev/misc/ publish checklists for Arduino, PlatformIO, and ESP-IDF
  • Updated scripts/sync_version.sh to sync version across all new metadata files
  • Added release step 11: verify llms.txt and agents.md are current

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

Breaking changes from v2.0.0

| Change | v2.0.0 | v2.0.1 |
|----...

Read more

FR_Math 2.0.7

26 Apr 21:02
5df9b79

Choose a tag to compare

FR_Math Release Notes

Version 2.0.7 (2026)

README restructure, accuracy table cleanup, and expanded cross-compile support.

New: FR_CORE_ONLY convenience define

A single #define FR_CORE_ONLY before including FR_math.h (or -DFR_CORE_ONLY
on the command line) now strips both print helpers and wave generators in one step.
It expands to FR_NO_PRINT + FR_NO_WAVES internally.

Accuracy table cleanup

The LSB column has been removed from the accuracy table output. Percent error
is the metric that matters to callers; LSB error is an implementation detail
that varies with the chosen radix.

Expanded cross-compile targets

  • RP2040 (Cortex-M0+) and STM32 (Cortex-M4) added as named targets
    in the Docker cross-build
  • 68HC11 toolchain added to the Docker image
  • Size table now shows two columns: Core (-DFR_CORE_ONLY) and Full
  • docker/build_sizes.sh outputs build/sizes.csv for automated patching
  • New scripts/update_sizes.sh auto-patches size tables into README, docs,
    and HTML pages

README restructure

Sections reordered: accuracy table moved above the size table to lead with
the library's primary selling point. Size table now shows Core vs Full columns.


Version 2.0.6 (2026)

Accuracy improvements, lean-build options, and library cleanup.

Accuracy & algorithms

  • FR_acos boundary fix: deferred quantization computes 1-x at the
    caller's radix instead of r15, giving 12x better accuracy near ±1.0
    (max LSB error 512.6 → 42.3)
  • FR_atan2 rewrite: uses asin/acos + hypot_fast8 with octant
    switching for well-conditioned results everywhere (0.41% peak vs
    20% for libfixmath)

Lean build options

Two new compile-time #define guards strip optional subsystems for
ROM-constrained targets:

Define Removes Savings
FR_NO_PRINT FR_printNumF/D/H, FR_numstr ~1.3 KB
FR_NO_WAVES fr_wave_*, fr_adsr_*, FR_HZ2BAM_INC ~0.6 KB

With both guards the core math library compiles to ~3.5 KB on x86-64
(clang -Os), roughly 2.6 KB on Thumb-2.

Removed

  • FR_hypot_fast (4-segment) deleted — FR_hypot_fast8 (8-segment)
    is strictly better in both accuracy (0.10% vs 0.34%) and is used
    internally by FR_atan2. The 4-segment variant was dead weight.

Other

  • libfixmath comparison benchmark (compare_lfm/) added to repo
  • Documentation updated across all markdown and HTML pages

Version 2.0.5 (2026)

Release pipeline fixes. No functional changes to the math library.

  • Fixed tools/make_release.sh failing after squash-merge: local master
    diverges from origin (squash creates a new commit), so git pull --ff-only fails. Now detects divergence and resets to origin/master.
  • Fixed on-master release path: script now pushes master to origin and
    waits for CI before tagging (previously skipped both, causing tags to
    point at commits not yet on the remote).
  • Release pipeline auto-commits pipeline-generated changes (badge
    updates, version sync) instead of failing on a dirty working tree.
    Unexpected dirty files still block the release.

Version 2.0.4 (2026)

CI fix release. No functional changes to the math library.

  • Fixed release.yml coverage step failing due to stale gcov invocation
  • Removed conflicting auto-release job from ci.yml (replaced by
    tag-triggered release.yml)
  • Documentation updated: release_management.md, docs/building.md,
    and pages/guide/building.html now accurately describe the guided
    release pipeline

Version 2.0.3 (2026)

CI and release pipeline cleanup. No functional changes to the math
library itself.

Release pipeline

  • New guided release script tools/make_release.sh (ported from xelp):
    validates, opens PR, waits for CI, merges, tags, waits for GitHub
    Release, then publishes to PlatformIO and ESP-IDF registries
  • Removed old scripts/make_release.sh (validation-only, manual merge)
  • All doc/page references updated to tools/make_release.sh
  • Cleaned up stale branches

Version 2.0.2 (2026)

Embedded library publishing support. No functional changes to the
math library itself — this release adds package manager integration
and improves example organization.

Library publishing

  • Added library.properties for Arduino Library Manager
  • Added library.json for PlatformIO Registry
  • Added idf_component.yml + CMakeLists.txt for ESP-IDF Component Registry
  • Added keywords.txt for Arduino IDE syntax highlighting
  • Added .github/workflows/release.yml for tag-triggered release validation

Examples reorganized

  • New focused Arduino sketches: basic-math, trig-functions, wave-generators
  • Moved FR_Math_Example1.cpp to examples/posix-example/
  • Removed symlinks from examples/arduino_smoke/ (Arduino forbids symlinks)
  • Added examples/README.md

Documentation

  • Added llms.txt — machine-readable API summary for AI coding agents
  • Added agents.md — coding agent conventions and contribution guide
  • Added dev/misc/ publish checklists for Arduino, PlatformIO, and ESP-IDF
  • Updated scripts/sync_version.sh to sync version across all new metadata files
  • Added release step 11: verify llms.txt and agents.md are current

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

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 behaviour)

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was miss...
Read more

FR_Math 2.0.6

25 Apr 17:40
be1f14b

Choose a tag to compare

FR_Math Release Notes

Version 2.0.6 (2026)

Accuracy improvements, lean-build options, and library cleanup.

Accuracy & algorithms

  • FR_acos boundary fix: deferred quantization computes 1-x at the
    caller's radix instead of r15, giving 12x better accuracy near ±1.0
    (max LSB error 512.6 → 42.3)
  • FR_atan2 rewrite: uses asin/acos + hypot_fast8 with octant
    switching for well-conditioned results everywhere (0.41% peak vs
    20% for libfixmath)

Lean build options

Two new compile-time #define guards strip optional subsystems for
ROM-constrained targets:

Define Removes Savings
FR_NO_PRINT FR_printNumF/D/H, FR_numstr ~1.3 KB
FR_NO_WAVES fr_wave_*, fr_adsr_*, FR_HZ2BAM_INC ~0.6 KB

With both guards the core math library compiles to ~3.5 KB on x86-64
(clang -Os), roughly 2.6 KB on Thumb-2.

Removed

  • FR_hypot_fast (4-segment) deleted — FR_hypot_fast8 (8-segment)
    is strictly better in both accuracy (0.10% vs 0.34%) and is used
    internally by FR_atan2. The 4-segment variant was dead weight.

Other

  • libfixmath comparison benchmark (compare_lfm/) added to repo
  • Documentation updated across all markdown and HTML pages

Version 2.0.5 (2026)

Release pipeline fixes. No functional changes to the math library.

  • Fixed tools/make_release.sh failing after squash-merge: local master
    diverges from origin (squash creates a new commit), so git pull --ff-only fails. Now detects divergence and resets to origin/master.
  • Fixed on-master release path: script now pushes master to origin and
    waits for CI before tagging (previously skipped both, causing tags to
    point at commits not yet on the remote).
  • Release pipeline auto-commits pipeline-generated changes (badge
    updates, version sync) instead of failing on a dirty working tree.
    Unexpected dirty files still block the release.

Version 2.0.4 (2026)

CI fix release. No functional changes to the math library.

  • Fixed release.yml coverage step failing due to stale gcov invocation
  • Removed conflicting auto-release job from ci.yml (replaced by
    tag-triggered release.yml)
  • Documentation updated: release_management.md, docs/building.md,
    and pages/guide/building.html now accurately describe the guided
    release pipeline

Version 2.0.3 (2026)

CI and release pipeline cleanup. No functional changes to the math
library itself.

Release pipeline

  • New guided release script tools/make_release.sh (ported from xelp):
    validates, opens PR, waits for CI, merges, tags, waits for GitHub
    Release, then publishes to PlatformIO and ESP-IDF registries
  • Removed old scripts/make_release.sh (validation-only, manual merge)
  • All doc/page references updated to tools/make_release.sh
  • Cleaned up stale branches

Version 2.0.2 (2026)

Embedded library publishing support. No functional changes to the
math library itself — this release adds package manager integration
and improves example organization.

Library publishing

  • Added library.properties for Arduino Library Manager
  • Added library.json for PlatformIO Registry
  • Added idf_component.yml + CMakeLists.txt for ESP-IDF Component Registry
  • Added keywords.txt for Arduino IDE syntax highlighting
  • Added .github/workflows/release.yml for tag-triggered release validation

Examples reorganized

  • New focused Arduino sketches: basic-math, trig-functions, wave-generators
  • Moved FR_Math_Example1.cpp to examples/posix-example/
  • Removed symlinks from examples/arduino_smoke/ (Arduino forbids symlinks)
  • Added examples/README.md

Documentation

  • Added llms.txt — machine-readable API summary for AI coding agents
  • Added agents.md — coding agent conventions and contribution guide
  • Added dev/misc/ publish checklists for Arduino, PlatformIO, and ESP-IDF
  • Updated scripts/sync_version.sh to sync version across all new metadata files
  • Added release step 11: verify llms.txt and agents.md are current

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

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 behaviour)

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was missing the accumulator in the mantissa-table
    step and returned wrong values for non-power-of-2 inputs. v2 rewrites
    the algorithm: leading-bit-position → normalize to s1.30 → 33-entry
    mantissa lookup with linear interpolation.
  • FR_ln / FR_log10: inherit the FR_log2 fix automatically
    (they are multiplies of FR_log2 by a constant).
  • FR_pow2: v1 used C truncation toward zero to extract the integer
    exponent, which gave wrong answers for negative non-integer inputs
    (e.g. FR_pow2(-0.5) returned ~2 instead of ~0.707). v2 uses
    mathematical floor (toward −∞) and a 17-entry fraction table with
    linear interp.
  • FR_atan2: v1 was a placeholder that returned garbage. v2 is a
    correct octant-reduced arctan with a 33-entry table. Max error ≤ 1°.
    v2 also drops the vestigial radix parameter — new signature is
    FR_atan2(s32 y, s32 x).
  • FR_atan: v1 was wired up incorrectly. v2 implements as
    FR_atan2(input, 1<<radix).
  • FR_Tan: v1 used s16 loop variables that overflowed for angles
    near 90°. v2 uses s32.
  • FR_TanI: removed dead unreachable code (if (270 == deg)).
  • FR_printNumD: v1 invoked unary minus on INT_MIN, which is
    undefined behavi...
Read more

FR_Math 2.0.5

20 Apr 06:58
20bd4c1

Choose a tag to compare

FR_Math Release Notes

Version 2.0.5 (2026)

Release pipeline fixes. No functional changes to the math library.

  • Fixed tools/make_release.sh failing after squash-merge: local master
    diverges from origin (squash creates a new commit), so git pull --ff-only fails. Now detects divergence and resets to origin/master.
  • Fixed on-master release path: script now pushes master to origin and
    waits for CI before tagging (previously skipped both, causing tags to
    point at commits not yet on the remote).
  • Release pipeline auto-commits pipeline-generated changes (badge
    updates, version sync) instead of failing on a dirty working tree.
    Unexpected dirty files still block the release.

Version 2.0.4 (2026)

CI fix release. No functional changes to the math library.

  • Fixed release.yml coverage step failing due to stale gcov invocation
  • Removed conflicting auto-release job from ci.yml (replaced by
    tag-triggered release.yml)
  • Documentation updated: release_management.md, docs/building.md,
    and pages/guide/building.html now accurately describe the guided
    release pipeline

Version 2.0.3 (2026)

CI and release pipeline cleanup. No functional changes to the math
library itself.

Release pipeline

  • New guided release script tools/make_release.sh (ported from xelp):
    validates, opens PR, waits for CI, merges, tags, waits for GitHub
    Release, then publishes to PlatformIO and ESP-IDF registries
  • Removed old scripts/make_release.sh (validation-only, manual merge)
  • All doc/page references updated to tools/make_release.sh
  • Cleaned up stale branches

Version 2.0.2 (2026)

Embedded library publishing support. No functional changes to the
math library itself — this release adds package manager integration
and improves example organization.

Library publishing

  • Added library.properties for Arduino Library Manager
  • Added library.json for PlatformIO Registry
  • Added idf_component.yml + CMakeLists.txt for ESP-IDF Component Registry
  • Added keywords.txt for Arduino IDE syntax highlighting
  • Added .github/workflows/release.yml for tag-triggered release validation

Examples reorganized

  • New focused Arduino sketches: basic-math, trig-functions, wave-generators
  • Moved FR_Math_Example1.cpp to examples/posix-example/
  • Removed symlinks from examples/arduino_smoke/ (Arduino forbids symlinks)
  • Added examples/README.md

Documentation

  • Added llms.txt — machine-readable API summary for AI coding agents
  • Added agents.md — coding agent conventions and contribution guide
  • Added dev/misc/ publish checklists for Arduino, PlatformIO, and ESP-IDF
  • Updated scripts/sync_version.sh to sync version across all new metadata files
  • Added release step 11: verify llms.txt and agents.md are current

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

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 behaviour)

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was missing the accumulator in the mantissa-table
    step and returned wrong values for non-power-of-2 inputs. v2 rewrites
    the algorithm: leading-bit-position → normalize to s1.30 → 33-entry
    mantissa lookup with linear interpolation.
  • FR_ln / FR_log10: inherit the FR_log2 fix automatically
    (they are multiplies of FR_log2 by a constant).
  • FR_pow2: v1 used C truncation toward zero to extract the integer
    exponent, which gave wrong answers for negative non-integer inputs
    (e.g. FR_pow2(-0.5) returned ~2 instead of ~0.707). v2 uses
    mathematical floor (toward −∞) and a 17-entry fraction table with
    linear interp.
  • FR_atan2: v1 was a placeholder that returned garbage. v2 is a
    correct octant-reduced arctan with a 33-entry table. Max error ≤ 1°.
    v2 also drops the vestigial radix parameter — new signature is
    FR_atan2(s32 y, s32 x).
  • FR_atan: v1 was wired up incorrectly. v2 implements as
    FR_atan2(input, 1<<radix).
  • FR_Tan: v1 used s16 loop variables that overflowed for angles
    near 90°. v2 uses s32.
  • FR_TanI: removed dead unreachable code (if (270 == deg)).
  • FR_printNumD: v1 invoked unary minus on INT_MIN, which is
    undefined behavior, and always returned 0. v2 works in unsigned
    magnitude and returns the real byte count (or −1 on null f).
  • FR_printNumF: same INT_MIN fix, plus v1's fraction extraction
    was mathematically wrong and printed bogus tail digits.
  • FR_printNumH: v1 shifted a signed negative int right. v2 casts
    to unsigned first.

Macro fixes

  • FR_DEG2RAD and FR_RAD2DEG: v1 had the macro bodies swapped
    relative to their names, so FR_DEG2RAD(x) actually multiplied by
    57.3 and FR_RAD2DEG(x) multiplied by 0.017. v2 swaps them back.
    FR_DEG2RAD also had missing parens around x in a subexpression.
  • FR_NUM: v1 signature was FR_NUM(i, f, r) and the body ignored
    the f argument entirely. v2 adds an explicit d digit-count
    argument — new signature is FR_NUM(i, f, d, r). Any caller of the
    v1 form must be updated.

New functionality

  • Radian-native trig (fr_cos, fr_sin, fr_tan, fr_cos_bam,
    fr_sin_bam, fr_cos_deg, fr_sin_deg): takes radians (or BAM, or
    integer degrees) directly rather than forcing everything through
    integer degrees. Uses a new 129-entry s0.15 quadrant cosine table in
    src/FR_trig_table.h with linear interpolation and...
Read more

FR_Math 2.0.2

19 Apr 21:47

Choose a tag to compare

FR_Math Release Notes

Version 2.0.2 (2026)

Embedded library publishing support. No functional changes to the
math library itself — this release adds package manager integration
and improves example organization.

Library publishing

  • Added library.properties for Arduino Library Manager
  • Added library.json for PlatformIO Registry
  • Added idf_component.yml + CMakeLists.txt for ESP-IDF Component Registry
  • Added keywords.txt for Arduino IDE syntax highlighting
  • Added .github/workflows/release.yml for tag-triggered release validation

Examples reorganized

  • New focused Arduino sketches: basic-math, trig-functions, wave-generators
  • Moved FR_Math_Example1.cpp to examples/posix-example/
  • Removed symlinks from examples/arduino_smoke/ (Arduino forbids symlinks)
  • Added examples/README.md

Documentation

  • Added llms.txt — machine-readable API summary for AI coding agents
  • Added agents.md — coding agent conventions and contribution guide
  • Added dev/misc/ publish checklists for Arduino, PlatformIO, and ESP-IDF
  • Updated scripts/sync_version.sh to sync version across all new metadata files
  • Added release step 11: verify llms.txt and agents.md are current

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

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 behaviour)

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was missing the accumulator in the mantissa-table
    step and returned wrong values for non-power-of-2 inputs. v2 rewrites
    the algorithm: leading-bit-position → normalize to s1.30 → 33-entry
    mantissa lookup with linear interpolation.
  • FR_ln / FR_log10: inherit the FR_log2 fix automatically
    (they are multiplies of FR_log2 by a constant).
  • FR_pow2: v1 used C truncation toward zero to extract the integer
    exponent, which gave wrong answers for negative non-integer inputs
    (e.g. FR_pow2(-0.5) returned ~2 instead of ~0.707). v2 uses
    mathematical floor (toward −∞) and a 17-entry fraction table with
    linear interp.
  • FR_atan2: v1 was a placeholder that returned garbage. v2 is a
    correct octant-reduced arctan with a 33-entry table. Max error ≤ 1°.
    v2 also drops the vestigial radix parameter — new signature is
    FR_atan2(s32 y, s32 x).
  • FR_atan: v1 was wired up incorrectly. v2 implements as
    FR_atan2(input, 1<<radix).
  • FR_Tan: v1 used s16 loop variables that overflowed for angles
    near 90°. v2 uses s32.
  • FR_TanI: removed dead unreachable code (if (270 == deg)).
  • FR_printNumD: v1 invoked unary minus on INT_MIN, which is
    undefined behavior, and always returned 0. v2 works in unsigned
    magnitude and returns the real byte count (or −1 on null f).
  • FR_printNumF: same INT_MIN fix, plus v1's fraction extraction
    was mathematically wrong and printed bogus tail digits.
  • FR_printNumH: v1 shifted a signed negative int right. v2 casts
    to unsigned first.

Macro fixes

  • FR_DEG2RAD and FR_RAD2DEG: v1 had the macro bodies swapped
    relative to their names, so FR_DEG2RAD(x) actually multiplied by
    57.3 and FR_RAD2DEG(x) multiplied by 0.017. v2 swaps them back.
    FR_DEG2RAD also had missing parens around x in a subexpression.
  • FR_NUM: v1 signature was FR_NUM(i, f, r) and the body ignored
    the f argument entirely. v2 adds an explicit d digit-count
    argument — new signature is FR_NUM(i, f, d, r). Any caller of the
    v1 form must be updated.

New functionality

  • Radian-native trig (fr_cos, fr_sin, fr_tan, fr_cos_bam,
    fr_sin_bam, fr_cos_deg, fr_sin_deg): takes radians (or BAM, or
    integer degrees) directly rather than forcing everything through
    integer degrees. Uses a new 129-entry s0.15 quadrant cosine table in
    src/FR_trig_table.h with linear interpolation and round-to-nearest.
    Max error ≤ 1 LSB of s0.15 (~3e−5). Mean error ~0.
  • BAM (Binary Angular Measure) macros: FR_DEG2BAM, FR_BAM2DEG,
    FR_RAD2BAM, FR_BAM2RAD. BAM is the natural integer representation
    for trig: 16 bits per full circle, top 2 bits select the quadrant,
    next 7 bits index the table, bottom 7 bits drive interpolation.
  • Table size is a compile-time knob: -DFR_TRIG_TABLE_BITS=8 gives
    a 257-entry table for halved worst-case error (default is 7 / 129
    entries).
  • Square root and hypot (FR_sqrt, FR_hypot): radix-aware fixed
    point square root and 2D vector magnitude. FR_sqrt uses a
    digit-by-digit (shift-and-subtract) integer isqrt on int64_t.
    Negative input returns FR_DOMAIN_ERROR (INT32_MIN). FR_hypot
    computes sqrt(x^2 + y^2) with no intermediate overflow up to the
    full s32 range. Bit-exact for perfect squares; max error ~1 LSB at
    the requested radix.
  • Fast approximate magnitude (FR_hypot_fast, FR_hypot_fast8):
    shift-only piecewise-linear approximation of sqrt(x^2 + y^2) — no
    multiply, no divide, no 64-bit math, no ROM table, no iteration.
    FR_hypot_fast uses 4 segments (~0.4% peak error);
    FR_hypot_fast8 uses 8 segments (~0.14% peak error). Based on the
    method of US Patent 6,567,777 B1 (Chatterjee, public domain). No
    radix parameter needed — the algorithm is scale-invariant.
  • Wave function family for embedded audio / LFOs / control
    signals. All take a u16 BAM phase and return s0.15 (s16, ±32767):
    • fr_wave_sqr(phase) — symmetric square wave.
    • fr_wave_pwm(phase, duty) — variabl...
Read more

FR_Math 2.0.1

16 Apr 02:31

Choose a tag to compare

FR_Math Release Notes

Version 2.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_bam now return s15.16 (was s0.15).
    Exact values at cardinal angles: cos(0°) = 65536, cos(90°) = 0.
    FR_TRIG_ONE = 65536.
  • FR_TanI / fr_tan return 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_atan gain an out_radix parameter
    and return radians at that radix (was degrees as s16).
  • FR_atan2(y, x, out_radix) also returns radians.
  • FR_BAM2RAD macro corrected (was off by a factor of 1024).

Rounding improvements

  • FR_FixMuls / FR_FixMulSat: add 0.5 LSB (+0x8000) before
    the >>16 shift. Both now round to nearest instead of
    truncating.
  • FR_sqrt / FR_hypot: the internal fr_isqrt64 now rounds to
    nearest (remainder > root → +1). Worst-case error drops from
    <1 LSB to ≤ 0.5 LSB.
  • FR_DIV now rounds to nearest (≤ 0.5 LSB error) instead of
    truncating. FR_DIV_TRUNC preserves the old truncating behaviour.

Improved exp / log accuracy

  • FR_pow2 table expanded from 17 entries (16 segments) to
    65 entries (64 segments, 260 bytes). Interpolation error drops
    by ~16×.
  • FR_log2 table expanded from 33 entries to 65 entries
    (6-bit index / 24-bit interpolation). Worst-case error ≤ 4 LSB
    at Q16.16.
  • FR_MULK28 macro 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_EXP and FR_POW10 now use FR_MULK28 for the base
    conversion instead of shift-only macros.
  • FR_ln and FR_log10 also use FR_MULK28 internally.
  • FR_EXP_FAST and FR_POW10_FAST added as shift-only
    alternatives for 8-bit targets where 64-bit multiply is
    expensive.

New symbols

  • FR_MIN, FR_MAX, FR_CLAMP — standard min/max/clamp.
  • FR_DIV_TRUNC(x, xr, y, yr) — truncating division (the old
    FR_DIV behaviour).
  • FR_MOD(x, xr, y, yr) — fixed-point modulus.
  • Radix-28 constants: FR_kLOG2E_28, FR_krLOG2E_28,
    FR_kLOG2_10_28, FR_krLOG2_10_28.

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 behaviour)

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was missing the accumulator in the mantissa-table
    step and returned wrong values for non-power-of-2 inputs. v2 rewrites
    the algorithm: leading-bit-position → normalize to s1.30 → 33-entry
    mantissa lookup with linear interpolation.
  • FR_ln / FR_log10: inherit the FR_log2 fix automatically
    (they are multiplies of FR_log2 by a constant).
  • FR_pow2: v1 used C truncation toward zero to extract the integer
    exponent, which gave wrong answers for negative non-integer inputs
    (e.g. FR_pow2(-0.5) returned ~2 instead of ~0.707). v2 uses
    mathematical floor (toward −∞) and a 17-entry fraction table with
    linear interp.
  • FR_atan2: v1 was a placeholder that returned garbage. v2 is a
    correct octant-reduced arctan with a 33-entry table. Max error ≤ 1°.
    v2 also drops the vestigial radix parameter — new signature is
    FR_atan2(s32 y, s32 x).
  • FR_atan: v1 was wired up incorrectly. v2 implements as
    FR_atan2(input, 1<<radix).
  • FR_Tan: v1 used s16 loop variables that overflowed for angles
    near 90°. v2 uses s32.
  • FR_TanI: removed dead unreachable code (if (270 == deg)).
  • FR_printNumD: v1 invoked unary minus on INT_MIN, which is
    undefined behavior, and always returned 0. v2 works in unsigned
    magnitude and returns the real byte count (or −1 on null f).
  • FR_printNumF: same INT_MIN fix, plus v1's fraction extraction
    was mathematically wrong and printed bogus tail digits.
  • FR_printNumH: v1 shifted a signed negative int right. v2 casts
    to unsigned first.

Macro fixes

  • FR_DEG2RAD and FR_RAD2DEG: v1 had the macro bodies swapped
    relative to their names, so FR_DEG2RAD(x) actually multiplied by
    57.3 and FR_RAD2DEG(x) multiplied by 0.017. v2 swaps them back.
    FR_DEG2RAD also had missing parens around x in a subexpression.
  • FR_NUM: v1 signature was FR_NUM(i, f, r) and the body ignored
    the f argument entirely. v2 adds an explicit d digit-count
    argument — new signature is FR_NUM(i, f, d, r). Any caller of the
    v1 form must be updated.

New functionality

  • Radian-native trig (fr_cos, fr_sin, fr_tan, fr_cos_bam,
    fr_sin_bam, fr_cos_deg, fr_sin_deg): takes radians (or BAM, or
    integer degrees) directly rather than forcing everything through
    integer degrees. Uses a new 129-entry s0.15 quadrant cosine table in
    src/FR_trig_table.h with linear interpolation and round-to-nearest.
    Max error ≤ 1 LSB of s0.15 (~3e−5). Mean error ~0.
  • BAM (Binary Angular Measure) macros: FR_DEG2BAM, FR_BAM2DEG,
    FR_RAD2BAM, FR_BAM2RAD. BAM is the natural integer representation
    for trig: 16 bits per full circle, top 2 bits select the quadrant,
    next 7 bits index the table, bottom 7 bits drive interpolation.
  • Table size is a compile-time knob: -DFR_TRIG_TABLE_BITS=8 gives
    a 257-entry table for halved worst-case error (default is 7 / 129
    entries).
  • Square root and hypot (FR_sqrt, FR_hypot): radix-aware fixed
    point square root and 2D vector magnitude. FR_sqrt uses a
    digit-by-digit (shift-and-subtract) integer isqrt on int64_t.
    Negative input returns FR_DOMAIN_ERROR (INT32_MIN). FR_hypot
    computes sqrt(x^2 + y^2) with no intermediate overflow up to the
    full s32 range. Bit-exact for perfect squares; max error ~1 LSB at
    the requested radix.
  • Fast approximate magnitude (FR_hypot_fast, FR_hypot_fast8):
    shift-only piecewise-linear approximation of sqrt(x^2 + y^2) — no
    multiply, no divide, no 64-bit math, no ROM table, no iteration.
    FR_hypot_fast uses 4 segments (~0.4% peak error);
    FR_hypot_fast8 uses 8 segments (~0.14% peak error). Based on the
    method of US Patent 6,567,777 B1 (Chatterjee, public domain). No
    radix parameter needed — the algorithm is scale-invariant.
  • Wave function family for embedded audio / LFOs / control
    signals. All take a u16 BAM phase and return s0.15 (s16, ±32767):
    • fr_wave_sqr(phase) — symmetric square wave.
    • fr_wave_pwm(phase, duty) — variable-duty pulse wave; duty is
      a u16 threshold in BAM units.
    • fr_wave_tri(phase) — symmetric triangle, peaks clamped to
      ±32767. Max error vs ideal triangle ~3e−5 (1 LSB s0.15).
    • fr_wave_saw(phase) — sawtooth, (s16)(phase - 0x8000) with
      boundary clamp.
    • fr_wave_tri_morph(phase, break_point) — variable-symmetry
      triangle that morphs into a sawtooth as break_point approaches
      0 or 0xffff. Returns unipolar [0, 32767]. Uses one division
      per sample.
    • fr_wave_noise(state) — 32-bit Galois LFSR (poly 0xD0000001,
      period 2^32 − 1) returning a full-range s16. Caller owns the
      u32 state; seed with any non-zero value.
  • FR_HZ2BAM_INC(hz, sample_rate): phase increment helper.
    Computes hz * 65536 / sample_rate so a u16 phase accumulator
    driven by this increment produces the requested frequency. Example:
    FR_HZ2BAM_INC(440, 48000) = 600 (≈ 439.45 Hz).
  • ADSR envelope generator (fr_adsr_t, fr_adsr_init,
    fr_adsr_trigger, fr_adsr_release, fr_adsr_step): linear-segment
    attack/decay/sustain/release envelope. Internal levels are stored as
    s1.30 so very long durations (e.g. 48000-sample attack at 48 kHz)
    still get a non-zero p...
Read more

FR_Math 2.0.0

11 Apr 18:44

Choose a tag to compare

FR_Math Release Notes

Version 2.0.0 (2026)

This is a significant bug-fix and precision-improvement release. Several
v1 functions produced wrong numerical results on every platform due to
arithmetic bugs; others produced wrong results specifically on 64-bit
hosts because of a typedef choice. Every changed function is covered by
the TDD characterization suite in tests/test_tdd.cpp.

See dev/fr_math_precision.md for the full per-symbol reference
(inputs, outputs, precision, saturation) and dev/fr_math2_impl_plan.md
for the implementation plan this release executed.

64-bit safety (portability)

  • FR_defs.h: migrated typedefs to <stdint.h> (s8int8_t,
    s32int32_t, etc.). v1 defined s32 as signed long, which is
    64 bits on LP64 platforms (Linux and macOS on x64 / ARM64), so every
    fixed-point computation that relied on s32 being exactly 32 bits
    silently produced wrong answers on desktop Linux and macOS. C99
    <stdint.h> is now mandatory in v2 (every modern toolchain — gcc,
    clang, MSVC, IAR, Keil C51, sdcc, MSP430-gcc, AVR-gcc, RISC-V/ARM —
    ships it). If you are stuck on a pre-C99 compiler, FR_Math 1.0.x
    remains the version for you.

Numerical fixes

  • FR_FixMulSat / FR_FixMuls: v1 used a split-multiply formula
    with an algebraic bug that returned wrong values for certain sign
    combinations. v2 uses an int64_t fast path with explicit
    saturation.
  • FR_log2: v1 was missing the accumulator in the mantissa-table
    step and returned wrong values for non-power-of-2 inputs. v2 rewrites
    the algorithm: leading-bit-position → normalize to s1.30 → 33-entry
    mantissa lookup with linear interpolation.
  • FR_ln / FR_log10: inherit the FR_log2 fix automatically
    (they are multiplies of FR_log2 by a constant).
  • FR_pow2: v1 used C truncation toward zero to extract the integer
    exponent, which gave wrong answers for negative non-integer inputs
    (e.g. FR_pow2(-0.5) returned ~2 instead of ~0.707). v2 uses
    mathematical floor (toward −∞) and a 17-entry fraction table with
    linear interp.
  • FR_atan2: v1 was a placeholder that returned garbage. v2 is a
    correct octant-reduced arctan with a 33-entry table. Max error ≤ 1°.
    v2 also drops the vestigial radix parameter — new signature is
    FR_atan2(s32 y, s32 x).
  • FR_atan: v1 was wired up incorrectly. v2 implements as
    FR_atan2(input, 1<<radix).
  • FR_Tan: v1 used s16 loop variables that overflowed for angles
    near 90°. v2 uses s32.
  • FR_TanI: removed dead unreachable code (if (270 == deg)).
  • FR_printNumD: v1 invoked unary minus on INT_MIN, which is
    undefined behavior, and always returned 0. v2 works in unsigned
    magnitude and returns the real byte count (or −1 on null f).
  • FR_printNumF: same INT_MIN fix, plus v1's fraction extraction
    was mathematically wrong and printed bogus tail digits.
  • FR_printNumH: v1 shifted a signed negative int right. v2 casts
    to unsigned first.

Macro fixes

  • FR_DEG2RAD and FR_RAD2DEG: v1 had the macro bodies swapped
    relative to their names, so FR_DEG2RAD(x) actually multiplied by
    57.3 and FR_RAD2DEG(x) multiplied by 0.017. v2 swaps them back.
    FR_DEG2RAD also had missing parens around x in a subexpression.
  • FR_NUM: v1 signature was FR_NUM(i, f, r) and the body ignored
    the f argument entirely. v2 adds an explicit d digit-count
    argument — new signature is FR_NUM(i, f, d, r). Any caller of the
    v1 form must be updated.

New functionality

  • Radian-native trig (fr_cos, fr_sin, fr_tan, fr_cos_bam,
    fr_sin_bam, fr_cos_deg, fr_sin_deg): takes radians (or BAM, or
    integer degrees) directly rather than forcing everything through
    integer degrees. Uses a new 129-entry s0.15 quadrant cosine table in
    src/FR_trig_table.h with linear interpolation and round-to-nearest.
    Max error ≤ 1 LSB of s0.15 (~3e−5). Mean error ~0.
  • BAM (Binary Angular Measure) macros: FR_DEG2BAM, FR_BAM2DEG,
    FR_RAD2BAM, FR_BAM2RAD. BAM is the natural integer representation
    for trig: 16 bits per full circle, top 2 bits select the quadrant,
    next 7 bits index the table, bottom 7 bits drive interpolation.
  • Table size is a compile-time knob: -DFR_TRIG_TABLE_BITS=8 gives
    a 257-entry table for halved worst-case error (default is 7 / 129
    entries).
  • Square root and hypot (FR_sqrt, FR_hypot): radix-aware fixed
    point square root and 2D vector magnitude. FR_sqrt uses a
    digit-by-digit (shift-and-subtract) integer isqrt on int64_t.
    Negative input returns FR_DOMAIN_ERROR (INT32_MIN). FR_hypot
    computes sqrt(x^2 + y^2) with no intermediate overflow up to the
    full s32 range. Bit-exact for perfect squares; max error ~1 LSB at
    the requested radix.
  • Fast approximate magnitude (FR_hypot_fast, FR_hypot_fast8):
    shift-only piecewise-linear approximation of sqrt(x^2 + y^2) — no
    multiply, no divide, no 64-bit math, no ROM table, no iteration.
    FR_hypot_fast uses 4 segments (~0.4% peak error);
    FR_hypot_fast8 uses 8 segments (~0.14% peak error). Based on the
    method of US Patent 6,567,777 B1 (Chatterjee, public domain). No
    radix parameter needed — the algorithm is scale-invariant.
  • Wave function family for embedded audio / LFOs / control
    signals. All take a u16 BAM phase and return s0.15 (s16, ±32767):
    • fr_wave_sqr(phase) — symmetric square wave.
    • fr_wave_pwm(phase, duty) — variable-duty pulse wave; duty is
      a u16 threshold in BAM units.
    • fr_wave_tri(phase) — symmetric triangle, peaks clamped to
      ±32767. Max error vs ideal triangle ~3e−5 (1 LSB s0.15).
    • fr_wave_saw(phase) — sawtooth, (s16)(phase - 0x8000) with
      boundary clamp.
    • fr_wave_tri_morph(phase, break_point) — variable-symmetry
      triangle that morphs into a sawtooth as break_point approaches
      0 or 0xffff. Returns unipolar [0, 32767]. Uses one division
      per sample.
    • fr_wave_noise(state) — 32-bit Galois LFSR (poly 0xD0000001,
      period 2^32 − 1) returning a full-range s16. Caller owns the
      u32 state; seed with any non-zero value.
  • FR_HZ2BAM_INC(hz, sample_rate): phase increment helper.
    Computes hz * 65536 / sample_rate so a u16 phase accumulator
    driven by this increment produces the requested frequency. Example:
    FR_HZ2BAM_INC(440, 48000) = 600 (≈ 439.45 Hz).
  • ADSR envelope generator (fr_adsr_t, fr_adsr_init,
    fr_adsr_trigger, fr_adsr_release, fr_adsr_step): linear-segment
    attack/decay/sustain/release envelope. Internal levels are stored as
    s1.30 so very long durations (e.g. 48000-sample attack at 48 kHz)
    still get a non-zero per-sample increment; fr_adsr_step returns
    s0.15 for direct multiplication into a wave sample. State machine
    exposes constants FR_ADSR_IDLE / _ATTACK / _DECAY / _SUSTAIN
    / _RELEASE.

New documentation

  • dev/fr_math_precision.md — comprehensive per-symbol precision
    reference. Every public macro, constant, and function is documented
    with inputs, output format, worst-case error, saturation behavior,
    and side-effect notes.
  • CONTRIBUTING.md — PR expectations, test discipline, portability
    rules, commit message format.
  • tools/interp_analysis.html — interactive Chart.js analysis of
    trig interpolation methods. Compares nearest-neighbor, linear
    truncated, linear rounded, cosine interp, smoothstep, Hermite cubic,
    and Catmull-Rom on the same 129-entry table, over θ ∈ [−45°, +45°].
    Includes pan/zoom on a second chart showing the actual interpolated
    values vs Math.cos reference. Use this to verify interpolation
    claims and to pick a default for the library.
  • scripts/clean_build.sh — one-shot clean of build/ and
    coverage/ directories. Handy when switching branches or debugging
    stale object files.

Breaking changes

  • FR_NUM signature: FR_NUM(i, f, r)FR_NUM(i, f, d, r). Any
    code that called the 3-argument form will fail to compile. The old
    form was broken (it ignored f entirely), so any caller was already
    getting wrong results.
  • FR_atan2 signature: FR_atan2(y, x, radix)FR_atan2(y, x).
    The radix parameter was vestigial (ignored by the v1 placeholder and
    unnecessary in v2).
  • FR_RESULT and FR_E_* codes removed: v1's HRESULT-style return
    codes are gone. The matrix inv() methods now return bool
    (true on success, false if singular). add(), sub(), and
    setrotate() return void. Math functions that can hit a domain
    error return the named sentinel FR_DOMAIN_ERROR; saturating
    arithmetic returns FR_OVERFLOW_POS / FR_OVERFLOW_NEG.
  • FR_SQUARE and FR_FIXMUL32u removed: these s16.16-only macros
    were narrow specializations of FR_FixMuls/FR_FixMulSat. Use the
    generic versions, which now have an int64_t fast path and work at
    any radix.
  • FR_NO_INT64 and FR_NO_STDINT build flags removed: every
    C99-or-newer toolchain on every architecture (including 8-bit
    targets like sdcc, AVR-gcc, MSP430-gcc) provides <stdint.h> and
    64-bit integer arithmetic, so the conditional fallbacks were
    carrying their weight in maintenance and ROM for no benefit.
  • Wider intermediate types: if you had code that poked at s32 as
    if it were long (e.g. printing with %ld), that will now warn.
    Use %d with s32 / int32_t, or cast.

Version 1.0.3 (2025)

Test Coverage Improvements

  • Increased overall test coverage from 4% to 72%
    • FR_math.c: 60% coverage
    • FR_math_2D.cpp: 98% coverage
  • Added comprehensive test suite with multiple test files:
    • test_comprehensive.c - Comprehensive tests for core math functions
    • test_overflow_saturation.c - Edge case an...
Read more

FR_Math v1.0.3

25 Aug 02:07

Choose a tag to compare

FR_Math Release Notes

Version 1.0.3 (2025)

Test Coverage Improvements

  • Increased overall test coverage from 4% to 72%
    • FR_math.c: 60% coverage
    • FR_math_2D.cpp: 98% coverage
  • Added comprehensive test suite with multiple test files:
    • test_comprehensive.c - Comprehensive tests for core math functions
    • test_overflow_saturation.c - Edge case and overflow behavior tests
    • test_full_coverage.c - Tests for previously uncovered functions
    • test_2d_complete.cpp - Complete 2D transformation matrix tests
  • Fixed test failures in 2D transformation tests (XFormPtI now correctly expects integer inputs)

Bug Fixes

  • Fixed FR_atan function - Was incorrectly calling FR_atan2 with wrong arguments, now properly calls FR_atanI
  • Fixed constant declarations - Changed FR_PI, FR_2PI, FR_E from non-const to proper const declarations
  • Fixed XFormPtI test assumptions - Tests were incorrectly passing fixed-point values instead of integers

Build System Enhancements

  • Added comprehensive Makefile targets:
    • make lib - Build static library
    • make test - Run all tests
    • make coverage - Generate coverage reports with lcov
    • make examples - Build example programs
    • make clean - Clean build artifacts
  • Added GitHub Actions CI/CD:
    • Multi-platform testing (Ubuntu, macOS)
    • Multi-compiler support (gcc, clang)
    • Cross-compilation testing (ARM, RISC-V)
    • 32-bit compatibility testing
    • Automated coverage reporting to Codecov
    • Overflow and saturation testing with sanitizers

Documentation Improvements

  • Cleaned up README.md:
    • Fixed grammar and spelling throughout
    • Added "Building and Testing" section with clear instructions
    • Improved formatting with consistent markdown usage
    • Added supported platforms list
    • Better code examples with syntax highlighting
    • Clearer mathematical notation and explanations
  • Added CLAUDE.md - Assistant-friendly documentation with:
    • Project structure overview
    • Key concepts and math notation explained
    • Testing and linting commands
    • Common pitfalls and tips
  • Added inline documentation for test files explaining coverage goals

Code Quality

  • Removed unused/unimplemented functions:
    • Removed FR_atan declaration (was declared but never implemented)
    • Cleaned up test code to remove references to non-existent functions
  • Fixed compiler warnings:
    • Resolved deprecated C++ warnings
    • Fixed format string warnings in tests
    • Addressed unused variable warnings
  • Improved code organization:
    • Better separation of test types
    • Clearer test naming conventions
    • More maintainable test structure

Platform Support

  • Verified compilation and testing on:
    • x86/x64 (Linux, macOS)
    • ARM (32-bit and 64-bit)
    • RISC-V
    • 32-bit x86 targets
  • Added cross-compilation support in CI

Version Updates

  • Updated all source file headers to version 1.0.3
  • Added version section to README.md

Previous Versions

Version 1.02

  • Initial public release
  • Basic fixed-point math operations
  • 2D transformation matrices
  • Core trigonometric functions

Version 1.01

  • Internal development version
  • Cleaned up naming conventions
  • Initial test framework

Note: FR_Math has been in development since 2000, originally used in embedded systems for Palm Pilots and later ARM cores. This is the first version with comprehensive testing and CI/CD integration.