1#![no_std]
22#![cfg_attr(feature = "f16", feature(f16))]
23#![cfg_attr(feature = "f128", feature(f128))]
24#![allow(missing_docs)]
25
26#[macro_use]
27mod macros;
28
29mod helpers;
30
31define!(BF16, name "BF16", unsigned u16, signed i16, with 8 exp bits, desc "a Google BFloat16 floating point number");
32define!(F16, name "F16", unsigned u16, signed i16, #[cfg(feature = "f16")] float f16, with 5 exp bits, desc "an IEEE 754 binary16 floating point number");
33define!(F32, name "F32", unsigned u32, signed i32, float f32, with 8 exp bits, desc "an IEEE 754 binary32 floating point number");
34define!(F64, name "F64", unsigned u64, signed i64, float f64, with 11 exp bits, desc "an IEEE 754 binary64 floating point number");
35define!(F128, name "F128", unsigned u128, signed i128, #[cfg(feature = "f128")] float f128, with 15 exp bits, desc "an IEEE 754 binary128 floating point number");
36
37impl core::fmt::Display for F64 {
38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39 let val = self.to_float();
40 core::fmt::Display::fmt(&val, f)
41 }
42}
43
44impl core::str::FromStr for F64 {
45 type Err = core::num::ParseFloatError;
46 fn from_str(s: &str) -> Result<Self, Self::Err> {
47 Ok(Self::from_float(s.parse()?))
48 }
49}
50
51impl core::fmt::Display for F32 {
52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53 let val = self.to_float();
54 core::fmt::Display::fmt(&val, f)
55 }
56}
57
58impl core::str::FromStr for F32 {
59 type Err = core::num::ParseFloatError;
60 fn from_str(s: &str) -> Result<Self, Self::Err> {
61 Ok(Self::from_float(s.parse()?))
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use core::num::FpCategory as Class;
69
70 #[test]
71 fn f32_smoke_test() {
72 const PZERO: F32 = F32::ZERO;
73 const NZERO: F32 = F32::NEG_ZERO;
74 const PNORM: F32 = F32::MIN_POSITIVE;
75 const NNORM: F32 = F32::MAX_NEGATIVE;
76 const PONE: F32 = F32::ONE;
77 const NONE: F32 = F32::NEG_ONE;
78 const PMAX: F32 = F32::MAX;
79 const NMAX: F32 = F32::MIN;
80 const PINF: F32 = F32::INFINITY;
81 const NINF: F32 = F32::NEG_INFINITY;
82 const PQNAN: F32 = F32::QNAN;
83 const PSNAN: F32 = F32::SNAN;
84 const NQNAN: F32 = F32::NEG_QNAN;
85 const NSNAN: F32 = F32::NEG_SNAN;
86 type Row = (u32, Class, bool, F32, f32);
87 const ROWS: [Row; 14] = [
88 (0x00000000, Class::Zero, false, PZERO, 0.0),
89 (0x80000000, Class::Zero, true, NZERO, -0.0),
90 (0x00800000, Class::Normal, false, PNORM, f32::MIN_POSITIVE),
91 (0x80800000, Class::Normal, true, NNORM, -f32::MIN_POSITIVE),
92 (0x3f800000, Class::Normal, false, PONE, 1.0),
93 (0xbf800000, Class::Normal, true, NONE, -1.0),
94 (0x7f7fffff, Class::Normal, false, PMAX, f32::MAX),
95 (0xff7fffff, Class::Normal, true, NMAX, -f32::MAX),
96 (0x7f800000, Class::Infinite, false, PINF, f32::INFINITY),
97 (0xff800000, Class::Infinite, true, NINF, f32::NEG_INFINITY),
98 (0x7f800001, Class::Nan, false, PSNAN, f32::NAN),
99 (0x7fc00001, Class::Nan, false, PQNAN, f32::NAN),
100 (0xff800001, Class::Nan, true, NSNAN, f32::NAN),
101 (0xffc00001, Class::Nan, true, NQNAN, f32::NAN),
102 ];
103 for (bits, class, neg, val, float) in ROWS {
104 assert_eq!(neg, val.is_sign_negative());
105 assert_eq!(class, val.classify());
106 assert_eq!(float.is_nan(), val.is_nan());
107 if !val.is_nan() {
108 assert_eq!(float, val.to_float());
109 }
110 assert_eq!(bits, val.to_bits());
111 }
112 }
113
114 #[test]
115 fn f64_smoke_test() {
116 const PZERO: F64 = F64::ZERO;
117 const NZERO: F64 = F64::NEG_ZERO;
118 const PNORM: F64 = F64::MIN_POSITIVE;
119 const NNORM: F64 = F64::MAX_NEGATIVE;
120 const PONE: F64 = F64::ONE;
121 const NONE: F64 = F64::NEG_ONE;
122 const PMAX: F64 = F64::MAX;
123 const NMAX: F64 = F64::MIN;
124 const PINF: F64 = F64::INFINITY;
125 const NINF: F64 = F64::NEG_INFINITY;
126 const PQNAN: F64 = F64::QNAN;
127 const PSNAN: F64 = F64::SNAN;
128 const NQNAN: F64 = F64::NEG_QNAN;
129 const NSNAN: F64 = F64::NEG_SNAN;
130 type Row = (u64, Class, bool, F64, f64);
131 const ROWS: [Row; 14] = [
132 (0x0000000000000000, Class::Zero, false, PZERO, 0.0),
133 (0x8000000000000000, Class::Zero, true, NZERO, -0.0),
134 (
135 0x0010000000000000,
136 Class::Normal,
137 false,
138 PNORM,
139 f64::MIN_POSITIVE,
140 ),
141 (
142 0x8010000000000000,
143 Class::Normal,
144 true,
145 NNORM,
146 -f64::MIN_POSITIVE,
147 ),
148 (0x3ff0000000000000, Class::Normal, false, PONE, 1.0),
149 (0xbff0000000000000, Class::Normal, true, NONE, -1.0),
150 (0x7fefffffffffffff, Class::Normal, false, PMAX, f64::MAX),
151 (0xffefffffffffffff, Class::Normal, true, NMAX, -f64::MAX),
152 (
153 0x7ff0000000000000,
154 Class::Infinite,
155 false,
156 PINF,
157 f64::INFINITY,
158 ),
159 (
160 0xfff0000000000000,
161 Class::Infinite,
162 true,
163 NINF,
164 f64::NEG_INFINITY,
165 ),
166 (0x7ff0000000000001, Class::Nan, false, PSNAN, f64::NAN),
167 (0x7ff8000000000001, Class::Nan, false, PQNAN, f64::NAN),
168 (0xfff0000000000001, Class::Nan, true, NSNAN, f64::NAN),
169 (0xfff8000000000001, Class::Nan, true, NQNAN, f64::NAN),
170 ];
171 for (bits, class, neg, val, float) in ROWS {
172 assert_eq!(neg, val.is_sign_negative());
173 assert_eq!(class, val.classify());
174 assert_eq!(float.is_nan(), val.is_nan());
175 if !val.is_nan() {
176 assert_eq!(float, val.to_float());
177 }
178 assert_eq!(bits, val.to_bits());
179 }
180 }
181}