Skip to content

Commit 3561187

Browse files
committed
Improve floating point documentation:
- Refine the "NaN as a special value" top level explanation of f32 - Refine `const NAN` docstring. - Refine `fn is_sign_positive` and `fn is_sign_negative` docstrings. - Refine `fn min` and `fn max` docstrings. - Refine `fn trunc` docstrings. - Refine `fn powi` docstrings. - Refine `fn copysign` docstrings. - Reword `NaN` and `NAN` as plain "NaN", unless they refer to the specific `const NAN`. - Reword "a number" to `self` in function docstrings to clarify. - Remove "Returns NAN if the number is NAN" as this is told to be the default behavior in the top explanation. - Remove "propagating NaNs", as full propagation (preservation of payloads) is not guaranteed.
1 parent 3e75146 commit 3561187

File tree

6 files changed

+126
-64
lines changed

6 files changed

+126
-64
lines changed

library/core/src/num/f32.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,15 @@ impl f32 {
418418
pub const MAX_10_EXP: i32 = 38;
419419

420420
/// Not a Number (NaN).
421+
///
422+
/// Note that IEEE-745 doesn't define just a single NaN value;
423+
/// a plethora of bit patterns are considered to be NaN.
424+
/// Furthermore, the standard makes a difference
425+
/// between a "signaling" and a "quiet" NaN,
426+
/// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
427+
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
428+
/// and the stability of its representation over Rust versions
429+
/// and target platforms isn't guaranteed.
421430
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
422431
pub const NAN: f32 = 0.0_f32 / 0.0_f32;
423432
/// Infinity (∞).
@@ -427,7 +436,7 @@ impl f32 {
427436
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
428437
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
429438

430-
/// Returns `true` if this value is `NaN`.
439+
/// Returns `true` if this value is NaN.
431440
///
432441
/// ```
433442
/// let nan = f32::NAN;
@@ -476,7 +485,7 @@ impl f32 {
476485
self.abs_private() == Self::INFINITY
477486
}
478487

479-
/// Returns `true` if this number is neither infinite nor `NaN`.
488+
/// Returns `true` if this number is neither infinite nor NaN.
480489
///
481490
/// ```
482491
/// let f = 7.0f32;
@@ -527,7 +536,7 @@ impl f32 {
527536
}
528537

529538
/// Returns `true` if the number is neither zero, infinite,
530-
/// [subnormal], or `NaN`.
539+
/// [subnormal], or NaN.
531540
///
532541
/// ```
533542
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
@@ -582,8 +591,12 @@ impl f32 {
582591
}
583592
}
584593

585-
/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
586-
/// positive sign bit and positive infinity.
594+
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
595+
/// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any
596+
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
597+
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
598+
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
599+
/// See [explanation of NaN as a special value](f32) for more info.
587600
///
588601
/// ```
589602
/// let f = 7.0_f32;
@@ -600,8 +613,12 @@ impl f32 {
600613
!self.is_sign_negative()
601614
}
602615

603-
/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
604-
/// negative sign bit and negative infinity.
616+
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
617+
/// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any
618+
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
619+
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
620+
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
621+
/// See [explanation of NaN as a special value](f32) for more info.
605622
///
606623
/// ```
607624
/// let f = 7.0f32;
@@ -674,17 +691,17 @@ impl f32 {
674691

675692
/// Returns the maximum of the two numbers.
676693
///
677-
/// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
678-
/// This matches the behavior of libm’s fmax.
694+
/// If one of the arguments is NaN, then the other argument is returned.
695+
/// This follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs;
696+
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
697+
/// This also matches the behavior of libm’s fmax.
679698
///
680699
/// ```
681700
/// let x = 1.0f32;
682701
/// let y = 2.0f32;
683702
///
684703
/// assert_eq!(x.max(y), y);
685704
/// ```
686-
///
687-
/// If one of the arguments is NaN, then the other argument is returned.
688705
#[must_use = "this returns the result of the comparison, without modifying either input"]
689706
#[stable(feature = "rust1", since = "1.0.0")]
690707
#[inline]
@@ -694,25 +711,25 @@ impl f32 {
694711

695712
/// Returns the minimum of the two numbers.
696713
///
697-
/// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs.
698-
/// This matches the behavior of libm’s fmin.
714+
/// If one of the arguments is NaN, then the other argument is returned.
715+
/// This follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs;
716+
/// this function handles all NaNs the same way and avoids minNum's problems with associativity.
717+
/// This also matches the behavior of libm’s fmin.
699718
///
700719
/// ```
701720
/// let x = 1.0f32;
702721
/// let y = 2.0f32;
703722
///
704723
/// assert_eq!(x.min(y), x);
705724
/// ```
706-
///
707-
/// If one of the arguments is NaN, then the other argument is returned.
708725
#[must_use = "this returns the result of the comparison, without modifying either input"]
709726
#[stable(feature = "rust1", since = "1.0.0")]
710727
#[inline]
711728
pub fn min(self, other: f32) -> f32 {
712729
intrinsics::minnumf32(self, other)
713730
}
714731

715-
/// Returns the maximum of the two numbers, propagating NaNs.
732+
/// Returns the maximum of the two numbers.
716733
///
717734
/// This returns NaN when *either* argument is NaN, as opposed to
718735
/// [`f32::max`] which only returns NaN when *both* arguments are NaN.
@@ -744,7 +761,7 @@ impl f32 {
744761
}
745762
}
746763

747-
/// Returns the minimum of the two numbers, propagating NaNs.
764+
/// Returns the minimum of the two numbers.
748765
///
749766
/// This returns NaN when *either* argument is NaN, as opposed to
750767
/// [`f32::min`] which only returns NaN when *both* arguments are NaN.

library/core/src/num/f64.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,15 @@ impl f64 {
417417
pub const MAX_10_EXP: i32 = 308;
418418

419419
/// Not a Number (NaN).
420+
///
421+
/// Note that IEEE-745 doesn't define just a single NaN value;
422+
/// a plethora of bit patterns are considered to be NaN.
423+
/// Furthermore, the standard makes a difference
424+
/// between a "signaling" and a "quiet" NaN,
425+
/// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
426+
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
427+
/// and the stability of its representation over Rust versions
428+
/// and target platforms isn't guaranteed.
420429
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
421430
pub const NAN: f64 = 0.0_f64 / 0.0_f64;
422431
/// Infinity (∞).
@@ -426,7 +435,7 @@ impl f64 {
426435
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
427436
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
428437

429-
/// Returns `true` if this value is `NaN`.
438+
/// Returns `true` if this value is NaN.
430439
///
431440
/// ```
432441
/// let nan = f64::NAN;
@@ -475,7 +484,7 @@ impl f64 {
475484
self.abs_private() == Self::INFINITY
476485
}
477486

478-
/// Returns `true` if this number is neither infinite nor `NaN`.
487+
/// Returns `true` if this number is neither infinite nor NaN.
479488
///
480489
/// ```
481490
/// let f = 7.0f64;
@@ -526,7 +535,7 @@ impl f64 {
526535
}
527536

528537
/// Returns `true` if the number is neither zero, infinite,
529-
/// [subnormal], or `NaN`.
538+
/// [subnormal], or NaN.
530539
///
531540
/// ```
532541
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
@@ -581,8 +590,12 @@ impl f64 {
581590
}
582591
}
583592

584-
/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
585-
/// positive sign bit and positive infinity.
593+
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
594+
/// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any
595+
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
596+
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
597+
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
598+
/// See [explanation of NaN as a special value](f32) for more info.
586599
///
587600
/// ```
588601
/// let f = 7.0_f64;
@@ -608,8 +621,12 @@ impl f64 {
608621
self.is_sign_positive()
609622
}
610623

611-
/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
612-
/// negative sign bit and negative infinity.
624+
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
625+
/// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any
626+
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
627+
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
628+
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
629+
/// See [explanation of NaN as a special value](f32) for more info.
613630
///
614631
/// ```
615632
/// let f = 7.0_f64;
@@ -690,17 +707,17 @@ impl f64 {
690707

691708
/// Returns the maximum of the two numbers.
692709
///
693-
/// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
694-
/// This matches the behavior of libm’s fmax.
710+
/// If one of the arguments is NaN, then the other argument is returned.
711+
/// This follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs;
712+
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
713+
/// This also matches the behavior of libm’s fmax.
695714
///
696715
/// ```
697716
/// let x = 1.0_f64;
698717
/// let y = 2.0_f64;
699718
///
700719
/// assert_eq!(x.max(y), y);
701720
/// ```
702-
///
703-
/// If one of the arguments is NaN, then the other argument is returned.
704721
#[must_use = "this returns the result of the comparison, without modifying either input"]
705722
#[stable(feature = "rust1", since = "1.0.0")]
706723
#[inline]
@@ -710,25 +727,25 @@ impl f64 {
710727

711728
/// Returns the minimum of the two numbers.
712729
///
713-
/// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs.
714-
/// This matches the behavior of libm’s fmin.
730+
/// If one of the arguments is NaN, then the other argument is returned.
731+
/// This follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs;
732+
/// this function handles all NaNs the same way and avoids minNum's problems with associativity.
733+
/// This also matches the behavior of libm’s fmin.
715734
///
716735
/// ```
717736
/// let x = 1.0_f64;
718737
/// let y = 2.0_f64;
719738
///
720739
/// assert_eq!(x.min(y), x);
721740
/// ```
722-
///
723-
/// If one of the arguments is NaN, then the other argument is returned.
724741
#[must_use = "this returns the result of the comparison, without modifying either input"]
725742
#[stable(feature = "rust1", since = "1.0.0")]
726743
#[inline]
727744
pub fn min(self, other: f64) -> f64 {
728745
intrinsics::minnumf64(self, other)
729746
}
730747

731-
/// Returns the maximum of the two numbers, propagating NaNs.
748+
/// Returns the maximum of the two numbers.
732749
///
733750
/// This returns NaN when *either* argument is NaN, as opposed to
734751
/// [`f64::max`] which only returns NaN when *both* arguments are NaN.
@@ -760,7 +777,7 @@ impl f64 {
760777
}
761778
}
762779

763-
/// Returns the minimum of the two numbers, propagating NaNs.
780+
/// Returns the minimum of the two numbers.
764781
///
765782
/// This returns NaN when *either* argument is NaN, as opposed to
766783
/// [`f64::min`] which only returns NaN when *both* arguments are NaN.

library/core/src/primitive_docs.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -977,10 +977,20 @@ mod prim_tuple {}
977977
/// like `1.0 / 0.0`.
978978
/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
979979
/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
980-
/// behavior: it is unequal to any float, including itself! It is also neither
981-
/// smaller nor greater than any float, making it impossible to sort. Lastly,
982-
/// it is considered infectious as almost all calculations where one of the
983-
/// operands is NaN will also result in NaN.
980+
/// behavior:
981+
/// - It is unequal to any float, including itself!
982+
/// - It is also neither smaller nor greater than any float, making it
983+
/// impossible to sort by the default comparison operation. This is the
984+
/// reason `f32` doesn't implement the `Ord` and `Eq` traits.
985+
/// - It is also considered *infectious* as almost all calculations where one
986+
/// of the operands is NaN will also result in NaN. The explanations on this
987+
/// page only explicitly document behavior on NaN operands if this default
988+
/// is *not* observed by the operation.
989+
/// - Lastly, there are multiple bit patterns that are considered NaN.
990+
/// Rust does not currently guarantee that the bit patterns of NaN are
991+
/// preserved over arithmetic operations,
992+
/// so there may be some surprising results upon inspecting the bit patterns,
993+
/// as the same calculations might produce NaNs with different bit patterns.
984994
///
985995
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
986996
///

library/std/src/f32.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub use core::f32::{
3030
#[cfg(not(test))]
3131
#[cfg_attr(bootstrap, lang = "f32_runtime")]
3232
impl f32 {
33-
/// Returns the largest integer less than or equal to a number.
33+
/// Returns the largest integer less than or equal to `self`.
3434
///
3535
/// # Examples
3636
///
@@ -51,7 +51,7 @@ impl f32 {
5151
unsafe { intrinsics::floorf32(self) }
5252
}
5353

54-
/// Returns the smallest integer greater than or equal to a number.
54+
/// Returns the smallest integer greater than or equal to `self`.
5555
///
5656
/// # Examples
5757
///
@@ -70,7 +70,7 @@ impl f32 {
7070
unsafe { intrinsics::ceilf32(self) }
7171
}
7272

73-
/// Returns the nearest integer to a number. Round half-way cases away from
73+
/// Returns the nearest integer to `self`. Round half-way cases away from
7474
/// `0.0`.
7575
///
7676
/// # Examples
@@ -90,7 +90,8 @@ impl f32 {
9090
unsafe { intrinsics::roundf32(self) }
9191
}
9292

93-
/// Returns the integer part of a number.
93+
/// Returns the integer part of `self`.
94+
/// This means that non-integer numbers are always truncated towards zero.
9495
///
9596
/// # Examples
9697
///
@@ -111,7 +112,7 @@ impl f32 {
111112
unsafe { intrinsics::truncf32(self) }
112113
}
113114

114-
/// Returns the fractional part of a number.
115+
/// Returns the fractional part of `self`.
115116
///
116117
/// # Examples
117118
///
@@ -132,8 +133,7 @@ impl f32 {
132133
self - self.trunc()
133134
}
134135

135-
/// Computes the absolute value of `self`. Returns `NAN` if the
136-
/// number is `NAN`.
136+
/// Computes the absolute value of `self`.
137137
///
138138
/// # Examples
139139
///
@@ -161,7 +161,7 @@ impl f32 {
161161
///
162162
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
163163
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
164-
/// - `NAN` if the number is `NAN`
164+
/// - NaN if the number is NaN
165165
///
166166
/// # Examples
167167
///
@@ -185,8 +185,10 @@ impl f32 {
185185
/// `sign`.
186186
///
187187
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
188-
/// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
189-
/// `sign` is returned.
188+
/// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
189+
/// `sign` is returned. Note, however, that conserving the sign bit on NaN
190+
/// across arithmetical operations is not generally guaranteed.
191+
/// See [explanation of NaN as a special value](primitive@f32) for more info.
190192
///
191193
/// # Examples
192194
///
@@ -299,7 +301,9 @@ impl f32 {
299301

300302
/// Raises a number to an integer power.
301303
///
302-
/// Using this function is generally faster than using `powf`
304+
/// Using this function is generally faster than using `powf`.
305+
/// It might have different sequence of rounding operations than `powf`,
306+
/// so the results are not guaranteed to agree.
303307
///
304308
/// # Examples
305309
///

0 commit comments

Comments
 (0)