2 个版本
| 0.1.1 | 2020 年 1 月 19 日 |
|---|---|
| 0.1.0 | 2020 年 1 月 19 日 |
#903 在 算法 中
每月 1,176 次下载
在 3 个crate中使用了(通过 giga-segy-core)
57KB
1K SLoC
ibmfloat
A Rust 库,用于处理 IBM 浮点数,特别关注将其转换为 IEEE-754 浮点值。
这个crate没有Rust依赖,没有C依赖,并且没有 unsafe 代码。它的 std 功能默认启用,可以通过禁用来支持 #![no_std] 环境。
转换过程和大部分测试套件来自 Python ibm2ieee 库。
性能
笔记本电脑的代表性结果
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]
转换为 f32 的开销比转换为 f64 要高。
用法
32位浮点数
ibmfloat::F32 表示一个32位IBM浮点数。它支持以下转换
- 通过
from_bits()和to_bits()将其转换为/从u32 - 通过
from_be_bytes()/to_be_bytes()将其转换为/从大端[u8; 4] - 通过
From/Into损失性地转换为f32 - 通过
From/Into无损性地转换为f64
IBM F32 单精度浮点数比 IEEE-754 f32 单精度浮点数的精度略低,但其覆盖的范围略大。典型大小的 F32 可以转换为 f32 而不会出现舍入或其他精度损失。将大范围的 F32 转换为 f32 将导致舍入;极大幅度的 F32 也可能导致溢出和下溢。
每个 F32 都可以精确地表示为一个 f64,不会出现舍入、溢出或下溢。那些寻求无损路径到 IEEE-754 的人应该将 F32 转换为 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位浮点数
ibmfloat::64 表示一个 64 位 IBM 浮点数。它支持以下转换
- 通过
from_bits()、to_bits()将其转换为/从u64 - 通过
from_be_bytes()/to_be_bytes()将其转换为/从大端[u8; 8] - 通过
From/Into损失性地转换为f32 - 通过
From/Into无损地将其转换为f64
IBM F64 浮点数的精度略高于 IEEE-754 f64 浮点数,但它们的覆盖范围略小。大多数转换将需要舍入,但不会出现溢出或下溢的风险。
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);
开发
请使用 cargo test、cargo clippy 和 cargo fmt 逐步进行。请还使用 cargo test --no-default-features 以防止意外破坏 #![no_std] 用户。GitHub Actions 在推送时运行这些命令。
ibm2ieee-sys/ 包含一个封装 ibm2ieee.c 的 crate,测试比较 ibm2ieee.c 对随机值的转换与 ibmfloat 的转换,以及两个库的基准测试。
$ cd ibm2ieee-sys/
$ cargo test
$ cargo bench
cargo fuzz 覆盖了四个 IBM 到 IEEE 转换路径,并将它们与 ibm2ieee-sys 进行比较。如果您对该逻辑进行修改,请按需运行它们。
$ cargo +nightly fuzz run ibm32ieee32
$ cargo +nightly fuzz run ibm32ieee64
$ cargo +nightly fuzz run ibm64ieee32
$ cargo +nightly fuzz run ibm64ieee64
其他参考
- ESA/390 增强浮点支持:概述 是一个很好的入门介绍
- Hercules 使用 C 实现了 IBM 浮点硬件