Skip to main content

qubit_atomic/atomic/
atomic_f32.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! # Atomic 32-bit Floating Point
10//!
11//! Provides an easy-to-use atomic 32-bit floating point type with sensible
12//! default memory orderings. Implemented using bit conversion with AtomicU32.
13
14use std::sync::atomic::AtomicU32;
15use std::sync::atomic::Ordering;
16
17use crate::atomic::atomic_number_ops::AtomicNumberOps;
18use crate::atomic::atomic_ops::AtomicOps;
19
20/// Atomic 32-bit floating point number.
21///
22/// Provides easy-to-use atomic operations with automatic memory ordering
23/// selection. Implemented using `AtomicU32` with bit conversion.
24///
25/// # Memory Ordering Strategy
26///
27/// This type uses the same memory ordering strategy as atomic integers:
28///
29/// - **Read operations** (`load`): Use `Acquire` ordering to ensure visibility
30///   of prior writes from other threads.
31///
32/// - **Write operations** (`store`): Use `Release` ordering to ensure
33///   visibility of prior writes to other threads.
34///
35/// - **Read-Modify-Write operations** (`swap`, `compare_set`): Use `AcqRel`
36///   ordering for full synchronization.
37///
38/// - **CAS-based arithmetic** (`fetch_add`, `fetch_sub`, etc.): Use `AcqRel` on
39///   success and `Acquire` on failure within the CAS loop. The loop ensures
40///   eventual consistency.
41///
42/// # Implementation Details
43///
44/// Since hardware doesn't provide native atomic floating-point operations,
45/// this type is implemented using `AtomicU32` with `f32::to_bits()` and
46/// `f32::from_bits()` conversions. This preserves bit patterns exactly,
47/// including special values like NaN and infinity.
48///
49/// # Features
50///
51/// - Automatic memory ordering selection
52/// - Arithmetic operations via CAS loops
53/// - Inline API over raw-bit atomic storage and CAS loops
54/// - Access to underlying type via `inner()` for advanced use cases
55///
56/// # Limitations
57///
58/// - Arithmetic operations use CAS loops (slower than integer operations)
59/// - CAS comparisons use exact IEEE-754 bit patterns, so different NaN payloads
60///   and `0.0`/`-0.0` are treated as different values
61/// - No max/min operations (complex floating point semantics)
62///
63/// # Examples
64///
65/// ```rust
66/// use qubit_atomic::Atomic;
67/// use std::sync::Arc;
68/// use std::thread;
69///
70/// let sum = Arc::new(Atomic::<f32>::new(0.0));
71/// let mut handles = vec![];
72///
73/// for _ in 0..10 {
74///     let sum = sum.clone();
75///     let handle = thread::spawn(move || {
76///         for _ in 0..100 {
77///             sum.fetch_add(0.1);
78///         }
79///     });
80///     handles.push(handle);
81/// }
82///
83/// for handle in handles {
84///     handle.join().unwrap();
85/// }
86///
87/// // Note: Due to floating point precision, result may not be exactly 100.0
88/// let result = sum.load();
89/// assert!((result - 100.0).abs() < 0.01);
90/// ```
91#[repr(transparent)]
92pub struct AtomicF32 {
93    /// Raw-bit atomic storage for the `f32` value.
94    inner: AtomicU32,
95}
96
97impl AtomicF32 {
98    /// Creates a new atomic floating point number.
99    ///
100    /// # Parameters
101    ///
102    /// * `value` - The initial value.
103    ///
104    /// # Returns
105    ///
106    /// An atomic `f32` initialized to `value`.
107    ///
108    /// # Examples
109    ///
110    /// ```rust
111    /// use qubit_atomic::Atomic;
112    ///
113    /// let atomic = Atomic::<f32>::new(3.14);
114    /// assert_eq!(atomic.load(), 3.14);
115    /// ```
116    #[inline]
117    pub const fn new(value: f32) -> Self {
118        Self {
119            inner: AtomicU32::new(value.to_bits()),
120        }
121    }
122
123    /// Gets the current value.
124    ///
125    /// # Memory Ordering
126    ///
127    /// Uses `Acquire` ordering on the underlying `AtomicU32`. This ensures
128    /// that all writes from other threads that happened before a `Release`
129    /// store are visible after this load.
130    ///
131    /// # Returns
132    ///
133    /// The current value.
134    ///
135    /// # Examples
136    ///
137    /// ```rust
138    /// use qubit_atomic::Atomic;
139    ///
140    /// let atomic = Atomic::<f32>::new(3.14);
141    /// assert_eq!(atomic.load(), 3.14);
142    /// ```
143    #[must_use]
144    #[inline(always)]
145    pub fn load(&self) -> f32 {
146        f32::from_bits(self.inner.load(Ordering::Acquire))
147    }
148
149    /// Sets a new value.
150    ///
151    /// # Memory Ordering
152    ///
153    /// Uses `Release` ordering on the underlying `AtomicU32`. This ensures
154    /// that all prior writes in this thread are visible to other threads
155    /// that perform an `Acquire` load.
156    ///
157    /// # Parameters
158    ///
159    /// * `value` - The new value to set.
160    ///
161    /// # Examples
162    ///
163    /// ```rust
164    /// use qubit_atomic::Atomic;
165    ///
166    /// let atomic = Atomic::<f32>::new(0.0);
167    /// atomic.store(3.14);
168    /// assert_eq!(atomic.load(), 3.14);
169    /// ```
170    #[inline(always)]
171    pub fn store(&self, value: f32) {
172        self.inner.store(value.to_bits(), Ordering::Release);
173    }
174
175    /// Swaps the current value with a new value, returning the old value.
176    ///
177    /// # Memory Ordering
178    ///
179    /// Uses `AcqRel` ordering on the underlying `AtomicU32`. This provides
180    /// full synchronization for this read-modify-write operation.
181    ///
182    /// # Parameters
183    ///
184    /// * `value` - The new value to swap in.
185    ///
186    /// # Returns
187    ///
188    /// The old value.
189    ///
190    /// # Examples
191    ///
192    /// ```rust
193    /// use qubit_atomic::Atomic;
194    ///
195    /// let atomic = Atomic::<f32>::new(1.0);
196    /// let old = atomic.swap(2.0);
197    /// assert_eq!(old, 1.0);
198    /// assert_eq!(atomic.load(), 2.0);
199    /// ```
200    #[must_use]
201    #[inline(always)]
202    pub fn swap(&self, value: f32) -> f32 {
203        f32::from_bits(self.inner.swap(value.to_bits(), Ordering::AcqRel))
204    }
205
206    /// Compares and sets the value atomically.
207    ///
208    /// If the current value equals `current`, sets it to `new` and returns
209    /// `Ok(())`. Otherwise, returns `Err(actual)` where `actual` is the
210    /// current value.
211    ///
212    /// Comparison uses the exact raw bit pattern produced by
213    /// [`f32::to_bits`], not [`PartialEq`].
214    ///
215    /// # Memory Ordering
216    ///
217    /// - **Success**: Uses `AcqRel` ordering on the underlying `AtomicU32` to
218    ///   ensure full synchronization when the exchange succeeds.
219    /// - **Failure**: Uses `Acquire` ordering to observe the actual value
220    ///   written by another thread.
221    ///
222    /// # Parameters
223    ///
224    /// * `current` - The expected current value.
225    /// * `new` - The new value to set if current matches.
226    ///
227    /// # Returns
228    ///
229    /// `Ok(())` when the value was replaced.
230    ///
231    /// # Errors
232    ///
233    /// Returns `Err(actual)` with the observed value when the raw-bit
234    /// comparison fails. In that case, `new` is not stored.
235    ///
236    /// # Warning
237    ///
238    /// NaN values compare by raw bits. A stored NaN and `current` must have
239    /// the same payload bits for the CAS to succeed.
240    ///
241    /// # Examples
242    ///
243    /// ```rust
244    /// use qubit_atomic::Atomic;
245    ///
246    /// let atomic = Atomic::<f32>::new(1.0);
247    /// assert!(atomic.compare_set(1.0, 2.0).is_ok());
248    /// assert_eq!(atomic.load(), 2.0);
249    /// ```
250    #[inline(always)]
251    pub fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
252        self.inner
253            .compare_exchange(
254                current.to_bits(),
255                new.to_bits(),
256                Ordering::AcqRel,
257                Ordering::Acquire,
258            )
259            .map(|_| ())
260            .map_err(f32::from_bits)
261    }
262
263    /// Weak version of compare-and-set.
264    ///
265    /// May spuriously fail even when the comparison succeeds. Should be used
266    /// in a loop.
267    ///
268    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
269    /// Comparison uses the exact raw bit pattern produced by
270    /// [`f32::to_bits`].
271    ///
272    /// # Parameters
273    ///
274    /// * `current` - The expected current value.
275    /// * `new` - The new value to set if current matches.
276    ///
277    /// # Returns
278    ///
279    /// `Ok(())` when the value was replaced.
280    ///
281    /// # Errors
282    ///
283    /// Returns `Err(actual)` with the observed value when the raw-bit
284    /// comparison fails, including possible spurious failures. In that case,
285    /// `new` is not stored.
286    ///
287    /// # Examples
288    ///
289    /// ```rust
290    /// use qubit_atomic::Atomic;
291    ///
292    /// let atomic = Atomic::<f32>::new(1.0);
293    /// let mut current = atomic.load();
294    /// loop {
295    ///     match atomic.compare_set_weak(current, current + 1.0) {
296    ///         Ok(_) => break,
297    ///         Err(actual) => current = actual,
298    ///     }
299    /// }
300    /// assert_eq!(atomic.load(), 2.0);
301    /// ```
302    #[inline(always)]
303    pub fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
304        self.inner
305            .compare_exchange_weak(
306                current.to_bits(),
307                new.to_bits(),
308                Ordering::AcqRel,
309                Ordering::Acquire,
310            )
311            .map(|_| ())
312            .map_err(f32::from_bits)
313    }
314
315    /// Compares and exchanges the value atomically, returning the previous
316    /// value.
317    ///
318    /// If the current value equals `current`, sets it to `new` and returns
319    /// the old value. Otherwise, returns the actual current value.
320    ///
321    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
322    ///
323    /// # Parameters
324    ///
325    /// * `current` - The expected current value.
326    /// * `new` - The new value to set if current matches.
327    ///
328    /// # Returns
329    ///
330    /// The value observed before the operation completed. If the returned
331    /// value has the same raw bits as `current`, the exchange succeeded;
332    /// otherwise it is the actual value that prevented the exchange.
333    ///
334    /// # Examples
335    ///
336    /// ```rust
337    /// use qubit_atomic::Atomic;
338    ///
339    /// let atomic = Atomic::<f32>::new(1.0);
340    /// let prev = atomic.compare_and_exchange(1.0, 2.0);
341    /// assert_eq!(prev, 1.0);
342    /// assert_eq!(atomic.load(), 2.0);
343    /// ```
344    #[must_use]
345    #[inline]
346    pub fn compare_and_exchange(&self, current: f32, new: f32) -> f32 {
347        match self.inner.compare_exchange(
348            current.to_bits(),
349            new.to_bits(),
350            Ordering::AcqRel,
351            Ordering::Acquire,
352        ) {
353            Ok(prev_bits) => f32::from_bits(prev_bits),
354            Err(actual_bits) => f32::from_bits(actual_bits),
355        }
356    }
357
358    /// Weak version of compare-and-exchange.
359    ///
360    /// May spuriously fail even when the comparison succeeds. Should be used
361    /// in a loop.
362    ///
363    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
364    ///
365    /// # Parameters
366    ///
367    /// * `current` - The expected current value.
368    /// * `new` - The new value to set if current matches.
369    ///
370    /// # Returns
371    ///
372    /// `Ok(previous)` when the value was replaced, or `Err(actual)` when the
373    /// comparison failed, including possible spurious failure. Values preserve
374    /// their exact raw bit patterns.
375    ///
376    /// # Examples
377    ///
378    /// ```rust
379    /// use qubit_atomic::Atomic;
380    ///
381    /// let atomic = Atomic::<f32>::new(1.0);
382    /// let mut current = atomic.load();
383    /// loop {
384    ///     match atomic.compare_and_exchange_weak(current, current + 1.0) {
385    ///         Ok(_) => break,
386    ///         Err(actual) => current = actual,
387    ///     }
388    /// }
389    /// assert_eq!(atomic.load(), 2.0);
390    /// ```
391    #[inline(always)]
392    pub fn compare_and_exchange_weak(
393        &self,
394        current: f32,
395        new: f32,
396    ) -> Result<f32, f32> {
397        self.inner
398            .compare_exchange_weak(
399                current.to_bits(),
400                new.to_bits(),
401                Ordering::AcqRel,
402                Ordering::Acquire,
403            )
404            .map(f32::from_bits)
405            .map_err(f32::from_bits)
406    }
407
408    /// Atomically adds a value, returning the old value.
409    ///
410    /// # Memory Ordering
411    ///
412    /// Internally uses a CAS loop with `compare_set_weak`, which uses
413    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
414    /// eventual consistency even under high contention.
415    ///
416    /// # Performance
417    ///
418    /// May be slow in high-contention scenarios due to the CAS loop.
419    /// Consider using atomic integers if performance is critical.
420    ///
421    /// # Parameters
422    ///
423    /// * `delta` - The value to add.
424    ///
425    /// # Returns
426    ///
427    /// The old value before adding.
428    ///
429    /// # Examples
430    ///
431    /// ```rust
432    /// use qubit_atomic::Atomic;
433    ///
434    /// let atomic = Atomic::<f32>::new(10.0);
435    /// let old = atomic.fetch_add(5.5);
436    /// assert_eq!(old, 10.0);
437    /// assert_eq!(atomic.load(), 15.5);
438    /// ```
439    #[inline(always)]
440    pub fn fetch_add(&self, delta: f32) -> f32 {
441        self.fetch_update(|current| current + delta)
442    }
443
444    /// Atomically subtracts a value, returning the old value.
445    ///
446    /// # Memory Ordering
447    ///
448    /// Internally uses a CAS loop with `compare_set_weak`, which uses
449    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
450    /// eventual consistency even under high contention.
451    ///
452    /// # Parameters
453    ///
454    /// * `delta` - The value to subtract.
455    ///
456    /// # Returns
457    ///
458    /// The old value before subtracting.
459    ///
460    /// # Examples
461    ///
462    /// ```rust
463    /// use qubit_atomic::Atomic;
464    ///
465    /// let atomic = Atomic::<f32>::new(10.0);
466    /// let old = atomic.fetch_sub(3.5);
467    /// assert_eq!(old, 10.0);
468    /// assert_eq!(atomic.load(), 6.5);
469    /// ```
470    #[inline(always)]
471    pub fn fetch_sub(&self, delta: f32) -> f32 {
472        self.fetch_update(|current| current - delta)
473    }
474
475    /// Atomically multiplies by a factor, returning the old value.
476    ///
477    /// # Memory Ordering
478    ///
479    /// Internally uses a CAS loop with `compare_set_weak`, which uses
480    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
481    /// eventual consistency even under high contention.
482    ///
483    /// # Parameters
484    ///
485    /// * `factor` - The factor to multiply by.
486    ///
487    /// # Returns
488    ///
489    /// The old value before multiplying.
490    ///
491    /// # Examples
492    ///
493    /// ```rust
494    /// use qubit_atomic::Atomic;
495    ///
496    /// let atomic = Atomic::<f32>::new(10.0);
497    /// let old = atomic.fetch_mul(2.5);
498    /// assert_eq!(old, 10.0);
499    /// assert_eq!(atomic.load(), 25.0);
500    /// ```
501    #[inline(always)]
502    pub fn fetch_mul(&self, factor: f32) -> f32 {
503        self.fetch_update(|current| current * factor)
504    }
505
506    /// Atomically divides by a divisor, returning the old value.
507    ///
508    /// # Memory Ordering
509    ///
510    /// Internally uses a CAS loop with `compare_set_weak`, which uses
511    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
512    /// eventual consistency even under high contention.
513    ///
514    /// # Parameters
515    ///
516    /// * `divisor` - The divisor to divide by.
517    ///
518    /// # Returns
519    ///
520    /// The old value before dividing.
521    ///
522    /// # Examples
523    ///
524    /// ```rust
525    /// use qubit_atomic::Atomic;
526    ///
527    /// let atomic = Atomic::<f32>::new(10.0);
528    /// let old = atomic.fetch_div(2.0);
529    /// assert_eq!(old, 10.0);
530    /// assert_eq!(atomic.load(), 5.0);
531    /// ```
532    #[inline(always)]
533    pub fn fetch_div(&self, divisor: f32) -> f32 {
534        self.fetch_update(|current| current / divisor)
535    }
536
537    /// Updates the value using a function, returning the old value.
538    ///
539    /// # Memory Ordering
540    ///
541    /// Internally uses a CAS loop with `compare_set_weak`, which uses
542    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
543    /// eventual consistency even under high contention.
544    ///
545    /// # Parameters
546    ///
547    /// * `f` - A function that takes the current value and returns the new
548    ///   value.
549    ///
550    /// # Returns
551    ///
552    /// The old value before the update.
553    ///
554    /// The closure may be called more than once when concurrent updates cause
555    /// CAS retries.
556    ///
557    /// # Examples
558    ///
559    /// ```rust
560    /// use qubit_atomic::Atomic;
561    ///
562    /// let atomic = Atomic::<f32>::new(10.0);
563    /// let old = atomic.fetch_update(|x| x * 2.0);
564    /// assert_eq!(old, 10.0);
565    /// assert_eq!(atomic.load(), 20.0);
566    /// ```
567    pub fn fetch_update<F>(&self, mut f: F) -> f32
568    where
569        F: FnMut(f32) -> f32,
570    {
571        let mut current = self.load();
572        loop {
573            let new = f(current);
574            match self.compare_set_weak(current, new) {
575                Ok(_) => return current,
576                Err(actual) => current = actual,
577            }
578        }
579    }
580
581    /// Updates the value using a function, returning the new value.
582    ///
583    /// Internally uses a CAS loop until the update succeeds.
584    ///
585    /// # Parameters
586    ///
587    /// * `f` - A function that takes the current value and returns the new
588    ///   value.
589    ///
590    /// # Returns
591    ///
592    /// The value committed by the successful update.
593    ///
594    /// The closure may be called more than once when concurrent updates cause
595    /// CAS retries.
596    ///
597    /// # Examples
598    ///
599    /// ```rust
600    /// use qubit_atomic::Atomic;
601    ///
602    /// let atomic = Atomic::<f32>::new(10.0);
603    /// let new = atomic.update_and_get(|x| x * 2.0);
604    /// assert_eq!(new, 20.0);
605    /// assert_eq!(atomic.load(), 20.0);
606    /// ```
607    pub fn update_and_get<F>(&self, mut f: F) -> f32
608    where
609        F: FnMut(f32) -> f32,
610    {
611        let mut current = self.load();
612        loop {
613            let new = f(current);
614            match self.compare_set_weak(current, new) {
615                Ok(_) => return new,
616                Err(actual) => current = actual,
617            }
618        }
619    }
620
621    /// Conditionally updates the value using a function.
622    ///
623    /// Internally uses a CAS loop until the update succeeds or the closure
624    /// rejects the current value by returning `None`.
625    ///
626    /// # Parameters
627    ///
628    /// * `f` - A function that takes the current value and returns the new
629    ///   value, or `None` to leave the value unchanged.
630    ///
631    /// # Returns
632    ///
633    /// `Some(old_value)` when the update succeeds, or `None` when `f` rejects
634    /// the observed current value.
635    ///
636    /// The closure may be called more than once when concurrent updates cause
637    /// CAS retries.
638    ///
639    /// # Examples
640    ///
641    /// ```rust
642    /// use qubit_atomic::Atomic;
643    ///
644    /// let atomic = Atomic::<f32>::new(1.5);
645    /// assert_eq!(atomic.try_update(|x| (x > 0.0).then_some(x * 2.0)), Some(1.5));
646    /// assert_eq!(atomic.load(), 3.0);
647    /// assert_eq!(atomic.try_update(|x| (x < 0.0).then_some(x * 2.0)), None);
648    /// assert_eq!(atomic.load(), 3.0);
649    /// ```
650    pub fn try_update<F>(&self, mut f: F) -> Option<f32>
651    where
652        F: FnMut(f32) -> Option<f32>,
653    {
654        let mut current = self.load();
655        loop {
656            let new = f(current)?;
657            match self.compare_set_weak(current, new) {
658                Ok(_) => return Some(current),
659                Err(actual) => current = actual,
660            }
661        }
662    }
663
664    /// Conditionally updates the value using a function, returning the new
665    /// value.
666    ///
667    /// Internally uses a CAS loop until the update succeeds or the closure
668    /// rejects the current value by returning `None`.
669    ///
670    /// # Parameters
671    ///
672    /// * `f` - A function that takes the current value and returns the new
673    ///   value, or `None` to leave the value unchanged.
674    ///
675    /// # Returns
676    ///
677    /// `Some(new_value)` when the update succeeds, or `None` when `f` rejects
678    /// the observed current value.
679    ///
680    /// The closure may be called more than once when concurrent updates cause
681    /// CAS retries.
682    ///
683    /// # Examples
684    ///
685    /// ```rust
686    /// use qubit_atomic::Atomic;
687    ///
688    /// let atomic = Atomic::<f32>::new(1.5);
689    /// assert_eq!(
690    ///     atomic.try_update_and_get(|x| (x > 0.0).then_some(x * 2.0)),
691    ///     Some(3.0),
692    /// );
693    /// assert_eq!(atomic.load(), 3.0);
694    /// assert_eq!(
695    ///     atomic.try_update_and_get(|x| (x < 0.0).then_some(x * 2.0)),
696    ///     None,
697    /// );
698    /// assert_eq!(atomic.load(), 3.0);
699    /// ```
700    pub fn try_update_and_get<F>(&self, mut f: F) -> Option<f32>
701    where
702        F: FnMut(f32) -> Option<f32>,
703    {
704        let mut current = self.load();
705        loop {
706            let new = f(current)?;
707            match self.compare_set_weak(current, new) {
708                Ok(_) => return Some(new),
709                Err(actual) => current = actual,
710            }
711        }
712    }
713
714    /// Gets a reference to the underlying standard library atomic type.
715    ///
716    /// This allows direct access to the standard library's atomic operations
717    /// for advanced use cases that require fine-grained control over memory
718    /// ordering.
719    ///
720    /// # Memory Ordering
721    ///
722    /// When using the returned reference, you have full control over memory
723    /// ordering. Remember to use `f32::to_bits()` and `f32::from_bits()` for
724    /// conversions.
725    ///
726    /// # Returns
727    ///
728    /// A reference to the underlying `std::sync::atomic::AtomicU32`.
729    ///
730    /// # Examples
731    ///
732    /// ```rust
733    /// use qubit_atomic::Atomic;
734    /// use std::sync::atomic::Ordering;
735    ///
736    /// let atomic = Atomic::<f32>::new(0.0);
737    /// atomic.inner().store(3.14_f32.to_bits(), Ordering::Relaxed);
738    /// let bits = atomic.inner().load(Ordering::Relaxed);
739    /// assert_eq!(f32::from_bits(bits), 3.14);
740    /// ```
741    #[must_use]
742    #[inline(always)]
743    pub fn inner(&self) -> &AtomicU32 {
744        &self.inner
745    }
746}
747
748impl AtomicOps for AtomicF32 {
749    type Value = f32;
750
751    #[inline(always)]
752    fn load(&self) -> f32 {
753        self.load()
754    }
755
756    #[inline(always)]
757    fn store(&self, value: f32) {
758        self.store(value);
759    }
760
761    #[inline(always)]
762    fn swap(&self, value: f32) -> f32 {
763        self.swap(value)
764    }
765
766    #[inline(always)]
767    fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
768        self.compare_set(current, new)
769    }
770
771    #[inline(always)]
772    fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
773        self.compare_set_weak(current, new)
774    }
775
776    #[inline(always)]
777    fn compare_exchange(&self, current: f32, new: f32) -> f32 {
778        self.compare_and_exchange(current, new)
779    }
780
781    #[inline(always)]
782    fn compare_exchange_weak(
783        &self,
784        current: f32,
785        new: f32,
786    ) -> Result<f32, f32> {
787        self.compare_and_exchange_weak(current, new)
788    }
789
790    #[inline(always)]
791    fn fetch_update<F>(&self, f: F) -> f32
792    where
793        F: FnMut(f32) -> f32,
794    {
795        self.fetch_update(f)
796    }
797
798    #[inline(always)]
799    fn update_and_get<F>(&self, f: F) -> f32
800    where
801        F: FnMut(f32) -> f32,
802    {
803        self.update_and_get(f)
804    }
805
806    #[inline(always)]
807    fn try_update<F>(&self, f: F) -> Option<f32>
808    where
809        F: FnMut(f32) -> Option<f32>,
810    {
811        self.try_update(f)
812    }
813
814    #[inline(always)]
815    fn try_update_and_get<F>(&self, f: F) -> Option<f32>
816    where
817        F: FnMut(f32) -> Option<f32>,
818    {
819        self.try_update_and_get(f)
820    }
821}
822
823impl AtomicNumberOps for AtomicF32 {
824    #[inline(always)]
825    fn fetch_add(&self, delta: f32) -> f32 {
826        self.fetch_add(delta)
827    }
828
829    #[inline(always)]
830    fn fetch_sub(&self, delta: f32) -> f32 {
831        self.fetch_sub(delta)
832    }
833
834    #[inline(always)]
835    fn fetch_mul(&self, factor: f32) -> f32 {
836        self.fetch_mul(factor)
837    }
838
839    #[inline(always)]
840    fn fetch_div(&self, divisor: f32) -> f32 {
841        self.fetch_div(divisor)
842    }
843}