Skip to main content

qubit_atomic/atomic/
atomic_f32.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11//! # Atomic 32-bit Floating Point
12//!
13//! Provides an easy-to-use atomic 32-bit floating point type with sensible
14//! default memory orderings. Implemented using bit conversion with AtomicU32.
15//!
16
17use std::sync::atomic::AtomicU32;
18use std::sync::atomic::Ordering;
19
20use crate::atomic::atomic_number_ops::AtomicNumberOps;
21use crate::atomic::atomic_ops::AtomicOps;
22
23/// Atomic 32-bit floating point number.
24///
25/// Provides easy-to-use atomic operations with automatic memory ordering
26/// selection. Implemented using `AtomicU32` with bit conversion.
27///
28/// # Memory Ordering Strategy
29///
30/// This type uses the same memory ordering strategy as atomic integers:
31///
32/// - **Read operations** (`load`): Use `Acquire` ordering to ensure
33///   visibility of prior writes from other threads.
34///
35/// - **Write operations** (`store`): Use `Release` ordering to ensure
36///   visibility of prior writes to other threads.
37///
38/// - **Read-Modify-Write operations** (`swap`, `compare_set`): Use
39///   `AcqRel` ordering for full synchronization.
40///
41/// - **CAS-based arithmetic** (`fetch_add`, `fetch_sub`, etc.): Use
42///   `AcqRel` on success and `Acquire` on failure within the CAS loop.
43///   The loop ensures eventual consistency.
44///
45/// # Implementation Details
46///
47/// Since hardware doesn't provide native atomic floating-point operations,
48/// this type is implemented using `AtomicU32` with `f32::to_bits()` and
49/// `f32::from_bits()` conversions. This preserves bit patterns exactly,
50/// including special values like NaN and infinity.
51///
52/// # Features
53///
54/// - Automatic memory ordering selection
55/// - Arithmetic operations via CAS loops
56/// - Zero-cost abstraction with inline methods
57/// - Access to underlying type via `inner()` for advanced use cases
58///
59/// # Limitations
60///
61/// - Arithmetic operations use CAS loops (slower than integer operations)
62/// - CAS comparisons use exact IEEE-754 bit patterns, so different NaN
63///   payloads and `0.0`/`-0.0` are treated as different values
64/// - No max/min operations (complex floating point semantics)
65///
66/// # Example
67///
68/// ```rust
69/// use qubit_atomic::Atomic;
70/// use std::sync::Arc;
71/// use std::thread;
72///
73/// let sum = Arc::new(Atomic::<f32>::new(0.0));
74/// let mut handles = vec![];
75///
76/// for _ in 0..10 {
77///     let sum = sum.clone();
78///     let handle = thread::spawn(move || {
79///         for _ in 0..100 {
80///             sum.fetch_add(0.1);
81///         }
82///     });
83///     handles.push(handle);
84/// }
85///
86/// for handle in handles {
87///     handle.join().unwrap();
88/// }
89///
90/// // Note: Due to floating point precision, result may not be exactly 100.0
91/// let result = sum.load();
92/// assert!((result - 100.0).abs() < 0.01);
93/// ```
94///
95#[repr(transparent)]
96pub struct AtomicF32 {
97    /// Raw-bit atomic storage for the `f32` value.
98    inner: AtomicU32,
99}
100
101impl AtomicF32 {
102    /// Creates a new atomic floating point number.
103    ///
104    /// # Parameters
105    ///
106    /// * `value` - The initial value.
107    ///
108    /// # Returns
109    ///
110    /// An atomic `f32` initialized to `value`.
111    ///
112    /// # Example
113    ///
114    /// ```rust
115    /// use qubit_atomic::Atomic;
116    ///
117    /// let atomic = Atomic::<f32>::new(3.14);
118    /// assert_eq!(atomic.load(), 3.14);
119    /// ```
120    #[inline]
121    pub const fn new(value: f32) -> Self {
122        Self {
123            inner: AtomicU32::new(value.to_bits()),
124        }
125    }
126
127    /// Gets the current value.
128    ///
129    /// # Memory Ordering
130    ///
131    /// Uses `Acquire` ordering on the underlying `AtomicU32`. This ensures
132    /// that all writes from other threads that happened before a `Release`
133    /// store are visible after this load.
134    ///
135    /// # Returns
136    ///
137    /// The current value.
138    ///
139    /// # Example
140    ///
141    /// ```rust
142    /// use qubit_atomic::Atomic;
143    ///
144    /// let atomic = Atomic::<f32>::new(3.14);
145    /// assert_eq!(atomic.load(), 3.14);
146    /// ```
147    #[inline]
148    pub fn load(&self) -> f32 {
149        f32::from_bits(self.inner.load(Ordering::Acquire))
150    }
151
152    /// Sets a new value.
153    ///
154    /// # Memory Ordering
155    ///
156    /// Uses `Release` ordering on the underlying `AtomicU32`. This ensures
157    /// that all prior writes in this thread are visible to other threads
158    /// that perform an `Acquire` load.
159    ///
160    /// # Parameters
161    ///
162    /// * `value` - The new value to set.
163    ///
164    /// # Example
165    ///
166    /// ```rust
167    /// use qubit_atomic::Atomic;
168    ///
169    /// let atomic = Atomic::<f32>::new(0.0);
170    /// atomic.store(3.14);
171    /// assert_eq!(atomic.load(), 3.14);
172    /// ```
173    #[inline]
174    pub fn store(&self, value: f32) {
175        self.inner.store(value.to_bits(), Ordering::Release);
176    }
177
178    /// Swaps the current value with a new value, returning the old value.
179    ///
180    /// # Memory Ordering
181    ///
182    /// Uses `AcqRel` ordering on the underlying `AtomicU32`. This provides
183    /// full synchronization for this read-modify-write operation.
184    ///
185    /// # Parameters
186    ///
187    /// * `value` - The new value to swap in.
188    ///
189    /// # Returns
190    ///
191    /// The old value.
192    ///
193    /// # Example
194    ///
195    /// ```rust
196    /// use qubit_atomic::Atomic;
197    ///
198    /// let atomic = Atomic::<f32>::new(1.0);
199    /// let old = atomic.swap(2.0);
200    /// assert_eq!(old, 1.0);
201    /// assert_eq!(atomic.load(), 2.0);
202    /// ```
203    #[inline]
204    pub fn swap(&self, value: f32) -> f32 {
205        f32::from_bits(self.inner.swap(value.to_bits(), Ordering::AcqRel))
206    }
207
208    /// Compares and sets the value atomically.
209    ///
210    /// If the current value equals `current`, sets it to `new` and returns
211    /// `Ok(())`. Otherwise, returns `Err(actual)` where `actual` is the
212    /// current value.
213    ///
214    /// Comparison uses the exact raw bit pattern produced by
215    /// [`f32::to_bits`], not [`PartialEq`].
216    ///
217    /// # Memory Ordering
218    ///
219    /// - **Success**: Uses `AcqRel` ordering on the underlying `AtomicU32`
220    ///   to ensure full synchronization when the exchange succeeds.
221    /// - **Failure**: Uses `Acquire` ordering to observe the actual value
222    ///   written by another thread.
223    ///
224    /// # Parameters
225    ///
226    /// * `current` - The expected current value.
227    /// * `new` - The new value to set if current matches.
228    ///
229    /// # Returns
230    ///
231    /// `Ok(())` when the value was replaced.
232    ///
233    /// # Errors
234    ///
235    /// Returns `Err(actual)` with the observed value when the raw-bit
236    /// comparison fails. In that case, `new` is not stored.
237    ///
238    /// # Warning
239    ///
240    /// NaN values compare by raw bits. A stored NaN and `current` must have
241    /// the same payload bits for the CAS to succeed.
242    ///
243    /// # Example
244    ///
245    /// ```rust
246    /// use qubit_atomic::Atomic;
247    ///
248    /// let atomic = Atomic::<f32>::new(1.0);
249    /// assert!(atomic.compare_set(1.0, 2.0).is_ok());
250    /// assert_eq!(atomic.load(), 2.0);
251    /// ```
252    #[inline]
253    pub fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
254        self.inner
255            .compare_exchange(
256                current.to_bits(),
257                new.to_bits(),
258                Ordering::AcqRel,
259                Ordering::Acquire,
260            )
261            .map(|_| ())
262            .map_err(f32::from_bits)
263    }
264
265    /// Weak version of compare-and-set.
266    ///
267    /// May spuriously fail even when the comparison succeeds. Should be used
268    /// in a loop.
269    ///
270    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
271    /// Comparison uses the exact raw bit pattern produced by
272    /// [`f32::to_bits`].
273    ///
274    /// # Parameters
275    ///
276    /// * `current` - The expected current value.
277    /// * `new` - The new value to set if current matches.
278    ///
279    /// # Returns
280    ///
281    /// `Ok(())` when the value was replaced.
282    ///
283    /// # Errors
284    ///
285    /// Returns `Err(actual)` with the observed value when the raw-bit
286    /// comparison fails, including possible spurious failures. In that case,
287    /// `new` is not stored.
288    ///
289    /// # Example
290    ///
291    /// ```rust
292    /// use qubit_atomic::Atomic;
293    ///
294    /// let atomic = Atomic::<f32>::new(1.0);
295    /// let mut current = atomic.load();
296    /// loop {
297    ///     match atomic.compare_set_weak(current, current + 1.0) {
298    ///         Ok(_) => break,
299    ///         Err(actual) => current = actual,
300    ///     }
301    /// }
302    /// assert_eq!(atomic.load(), 2.0);
303    /// ```
304    #[inline]
305    pub fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
306        self.inner
307            .compare_exchange_weak(
308                current.to_bits(),
309                new.to_bits(),
310                Ordering::AcqRel,
311                Ordering::Acquire,
312            )
313            .map(|_| ())
314            .map_err(f32::from_bits)
315    }
316
317    /// Compares and exchanges the value atomically, returning the previous
318    /// value.
319    ///
320    /// If the current value equals `current`, sets it to `new` and returns
321    /// the old value. Otherwise, returns the actual current value.
322    ///
323    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
324    ///
325    /// # Parameters
326    ///
327    /// * `current` - The expected current value.
328    /// * `new` - The new value to set if current matches.
329    ///
330    /// # Returns
331    ///
332    /// The value observed before the operation completed. If the returned
333    /// value has the same raw bits as `current`, the exchange succeeded;
334    /// otherwise it is the actual value that prevented the exchange.
335    ///
336    /// # Example
337    ///
338    /// ```rust
339    /// use qubit_atomic::Atomic;
340    ///
341    /// let atomic = Atomic::<f32>::new(1.0);
342    /// let prev = atomic.compare_and_exchange(1.0, 2.0);
343    /// assert_eq!(prev, 1.0);
344    /// assert_eq!(atomic.load(), 2.0);
345    /// ```
346    #[inline]
347    pub fn compare_and_exchange(&self, current: f32, new: f32) -> f32 {
348        match self.inner.compare_exchange(
349            current.to_bits(),
350            new.to_bits(),
351            Ordering::AcqRel,
352            Ordering::Acquire,
353        ) {
354            Ok(prev_bits) => f32::from_bits(prev_bits),
355            Err(actual_bits) => f32::from_bits(actual_bits),
356        }
357    }
358
359    /// Weak version of compare-and-exchange.
360    ///
361    /// May spuriously fail even when the comparison succeeds. Should be used
362    /// in a loop.
363    ///
364    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
365    ///
366    /// # Parameters
367    ///
368    /// * `current` - The expected current value.
369    /// * `new` - The new value to set if current matches.
370    ///
371    /// # Returns
372    ///
373    /// `Ok(previous)` when the value was replaced, or `Err(actual)` when the
374    /// comparison failed, including possible spurious failure. Values preserve
375    /// their exact raw bit patterns.
376    ///
377    /// # Example
378    ///
379    /// ```rust
380    /// use qubit_atomic::Atomic;
381    ///
382    /// let atomic = Atomic::<f32>::new(1.0);
383    /// let mut current = atomic.load();
384    /// loop {
385    ///     match atomic.compare_and_exchange_weak(current, current + 1.0) {
386    ///         Ok(_) => break,
387    ///         Err(actual) => current = actual,
388    ///     }
389    /// }
390    /// assert_eq!(atomic.load(), 2.0);
391    /// ```
392    #[inline]
393    pub fn compare_and_exchange_weak(&self, current: f32, new: f32) -> 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 value.
665    ///
666    /// Internally uses a CAS loop until the update succeeds or the closure
667    /// rejects the current value by returning `None`.
668    ///
669    /// # Parameters
670    ///
671    /// * `f` - A function that takes the current value and returns the new
672    ///   value, or `None` to leave the value unchanged.
673    ///
674    /// # Returns
675    ///
676    /// `Some(new_value)` when the update succeeds, or `None` when `f` rejects
677    /// the observed current value.
678    ///
679    /// The closure may be called more than once when concurrent updates cause
680    /// CAS retries.
681    ///
682    /// # Example
683    ///
684    /// ```rust
685    /// use qubit_atomic::Atomic;
686    ///
687    /// let atomic = Atomic::<f32>::new(1.5);
688    /// assert_eq!(
689    ///     atomic.try_update_and_get(|x| (x > 0.0).then_some(x * 2.0)),
690    ///     Some(3.0),
691    /// );
692    /// assert_eq!(atomic.load(), 3.0);
693    /// assert_eq!(
694    ///     atomic.try_update_and_get(|x| (x < 0.0).then_some(x * 2.0)),
695    ///     None,
696    /// );
697    /// assert_eq!(atomic.load(), 3.0);
698    /// ```
699    #[inline]
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    /// # Example
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    #[inline]
742    pub fn inner(&self) -> &AtomicU32 {
743        &self.inner
744    }
745}
746
747impl AtomicOps for AtomicF32 {
748    type Value = f32;
749
750    #[inline]
751    fn load(&self) -> f32 {
752        self.load()
753    }
754
755    #[inline]
756    fn store(&self, value: f32) {
757        self.store(value);
758    }
759
760    #[inline]
761    fn swap(&self, value: f32) -> f32 {
762        self.swap(value)
763    }
764
765    #[inline]
766    fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
767        self.compare_set(current, new)
768    }
769
770    #[inline]
771    fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
772        self.compare_set_weak(current, new)
773    }
774
775    #[inline]
776    fn compare_exchange(&self, current: f32, new: f32) -> f32 {
777        self.compare_and_exchange(current, new)
778    }
779
780    #[inline]
781    fn compare_exchange_weak(&self, current: f32, new: f32) -> Result<f32, f32> {
782        self.compare_and_exchange_weak(current, new)
783    }
784
785    #[inline]
786    fn fetch_update<F>(&self, f: F) -> f32
787    where
788        F: FnMut(f32) -> f32,
789    {
790        self.fetch_update(f)
791    }
792
793    #[inline]
794    fn update_and_get<F>(&self, f: F) -> f32
795    where
796        F: FnMut(f32) -> f32,
797    {
798        self.update_and_get(f)
799    }
800
801    #[inline]
802    fn try_update<F>(&self, f: F) -> Option<f32>
803    where
804        F: FnMut(f32) -> Option<f32>,
805    {
806        self.try_update(f)
807    }
808
809    #[inline]
810    fn try_update_and_get<F>(&self, f: F) -> Option<f32>
811    where
812        F: FnMut(f32) -> Option<f32>,
813    {
814        self.try_update_and_get(f)
815    }
816}
817
818impl AtomicNumberOps for AtomicF32 {
819    #[inline]
820    fn fetch_add(&self, delta: f32) -> f32 {
821        self.fetch_add(delta)
822    }
823
824    #[inline]
825    fn fetch_sub(&self, delta: f32) -> f32 {
826        self.fetch_sub(delta)
827    }
828
829    #[inline]
830    fn fetch_mul(&self, factor: f32) -> f32 {
831        self.fetch_mul(factor)
832    }
833
834    #[inline]
835    fn fetch_div(&self, divisor: f32) -> f32 {
836        self.fetch_div(divisor)
837    }
838}