#![no_std]
#![cfg_attr(feature = "f16", feature(f16))]
#![cfg_attr(feature = "f128", feature(f128))]
#![allow(missing_docs)]
#[macro_use]
mod macros;
mod helpers;
define! {
#[doc = "A newtype containing the raw bits of a Google BFloat16 floating point number."]
#[doc = ""]
#[doc = "Values of this type are hashable and have a well-defined total order: the one given "]
#[doc = "by [`Self::total_cmp`]. As a consequence, `+0.0` is not equal to `-0.0`, and NaN "]
#[doc = "compares equal to NaN if both NaN values have exactly the same bit pattern."]
pub struct BF16;
size 16 bits;
exp 8 bits;
repr u16 / i16;
}
define! {
#[doc = "A newtype containing the raw bits of an IEEE 754 binary16 floating point number."]
#[doc = ""]
#[doc = "Values of this type are hashable and have a well-defined total order: the one given "]
#[doc = "by [`Self::total_cmp`]. As a consequence, `+0.0` is not equal to `-0.0`, and NaN "]
#[doc = "compares equal to NaN if both NaN values have exactly the same bit pattern."]
#[doc = ""]
#[doc = "# Features"]
#[doc = ""]
#[doc = "Crate feature `f16` enables use of the Rust [`f16`] primitive type, which is a"]
#[doc = "nightly-only language feature that's only functional on certain architectures."]
pub struct F16;
size 16 bits;
exp 5 bits;
repr u16 / i16;
float f16 with feature "f16";
}
define! {
#[doc = "A newtype containing the raw bits of an IEEE 754 binary32 floating point number."]
#[doc = ""]
#[doc = "Values of this type are hashable and have a well-defined total order: the one given "]
#[doc = "by [`Self::total_cmp`]. As a consequence, `+0.0` is not equal to `-0.0`, and NaN "]
#[doc = "compares equal to NaN if both NaN values have exactly the same bit pattern."]
pub struct F32;
size 32 bits;
exp 8 bits;
repr u32 / i32;
float f32;
}
define! {
#[doc = "A newtype containing the raw bits of an IEEE 754 binary64 floating point number."]
#[doc = ""]
#[doc = "Values of this type are hashable and have a well-defined total order: the one given "]
#[doc = "by [`Self::total_cmp`]. As a consequence, `+0.0` is not equal to `-0.0`, and NaN "]
#[doc = "compares equal to NaN if both NaN values have exactly the same bit pattern."]
pub struct F64;
size 64 bits;
exp 11 bits;
repr u64 / i64;
float f64;
}
define! {
#[doc = "A newtype containing the raw bits of an IEEE 754 binary128 floating point number."]
#[doc = ""]
#[doc = "Values of this type are hashable and have a well-defined total order: the one given "]
#[doc = "by [`Self::total_cmp`]. As a consequence, `+0.0` is not equal to `-0.0`, and NaN "]
#[doc = "compares equal to NaN if both NaN values have exactly the same bit pattern."]
#[doc = ""]
#[doc = "# Features"]
#[doc = ""]
#[doc = "Crate feature `f128` enables use of the Rust [`f128`] primitive type, which is a"]
#[doc = "nightly-only language feature that's only functional on certain architectures."]
pub struct F128;
size 128 bits;
exp 15 bits;
repr u128 / i128;
float f128 with feature "f128";
}
impl core::fmt::Display for F64 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let val = self.to_float();
core::fmt::Display::fmt(&val, f)
}
}
impl core::str::FromStr for F64 {
type Err = core::num::ParseFloatError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from_float(s.parse()?))
}
}
impl core::fmt::Display for F32 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let val = self.to_float();
core::fmt::Display::fmt(&val, f)
}
}
impl core::str::FromStr for F32 {
type Err = core::num::ParseFloatError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from_float(s.parse()?))
}
}
#[cfg(test)]
mod tests {
use core::num::FpCategory;
use super::*;
use crate::helpers::{C_INF, C_NAN, C_NORM, C_ZERO};
#[test]
fn f32_smoke_test() {
const P_ZERO: F32 = F32::ZERO;
const N_ZERO: F32 = F32::NEG_ZERO;
const P_TINY: F32 = F32::MIN_POSITIVE;
const N_TINY: F32 = F32::MAX_NEGATIVE;
const P_ONE: F32 = F32::ONE;
const N_ONE: F32 = F32::NEG_ONE;
const P_MAX: F32 = F32::MAX;
const N_MAX: F32 = F32::MIN;
const P_INF: F32 = F32::INFINITY;
const N_INF: F32 = F32::NEG_INFINITY;
const P_QNAN: F32 = F32::QNAN;
const P_SNAN: F32 = F32::SNAN;
const N_QNAN: F32 = F32::NEG_QNAN;
const N_SNAN: F32 = F32::NEG_SNAN;
type Row = (u32, FpCategory, bool, F32, f32);
const ROWS: [Row; 14] = [
(0x00000000, C_ZERO, false, P_ZERO, 0.0),
(0x80000000, C_ZERO, true, N_ZERO, -0.0),
(0x00800000, C_NORM, false, P_TINY, f32::MIN_POSITIVE),
(0x80800000, C_NORM, true, N_TINY, -f32::MIN_POSITIVE),
(0x3f800000, C_NORM, false, P_ONE, 1.0),
(0xbf800000, C_NORM, true, N_ONE, -1.0),
(0x7f7fffff, C_NORM, false, P_MAX, f32::MAX),
(0xff7fffff, C_NORM, true, N_MAX, -f32::MAX),
(0x7f800000, C_INF, false, P_INF, f32::INFINITY),
(0xff800000, C_INF, true, N_INF, f32::NEG_INFINITY),
(0x7f800001, C_NAN, false, P_SNAN, f32::NAN),
(0x7fc00001, C_NAN, false, P_QNAN, f32::NAN),
(0xff800001, C_NAN, true, N_SNAN, f32::NAN),
(0xffc00001, C_NAN, true, N_QNAN, f32::NAN),
];
for (bits, class, neg, val, float) in ROWS {
assert_eq!(neg, val.is_sign_negative());
assert_eq!(class, val.classify());
assert_eq!(float.is_nan(), val.is_nan());
if !val.is_nan() {
assert_eq!(float, val.to_float());
}
assert_eq!(bits, val.to_bits());
}
}
#[test]
fn f64_smoke_test() {
const P_ZERO: F64 = F64::ZERO;
const N_ZERO: F64 = F64::NEG_ZERO;
const P_TINY: F64 = F64::MIN_POSITIVE;
const N_TINY: F64 = F64::MAX_NEGATIVE;
const P_ONE: F64 = F64::ONE;
const N_ONE: F64 = F64::NEG_ONE;
const P_MAX: F64 = F64::MAX;
const N_MAX: F64 = F64::MIN;
const P_INF: F64 = F64::INFINITY;
const N_INF: F64 = F64::NEG_INFINITY;
const P_QNAN: F64 = F64::QNAN;
const P_SNAN: F64 = F64::SNAN;
const N_QNAN: F64 = F64::NEG_QNAN;
const N_SNAN: F64 = F64::NEG_SNAN;
type Row = (u64, FpCategory, bool, F64, f64);
const ROWS: [Row; 14] = [
(0x0000000000000000, C_ZERO, false, P_ZERO, 0.0),
(0x8000000000000000, C_ZERO, true, N_ZERO, -0.0),
(0x0010000000000000, C_NORM, false, P_TINY, f64::MIN_POSITIVE),
(0x8010000000000000, C_NORM, true, N_TINY, -f64::MIN_POSITIVE),
(0x3ff0000000000000, C_NORM, false, P_ONE, 1.0),
(0xbff0000000000000, C_NORM, true, N_ONE, -1.0),
(0x7fefffffffffffff, C_NORM, false, P_MAX, f64::MAX),
(0xffefffffffffffff, C_NORM, true, N_MAX, -f64::MAX),
(0x7ff0000000000000, C_INF, false, P_INF, f64::INFINITY),
(0xfff0000000000000, C_INF, true, N_INF, f64::NEG_INFINITY),
(0x7ff0000000000001, C_NAN, false, P_SNAN, f64::NAN),
(0x7ff8000000000001, C_NAN, false, P_QNAN, f64::NAN),
(0xfff0000000000001, C_NAN, true, N_SNAN, f64::NAN),
(0xfff8000000000001, C_NAN, true, N_QNAN, f64::NAN),
];
for (bits, class, neg, val, float) in ROWS {
assert_eq!(neg, val.is_sign_negative());
assert_eq!(class, val.classify());
assert_eq!(float.is_nan(), val.is_nan());
if !val.is_nan() {
assert_eq!(float, val.to_float());
}
assert_eq!(bits, val.to_bits());
}
}
}