tensor4all_core/global_default.rs
1//! Global default values with atomic access.
2//!
3//! This module provides a type-safe way to manage global default values
4//! that can be accessed and modified atomically.
5
6use std::sync::atomic::{AtomicU64, Ordering};
7use thiserror::Error;
8
9/// Error for invalid tolerance values.
10#[derive(Debug, Error, Clone, Copy)]
11#[error("Invalid rtol value: {0}. rtol must be finite and non-negative.")]
12pub struct InvalidRtolError(pub f64);
13
14/// A global default f64 value with atomic access.
15///
16/// This type provides thread-safe access to a global default value,
17/// typically used for tolerance parameters like `rtol`.
18///
19/// # Example
20///
21/// ```
22/// use tensor4all_core::GlobalDefault;
23///
24/// static MY_DEFAULT: GlobalDefault = GlobalDefault::new(1e-12);
25///
26/// // Get the default value
27/// let rtol = MY_DEFAULT.get();
28///
29/// // Set a new default value
30/// MY_DEFAULT.set(1e-10).unwrap();
31/// ```
32pub struct GlobalDefault {
33 value: AtomicU64,
34}
35
36impl GlobalDefault {
37 /// Create a new global default with the given initial value.
38 ///
39 /// This is a const fn, so it can be used in static declarations.
40 #[must_use]
41 pub const fn new(initial: f64) -> Self {
42 Self {
43 value: AtomicU64::new(initial.to_bits()),
44 }
45 }
46
47 /// Get the current default value.
48 #[must_use]
49 pub fn get(&self) -> f64 {
50 f64::from_bits(self.value.load(Ordering::Relaxed))
51 }
52
53 /// Set a new default value.
54 ///
55 /// # Errors
56 ///
57 /// Returns `InvalidRtolError` if the value is not finite or is negative.
58 pub fn set(&self, value: f64) -> Result<(), InvalidRtolError> {
59 if !value.is_finite() || value < 0.0 {
60 return Err(InvalidRtolError(value));
61 }
62 self.value.store(value.to_bits(), Ordering::Relaxed);
63 Ok(())
64 }
65
66 /// Set a new default value without validation.
67 ///
68 /// # Safety
69 ///
70 /// The caller must ensure the value is valid (finite and non-negative).
71 pub fn set_unchecked(&self, value: f64) {
72 self.value.store(value.to_bits(), Ordering::Relaxed);
73 }
74}
75
76// Safety: AtomicU64 is Sync, so GlobalDefault is too
77unsafe impl Sync for GlobalDefault {}
78
79#[cfg(test)]
80mod tests;