Simple embedded math lib for motors, audio, dashboards and more. NO FPU or deps except stdint.
Project details
Need math support on your embedded target but don't have an FPU? Use FR_math - a fixed point library with trig, log, pow, wave-gen, and variable radix support for projects running on low end microcontrollers.
See: Documentation & Guide — for API reference, examples, fixed-point primer, build instructions.
FR_Math is a compact, integer-only fixed-point math library built for systems where floating point is too slow, too big, or unavailable. Designed for embedded targets ranging from legacy 16 MHz 68k processors to modern Cortex-M and RISC-V cores, it provides a full suite of math primitives — trigonometry, logarithms, roots, transforms, and signal generators — while remaining deterministic, portable, and small.
Unlike most fixed-point libraries, FR_Math lets the caller choose the binary point (radix) per operation, trading precision and range explicitly instead of locking into a single format. Pure C with C++ wrappers — compiles cleanly under C99, C11, C17, C++11 and later.
Compiles under Arduino, PlatformIO, Espressif, many older embedded targets.
Zero dependencies beyond <stdint.h>.
Note qf_math is the float32 version of this library with the same functions. If you have floating point support on your platform and want a faster, lighter version of libm consider that library.
Errors below are measured at Q16.16 (s15.16). All functions accept any radix — Q16.16 is just the reference point for the table.
At other radixes (3-bit, 24-bit, etc.) accuracy will differ due to the number of fractional bits available.
| Function | Max err (%)* | Avg err (%) | Note |
|---|---|---|---|
| sin/cos (BAM) | 0.1526 | 0.0030 | very fast binary angle trig |
| sin/cos (deg) | 0.1526 | 0.0029 | degree input trig fns |
| sin/cos (rad) | 0.1828 | 0.0033 | radian (traditional) trig |
| tan (BAM) | 0.5823 | 0.0008 | binary angle tangent; ±maxint at poles |
| tan (deg) | 0.5311 | 0.0008 | degree input tangent; saturated at poles |
| tan (rad) | 0.0386 | 0.0001 | radian (traditional) tangent |
| asin / acos | 0.7771 | 0.0280 | reverse trig, radian output |
| atan2 | 0.2564 | 0.0237 | reverse tangent, always safe |
| atan | 0.2425 | 0.0155 | reverse tangent, accepts up to maxint |
| sqrt | 0.0000 | 0.0000 | Round-to-nearest |
| log2 | 0.0116 | 0.0016 | shift/add only for speed |
| pow2 | 0.0018 | 0.0004 | shift/add only for speed |
| ln, log10 | 0.0004 | 0.0000 | shift/add only for speed |
| exp | 0.0003 | 0.0000 | shift/add only for speed |
| exp_fast | 0.0009 | 0.0001 | Shift-only scaling |
| pow10 | 0.0005 | 0.0000 | shift/add only for speed |
| pow10_fast | 0.0022 | 0.0002 | Shift-only scaling |
| hypot (exact) | 0.0000 | 0.0000 | Uses 64-bit intermediate |
| hypot_fast8 (8-seg) | 0.0915 | 0.0320 | Shift-only, no multiply |
*Relative error; reference clamped to 1% of full-scale output.
| Area | Functions |
|---|---|
| Arithmetic | FR_ADD, FR_SUB, FR_DIV, FR_DIV32, FR_MOD, FR_FixMuls, FR_FixMulSat, FR_CHRDX |
| Utility | FR_MIN, FR_MAX, FR_CLAMP, FR_ABS, FR_SGN |
| Trig (degree) | fr_sin_deg, fr_cos_deg, fr_tan_deg, FR_SinI, FR_CosI, FR_TanI |
| Trig (radian/BAM) | fr_sin, fr_cos, fr_tan, fr_sin_bam, fr_cos_bam, fr_tan_bam |
| Inverse trig | FR_atan, FR_atan2, FR_asin, FR_acos |
| Log / exp | FR_log2, FR_ln, FR_log10, FR_pow2, FR_EXP, FR_POW10, FR_EXP_FAST, FR_POW10_FAST, FR_MULK28 |
| Roots | FR_sqrt, FR_hypot, FR_hypot_fast8 |
| Wave generators | fr_wave_sqr, fr_wave_pwm, fr_wave_tri, fr_wave_saw, fr_wave_tri_morph, fr_wave_noise |
| Envelope | fr_adsr_init, fr_adsr_trigger, fr_adsr_release, fr_adsr_step |
| 2D transforms | FR_Matrix2D_CPT (mul, add, sub, det, inv, setrotate, XFormPtI, XFormPtI16) |
| Formatted output | FR_printNumD, FR_printNumF, FR_printNumH, FR_numstr |
.text section sizes, all code + internal tables, ROMable. Sorted 8-bit → 64-bit.
| Target | Lean | Core | Full |
|---|---|---|---|
| AVR ATmega328P (8-bit) | 9.2 KB | 12.8 KB | 15.4 KB |
| 68HC11 (8-bit) | 13.3 KB | 18.4 KB | 22.6 KB |
| MSP430 (16-bit) | 7.8 KB | 10.7 KB | 12.8 KB |
| Xtensa LX7 (ESP32-S3) | 2.9 KB | 4.2 KB | 5.3 KB |
| Cortex-M4 (32-bit) | 3.3 KB | 4.4 KB | 5.5 KB |
| Cortex-M0 (32-bit) | 3.4 KB | 4.5 KB | 5.7 KB |
| RISC-V rv32 | 4.1 KB | 5.5 KB | 6.8 KB |
| Xtensa LX106 (ESP8266) | 4.2 KB | 5.8 KB | 7.3 KB |
| m68k (32-bit) | 4.4 KB | 6.2 KB | 7.8 KB |
| MIPS32 | 4.7 KB | 6.6 KB | 8.7 KB |
| x86-32 | 5.3 KB | 7.2 KB | 9.2 KB |
| RISC-V rv64 | 4.0 KB | 5.5 KB | 6.8 KB |
| x86-64 (GCC) | 4.6 KB | 6.1 KB | 8.0 KB |
| AArch64 (ARM64) | 4.8 KB | 6.6 KB | 8.7 KB |
Comments
0Start the conversation
Share the first comment.