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/// # Example
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    /// # Example
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    /// # Example
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    #[inline]
144    pub fn load(&self) -> f32 {
145        f32::from_bits(self.inner.load(Ordering::Acquire))
146    }
147
148    /// Sets a new value.
149    ///
150    /// # Memory Ordering
151    ///
152    /// Uses `Release` ordering on the underlying `AtomicU32`. This ensures
153    /// that all prior writes in this thread are visible to other threads
154    /// that perform an `Acquire` load.
155    ///
156    /// # Parameters
157    ///
158    /// * `value` - The new value to set.
159    ///
160    /// # Example
161    ///
162    /// ```rust
163    /// use qubit_atomic::Atomic;
164    ///
165    /// let atomic = Atomic::<f32>::new(0.0);
166    /// atomic.store(3.14);
167    /// assert_eq!(atomic.load(), 3.14);
168    /// ```
169    #[inline]
170    pub fn store(&self, value: f32) {
171        self.inner.store(value.to_bits(), Ordering::Release);
172    }
173
174    /// Swaps the current value with a new value, returning the old value.
175    ///
176    /// # Memory Ordering
177    ///
178    /// Uses `AcqRel` ordering on the underlying `AtomicU32`. This provides
179    /// full synchronization for this read-modify-write operation.
180    ///
181    /// # Parameters
182    ///
183    /// * `value` - The new value to swap in.
184    ///
185    /// # Returns
186    ///
187    /// The old value.
188    ///
189    /// # Example
190    ///
191    /// ```rust
192    /// use qubit_atomic::Atomic;
193    ///
194    /// let atomic = Atomic::<f32>::new(1.0);
195    /// let old = atomic.swap(2.0);
196    /// assert_eq!(old, 1.0);
197    /// assert_eq!(atomic.load(), 2.0);
198    /// ```
199    #[inline]
200    pub fn swap(&self, value: f32) -> f32 {
201        f32::from_bits(self.inner.swap(value.to_bits(), Ordering::AcqRel))
202    }
203
204    /// Compares and sets the value atomically.
205    ///
206    /// If the current value equals `current`, sets it to `new` and returns
207    /// `Ok(())`. Otherwise, returns `Err(actual)` where `actual` is the
208    /// current value.
209    ///
210    /// Comparison uses the exact raw bit pattern produced by
211    /// [`f32::to_bits`], not [`PartialEq`].
212    ///
213    /// # Memory Ordering
214    ///
215    /// - **Success**: Uses `AcqRel` ordering on the underlying `AtomicU32` to
216    ///   ensure full synchronization when the exchange succeeds.
217    /// - **Failure**: Uses `Acquire` ordering to observe the actual value
218    ///   written by another thread.
219    ///
220    /// # Parameters
221    ///
222    /// * `current` - The expected current value.
223    /// * `new` - The new value to set if current matches.
224    ///
225    /// # Returns
226    ///
227    /// `Ok(())` when the value was replaced.
228    ///
229    /// # Errors
230    ///
231    /// Returns `Err(actual)` with the observed value when the raw-bit
232    /// comparison fails. In that case, `new` is not stored.
233    ///
234    /// # Warning
235    ///
236    /// NaN values compare by raw bits. A stored NaN and `current` must have
237    /// the same payload bits for the CAS to succeed.
238    ///
239    /// # Example
240    ///
241    /// ```rust
242    /// use qubit_atomic::Atomic;
243    ///
244    /// let atomic = Atomic::<f32>::new(1.0);
245    /// assert!(atomic.compare_set(1.0, 2.0).is_ok());
246    /// assert_eq!(atomic.load(), 2.0);
247    /// ```
248    #[inline]
249    pub fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
250        self.inner
251            .compare_exchange(
252                current.to_bits(),
253                new.to_bits(),
254                Ordering::AcqRel,
255                Ordering::Acquire,
256            )
257            .map(|_| ())
258            .map_err(f32::from_bits)
259    }
260
261    /// Weak version of compare-and-set.
262    ///
263    /// May spuriously fail even when the comparison succeeds. Should be used
264    /// in a loop.
265    ///
266    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
267    /// Comparison uses the exact raw bit pattern produced by
268    /// [`f32::to_bits`].
269    ///
270    /// # Parameters
271    ///
272    /// * `current` - The expected current value.
273    /// * `new` - The new value to set if current matches.
274    ///
275    /// # Returns
276    ///
277    /// `Ok(())` when the value was replaced.
278    ///
279    /// # Errors
280    ///
281    /// Returns `Err(actual)` with the observed value when the raw-bit
282    /// comparison fails, including possible spurious failures. In that case,
283    /// `new` is not stored.
284    ///
285    /// # Example
286    ///
287    /// ```rust
288    /// use qubit_atomic::Atomic;
289    ///
290    /// let atomic = Atomic::<f32>::new(1.0);
291    /// let mut current = atomic.load();
292    /// loop {
293    ///     match atomic.compare_set_weak(current, current + 1.0) {
294    ///         Ok(_) => break,
295    ///         Err(actual) => current = actual,
296    ///     }
297    /// }
298    /// assert_eq!(atomic.load(), 2.0);
299    /// ```
300    #[inline]
301    pub fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
302        self.inner
303            .compare_exchange_weak(
304                current.to_bits(),
305                new.to_bits(),
306                Ordering::AcqRel,
307                Ordering::Acquire,
308            )
309            .map(|_| ())
310            .map_err(f32::from_bits)
311    }
312
313    /// Compares and exchanges the value atomically, returning the previous
314    /// value.
315    ///
316    /// If the current value equals `current`, sets it to `new` and returns
317    /// the old value. Otherwise, returns the actual current value.
318    ///
319    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
320    ///
321    /// # Parameters
322    ///
323    /// * `current` - The expected current value.
324    /// * `new` - The new value to set if current matches.
325    ///
326    /// # Returns
327    ///
328    /// The value observed before the operation completed. If the returned
329    /// value has the same raw bits as `current`, the exchange succeeded;
330    /// otherwise it is the actual value that prevented the exchange.
331    ///
332    /// # Example
333    ///
334    /// ```rust
335    /// use qubit_atomic::Atomic;
336    ///
337    /// let atomic = Atomic::<f32>::new(1.0);
338    /// let prev = atomic.compare_and_exchange(1.0, 2.0);
339    /// assert_eq!(prev, 1.0);
340    /// assert_eq!(atomic.load(), 2.0);
341    /// ```
342    #[inline]
343    pub fn compare_and_exchange(&self, current: f32, new: f32) -> f32 {
344        match self.inner.compare_exchange(
345            current.to_bits(),
346            new.to_bits(),
347            Ordering::AcqRel,
348            Ordering::Acquire,
349        ) {
350            Ok(prev_bits) => f32::from_bits(prev_bits),
351            Err(actual_bits) => f32::from_bits(actual_bits),
352        }
353    }
354
355    /// Weak version of compare-and-exchange.
356    ///
357    /// May spuriously fail even when the comparison succeeds. Should be used
358    /// in a loop.
359    ///
360    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
361    ///
362    /// # Parameters
363    ///
364    /// * `current` - The expected current value.
365    /// * `new` - The new value to set if current matches.
366    ///
367    /// # Returns
368    ///
369    /// `Ok(previous)` when the value was replaced, or `Err(actual)` when the
370    /// comparison failed, including possible spurious failure. Values preserve
371    /// their exact raw bit patterns.
372    ///
373    /// # Example
374    ///
375    /// ```rust
376    /// use qubit_atomic::Atomic;
377    ///
378    /// let atomic = Atomic::<f32>::new(1.0);
379    /// let mut current = atomic.load();
380    /// loop {
381    ///     match atomic.compare_and_exchange_weak(current, current + 1.0) {
382    ///         Ok(_) => break,
383    ///         Err(actual) => current = actual,
384    ///     }
385    /// }
386    /// assert_eq!(atomic.load(), 2.0);
387    /// ```
388    #[inline]
389    pub fn compare_and_exchange_weak(
390        &self,
391        current: f32,
392        new: f32,
393    ) -> Result<f32, f32> {
394        self.inner
395            .compare_exchange_weak(
396                current.to_bits(),
397                new.to_bits(),
398                Ordering::AcqRel,
399                Ordering::Acquire,
400            )
401            .map(f32::from_bits)
402            .map_err(f32::from_bits)
403    }
404
405    /// Atomically adds a value, returning the old value.
406    ///
407    /// # Memory Ordering
408    ///
409    /// Internally uses a CAS loop with `compare_set_weak`, which uses
410    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
411    /// eventual consistency even under high contention.
412    ///
413    /// # Performance
414    ///
415    /// May be slow in high-contention scenarios due to the CAS loop.
416    /// Consider using atomic integers if performance is critical.
417    ///
418    /// # Parameters
419    ///
420    /// * `delta` - The value to add.
421    ///
422    /// # Returns
423    ///
424    /// The old value before adding.
425    ///
426    /// # Example
427    ///
428    /// ```rust
429    /// use qubit_atomic::Atomic;
430    ///
431    /// let atomic = Atomic::<f32>::new(10.0);
432    /// let old = atomic.fetch_add(5.5);
433    /// assert_eq!(old, 10.0);
434    /// assert_eq!(atomic.load(), 15.5);
435    /// ```
436    #[inline]
437    pub fn fetch_add(&self, delta: f32) -> f32 {
438        self.fetch_update(|current| current + delta)
439    }
440
441    /// Atomically subtracts a value, returning the old value.
442    ///
443    /// # Memory Ordering
444    ///
445    /// Internally uses a CAS loop with `compare_set_weak`, which uses
446    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
447    /// eventual consistency even under high contention.
448    ///
449    /// # Parameters
450    ///
451    /// * `delta` - The value to subtract.
452    ///
453    /// # Returns
454    ///
455    /// The old value before subtracting.
456    ///
457    /// # Example
458    ///
459    /// ```rust
460    /// use qubit_atomic::Atomic;
461    ///
462    /// let atomic = Atomic::<f32>::new(10.0);
463    /// let old = atomic.fetch_sub(3.5);
464    /// assert_eq!(old, 10.0);
465    /// assert_eq!(atomic.load(), 6.5);
466    /// ```
467    #[inline]
468    pub fn fetch_sub(&self, delta: f32) -> f32 {
469        self.fetch_update(|current| current - delta)
470    }
471
472    /// Atomically multiplies by a factor, returning the old value.
473    ///
474    /// # Memory Ordering
475    ///
476    /// Internally uses a CAS loop with `compare_set_weak`, which uses
477    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
478    /// eventual consistency even under high contention.
479    ///
480    /// # Parameters
481    ///
482    /// * `factor` - The factor to multiply by.
483    ///
484    /// # Returns
485    ///
486    /// The old value before multiplying.
487    ///
488    /// # Example
489    ///
490    /// ```rust
491    /// use qubit_atomic::Atomic;
492    ///
493    /// let atomic = Atomic::<f32>::new(10.0);
494    /// let old = atomic.fetch_mul(2.5);
495    /// assert_eq!(old, 10.0);
496    /// assert_eq!(atomic.load(), 25.0);
497    /// ```
498    #[inline]
499    pub fn fetch_mul(&self, factor: f32) -> f32 {
500        self.fetch_update(|current| current * factor)
501    }
502
503    /// Atomically divides by a divisor, returning the old value.
504    ///
505    /// # Memory Ordering
506    ///
507    /// Internally uses a CAS loop with `compare_set_weak`, which uses
508    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
509    /// eventual consistency even under high contention.
510    ///
511    /// # Parameters
512    ///
513    /// * `divisor` - The divisor to divide by.
514    ///
515    /// # Returns
516    ///
517    /// The old value before dividing.
518    ///
519    /// # Example
520    ///
521    /// ```rust
522    /// use qubit_atomic::Atomic;
523    ///
524    /// let atomic = Atomic::<f32>::new(10.0);
525    /// let old = atomic.fetch_div(2.0);
526    /// assert_eq!(old, 10.0);
527    /// assert_eq!(atomic.load(), 5.0);
528    /// ```
529    #[inline]
530    pub fn fetch_div(&self, divisor: f32) -> f32 {
531        self.fetch_update(|current| current / divisor)
532    }
533
534    /// Updates the value using a function, returning the old value.
535    ///
536    /// # Memory Ordering
537    ///
538    /// Internally uses a CAS loop with `compare_set_weak`, which uses
539    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
540    /// eventual consistency even under high contention.
541    ///
542    /// # Parameters
543    ///
544    /// * `f` - A function that takes the current value and returns the new
545    ///   value.
546    ///
547    /// # Returns
548    ///
549    /// The old value before the update.
550    ///
551    /// The closure may be called more than once when concurrent updates cause
552    /// CAS retries.
553    ///
554    /// # Example
555    ///
556    /// ```rust
557    /// use qubit_atomic::Atomic;
558    ///
559    /// let atomic = Atomic::<f32>::new(10.0);
560    /// let old = atomic.fetch_update(|x| x * 2.0);
561    /// assert_eq!(old, 10.0);
562    /// assert_eq!(atomic.load(), 20.0);
563    /// ```
564    #[inline]
565    pub fn fetch_update<F>(&self, mut f: F) -> f32
566    where
567        F: FnMut(f32) -> f32,
568    {
569        let mut current = self.load();
570        loop {
571            let new = f(current);
572            match self.compare_set_weak(current, new) {
573                Ok(_) => return current,
574                Err(actual) => current = actual,
575            }
576        }
577    }
578
579    /// Updates the value using a function, returning the new value.
580    ///
581    /// Internally uses a CAS loop until the update succeeds.
582    ///
583    /// # Parameters
584    ///
585    /// * `f` - A function that takes the current value and returns the new
586    ///   value.
587    ///
588    /// # Returns
589    ///
590    /// The value committed by the successful update.
591    ///
592    /// The closure may be called more than once when concurrent updates cause
593    /// CAS retries.
594    ///
595    /// # Example
596    ///
597    /// ```rust
598    /// use qubit_atomic::Atomic;
599    ///
600    /// let atomic = Atomic::<f32>::new(10.0);
601    /// let new = atomic.update_and_get(|x| x * 2.0);
602    /// assert_eq!(new, 20.0);
603    /// assert_eq!(atomic.load(), 20.0);
604    /// ```
605    #[inline]
606    pub fn update_and_get<F>(&self, mut f: F) -> f32
607    where
608        F: FnMut(f32) -> f32,
609    {
610        let mut current = self.load();
611        loop {
612            let new = f(current);
613            match self.compare_set_weak(current, new) {
614                Ok(_) => return new,
615                Err(actual) => current = actual,
616            }
617        }
618    }
619
620    /// Conditionally updates the value using a function.
621    ///
622    /// Internally uses a CAS loop until the update succeeds or the closure
623    /// rejects the current value by returning `None`.
624    ///
625    /// # Parameters
626    ///
627    /// * `f` - A function that takes the current value and returns the new
628    ///   value, or `None` to leave the value unchanged.
629    ///
630    /// # Returns
631    ///
632    /// `Some(old_value)` when the update succeeds, or `None` when `f` rejects
633    /// the observed current value.
634    ///
635    /// The closure may be called more than once when concurrent updates cause
636    /// CAS retries.
637    ///
638    /// # Example
639    ///
640    /// ```rust
641    /// use qubit_atomic::Atomic;
642    ///
643    /// let atomic = Atomic::<f32>::new(1.5);
644    /// assert_eq!(atomic.try_update(|x| (x > 0.0).then_some(x * 2.0)), Some(1.5));
645    /// assert_eq!(atomic.load(), 3.0);
646    /// assert_eq!(atomic.try_update(|x| (x < 0.0).then_some(x * 2.0)), None);
647    /// assert_eq!(atomic.load(), 3.0);
648    /// ```
649    #[inline]
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    /// # Example
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    #[inline]
701    pub fn try_update_and_get<F>(&self, mut f: F) -> Option<f32>
702    where
703        F: FnMut(f32) -> Option<f32>,
704    {
705        let mut current = self.load();
706        loop {
707            let new = f(current)?;
708            match self.compare_set_weak(current, new) {
709                Ok(_) => return Some(new),
710                Err(actual) => current = actual,
711            }
712        }
713    }
714
715    /// Gets a reference to the underlying standard library atomic type.
716    ///
717    /// This allows direct access to the standard library's atomic operations
718    /// for advanced use cases that require fine-grained control over memory
719    /// ordering.
720    ///
721    /// # Memory Ordering
722    ///
723    /// When using the returned reference, you have full control over memory
724    /// ordering. Remember to use `f32::to_bits()` and `f32::from_bits()` for
725    /// conversions.
726    ///
727    /// # Returns
728    ///
729    /// A reference to the underlying `std::sync::atomic::AtomicU32`.
730    ///
731    /// # Example
732    ///
733    /// ```rust
734    /// use qubit_atomic::Atomic;
735    /// use std::sync::atomic::Ordering;
736    ///
737    /// let atomic = Atomic::<f32>::new(0.0);
738    /// atomic.inner().store(3.14_f32.to_bits(), Ordering::Relaxed);
739    /// let bits = atomic.inner().load(Ordering::Relaxed);
740    /// assert_eq!(f32::from_bits(bits), 3.14);
741    /// ```
742    #[inline]
743    pub fn inner(&self) -> &AtomicU32 {
744        &self.inner
745    }
746}
747
748impl AtomicOps for AtomicF32 {
749    type Value = f32;
750
751    #[inline]
752    fn load(&self) -> f32 {
753        self.load()
754    }
755
756    #[inline]
757    fn store(&self, value: f32) {
758        self.store(value);
759    }
760
761    #[inline]
762    fn swap(&self, value: f32) -> f32 {
763        self.swap(value)
764    }
765
766    #[inline]
767    fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
768        self.compare_set(current, new)
769    }
770
771    #[inline]
772    fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
773        self.compare_set_weak(current, new)
774    }
775
776    #[inline]
777    fn compare_exchange(&self, current: f32, new: f32) -> f32 {
778        self.compare_and_exchange(current, new)
779    }
780
781    #[inline]
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]
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]
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]
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]
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]
825    fn fetch_add(&self, delta: f32) -> f32 {
826        self.fetch_add(delta)
827    }
828
829    #[inline]
830    fn fetch_sub(&self, delta: f32) -> f32 {
831        self.fetch_sub(delta)
832    }
833
834    #[inline]
835    fn fetch_mul(&self, factor: f32) -> f32 {
836        self.fetch_mul(factor)
837    }
838
839    #[inline]
840    fn fetch_div(&self, divisor: f32) -> f32 {
841        self.fetch_div(divisor)
842    }
843}