diff --git a/src/ui/pages/cpu.rs b/src/ui/pages/cpu.rs index 62c81d8b..6f9d19e9 100644 --- a/src/ui/pages/cpu.rs +++ b/src/ui/pages/cpu.rs @@ -8,7 +8,7 @@ use crate::ui::widgets::graph_box::ResGraphBox; use crate::utils::cpu::{CpuData, CpuInfo}; use crate::utils::settings::SETTINGS; use crate::utils::units::{convert_frequency, convert_temperature}; -use crate::utils::{cpu, NaNDefault, NUM_CPUS}; +use crate::utils::{cpu, FiniteOr, NUM_CPUS}; mod imp { use std::cell::{Cell, RefCell}; @@ -347,7 +347,8 @@ impl ResCPU { .saturating_sub(imp.old_total_usage.get().1); let work_total_time = sum_total_delta.saturating_sub(idle_total_delta); - let total_fraction = ((work_total_time as f64) / (sum_total_delta as f64)).nan_default(0.0); + let total_fraction = + ((work_total_time as f64) / (sum_total_delta as f64)).finite_or_default(); imp.total_cpu.graph().push_data_point(total_fraction); @@ -375,7 +376,7 @@ impl ResCPU { let work_thread_time = sum_thread_delta.saturating_sub(idle_thread_delta); let curr_threadbox = &imp.thread_graphs.borrow()[i]; let thread_fraction = - ((work_thread_time as f64) / (sum_thread_delta as f64)).nan_default(0.0); + ((work_thread_time as f64) / (sum_thread_delta as f64)).finite_or_default(); curr_threadbox.graph().push_data_point(thread_fraction); curr_threadbox.set_subtitle(&format!("{} %", (thread_fraction * 100.0).round())); diff --git a/src/ui/pages/gpu.rs b/src/ui/pages/gpu.rs index 85621ecb..afb4e595 100644 --- a/src/ui/pages/gpu.rs +++ b/src/ui/pages/gpu.rs @@ -5,7 +5,7 @@ use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; use crate::utils::gpu::{Gpu, GpuData}; use crate::utils::units::{convert_frequency, convert_power, convert_storage, convert_temperature}; -use crate::utils::{pci, NaNDefault}; +use crate::utils::{pci, FiniteOr}; mod imp { use std::cell::{Cell, RefCell}; @@ -361,7 +361,7 @@ impl ResGPU { let used_vram_fraction = if let (Some(total_vram), Some(used_vram)) = (total_vram, used_vram) { - Some((*used_vram as f64 / *total_vram as f64).nan_default(0.0)) + Some((*used_vram as f64 / *total_vram as f64).finite_or_default()) } else { None }; diff --git a/src/ui/pages/memory.rs b/src/ui/pages/memory.rs index 13c1b5d2..0749a186 100644 --- a/src/ui/pages/memory.rs +++ b/src/ui/pages/memory.rs @@ -5,7 +5,7 @@ use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; use crate::utils::memory::{self, MemoryData, MemoryDevice}; use crate::utils::units::convert_storage; -use crate::utils::NaNDefault; +use crate::utils::FiniteOr; mod imp { use std::cell::{Cell, RefCell}; @@ -331,7 +331,7 @@ impl ResMemory { let used_swap = total_swap.saturating_sub(free_swap); let memory_fraction = used_mem as f64 / total_mem as f64; - let swap_fraction = (used_swap as f64 / total_swap as f64).nan_default(0.0); + let swap_fraction = (used_swap as f64 / total_swap as f64).finite_or_default(); let formatted_used_mem = convert_storage(used_mem as f64, false); let formatted_total_mem = convert_storage(total_mem as f64, false); diff --git a/src/utils/app.rs b/src/utils/app.rs index af8e2a9c..5457bdc6 100644 --- a/src/utils/app.rs +++ b/src/utils/app.rs @@ -19,7 +19,7 @@ use crate::i18n::i18n; use super::{ boot_time, process::{Process, ProcessAction}, - NaNDefault, + FiniteOr, }; // This contains executable names that are blacklisted from being recognized as applications @@ -516,7 +516,7 @@ impl AppsContext { } else { ((new.gfx.saturating_sub(old.gfx) as f32) / (timestamp.saturating_sub(timestamp_last) as f32)) - .nan_default(0.0) + .finite_or_default() / 1_000_000.0 } }) @@ -554,7 +554,7 @@ impl AppsContext { } else { ((new.enc.saturating_sub(old.enc) as f32) / (timestamp.saturating_sub(timestamp_last) as f32)) - .nan_default(0.0) + .finite_or_default() / 1_000_000.0 } }) @@ -592,7 +592,7 @@ impl AppsContext { } else { ((new.dec.saturating_sub(old.dec) as f32) / (timestamp.saturating_sub(timestamp_last) as f32)) - .nan_default(0.0) + .finite_or_default() / 1_000_000.0 } }) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index a561014a..0c191ea7 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -83,27 +83,73 @@ pub fn boot_time() -> Result { }) } -pub trait NaNDefault { - /// Returns the given `default` value if the variable is NaN, +pub trait FiniteOr { + /// Returns the given `x` value if the variable is NaN or infinite, /// and returns itself otherwise. #[must_use] - fn nan_default(&self, default: Self) -> Self; + fn finite_or(&self, x: Self) -> Self; + + /// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise returns its default + fn finite_or_default(&self) -> Self; + + /// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise runs `f` + fn finite_or_else Self>(&self, f: F) -> Self + where + Self: Sized; } -impl NaNDefault for f64 { - fn nan_default(&self, default: Self) -> Self { - if self.is_nan() { - default +impl FiniteOr for f64 { + fn finite_or(&self, x: Self) -> Self { + if !self.is_finite() { + x + } else { + *self + } + } + + fn finite_or_default(&self) -> Self { + if !self.is_finite() { + Self::default() + } else { + *self + } + } + + fn finite_or_else Self>(&self, f: F) -> Self + where + Self: Sized, + { + if !self.is_finite() { + f(*self) } else { *self } } } -impl NaNDefault for f32 { - fn nan_default(&self, default: Self) -> Self { - if self.is_nan() { - default +impl FiniteOr for f32 { + fn finite_or(&self, x: Self) -> Self { + if !self.is_finite() { + x + } else { + *self + } + } + + fn finite_or_default(&self) -> Self { + if !self.is_finite() { + Self::default() + } else { + *self + } + } + + fn finite_or_else Self>(&self, f: F) -> Self + where + Self: Sized, + { + if !self.is_finite() { + f(*self) } else { *self } diff --git a/src/utils/process.rs b/src/utils/process.rs index 68fd58d4..8de41993 100644 --- a/src/utils/process.rs +++ b/src/utils/process.rs @@ -18,7 +18,7 @@ use gtk::{ use crate::config; use super::{ - boot_time, NaNDefault, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE, + boot_time, FiniteOr, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE, }; static OTHER_PROCESS: LazyLock> = LazyLock::new(|| { @@ -270,7 +270,8 @@ impl Process { * 1000.0; let delta_time = self.data.timestamp.saturating_sub(self.timestamp_last); - delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32 + (delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32) + .finite_or_default() } } @@ -320,7 +321,7 @@ impl Process { } else { ((usage.gfx.saturating_sub(old_usage.gfx) as f32) / (self.data.timestamp.saturating_sub(self.timestamp_last) as f32) - .nan_default(0.0)) + .finite_or_default()) / 1_000_000.0 }; @@ -345,7 +346,7 @@ impl Process { } else { ((usage.enc.saturating_sub(old_usage.enc) as f32) / (self.data.timestamp.saturating_sub(self.timestamp_last) as f32) - .nan_default(0.0)) + .finite_or_default()) / 1_000_000.0 }; @@ -370,7 +371,7 @@ impl Process { } else { ((usage.dec.saturating_sub(old_usage.dec) as f32) / (self.data.timestamp.saturating_sub(self.timestamp_last) as f32) - .nan_default(0.0)) + .finite_or_default()) / 1_000_000.0 };