use crate::math::log_add;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug)]
pub struct AtomicF64(AtomicU64);
impl AtomicF64 {
pub fn new(v: f64) -> Self {
Self(AtomicU64::new(v.to_bits()))
}
pub fn load(&self) -> f64 {
f64::from_bits(self.0.load(Ordering::Relaxed))
}
pub fn store(&self, v: f64) {
self.0.store(v.to_bits(), Ordering::Relaxed);
}
pub fn fetch_update<F: Fn(f64) -> f64>(&self, f: F) -> f64 {
let mut cur = self.0.load(Ordering::Relaxed);
loop {
let next = f(f64::from_bits(cur)).to_bits();
match self
.0
.compare_exchange_weak(cur, next, Ordering::Relaxed, Ordering::Relaxed)
{
Ok(_) => return f64::from_bits(next),
Err(actual) => cur = actual,
}
}
}
pub fn log_add_assign(&self, log_inc: f64) {
self.fetch_update(|cur| log_add(cur, log_inc));
}
pub fn add_assign(&self, inc: f64) {
self.fetch_update(|cur| cur + inc);
}
}
impl Default for AtomicF64 {
fn default() -> Self {
Self::new(0.0)
}
}