1use crate::vector2::Vector2;
13use num_complex::Complex;
14use std::sync::atomic::{AtomicU64, Ordering};
15
16pub struct AtomicF64x2 {
22 seq: AtomicU64,
23 c0: AtomicU64,
24 c1: AtomicU64,
25}
26
27impl AtomicF64x2 {
28 pub fn new(x: f64, y: f64) -> Self {
30 AtomicF64x2 {
31 seq: AtomicU64::new(0),
32 c0: AtomicU64::new(x.to_bits()),
33 c1: AtomicU64::new(y.to_bits()),
34 }
35 }
36
37 pub fn load(&self) -> [f64; 2] {
39 loop {
40 let s1 = self.seq.load(Ordering::Acquire);
41 let c0 = f64::from_bits(self.c0.load(Ordering::Relaxed));
42 let c1 = f64::from_bits(self.c1.load(Ordering::Relaxed));
43 let s2 = self.seq.load(Ordering::Acquire);
44 if s1 == s2 && s1 % 2 == 0 {
45 return [c0, c1];
46 }
47 }
48 }
49
50 pub fn store(&self, x: f64, y: f64) {
52 let s = self.seq.load(Ordering::Relaxed);
53 self.seq.store(s + 1, Ordering::Release); self.c0.store(x.to_bits(), Ordering::Relaxed);
55 self.c1.store(y.to_bits(), Ordering::Relaxed);
56 self.seq.store(s + 2, Ordering::Release); }
58}
59
60pub struct AtomicComplex(AtomicF64x2);
62
63impl AtomicComplex {
64 #[inline]
66 pub fn new(z: Complex<f64>) -> Self {
67 AtomicComplex(AtomicF64x2::new(z.re, z.im))
68 }
69
70 pub fn load(&self) -> Complex<f64> {
72 let [re, im] = self.0.load();
73 Complex::new(re, im)
74 }
75
76 #[inline]
78 pub fn store(&self, z: Complex<f64>) {
79 self.0.store(z.re, z.im);
80 }
81}
82
83pub struct AtomicVec2(AtomicF64x2);
85
86impl AtomicVec2 {
87 #[inline]
89 pub fn new(v: Vector2<f64>) -> Self {
90 AtomicVec2(AtomicF64x2::new(v.x_, v.y_))
91 }
92
93 pub fn load(&self) -> Vector2<f64> {
95 let [x, y] = self.0.load();
96 Vector2::new(x, y)
97 }
98
99 #[inline]
101 pub fn store(&self, v: Vector2<f64>) {
102 self.0.store(v.x_, v.y_);
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_atomic_f64x2_roundtrip() {
112 let slot = AtomicF64x2::new(1.0, 2.0);
113 assert_eq!(slot.load(), [1.0, 2.0]);
114 slot.store(3.0, 4.0);
115 assert_eq!(slot.load(), [3.0, 4.0]);
116 }
117
118 #[test]
119 fn test_atomic_complex_roundtrip() {
120 let slot = AtomicComplex::new(Complex::new(1.0, -2.5));
121 assert_eq!(slot.load(), Complex::new(1.0, -2.5));
122 slot.store(Complex::new(-3.0, 0.5));
123 assert_eq!(slot.load(), Complex::new(-3.0, 0.5));
124 }
125
126 #[test]
127 fn test_atomic_vec2_roundtrip() {
128 let slot = AtomicVec2::new(Vector2::new(1.0, 2.0));
129 assert_eq!(slot.load(), Vector2::new(1.0, 2.0));
130 slot.store(Vector2::new(3.0, 4.0));
131 assert_eq!(slot.load(), Vector2::new(3.0, 4.0));
132 }
133}