1use crate::math::log_add;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6#[derive(Debug)]
11pub struct AtomicF64(AtomicU64);
12
13impl AtomicF64 {
14 pub fn new(v: f64) -> Self {
15 Self(AtomicU64::new(v.to_bits()))
16 }
17
18 pub fn load(&self) -> f64 {
19 f64::from_bits(self.0.load(Ordering::Relaxed))
20 }
21
22 pub fn store(&self, v: f64) {
23 self.0.store(v.to_bits(), Ordering::Relaxed);
24 }
25
26 pub fn fetch_update<F: Fn(f64) -> f64>(&self, f: F) -> f64 {
28 let mut cur = self.0.load(Ordering::Relaxed);
29 loop {
30 let next = f(f64::from_bits(cur)).to_bits();
31 match self
32 .0
33 .compare_exchange_weak(cur, next, Ordering::Relaxed, Ordering::Relaxed)
34 {
35 Ok(_) => return f64::from_bits(next),
36 Err(actual) => cur = actual,
37 }
38 }
39 }
40
41 pub fn log_add_assign(&self, log_inc: f64) {
44 self.fetch_update(|cur| log_add(cur, log_inc));
45 }
46
47 pub fn add_assign(&self, inc: f64) {
49 self.fetch_update(|cur| cur + inc);
50 }
51}
52
53impl Default for AtomicF64 {
54 fn default() -> Self {
55 Self::new(0.0)
56 }
57}