From fc3f723b0459772d32cbd408d6f7a337ae3e86b1 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sat, 23 Nov 2024 16:48:25 -0800 Subject: [PATCH] ui: Use `PositiveSign` instead of `NotNan` in `FpsCounter`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of . This doesn’t directly remove any negative-zero hazards, but it is a more appropriately bounded data type regardless (frame time cannot be negative). --- all-is-cubes-base/src/math/restricted_number.rs | 11 +++++++++++ all-is-cubes-ui/src/apps/time.rs | 10 +++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/all-is-cubes-base/src/math/restricted_number.rs b/all-is-cubes-base/src/math/restricted_number.rs index f2e1e84c5..41772c6d1 100644 --- a/all-is-cubes-base/src/math/restricted_number.rs +++ b/all-is-cubes-base/src/math/restricted_number.rs @@ -59,6 +59,17 @@ impl PositiveSign { unsafe { NotNan::new_unchecked(self.0) } } + /// Returns whether the value is finite. + /// + /// Since the value is statically guaranteed to be neither NaN nor negative, + /// the only case where this returns `false` is when the value is positive infinity. + #[inline] + pub fn is_finite(&self) -> bool { + // We could delegate to FloatCore::is_finite() but that would perform an unnecessary + // NaN check. + self.0 != T::infinity() + } + #[cfg(test)] #[track_caller] pub(crate) fn consistency_check(self) diff --git a/all-is-cubes-ui/src/apps/time.rs b/all-is-cubes-ui/src/apps/time.rs index c64d8ae4f..12c9541ed 100644 --- a/all-is-cubes-ui/src/apps/time.rs +++ b/all-is-cubes-ui/src/apps/time.rs @@ -1,4 +1,4 @@ -use all_is_cubes::math::NotNan; +use all_is_cubes::math::{zo64, PositiveSign, ZeroOne}; use all_is_cubes::time::{Duration, Instant, TickSchedule}; #[cfg(doc)] use all_is_cubes::universe::Universe; @@ -142,7 +142,7 @@ impl FrameClock { #[derive(Clone, Debug, Eq, PartialEq)] #[doc(hidden)] // TODO: Decide whether we want FpsCounter in our public API pub struct FpsCounter { - average_frame_time_seconds: Option>, + average_frame_time_seconds: Option>, last_frame: Option, } @@ -179,12 +179,12 @@ impl FpsCounter { None } }) - .and_then(|duration| NotNan::new(duration.as_secs_f64()).ok()); + .and_then(|duration| PositiveSign::try_from(duration.as_secs_f64()).ok()); if let Some(this_seconds) = this_seconds { self.average_frame_time_seconds = Some( if let Some(previous) = self.average_frame_time_seconds.filter(|v| v.is_finite()) { - let mix = 2.0f64.powi(-3); - this_seconds * mix + previous * (1. - mix) + const MIX: ZeroOne = zo64(1.0 / 8.0); + this_seconds * MIX + previous * MIX.complement() } else { // recover from any weirdness or initial state this_seconds