pub struct Float128 { /* private fields */ }Expand description
An IEEE 754-2008 binary128 value.
Held as the 128-bit pattern, because that is what goes on the wire
and every operation here is defined on it. to_be_bytes and
from_be_bytes are the wire form: CORBA Figure 9.2 shows the whole
sixteen bytes reversed between the two orders, not two eight-byte
halves swapped independently, and RTI Connext 7.7 was measured doing
exactly that (docs/float128-column.md §2).
§Equality
PartialEq is IEEE equality, the same as f64: -0.0 == 0.0, and a
NaN equals nothing including itself. So there is no Eq, no Ord
and no Hash — a key holder wants the bit pattern, which
Float128::to_bits and Float128::to_be_bytes give, and a total
order is Float128::total_cmp. Deriving Eq on IEEE equality
would make -0.0 and 0.0 interchangeable in a hash map, which is
how a key holder loses an instance.
Implementations§
Source§impl Float128
impl Float128
Sourcepub fn total_cmp(self, other: Self) -> Ordering
pub fn total_cmp(self, other: Self) -> Ordering
IEEE 754-2008 clause 5.10 totalOrder.
A total order over every bit pattern: -NaN < -inf < … < -0.0 < +0.0 < … < +inf < +NaN, with NaNs ordered by payload. This is
what a @key member and a sorted expectation need — partial_cmp
returning None for a NaN key would leave the sort order to
whatever the caller’s comparator does with None, which is how
two peers disagree about instance order for a sample neither
considers unusual.
The same construction f64::total_cmp uses: read the pattern as
a sign-magnitude integer and map it onto a two’s-complement one.
Sourcepub fn total_max(self, other: Self) -> Self
pub fn total_max(self, other: Self) -> Self
The larger of two values under Self::total_cmp.
Sourcepub fn total_min(self, other: Self) -> Self
pub fn total_min(self, other: Self) -> Self
The smaller of two values under Self::total_cmp.
Source§impl Float128
impl Float128
Sourcepub fn from_f64(value: f64) -> Self
pub fn from_f64(value: f64) -> Self
From an f64. Always exact: binary128 covers every binary64
value, subnormals included, with 60 fraction bits to spare.
Examples found in repository?
34fn main() {
35 let named = [
36 Float128::ZERO,
37 Float128::NEG_ZERO,
38 Float128::ONE,
39 Float128::NEG_ONE,
40 Float128::MAX,
41 Float128::MIN,
42 Float128::MIN_POSITIVE,
43 Float128::MIN_SUBNORMAL,
44 Float128::EPSILON,
45 Float128::from_bits(Float128::ONE.to_bits() + 1),
46 Float128::from_bits(Float128::MIN_POSITIVE.to_bits() - 1),
47 Float128::from_f64(1.5),
48 Float128::from_f64(-2.75),
49 Float128::from_f64(0.1),
50 Float128::from_f64(f64::MAX),
51 Float128::from_f64(f64::MIN_POSITIVE),
52 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 52)),
53 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 12)),
54 ];
55 let mut rng = Xorshift(0x0aac_1e50_dead_beef);
56 let mut patterns: Vec<Float128> = named.to_vec();
57 for _ in 0..500 {
58 let bits = (u128::from(rng.next_u64()) << 64) | u128::from(rng.next_u64());
59 // Finite only: quadmath prints `inf` and `nan` without digits,
60 // and those cases are pinned by name in the unit tests instead.
61 let exponent = u128::from(rng.next_u64() as u16 % 0x7fff) << 112;
62 patterns.push(Float128::from_bits(
63 (bits & !(0x7fffu128 << 112)) | exponent,
64 ));
65 }
66 for value in patterns {
67 println!("{:032x} {}", value.to_bits(), value.to_shortest_decimal());
68 }
69}Sourcepub fn from_i128_rounded(value: i128) -> Self
pub fn from_i128_rounded(value: i128) -> Self
From any signed integer up to 128 bits, rounding to nearest with ties to even. Exact for everything up to 2^113.
Sourcepub fn from_u128_rounded(value: u128) -> Self
pub fn from_u128_rounded(value: u128) -> Self
From any unsigned integer up to 128 bits, rounding to nearest with ties to even. Exact for everything up to 2^113.
Sourcepub fn try_from_i128(value: i128) -> Result<Self, Inexact<Self>>
pub fn try_from_i128(value: i128) -> Result<Self, Inexact<Self>>
Source§impl Float128
impl Float128
Sourcepub fn to_f64_rounded(self) -> f64
pub fn to_f64_rounded(self) -> f64
To an f64, rounding to nearest with ties to even.
Overflow gives an infinity and underflow a signed zero, which is
what IEEE 754-2008 clause 7.4 requires; both are inexact and
Self::to_f64 reports them.
Sourcepub fn to_f32_rounded(self) -> f32
pub fn to_f32_rounded(self) -> f32
To an f32, rounding to nearest with ties to even.
Source§impl Float128
impl Float128
Sourcepub const fn quiet_nan(payload: u128) -> Self
pub const fn quiet_nan(payload: u128) -> Self
A quiet NaN carrying payload in its low fraction bits.
A wire test needs a NaN it can recognise on the other side, and
Float128::NAN is one pattern out of 2^113. The payload is
masked to the bits below the quiet flag, so no argument can
produce an infinity by accident.
Sourcepub const fn neg_quiet_nan(payload: u128) -> Self
pub const fn neg_quiet_nan(payload: u128) -> Self
The same, negative.
Source§impl Float128
impl Float128
Sourcepub fn to_exact_decimal(&self) -> String
pub fn to_exact_decimal(&self) -> String
Every digit the value has, exactly.
1.5 gives "1.5"; the smallest subnormal gives its full 11 500
digits. Infinities and NaNs give "inf", "-inf" and "nan",
which is what FromStr reads back.
Sourcepub fn to_shortest_decimal(&self) -> String
pub fn to_shortest_decimal(&self) -> String
The fewest digits that read back as this exact bit pattern.
Found by rounding the exact expansion to one digit, then two, and
asking FromStr whether it comes back — so the answer is true of
this parser rather than true of a rule about digit counts.
Thirty-six always succeeds; Float128::DIGITS_ROUND_TRIP is
that bound.
Examples found in repository?
34fn main() {
35 let named = [
36 Float128::ZERO,
37 Float128::NEG_ZERO,
38 Float128::ONE,
39 Float128::NEG_ONE,
40 Float128::MAX,
41 Float128::MIN,
42 Float128::MIN_POSITIVE,
43 Float128::MIN_SUBNORMAL,
44 Float128::EPSILON,
45 Float128::from_bits(Float128::ONE.to_bits() + 1),
46 Float128::from_bits(Float128::MIN_POSITIVE.to_bits() - 1),
47 Float128::from_f64(1.5),
48 Float128::from_f64(-2.75),
49 Float128::from_f64(0.1),
50 Float128::from_f64(f64::MAX),
51 Float128::from_f64(f64::MIN_POSITIVE),
52 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 52)),
53 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 12)),
54 ];
55 let mut rng = Xorshift(0x0aac_1e50_dead_beef);
56 let mut patterns: Vec<Float128> = named.to_vec();
57 for _ in 0..500 {
58 let bits = (u128::from(rng.next_u64()) << 64) | u128::from(rng.next_u64());
59 // Finite only: quadmath prints `inf` and `nan` without digits,
60 // and those cases are pinned by name in the unit tests instead.
61 let exponent = u128::from(rng.next_u64() as u16 % 0x7fff) << 112;
62 patterns.push(Float128::from_bits(
63 (bits & !(0x7fffu128 << 112)) | exponent,
64 ));
65 }
66 for value in patterns {
67 println!("{:032x} {}", value.to_bits(), value.to_shortest_decimal());
68 }
69}Source§impl Float128
impl Float128
Sourcepub const NEG_ZERO: Self
pub const NEG_ZERO: Self
Negative zero. Distinct from Self::ZERO on the wire, equal to
it under ==, ordered below it by Self::total_cmp.
Sourcepub const NEG_INFINITY: Self
pub const NEG_INFINITY: Self
Negative infinity.
Sourcepub const MIN_POSITIVE: Self
pub const MIN_POSITIVE: Self
The smallest positive normal value, 2^-16382.
Sourcepub const MIN_SUBNORMAL: Self
pub const MIN_SUBNORMAL: Self
The smallest positive value of any kind, 2^-16494.
Sourcepub const MANTISSA_DIGITS: u32 = SIGNIFICAND_BITS
pub const MANTISSA_DIGITS: u32 = SIGNIFICAND_BITS
Significand bits including the implicit leading one: 113.
Sourcepub const DIGITS_ROUND_TRIP: usize = 36
pub const DIGITS_ROUND_TRIP: usize = 36
Decimal digits that always round-trip: ceil(113 * log10 2) + 1.
Thirty-six is the number Float128::to_shortest_decimal never
exceeds and the number a peer needs to read one back exactly.
Sourcepub const fn from_bits(bits: u128) -> Self
pub const fn from_bits(bits: u128) -> Self
From the raw 128-bit pattern.
Examples found in repository?
34fn main() {
35 let named = [
36 Float128::ZERO,
37 Float128::NEG_ZERO,
38 Float128::ONE,
39 Float128::NEG_ONE,
40 Float128::MAX,
41 Float128::MIN,
42 Float128::MIN_POSITIVE,
43 Float128::MIN_SUBNORMAL,
44 Float128::EPSILON,
45 Float128::from_bits(Float128::ONE.to_bits() + 1),
46 Float128::from_bits(Float128::MIN_POSITIVE.to_bits() - 1),
47 Float128::from_f64(1.5),
48 Float128::from_f64(-2.75),
49 Float128::from_f64(0.1),
50 Float128::from_f64(f64::MAX),
51 Float128::from_f64(f64::MIN_POSITIVE),
52 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 52)),
53 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 12)),
54 ];
55 let mut rng = Xorshift(0x0aac_1e50_dead_beef);
56 let mut patterns: Vec<Float128> = named.to_vec();
57 for _ in 0..500 {
58 let bits = (u128::from(rng.next_u64()) << 64) | u128::from(rng.next_u64());
59 // Finite only: quadmath prints `inf` and `nan` without digits,
60 // and those cases are pinned by name in the unit tests instead.
61 let exponent = u128::from(rng.next_u64() as u16 % 0x7fff) << 112;
62 patterns.push(Float128::from_bits(
63 (bits & !(0x7fffu128 << 112)) | exponent,
64 ));
65 }
66 for value in patterns {
67 println!("{:032x} {}", value.to_bits(), value.to_shortest_decimal());
68 }
69}Sourcepub const fn to_bits(self) -> u128
pub const fn to_bits(self) -> u128
The raw 128-bit pattern.
Examples found in repository?
34fn main() {
35 let named = [
36 Float128::ZERO,
37 Float128::NEG_ZERO,
38 Float128::ONE,
39 Float128::NEG_ONE,
40 Float128::MAX,
41 Float128::MIN,
42 Float128::MIN_POSITIVE,
43 Float128::MIN_SUBNORMAL,
44 Float128::EPSILON,
45 Float128::from_bits(Float128::ONE.to_bits() + 1),
46 Float128::from_bits(Float128::MIN_POSITIVE.to_bits() - 1),
47 Float128::from_f64(1.5),
48 Float128::from_f64(-2.75),
49 Float128::from_f64(0.1),
50 Float128::from_f64(f64::MAX),
51 Float128::from_f64(f64::MIN_POSITIVE),
52 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 52)),
53 Float128::from_bits(Float128::ONE.to_bits() | (1u128 << 12)),
54 ];
55 let mut rng = Xorshift(0x0aac_1e50_dead_beef);
56 let mut patterns: Vec<Float128> = named.to_vec();
57 for _ in 0..500 {
58 let bits = (u128::from(rng.next_u64()) << 64) | u128::from(rng.next_u64());
59 // Finite only: quadmath prints `inf` and `nan` without digits,
60 // and those cases are pinned by name in the unit tests instead.
61 let exponent = u128::from(rng.next_u64() as u16 % 0x7fff) << 112;
62 patterns.push(Float128::from_bits(
63 (bits & !(0x7fffu128 << 112)) | exponent,
64 ));
65 }
66 for value in patterns {
67 println!("{:032x} {}", value.to_bits(), value.to_shortest_decimal());
68 }
69}Sourcepub const fn from_be_bytes(bytes: [u8; 16]) -> Self
pub const fn from_be_bytes(bytes: [u8; 16]) -> Self
From sixteen big-endian bytes — the CDR big-endian wire form.
Sourcepub const fn to_be_bytes(self) -> [u8; 16]
pub const fn to_be_bytes(self) -> [u8; 16]
Sixteen big-endian bytes.
Sourcepub const fn from_le_bytes(bytes: [u8; 16]) -> Self
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self
From sixteen little-endian bytes — the CDR little-endian wire form, which is the big-endian one reversed as a whole.
Sourcepub const fn to_le_bytes(self) -> [u8; 16]
pub const fn to_le_bytes(self) -> [u8; 16]
Sixteen little-endian bytes.
Sourcepub const fn is_sign_negative(self) -> bool
pub const fn is_sign_negative(self) -> bool
The sign bit, as it is stored. True for negative, including
-0.0 and a negative NaN.
Sourcepub const fn is_sign_positive(self) -> bool
pub const fn is_sign_positive(self) -> bool
The complement of Self::is_sign_negative.
Sourcepub const fn is_infinite(self) -> bool
pub const fn is_infinite(self) -> bool
Whether this is an infinity.
Sourcepub const fn is_subnormal(self) -> bool
pub const fn is_subnormal(self) -> bool
Whether this is finite, non-zero and below Self::MIN_POSITIVE.
Sourcepub const fn is_normal(self) -> bool
pub const fn is_normal(self) -> bool
Whether this is finite and normal — not zero, not subnormal.
Sourcepub const fn is_quiet_nan(self) -> bool
pub const fn is_quiet_nan(self) -> bool
Whether this NaN is quiet. False for anything that is not a NaN.
Sourcepub const fn abs(self) -> Self
pub const fn abs(self) -> Self
The same magnitude with the sign bit cleared. NaN payloads and signalling-ness survive, per IEEE 754-2008 clause 5.5.1.
Sourcepub const fn decompose(self) -> Option<(bool, u128, i32)>
pub const fn decompose(self) -> Option<(bool, u128, i32)>
The value as (negative, significand, exponent) with
value = (-1)^negative * significand * 2^exponent.
None for an infinity or a NaN, which no such triple describes.
The significand is the integral one — the implicit leading bit
is materialised for a normal value — so the triple is exact and
needs no separate “is subnormal” flag to interpret.
Source§impl Float128
impl Float128
Sourcepub fn from_x87_extended(value: Extended80) -> Self
pub fn from_x87_extended(value: Extended80) -> Self
From x87 double-extended. Always exact: 64 significand bits fit inside 113, and the two formats share an exponent bias and range.
The unnormal and pseudo-* encodings the 8087 defined and the 80387 dropped — a cleared integer bit with a non-zero exponent — have no binary128 counterpart. They are decoded as what the significand and exponent say, which is what every current x86 treats them as when it does not fault.
Sourcepub fn from_x87_padded_bytes(bytes: [u8; 16]) -> Self
pub fn from_x87_padded_bytes(bytes: [u8; 16]) -> Self
From the sixteen bytes an x86-64 Fast DDS or OpenDDS writes.
The padding is dropped; see Extended80::from_padded_le_bytes.
Sourcepub fn to_x87_extended(self) -> (Extended80, bool)
pub fn to_x87_extended(self) -> (Extended80, bool)
To x87 double-extended, rounding to nearest with ties to even.
Returns the value and whether the conversion was exact. It is inexact whenever the significand needs more than 64 bits, which is most of binary128 — that is the whole cost of the x86 dialect, and it is returned rather than swallowed so a bridge can refuse.
Sourcepub fn to_x87_padded_bytes(self) -> ([u8; 16], bool)
pub fn to_x87_padded_bytes(self) -> ([u8; 16], bool)
To the sixteen bytes an x86-64 long double occupies, padding
zeroed.
The boolean is Float128::to_x87_extended’s: true when the
value survived.
Trait Implementations§
impl Copy for Float128
Source§impl FromStr for Float128
impl FromStr for Float128
Source§fn from_str(text: &str) -> Result<Self, Self::Err>
fn from_str(text: &str) -> Result<Self, Self::Err>
Correctly rounded, round to nearest with ties to even.
Never goes through an f64: a two-step parse rounds twice, and
double rounding gets the last bit wrong for the values that
matter here.
Source§type Err = ParseFloat128Error
type Err = ParseFloat128Error
Source§impl PartialEq for Float128
impl PartialEq for Float128
Source§fn eq(&self, other: &Self) -> bool
fn eq(&self, other: &Self) -> bool
IEEE 754-2008 clause 5.11 compareQuietEqual.
-0.0 == 0.0, and a NaN is equal to nothing, itself included.
The same contract f64 has, so a generated structure holding a
Float128 compares the way the same structure holding a double
does — a binding whose equality changed with the member’s width
would be a binding that fails a round trip test for a reason that
has nothing to do with the wire.
Source§impl PartialOrd for Float128
impl PartialOrd for Float128
Source§fn partial_cmp(&self, other: &Self) -> Option<Ordering>
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
IEEE 754-2008 clause 5.11. None when either side is a NaN, the
unordered case.