Skip to content

Commit 364c7ac

Browse files
authored
Merge pull request #15 from tgross35/statusand-unwrap
Update documentation and add `StatusAnd::unwrap()`
2 parents 2ced82c + 64c4999 commit 364c7ac

File tree

4 files changed

+86
-23
lines changed

4 files changed

+86
-23
lines changed

build.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const SRC_LIB_RS_CONTENTS: &str = include_str!("src/lib.rs");
44
const EXPECTED_SRC_LIB_RS_PREFIX: &str = "\
55
//! Port of LLVM's APFloat software floating-point implementation from the
66
//! following C++ sources (please update commit hash when backporting):
7-
//! https://github.com/llvm/llvm-project/commit/";
7+
//! <https://github.com/llvm/llvm-project/commit/";
88

99
fn main() {
1010
// HACK(eddyb) disable the default of re-running the build script on *any*
@@ -16,11 +16,14 @@ fn main() {
1616
.ok_or(())
1717
.map_err(|_| format!("expected `src/lib.rs` to start with:\n\n{EXPECTED_SRC_LIB_RS_PREFIX}"))
1818
.and_then(|commit_hash_plus_rest_of_file| {
19-
Ok(commit_hash_plus_rest_of_file
19+
commit_hash_plus_rest_of_file
2020
.split_once('\n')
21-
.ok_or("expected `src/lib.rs` to have more than 3 lines")?)
21+
.ok_or("expected `src/lib.rs` to have more than 3 lines")?
22+
.0
23+
.strip_suffix(">")
24+
.ok_or("expected trailing hyperlink anchor `>`".into())
2225
})
23-
.and_then(|(commit_hash, _)| {
26+
.and_then(|commit_hash| {
2427
if commit_hash.len() != 40 || !commit_hash.chars().all(|c| matches!(c, '0'..='9'|'a'..='f')) {
2528
Err(format!("expected `src/lib.rs` to have a valid commit hash, found {commit_hash:?}"))
2629
} else {

src/ieee.rs

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Support for floating point types compatible with IEEE 754.
2+
13
use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO};
24
use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd};
35

@@ -8,6 +10,12 @@ use core::marker::PhantomData;
810
use core::mem;
911
use core::ops::Neg;
1012

13+
/// A floating point number that uses IEEE semantics.
14+
///
15+
/// Usually you will want to use the available type aliases of this type
16+
/// (e.g., [`Single`], [`Double`]) rather than referencing it directly.
17+
///
18+
/// If `S` implements [`Semantics`], this type will implement [`Float`].
1119
#[must_use]
1220
pub struct IeeeFloat<S> {
1321
/// Absolute significand value (including the integer bit).
@@ -84,7 +92,7 @@ pub enum NonfiniteBehavior {
8492
/// Only the Float8E5M2 has this behavior. There is no Inf representation. A
8593
/// value is NaN if the exponent field and the mantissa field are all 1s.
8694
/// This behavior matches the FP8 E4M3 type described in
87-
/// https://arxiv.org/abs/2209.05433. We treat both signed and unsigned NaNs
95+
/// <https://arxiv.org/abs/2209.05433>. We treat both signed and unsigned NaNs
8896
/// as non-signalling, although the paper does not state whether the NaN
8997
/// values are signalling or not.
9098
NanOnly,
@@ -276,46 +284,75 @@ impl<S> Clone for IeeeFloat<S> {
276284
}
277285

278286
macro_rules! ieee_semantics {
279-
($($name:ident = $sem:ident($bits:tt : $exp_bits:tt) $({ $($extra:tt)* })?),* $(,)?) => {
280-
$(pub struct $sem;)*
281-
$(pub type $name = IeeeFloat<$sem>;)*
282-
$(impl Semantics for $sem {
283-
const BITS: usize = $bits;
284-
const EXP_BITS: usize = $exp_bits;
287+
($(
288+
$(#[$meta:meta])*
289+
$name:ident = $sem:ident($bits:tt : $exp_bits:tt) $({ $($extra:tt)* })?
290+
),* $(,)?) => {
291+
$(
292+
#[doc = concat!("Floating point semantics for [`", stringify!($name), "`].")]
293+
///
294+
/// See that type for more details.
295+
pub struct $sem;
296+
297+
$(#[$meta])*
298+
pub type $name = IeeeFloat<$sem>;
285299

286-
$($($extra)*)?
287-
})*
300+
impl Semantics for $sem {
301+
const BITS: usize = $bits;
302+
const EXP_BITS: usize = $exp_bits;
303+
304+
$($($extra)*)?
305+
}
306+
)*
288307
}
289308
}
290309

291310
ieee_semantics! {
311+
/// IEEE binary16 half-precision (16-bit) floating point number.
292312
Half = HalfS(16:5),
313+
314+
/// IEEE binary32 single-precision (32-bit) floating point number.
293315
Single = SingleS(32:8),
316+
317+
/// IEEE binary64 double-precision (64-bit) floating point number.
294318
Double = DoubleS(64:11),
295-
Quad = QuadS(128:15),
296319

297-
// Non-standard IEEE-like semantics:
320+
/// IEEE binary128 quadruple-precision (128-bit) floating point number.
321+
Quad = QuadS(128:15),
298322

299-
// FIXME(eddyb) document this as "Brain Float 16" (C++ didn't have docs).
323+
/// 16-bit brain floating point number.
324+
///
325+
/// This is not an IEEE kind but uses the same semantics.
300326
BFloat = BFloatS(16:8),
301327

302-
// 8-bit floating point number following IEEE-754 conventions with bit
303-
// layout S1E5M2 as described in https://arxiv.org/abs/2209.05433.
328+
/// 8-bit floating point number with S1E5M2 bit layout.
329+
///
330+
/// Follows IEEE-754 conventions with S1E5M2 bit layout as described in
331+
/// <https://arxiv.org/abs/2209.05433>.
304332
Float8E5M2 = Float8E5M2S(8:5),
305333

306-
// 8-bit floating point number mostly following IEEE-754 conventions with
307-
// bit layout S1E4M3 as described in https://arxiv.org/abs/2209.05433.
308-
// Unlike IEEE-754 types, there are no infinity values, and NaN is
309-
// represented with the exponent and mantissa bits set to all 1s.
334+
/// 8-bit floating point number with S1E4M3 bit layout.
335+
///
336+
/// This type mostly follows IEEE-754 conventions with a
337+
/// bit layout S1E4M3 as described in <https://arxiv.org/abs/2209.05433>.
338+
/// Unlike IEEE-754 types, there are no infinity values, and NaN is
339+
/// represented with the exponent and mantissa bits set to all 1s.
310340
Float8E4M3FN = Float8E4M3FNS(8:4) {
311341
const NONFINITE_BEHAVIOR: NonfiniteBehavior = NonfiniteBehavior::NanOnly;
312342
},
313343
}
314344

315345
// FIXME(eddyb) consider moving X87-specific logic to a "has explicit integer bit"
316346
// associated `const` on `Semantics` itself.
347+
/// Floating point semantics for [`X87DoubleExtended`].
348+
///
349+
/// See that type for more details.
317350
pub struct X87DoubleExtendedS;
351+
352+
/// 80-bit floating point number that uses IEEE extended precision semantics, as used
353+
/// by x87 `long double`.
318354
pub type X87DoubleExtended = IeeeFloat<X87DoubleExtendedS>;
355+
319356
impl Semantics for X87DoubleExtendedS {
320357
const BITS: usize = 80;
321358
const EXP_BITS: usize = 15;

src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Port of LLVM's APFloat software floating-point implementation from the
22
//! following C++ sources (please update commit hash when backporting):
3-
//! https://github.com/llvm/llvm-project/commit/462a31f5a5abb905869ea93cc49b096079b11aa4
3+
//! <https://github.com/llvm/llvm-project/commit/462a31f5a5abb905869ea93cc49b096079b11aa4>
44
//! * `llvm/include/llvm/ADT/APFloat.h` -> `Float` and `FloatConvert` traits
55
//! * `llvm/lib/Support/APFloat.cpp` -> `ieee` and `ppc` modules
66
//! * `llvm/unittests/ADT/APFloatTest.cpp` -> `tests` directory
@@ -64,6 +64,7 @@ bitflags! {
6464
}
6565
}
6666

67+
/// The result of a computation consisting of the output value and the exceptions, if any.
6768
#[must_use]
6869
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
6970
pub struct StatusAnd<T> {
@@ -72,12 +73,14 @@ pub struct StatusAnd<T> {
7273
}
7374

7475
impl Status {
76+
/// Add a value to this status to create a [`StatusAnd`].
7577
pub fn and<T>(self, value: T) -> StatusAnd<T> {
7678
StatusAnd { status: self, value }
7779
}
7880
}
7981

8082
impl<T> StatusAnd<T> {
83+
/// Keep the existing status but apply a transformation to `value`.
8184
pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> StatusAnd<U> {
8285
StatusAnd {
8386
status: self.status,
@@ -86,6 +89,14 @@ impl<T> StatusAnd<T> {
8689
}
8790
}
8891

92+
impl<T: core::fmt::Debug> StatusAnd<T> {
93+
/// Extract the inner value if there were no errors. If there were errors, panic.
94+
pub fn unwrap(self) -> T {
95+
assert_eq!(self.status, Status::OK, "called `StatusAnd::unwrap()` on an error value. Value: {:?}", self.value);
96+
self.value
97+
}
98+
}
99+
89100
#[macro_export]
90101
macro_rules! unpack {
91102
($status:ident|=, $e:expr) => {
@@ -145,6 +156,7 @@ pub const IEK_INF: ExpInt = ExpInt::max_value();
145156
pub const IEK_NAN: ExpInt = ExpInt::min_value();
146157
pub const IEK_ZERO: ExpInt = ExpInt::min_value() + 1;
147158

159+
/// An error which can occur when parsing a floating point number from a string.
148160
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
149161
pub struct ParseError(pub &'static str);
150162

@@ -590,6 +602,7 @@ pub trait Float:
590602
}
591603
}
592604

605+
/// Convert between floating point types.
593606
pub trait FloatConvert<T: Float>: Float {
594607
/// Convert a value of one floating point type to another.
595608
/// The return value corresponds to the IEEE754 exceptions. *loses_info
@@ -598,6 +611,8 @@ pub trait FloatConvert<T: Float>: Float {
598611
/// original value (this is almost the same as return value==Status::OK,
599612
/// but there are edge cases where this is not so).
600613
fn convert_r(self, round: Round, loses_info: &mut bool) -> StatusAnd<T>;
614+
615+
/// Convert with default [`NearestTiesToEven`](Round::NearestTiesToEven) rounding.
601616
fn convert(self, loses_info: &mut bool) -> StatusAnd<T> {
602617
self.convert_r(Round::NearestTiesToEven, loses_info)
603618
}

src/ppc.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
//! Support for floating point types that use PowerPC semantics.
2+
13
use crate::ieee;
24
use crate::{Category, ExpInt, Float, FloatConvert, ParseError, Round, Status, StatusAnd};
35

46
use core::cmp::Ordering;
57
use core::fmt;
68
use core::ops::Neg;
79

10+
/// A larger floating point number represented by two smaller floats.
811
#[must_use]
912
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
1013
pub struct DoubleFloat<F>(F, F);
14+
15+
/// 128-bit floating point number comprised of two IEEE [`Double`](ieee::Double) values.
16+
///
17+
/// This is the "IBM Extended Double" format, described at
18+
/// <https://www.ibm.com/docs/en/aix/7.3?topic=sepl-128-bit-long-double-floating-point-data-type>.
1119
pub type DoubleDouble = DoubleFloat<ieee::Double>;
1220

1321
// These are legacy semantics for the Fallback, inaccrurate implementation of

0 commit comments

Comments
 (0)