fixed-math-taylor 0.3.4

High-performance fixed-point trigonometry library optimized for microcontrollers without FPU. 100% no_std.
Documentation

Fixed-Math-Taylor

Crates.io Docs.rs License: GPL-2.0+

A lightweight, zero-dependency fixed-point trigonometry library optimized for embedded systems and microcontrollers without a floating-point unit (FPU).

⚠️ Security Note (v0.3.4)IMPORTANT: Please do not use versions prior to 0.3.4.Earlier versions contained an integer overflow bug in the Taylor engine when approaching 90° ($PI/2$).Fixed in v0.3.4:Internal calculations upgraded to i64 to prevent overflows.Added Arithmetic Saturation (clamping) to ensure results stay within [-32767, 32767].Verified on RP2350(Raspberry Pi Pico 2) hardware.

Overview

Fixed-Math-Taylor eliminates the computational overhead of software floating-point emulation on resource-constrained devices by implementing trigonometric functions using pure integer arithmetic and bit shifts. Designed specifically for the RP2040 and similar microcontrollers, it delivers production-ready performance with multiple calculation engines to suit different use cases.

Performance Advantage

  • No FPU emulation overhead: Uses only integer operations (no f32/f64 soft math)
  • Deterministic execution: No floating-point rounding surprises
  • Minimal code size: Optimized to ~1-2KB with single engine
  • Embedded-friendly: #![no_std] compatible, zero allocations

Installation

Add to your Cargo.toml:

[dependencies]
fixed-math-taylor = { version = "0.3.3", features = ["lut"] }

Choose one calculation engine via features:

  • lut – Lookup table + interpolation (recommended for most cases)
  • taylor – Pure algorithmic Taylor series
  • fast-sin – Ultra-fast Bhaskara I approximation

Quick Start

use fixed_math_taylor::{sin_fixed, cos_fixed, Angle, Fixed};

fn main() {
    // Angle: 0 to 65535 represents 0 to 2π
    let angle: Angle = 16384; // This is π/2
    
    // Results are in Q15 fixed-point format
    // 32767 ≈ 1.0, -32768 ≈ -1.0
    let sin_value: Fixed = sin_fixed(angle);
    let cos_value: Fixed = cos_fixed(angle);
    
    // Convert to regular float for display/use
    let sin_f32 = (sin_value as f32) / 32767.0;
    let cos_f32 = (cos_value as f32) / 32767.0;
    
    println!("sin(π/2) ≈ {:.4}", sin_f32); // Output: 1.0000
    println!("cos(π/2) ≈ {:.4}", cos_f32); // Output: ~0.0000
}

Number Formats

Q15 Fixed-Point Output

All trigonometric functions return Fixed (i16) in Q15 format:

Value Represents
32767 +1.0
16384 +0.5
0 0.0
-16384 -0.5
-32768 ≈-1.0

Conversion formula:

let value_f32 = (fixed_value as f32) / 32767.0;

Angle Input (u16)

Angles use a full 16-bit range for 2π:

Angle Radians
0 0
16384 π/2
32768 π
49152 3π/2
65535 ≈2π

Calculation Engines

1. LUT (Lookup Table) – features = ["lut"]

Recommended for most applications.

  • Method: 257-entry lookup table + linear interpolation
  • Precision: ~0.1% error
  • Speed: Fastest (2-3 CPU cycles)
  • Memory: 640 bytes Flash
  • Best for: Motor control, audio synthesis, PID loops, real-time systems

Uses quadrant symmetry to minimize Flash footprint while maintaining high accuracy through interpolation.

use fixed_math_taylor::{sin_fixed, cos_fixed, sin_cos};

let angle = 16384;
let s = sin_fixed(angle);
let c = cos_fixed(angle);

// Combined sin/cos (slightly faster than calling both)
let (s, c) = sin_cos(angle);

2. Taylor Series – features = ["taylor"]

Pure algorithmic approach.

  • Method: 5th-order Taylor expansion in Q15
  • Precision: High (0.01% error)
  • Speed: Fast (10-15 CPU cycles)
  • Memory: ~500 bytes Flash (no runtime table)
  • Best for: Algorithm-only designs, scenarios where Flash preservation is critical
#[cfg(feature = "taylor")]
use fixed_math_taylor::taylor_impl;

let angle = 16384;
let s = taylor_impl::sin_taylor(angle);
let c = taylor_impl::cos_taylor(angle);

3. Fast-Sin (Bhaskara I) – features = ["fast-sin"]

Maximum speed with acceptable precision.

  • Method: Bhaskara I approximation formula
  • Precision: Medium (~0.5% error)
  • Speed: Fastest (1-2 CPU cycles)
  • Memory: ~300 bytes Flash
  • Best for: Graphics, animations, scenarios where ultra-high precision isn't needed
#[cfg(feature = "fast-sin")]
use fixed_math_taylor::fast_impl;

let angle = 16384;
let s = fast_impl::sin_fast(angle);
let c = fast_impl::cos_fast(angle);

Feature Comparison Table

Feature Method Precision Speed Flash Use Case
lut Table + Interp ~0.1% err ⚡⚡⚡ 640 B Control, audio, motors
taylor Taylor Series ~0.01% err ⚡⚡ 500 B Pure algorithms
fast-sin Bhaskara I ~0.5% err ⚡⚡⚡⚡ 300 B Graphics, animations

Typical Use Cases

Motor Control & PID Loops

Use LUT engine (features = ["lut"]). The 0.1% precision is more than sufficient for control loops, and the speed is optimal for real-time systems.

Audio Synthesis

Use LUT engine. Linear interpolation provides smooth curve generation without aliasing issues.

Graphics & Game Development

Use Fast-Sin engine (features = ["fast-sin"]). The speed advantage justifies the lower precision for visual effects.

Precise Numerical Algorithms

Use Taylor engine (features = ["taylor"]). Pure algorithmic computation without Flash tables.

Embedded Integration Example

RP2040 (Raspberry Pi Pico)

#![no_std]
#![no_main]

use fixed_math_taylor::sin_fixed;

#[entry]
fn main() -> ! {
    // Your initialization code...
    
    loop {
        // Generate a smooth sine wave for PWM output
        for angle in (0..65536).step_by(256) {
            let sample = sin_fixed(angle as u16);
            // Use `sample` to drive PWM or other outputs
        }
    }
}

Technical Details

Q15 Arithmetic

Q15 is a 16-bit signed fixed-point format where:

  • The sign bit is separate (bit 15)
  • Bits 14-0 represent the fractional part
  • Maximum value: 32767 ≈ 1.0
  • Minimum value: -32768 ≈ -1.0

Why Q15?

  • Perfect fit for 16-bit microcontroller ALUs
  • Provides 15-bit precision (0.003% resolution)
  • Single 16×16→32 multiply operation (standard ALU feature)

Quadrant Symmetry Optimization

The LUT engine exploits trigonometric symmetry to reduce memory:

  • Stores only first quadrant (0 to π/2): 257 points
  • Uses symmetry properties for quadrants 2-4
  • Linear interpolation ensures smooth transitions between table points
  • Total: 640 bytes vs. 1KB+ for naive full table

Overflow Prevention

Internal intermediate calculations use 64-bit registers when necessary to prevent overflow while maintaining the speed of 32-bit arithmetic.

Testing & Validation

Comprehensive test suite validates:

  • Mathematical accuracy across all quadrants
  • Sign correctness near π and 2π boundaries
  • Interpolation consistency (LUT engine)
  • Taylor expansion coefficients (Taylor engine)

Run tests:

cargo test --all-features

License

Copyright © 2026 Jorge Andre Castro

This is distributed under the GNU General Public License v2.0 or later. All derivative code must remain free and open source.

See LICENSE for full details.

Performance Benchmarks

Typical execution times on RP2040 (125 MHz):

Engine sin() cos() sin_cos()
LUT 2.4 µs 2.4 µs 3.5 µs
Taylor 12.8 µs 12.8 µs 24 µs
Fast-Sin 1.6 µs 1.6 µs 3.2 µs

(Approximate; varies with compiler optimizations)

Contributing

Found a bug or have a suggestion? Please open an issue or pull request on GitHub.

Future Enhancements

Planned additions:

  • Tangent function (tan)
  • Inverse trigonometric functions (arcsin, arccos)
  • Additional engine optimizations for ARM Cortex-M0+ and M4

Built for speed and efficiency on resource-constrained systems.