Skip to content

Fix inverted is_all_nan / is_any_nan / is_all_infinite / is_any_infinite - #1614

Open
youdie006 wants to merge 1 commit into
rust-ndarray:masterfrom
youdie006:fix/1612-is-all-nan-inverted
Open

Fix inverted is_all_nan / is_any_nan / is_all_infinite / is_any_infinite#1614
youdie006 wants to merge 1 commit into
rust-ndarray:masterfrom
youdie006:fix/1612-is-all-nan-inverted

Conversation

@youdie006

Copy link
Copy Markdown

Fixes #1612.

Root cause

The boolean_ops! macro in src/numeric/impl_float_maths.rs had an inverted $all predicate: Zip::from(self).all(|&elt| !elt.$func()) tests "all elements are NOT NaN", the opposite of the documented "true if all elements are NaN". $any was defined as !self.$all(), so the double negation made is_any_* appear correct while is_all_* returned true for an all-finite array.

Fix

Both predicates are corrected together (fixing only $all would break the is_any_* methods that currently ride on the double negation):

  • $all -> Zip::from(self).all(|&elt| elt.$func())
  • $any -> Zip::from(self).any(|&elt| elt.$func())

This fixes is_all_nan, is_any_nan, is_all_infinite, and is_any_infinite in one change. Empty-array semantics are preserved (all -> true, any -> false).

@dbranford correctly identified the $all flip and raised the is_any question in the issue thread; this PR applies both corrections and adds regression coverage.

Tests

New tests/nan_all_repro.rs covers both the NaN and infinite families with f64: all-finite (is_all_* and is_any_* false), all-nan/all-inf (is_all_* and is_any_* true), and mixed (is_all_* false, is_any_* true).

Red-green verified: with the fix reverted, the first assertion (!all_finite.is_all_nan()) panics; with the fix, both tests pass. cargo fmt (nightly, per repo rustfmt.toml), cargo clippy (no new warnings), and the existing tests/numeric.rs suite all pass.


AI-assisted: this change was prepared with the help of an AI coding assistant and reviewed by me before submission.

The boolean_ops! macro in src/numeric/impl_float_maths.rs had an inverted $all
predicate: Zip::from(self).all(|&elt| !elt.$func()) tests "all elements are NOT
NaN", the opposite of the documented "true if all elements are NaN". $any was
defined as !self.$all(), so the double negation made is_any_* appear correct
while is_all_* returned true for an all-finite array.

Correct both predicates together (fixing only $all would break the is_any_*
methods that ride on the double negation):
  $all -> Zip::from(self).all(|&elt| elt.$func())
  $any -> Zip::from(self).any(|&elt| elt.$func())

Empty-array semantics are preserved (all -> true, any -> false).

Fixes rust-ndarray#1612
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.is_all_nan() returns true for an all-finite array

1 participant