From 7db85958b434e67f3d98a8dd5164344d8bc1bdbd Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 17 May 2024 19:16:38 -0500 Subject: [PATCH 1/3] Add documentation where it was missing. Most types didn't have any documentation. Add it. --- build.rs | 11 +++++--- src/ieee.rs | 73 ++++++++++++++++++++++++++++++++++++++++------------- src/lib.rs | 10 +++++++- src/ppc.rs | 8 ++++++ 4 files changed, 79 insertions(+), 23 deletions(-) diff --git a/build.rs b/build.rs index a7398a2..920b3b4 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,7 @@ const SRC_LIB_RS_CONTENTS: &str = include_str!("src/lib.rs"); const EXPECTED_SRC_LIB_RS_PREFIX: &str = "\ //! Port of LLVM's APFloat software floating-point implementation from the //! following C++ sources (please update commit hash when backporting): -//! https://github.com/llvm/llvm-project/commit/"; +//! ") + .ok_or("expected trailing hyperlink anchor `>`".into()) }) - .and_then(|(commit_hash, _)| { + .and_then(|commit_hash| { if commit_hash.len() != 40 || !commit_hash.chars().all(|c| matches!(c, '0'..='9'|'a'..='f')) { Err(format!("expected `src/lib.rs` to have a valid commit hash, found {commit_hash:?}")) } else { diff --git a/src/ieee.rs b/src/ieee.rs index 06f2f08..bfa7a6a 100644 --- a/src/ieee.rs +++ b/src/ieee.rs @@ -1,3 +1,5 @@ +//! Support for floating point types compatible with IEEE 754. + use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO}; use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd}; @@ -8,6 +10,12 @@ use core::marker::PhantomData; use core::mem; use core::ops::Neg; +/// A floating point number that uses IEEE semantics. +/// +/// Usually you will want the type aliases ([`Single`], [`Double`], ...) rather than using this +/// directly. +/// +/// If `S` implements [`Semantics`], this type will implement [`Float`]. #[must_use] pub struct IeeeFloat { /// Absolute significand value (including the integer bit). @@ -84,7 +92,7 @@ pub enum NonfiniteBehavior { /// Only the Float8E5M2 has this behavior. There is no Inf representation. A /// value is NaN if the exponent field and the mantissa field are all 1s. /// This behavior matches the FP8 E4M3 type described in - /// https://arxiv.org/abs/2209.05433. We treat both signed and unsigned NaNs + /// . We treat both signed and unsigned NaNs /// as non-signalling, although the paper does not state whether the NaN /// values are signalling or not. NanOnly, @@ -276,37 +284,59 @@ impl Clone for IeeeFloat { } macro_rules! ieee_semantics { - ($($name:ident = $sem:ident($bits:tt : $exp_bits:tt) $({ $($extra:tt)* })?),* $(,)?) => { - $(pub struct $sem;)* - $(pub type $name = IeeeFloat<$sem>;)* - $(impl Semantics for $sem { - const BITS: usize = $bits; - const EXP_BITS: usize = $exp_bits; + ($( + $(#[$meta:meta])* + $name:ident = $sem:ident($bits:tt : $exp_bits:tt) $({ $($extra:tt)* })? + ),* $(,)?) => { + $( + #[doc = concat!("Floating point semantics for [`", stringify!($name), "`].")] + /// + /// See that type for more details. + pub struct $sem; + + $(#[$meta])* + pub type $name = IeeeFloat<$sem>; - $($($extra)*)? - })* + impl Semantics for $sem { + const BITS: usize = $bits; + const EXP_BITS: usize = $exp_bits; + + $($($extra)*)? + } + )* } } ieee_semantics! { + /// IEEE binary16 half-precision (16-bit) floating point number. Half = HalfS(16:5), + + /// IEEE binary32 single-precision (32-bit) floating point number. Single = SingleS(32:8), + + /// IEEE binary64 double-precision (64-bit) floating point number. Double = DoubleS(64:11), - Quad = QuadS(128:15), - // Non-standard IEEE-like semantics: + /// IEEE binary128 quadruple-precision (128-bit) floating point number. + Quad = QuadS(128:15), - // FIXME(eddyb) document this as "Brain Float 16" (C++ didn't have docs). + /// 16-bit brain floating point number. + /// + /// This is not an IEEE kind but uses the same semantics. BFloat = BFloatS(16:8), - // 8-bit floating point number following IEEE-754 conventions with bit - // layout S1E5M2 as described in https://arxiv.org/abs/2209.05433. + /// 8-bit floating point number with S1E5M2 bit layout. + /// + /// Follows IEEE-754 conventions with S1E5M2 bit layout as described in + /// . Float8E5M2 = Float8E5M2S(8:5), - // 8-bit floating point number mostly following IEEE-754 conventions with - // bit layout S1E4M3 as described in https://arxiv.org/abs/2209.05433. - // Unlike IEEE-754 types, there are no infinity values, and NaN is - // represented with the exponent and mantissa bits set to all 1s. + /// 8-bit floating point number with S1E4M3 bit layout. + /// + /// This type mostly follows IEEE-754 conventions with a + /// bit layout S1E4M3 as described in . + /// Unlike IEEE-754 types, there are no infinity values, and NaN is + /// represented with the exponent and mantissa bits set to all 1s. Float8E4M3FN = Float8E4M3FNS(8:4) { const NONFINITE_BEHAVIOR: NonfiniteBehavior = NonfiniteBehavior::NanOnly; }, @@ -314,8 +344,15 @@ ieee_semantics! { // FIXME(eddyb) consider moving X87-specific logic to a "has explicit integer bit" // associated `const` on `Semantics` itself. +/// Floating point semantics for [`X87DoubleExtended`] +/// +/// See that type for more details. pub struct X87DoubleExtendedS; + +/// 80-bit floating point number that uses IEEE extended precision semantics, as used +/// by x87 `long double`. pub type X87DoubleExtended = IeeeFloat; + impl Semantics for X87DoubleExtendedS { const BITS: usize = 80; const EXP_BITS: usize = 15; diff --git a/src/lib.rs b/src/lib.rs index 90c47da..00830f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! Port of LLVM's APFloat software floating-point implementation from the //! following C++ sources (please update commit hash when backporting): -//! https://github.com/llvm/llvm-project/commit/462a31f5a5abb905869ea93cc49b096079b11aa4 +//! //! * `llvm/include/llvm/ADT/APFloat.h` -> `Float` and `FloatConvert` traits //! * `llvm/lib/Support/APFloat.cpp` -> `ieee` and `ppc` modules //! * `llvm/unittests/ADT/APFloatTest.cpp` -> `tests` directory @@ -64,6 +64,8 @@ bitflags! { } } +/// The result of a computation including the output value and and any exceptions if there were +/// errors. #[must_use] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct StatusAnd { @@ -72,12 +74,14 @@ pub struct StatusAnd { } impl Status { + /// Add a value to this status to create a [`StatusAnd`]. pub fn and(self, value: T) -> StatusAnd { StatusAnd { status: self, value } } } impl StatusAnd { + /// Keep the existing status but apply a transformation to `value`. pub fn map U, U>(self, f: F) -> StatusAnd { StatusAnd { status: self.status, @@ -145,6 +149,7 @@ pub const IEK_INF: ExpInt = ExpInt::max_value(); pub const IEK_NAN: ExpInt = ExpInt::min_value(); pub const IEK_ZERO: ExpInt = ExpInt::min_value() + 1; +/// An error creating a floating point from a string. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct ParseError(pub &'static str); @@ -590,6 +595,7 @@ pub trait Float: } } +/// Convert between floating point types. pub trait FloatConvert: Float { /// Convert a value of one floating point type to another. /// The return value corresponds to the IEEE754 exceptions. *loses_info @@ -598,6 +604,8 @@ pub trait FloatConvert: Float { /// original value (this is almost the same as return value==Status::OK, /// but there are edge cases where this is not so). fn convert_r(self, round: Round, loses_info: &mut bool) -> StatusAnd; + + /// Convert with default [`NearestTiesToEven`](Round::NearestTiesToEven) rounding. fn convert(self, loses_info: &mut bool) -> StatusAnd { self.convert_r(Round::NearestTiesToEven, loses_info) } diff --git a/src/ppc.rs b/src/ppc.rs index b03efff..6454416 100644 --- a/src/ppc.rs +++ b/src/ppc.rs @@ -1,3 +1,5 @@ +//! Support for floating point types that use PowerPC semantics. + use crate::ieee; use crate::{Category, ExpInt, Float, FloatConvert, ParseError, Round, Status, StatusAnd}; @@ -5,9 +7,15 @@ use core::cmp::Ordering; use core::fmt; use core::ops::Neg; +/// A larger floating point number represented by two smaller floats. #[must_use] #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct DoubleFloat(F, F); + +/// 128-bit floating point number comprised of two IEEE [`Double`](ieee::Double) values. +/// +/// This is the "IBM Extended Double" format, described at +/// . pub type DoubleDouble = DoubleFloat; // These are legacy semantics for the Fallback, inaccrurate implementation of From a3dea6ed4b3bf7a2e1eb68fb4827da331c6e6b27 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 17 May 2024 19:26:37 -0500 Subject: [PATCH 2/3] Add a `unwrap()` function to `StatusAnd`. This provides an easy way to get the value and check for errors. --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 00830f8..8972d84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,14 @@ impl StatusAnd { } } +impl StatusAnd { + /// Extract the inner value if there were no errors. If there were errors, panic. + pub fn unwrap(self) -> T { + assert_eq!(self.status, Status::OK, "called `StatusAnd::unwrap()` on an error value. Value: {:?}", self.value); + self.value + } +} + #[macro_export] macro_rules! unpack { ($status:ident|=, $e:expr) => { From 64c499985b2b80ac632dc2ffae5f0bd634369d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 4 Jul 2024 14:22:35 +0200 Subject: [PATCH 3/3] Apply suggestions from code review --- src/ieee.rs | 6 +++--- src/lib.rs | 5 ++--- src/ppc.rs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/ieee.rs b/src/ieee.rs index bfa7a6a..8b1d67b 100644 --- a/src/ieee.rs +++ b/src/ieee.rs @@ -12,8 +12,8 @@ use core::ops::Neg; /// A floating point number that uses IEEE semantics. /// -/// Usually you will want the type aliases ([`Single`], [`Double`], ...) rather than using this -/// directly. +/// Usually you will want to use the available type aliases of this type +/// (e.g., [`Single`], [`Double`]) rather than referencing it directly. /// /// If `S` implements [`Semantics`], this type will implement [`Float`]. #[must_use] @@ -344,7 +344,7 @@ ieee_semantics! { // FIXME(eddyb) consider moving X87-specific logic to a "has explicit integer bit" // associated `const` on `Semantics` itself. -/// Floating point semantics for [`X87DoubleExtended`] +/// Floating point semantics for [`X87DoubleExtended`]. /// /// See that type for more details. pub struct X87DoubleExtendedS; diff --git a/src/lib.rs b/src/lib.rs index 8972d84..8642a22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,8 +64,7 @@ bitflags! { } } -/// The result of a computation including the output value and and any exceptions if there were -/// errors. +/// The result of a computation consisting of the output value and the exceptions, if any. #[must_use] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct StatusAnd { @@ -157,7 +156,7 @@ pub const IEK_INF: ExpInt = ExpInt::max_value(); pub const IEK_NAN: ExpInt = ExpInt::min_value(); pub const IEK_ZERO: ExpInt = ExpInt::min_value() + 1; -/// An error creating a floating point from a string. +/// An error which can occur when parsing a floating point number from a string. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct ParseError(pub &'static str); diff --git a/src/ppc.rs b/src/ppc.rs index 6454416..618740c 100644 --- a/src/ppc.rs +++ b/src/ppc.rs @@ -15,7 +15,7 @@ pub struct DoubleFloat(F, F); /// 128-bit floating point number comprised of two IEEE [`Double`](ieee::Double) values. /// /// This is the "IBM Extended Double" format, described at -/// . +/// . pub type DoubleDouble = DoubleFloat; // These are legacy semantics for the Fallback, inaccrurate implementation of