2 releases

0.1.1 Jan 19, 2020
0.1.0 Jan 19, 2020

#2774 in Algorithms

Download history 1025/week @ 2026-03-26 4046/week @ 2026-04-02 6198/week @ 2026-04-09 5721/week @ 2026-04-16 5107/week @ 2026-04-23 3849/week @ 2026-04-30 3503/week @ 2026-05-07 5996/week @ 2026-05-14 3588/week @ 2026-05-21 3359/week @ 2026-05-28 3801/week @ 2026-06-04 4581/week @ 2026-06-11 4507/week @ 2026-06-18 3849/week @ 2026-06-25 2360/week @ 2026-07-02 2286/week @ 2026-07-09

13,797 downloads per month
Used in 4 crates (2 directly)

BSD-3-Clause

57KB
1K SLoC

ibmfloat

A Rust library for IBM floating point numbers, specifically focused on converting them to IEEE-754 floating point values.

This crate has no Rust dependencies, no C dependencies, and no unsafe code. Its std feature is enabled by default, and it can be disabled to support #![no_std] environments.

The conversion processes and much of the test suite are derived from the Python ibm2ieee library.

Performance

Representative results from a laptop:

F32 to f32              time:   [6.7092 ns 6.7734 ns 6.8454 ns]                        
F32 to f64              time:   [2.4642 ns 2.4965 ns 2.5326 ns]                        
F64 to f32              time:   [7.2500 ns 7.3315 ns 7.4169 ns]                        
F64 to f64              time:   [2.7761 ns 2.8028 ns 2.8342 ns]                        

Conversions to f32 are more expensive than conversions to f64.

Usage

32-bit floats

ibmfloat::F32 represents a 32-bit IBM floating point number. It supports the conversions:

  • Transmuting to/from a u32 via from_bits(), to_bits()
  • Transmuting to/from a big-endian [u8; 4] via from_be_bytes()/to_be_bytes()
  • Lossily converting to an f32 via From/Into
  • Losslessly converting to an f64 via From/Into

IBM F32 floats have slightly less precision than IEEE-754 f32 floats, but it covers a slightly larger domain. F32s of typical magnitude can be converted to f32 without rounding or other loss of precision. Converting F32s of large magnitude to f32 will cause rounding; F32s of extreme magnitude can also cause overflow and underflow to occur.

Every F32 can be precisely represented as an f64, without rounding, overflow, or underflow. Those seeking a lossless path to IEEE-754 should convert F32 to f64.

// Use the example -118.625:
//   https://en.wikipedia.org/wiki/IBM_hexadecimal_floating_point#Example
let foreign_float = ibmfloat::F32::from_bits(0b1_1000010_0111_0110_1010_0000_0000_0000);

let native_float = f32::from(foreign_float);
assert_eq!(native_float, -118.625f32);

let native_float: f32 = foreign_float.into();
assert_eq!(native_float, -118.625f32);

64-bit floats

ibmfloat::64 represents a 64-bit IBM floating point number. It supports the conversions:

  • Transmuting to/from a u64 via from_bits(), to_bits()
  • Transmuting to/from a big-endian [u8; 8] via from_be_bytes()/to_be_bytes()
  • Lossily converting to an f32 via From/Into
  • Lossily converting to an f64 via From/Into

IBM F64 floats have slightly more precision than IEEE-754 f64 floats, but they cover a slightly smaller domain. Most conversions will require rounding, but there is no risk of overflow or underflow.

let foreign_float = ibmfloat::F64::from_bits(0x4110000000000000);

let native_float = f64::from(foreign_float);
assert_eq!(native_float, 1.0f64);

let native_float: f64 = foreign_float.into();
assert_eq!(native_float, 1.0f64);

Development

Please use cargo test, cargo clippy, and cargo fmt as you go. Please also cargo test --no-default-features to prevent accidental breakage for #![no_std] users. GitHub Actions runs each of these commands on push.

ibm2ieee-sys/ contains a crate wrapping ibm2ieee.c, tests which compare ibm2ieee.c's conversion to ibmfloat's conversions over random values, and benchmarks of both libraries.

$ cd ibm2ieee-sys/
$ cargo test
$ cargo bench

cargo fuzz covers each of the four IBM to IEEE conversion paths, comparing them to ibm2ieee-sys. Please run them as needed if you tinker with that logic.

$ cargo +nightly fuzz run ibm32ieee32
$ cargo +nightly fuzz run ibm32ieee64
$ cargo +nightly fuzz run ibm64ieee32
$ cargo +nightly fuzz run ibm64ieee64

Additional references:

No runtime deps

Features