floatguard 0.1.2

A library for checked floating-point arithmetic in Rust, safely elminating NaN and Infinity from floating-point computations.
Documentation

FloatGuard (floatguard)

Crates.io Docs.rs License

Build Status codecov Release

A low-cost, zero-overhead wrapper around f64 that eliminates the risk of NaN and infinity in floating-point computations.

Why?

Floating-point math in Rust (and most languages) silently permits values like NaN, INFINITY, and -INFINITY. These values conform to the IEEE 754 standard and exist to support interoperability with C libraries and hardware.

However, in many applications, they behave like floating-point landmines — silently propagating through computations and causing unexpected or confusing results. They're the numerical equivalent of a null pointer or an uncaught exception.

floatguard introduces two types to address this problem explicitly:

  • GuardedF64: A wrapper around f64 that guarantees the value is finite — it will never contain NaN, INFINITY, or -INFINITY. Any operation that could produce an invalid value returns an UnguardedF64 instead.
  • UnguardedF64: A lightweight wrapper that may contain invalid states like NaN or infinities. It allows chained operations without incurring a validity check at every step. Before use, the value must be validated with .check(), which either returns a valid GuardedF64 or an error.

This model provides both safety and performance, by enabling deferred validation and avoiding silent propagation of invalid values.

Example

use floatguard::GuardedF64;

fn main() {
    let a = GuardedF64::new(1.0).unwrap();
    let b = GuardedF64::new(2.0).unwrap();

    // Valid arithmetic
    let c = a + b; // c is UnguardedF64(3.0)

    match c.check() {
        Ok(valid) => println!("Valid result: {valid}"),
        Err(e) => println!("Error: {e}"),
    }

    // Invalid arithmetic
    let d = c / GuardedF64::new(0.0).unwrap(); // d is UnguardedF64(NaN)

    match d.check() {
        Ok(valid) => println!("Valid result: {valid}"),
        Err(e) => println!("Error: {e}"),
    }
}

Output:

Valid result: 3
Error: The floating-point value is poisoned

Features

  • Finite guarantees: GuardedF64 and GuardedF32 never contain NaN or infinities.
  • Deferred validation: UnguardedF64 and UnguardedF32 allow efficient math, checked only when needed.
  • Drop-in operators: Full support for +, -, *, /, +=, -=, etc.
  • Conversions: TryFrom<f64>, Into<f64>, and more.
  • #![no_std] compatible.

Crate Features

  • std (default) — Enables std-based functionality (currently unused but reserved for future expansion).

Safety and Limitations

  • Any operation that may result in an invalid value returns an "unguarded" value.
  • Use .check() to convert an "unguarded" value into a "guarded" one, or catch an error if the value is invalid.

MSRV

Minimum Supported Rust Version: 1.85.1

License

You may choose between the following licenses for this crate: