Proposal
Problem statement
It is common to need to deal with NaN in some way in floating point code. It is a uniquely problematic value. Infinities are typically easy to handle through clamping/comparisons, but NaN always needs its own path unless being exceptionally tricky.
Motivating examples or use cases
Searching for if ident.is_nan() gives a lot of examples that would be written cleaner with replace_nan:
fn compute_bar_units(mut percent: f64, total_chars: usize) -> usize {
if percent.is_nan() {
percent = 0.0;
}
(percent.round() * total_chars as f64 / 100.0).ceil() as usize
This could simply be
fn compute_bar_units(percent: f64, total_chars: usize) -> usize {
(percent.replace_nan(0.0).round() * total_chars as f64 / 100.0).ceil() as usize
Or
let potential = -y * a.ln() - (1.0 - y) * (1.0 - a).ln();
result += if potential.is_nan() { 0.0 } else { potential };
could just be
result += (-y * a.ln() - (1.0 - y) * (1.0 - a).ln()).replace_nan(0.0);
Quite often when you are checking for is_nan() and then doing something different, you could just unconditionally do something after replacing NaN with some value (often, but not always, 0).
Solution sketch
Add the following function to all float types:
impl fN {
/// If `self` is a NaN it is replaced with the given value,
/// otherwise `self` is returned unchanged.
fn replace_nan(self, value: Self) -> Self {
if self.is_nan() { value } else { self }
}
}
Alternatives
Simply write an if statement. However this often breaks arithmetic chains because there are two references to self, meaning you have to assign to (an otherwise often meaningless) temporary variable, or use mutability.
Links and related work
Proposal
Problem statement
It is common to need to deal with NaN in some way in floating point code. It is a uniquely problematic value. Infinities are typically easy to handle through clamping/comparisons, but NaN always needs its own path unless being exceptionally tricky.
Motivating examples or use cases
Searching for
if ident.is_nan()gives a lot of examples that would be written cleaner withreplace_nan:This could simply be
Or
could just be
Quite often when you are checking for
is_nan()and then doing something different, you could just unconditionally do something after replacingNaNwith some value (often, but not always, 0).Solution sketch
Add the following function to all float types:
Alternatives
Simply write an
ifstatement. However this often breaks arithmetic chains because there are two references toself, meaning you have to assign to (an otherwise often meaningless) temporary variable, or use mutability.Links and related work
np.nan_to_numpl.fill_nanreplace_na