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(current.to_bits(), new.to_bits(), Ordering::AcqRel, Ordering::Acquire)
256            .map(|_| ())
257            .map_err(f32::from_bits)
258    }
259
260    /// Weak version of compare-and-set.
261    ///
262    /// May spuriously fail even when the comparison succeeds. Should be used
263    /// in a loop.
264    ///
265    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
266    /// Comparison uses the exact raw bit pattern produced by
267    /// [`f32::to_bits`].
268    ///
269    /// # Parameters
270    ///
271    /// * `current` - The expected current value.
272    /// * `new` - The new value to set if current matches.
273    ///
274    /// # Returns
275    ///
276    /// `Ok(())` when the value was replaced.
277    ///
278    /// # Errors
279    ///
280    /// Returns `Err(actual)` with the observed value when the raw-bit
281    /// comparison fails, including possible spurious failures. In that case,
282    /// `new` is not stored.
283    ///
284    /// # Example
285    ///
286    /// ```rust
287    /// use qubit_atomic::Atomic;
288    ///
289    /// let atomic = Atomic::<f32>::new(1.0);
290    /// let mut current = atomic.load();
291    /// loop {
292    ///     match atomic.compare_set_weak(current, current + 1.0) {
293    ///         Ok(_) => break,
294    ///         Err(actual) => current = actual,
295    ///     }
296    /// }
297    /// assert_eq!(atomic.load(), 2.0);
298    /// ```
299    #[inline]
300    pub fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
301        self.inner
302            .compare_exchange_weak(current.to_bits(), new.to_bits(), Ordering::AcqRel, Ordering::Acquire)
303            .map(|_| ())
304            .map_err(f32::from_bits)
305    }
306
307    /// Compares and exchanges the value atomically, returning the previous
308    /// value.
309    ///
310    /// If the current value equals `current`, sets it to `new` and returns
311    /// the old value. Otherwise, returns the actual current value.
312    ///
313    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
314    ///
315    /// # Parameters
316    ///
317    /// * `current` - The expected current value.
318    /// * `new` - The new value to set if current matches.
319    ///
320    /// # Returns
321    ///
322    /// The value observed before the operation completed. If the returned
323    /// value has the same raw bits as `current`, the exchange succeeded;
324    /// otherwise it is the actual value that prevented the exchange.
325    ///
326    /// # Example
327    ///
328    /// ```rust
329    /// use qubit_atomic::Atomic;
330    ///
331    /// let atomic = Atomic::<f32>::new(1.0);
332    /// let prev = atomic.compare_and_exchange(1.0, 2.0);
333    /// assert_eq!(prev, 1.0);
334    /// assert_eq!(atomic.load(), 2.0);
335    /// ```
336    #[inline]
337    pub fn compare_and_exchange(&self, current: f32, new: f32) -> f32 {
338        match self
339            .inner
340            .compare_exchange(current.to_bits(), new.to_bits(), Ordering::AcqRel, Ordering::Acquire)
341        {
342            Ok(prev_bits) => f32::from_bits(prev_bits),
343            Err(actual_bits) => f32::from_bits(actual_bits),
344        }
345    }
346
347    /// Weak version of compare-and-exchange.
348    ///
349    /// May spuriously fail even when the comparison succeeds. Should be used
350    /// in a loop.
351    ///
352    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
353    ///
354    /// # Parameters
355    ///
356    /// * `current` - The expected current value.
357    /// * `new` - The new value to set if current matches.
358    ///
359    /// # Returns
360    ///
361    /// `Ok(previous)` when the value was replaced, or `Err(actual)` when the
362    /// comparison failed, including possible spurious failure. Values preserve
363    /// their exact raw bit patterns.
364    ///
365    /// # Example
366    ///
367    /// ```rust
368    /// use qubit_atomic::Atomic;
369    ///
370    /// let atomic = Atomic::<f32>::new(1.0);
371    /// let mut current = atomic.load();
372    /// loop {
373    ///     match atomic.compare_and_exchange_weak(current, current + 1.0) {
374    ///         Ok(_) => break,
375    ///         Err(actual) => current = actual,
376    ///     }
377    /// }
378    /// assert_eq!(atomic.load(), 2.0);
379    /// ```
380    #[inline]
381    pub fn compare_and_exchange_weak(&self, current: f32, new: f32) -> Result<f32, f32> {
382        self.inner
383            .compare_exchange_weak(current.to_bits(), new.to_bits(), Ordering::AcqRel, Ordering::Acquire)
384            .map(f32::from_bits)
385            .map_err(f32::from_bits)
386    }
387
388    /// Atomically adds a value, returning the old value.
389    ///
390    /// # Memory Ordering
391    ///
392    /// Internally uses a CAS loop with `compare_set_weak`, which uses
393    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
394    /// eventual consistency even under high contention.
395    ///
396    /// # Performance
397    ///
398    /// May be slow in high-contention scenarios due to the CAS loop.
399    /// Consider using atomic integers if performance is critical.
400    ///
401    /// # Parameters
402    ///
403    /// * `delta` - The value to add.
404    ///
405    /// # Returns
406    ///
407    /// The old value before adding.
408    ///
409    /// # Example
410    ///
411    /// ```rust
412    /// use qubit_atomic::Atomic;
413    ///
414    /// let atomic = Atomic::<f32>::new(10.0);
415    /// let old = atomic.fetch_add(5.5);
416    /// assert_eq!(old, 10.0);
417    /// assert_eq!(atomic.load(), 15.5);
418    /// ```
419    #[inline]
420    pub fn fetch_add(&self, delta: f32) -> f32 {
421        self.fetch_update(|current| current + delta)
422    }
423
424    /// Atomically subtracts a value, returning the old value.
425    ///
426    /// # Memory Ordering
427    ///
428    /// Internally uses a CAS loop with `compare_set_weak`, which uses
429    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
430    /// eventual consistency even under high contention.
431    ///
432    /// # Parameters
433    ///
434    /// * `delta` - The value to subtract.
435    ///
436    /// # Returns
437    ///
438    /// The old value before subtracting.
439    ///
440    /// # Example
441    ///
442    /// ```rust
443    /// use qubit_atomic::Atomic;
444    ///
445    /// let atomic = Atomic::<f32>::new(10.0);
446    /// let old = atomic.fetch_sub(3.5);
447    /// assert_eq!(old, 10.0);
448    /// assert_eq!(atomic.load(), 6.5);
449    /// ```
450    #[inline]
451    pub fn fetch_sub(&self, delta: f32) -> f32 {
452        self.fetch_update(|current| current - delta)
453    }
454
455    /// Atomically multiplies by a factor, returning the old value.
456    ///
457    /// # Memory Ordering
458    ///
459    /// Internally uses a CAS loop with `compare_set_weak`, which uses
460    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
461    /// eventual consistency even under high contention.
462    ///
463    /// # Parameters
464    ///
465    /// * `factor` - The factor to multiply by.
466    ///
467    /// # Returns
468    ///
469    /// The old value before multiplying.
470    ///
471    /// # Example
472    ///
473    /// ```rust
474    /// use qubit_atomic::Atomic;
475    ///
476    /// let atomic = Atomic::<f32>::new(10.0);
477    /// let old = atomic.fetch_mul(2.5);
478    /// assert_eq!(old, 10.0);
479    /// assert_eq!(atomic.load(), 25.0);
480    /// ```
481    #[inline]
482    pub fn fetch_mul(&self, factor: f32) -> f32 {
483        self.fetch_update(|current| current * factor)
484    }
485
486    /// Atomically divides by a divisor, returning the old value.
487    ///
488    /// # Memory Ordering
489    ///
490    /// Internally uses a CAS loop with `compare_set_weak`, which uses
491    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
492    /// eventual consistency even under high contention.
493    ///
494    /// # Parameters
495    ///
496    /// * `divisor` - The divisor to divide by.
497    ///
498    /// # Returns
499    ///
500    /// The old value before dividing.
501    ///
502    /// # Example
503    ///
504    /// ```rust
505    /// use qubit_atomic::Atomic;
506    ///
507    /// let atomic = Atomic::<f32>::new(10.0);
508    /// let old = atomic.fetch_div(2.0);
509    /// assert_eq!(old, 10.0);
510    /// assert_eq!(atomic.load(), 5.0);
511    /// ```
512    #[inline]
513    pub fn fetch_div(&self, divisor: f32) -> f32 {
514        self.fetch_update(|current| current / divisor)
515    }
516
517    /// Updates the value using a function, returning the old value.
518    ///
519    /// # Memory Ordering
520    ///
521    /// Internally uses a CAS loop with `compare_set_weak`, which uses
522    /// `AcqRel` on success and `Acquire` on failure. The loop ensures
523    /// eventual consistency even under high contention.
524    ///
525    /// # Parameters
526    ///
527    /// * `f` - A function that takes the current value and returns the new
528    ///   value.
529    ///
530    /// # Returns
531    ///
532    /// The old value before the update.
533    ///
534    /// The closure may be called more than once when concurrent updates cause
535    /// CAS retries.
536    ///
537    /// # Example
538    ///
539    /// ```rust
540    /// use qubit_atomic::Atomic;
541    ///
542    /// let atomic = Atomic::<f32>::new(10.0);
543    /// let old = atomic.fetch_update(|x| x * 2.0);
544    /// assert_eq!(old, 10.0);
545    /// assert_eq!(atomic.load(), 20.0);
546    /// ```
547    #[inline]
548    pub fn fetch_update<F>(&self, mut f: F) -> f32
549    where
550        F: FnMut(f32) -> f32,
551    {
552        let mut current = self.load();
553        loop {
554            let new = f(current);
555            match self.compare_set_weak(current, new) {
556                Ok(_) => return current,
557                Err(actual) => current = actual,
558            }
559        }
560    }
561
562    /// Updates the value using a function, returning the new value.
563    ///
564    /// Internally uses a CAS loop until the update succeeds.
565    ///
566    /// # Parameters
567    ///
568    /// * `f` - A function that takes the current value and returns the new
569    ///   value.
570    ///
571    /// # Returns
572    ///
573    /// The value committed by the successful update.
574    ///
575    /// The closure may be called more than once when concurrent updates cause
576    /// CAS retries.
577    ///
578    /// # Example
579    ///
580    /// ```rust
581    /// use qubit_atomic::Atomic;
582    ///
583    /// let atomic = Atomic::<f32>::new(10.0);
584    /// let new = atomic.update_and_get(|x| x * 2.0);
585    /// assert_eq!(new, 20.0);
586    /// assert_eq!(atomic.load(), 20.0);
587    /// ```
588    #[inline]
589    pub fn update_and_get<F>(&self, mut f: F) -> f32
590    where
591        F: FnMut(f32) -> f32,
592    {
593        let mut current = self.load();
594        loop {
595            let new = f(current);
596            match self.compare_set_weak(current, new) {
597                Ok(_) => return new,
598                Err(actual) => current = actual,
599            }
600        }
601    }
602
603    /// Conditionally updates the value using a function.
604    ///
605    /// Internally uses a CAS loop until the update succeeds or the closure
606    /// rejects the current value by returning `None`.
607    ///
608    /// # Parameters
609    ///
610    /// * `f` - A function that takes the current value and returns the new
611    ///   value, or `None` to leave the value unchanged.
612    ///
613    /// # Returns
614    ///
615    /// `Some(old_value)` when the update succeeds, or `None` when `f` rejects
616    /// the observed current value.
617    ///
618    /// The closure may be called more than once when concurrent updates cause
619    /// CAS retries.
620    ///
621    /// # Example
622    ///
623    /// ```rust
624    /// use qubit_atomic::Atomic;
625    ///
626    /// let atomic = Atomic::<f32>::new(1.5);
627    /// assert_eq!(atomic.try_update(|x| (x > 0.0).then_some(x * 2.0)), Some(1.5));
628    /// assert_eq!(atomic.load(), 3.0);
629    /// assert_eq!(atomic.try_update(|x| (x < 0.0).then_some(x * 2.0)), None);
630    /// assert_eq!(atomic.load(), 3.0);
631    /// ```
632    #[inline]
633    pub fn try_update<F>(&self, mut f: F) -> Option<f32>
634    where
635        F: FnMut(f32) -> Option<f32>,
636    {
637        let mut current = self.load();
638        loop {
639            let new = f(current)?;
640            match self.compare_set_weak(current, new) {
641                Ok(_) => return Some(current),
642                Err(actual) => current = actual,
643            }
644        }
645    }
646
647    /// Conditionally updates the value using a function, returning the new value.
648    ///
649    /// Internally uses a CAS loop until the update succeeds or the closure
650    /// rejects the current value by returning `None`.
651    ///
652    /// # Parameters
653    ///
654    /// * `f` - A function that takes the current value and returns the new
655    ///   value, or `None` to leave the value unchanged.
656    ///
657    /// # Returns
658    ///
659    /// `Some(new_value)` when the update succeeds, or `None` when `f` rejects
660    /// the observed current value.
661    ///
662    /// The closure may be called more than once when concurrent updates cause
663    /// CAS retries.
664    ///
665    /// # Example
666    ///
667    /// ```rust
668    /// use qubit_atomic::Atomic;
669    ///
670    /// let atomic = Atomic::<f32>::new(1.5);
671    /// assert_eq!(
672    ///     atomic.try_update_and_get(|x| (x > 0.0).then_some(x * 2.0)),
673    ///     Some(3.0),
674    /// );
675    /// assert_eq!(atomic.load(), 3.0);
676    /// assert_eq!(
677    ///     atomic.try_update_and_get(|x| (x < 0.0).then_some(x * 2.0)),
678    ///     None,
679    /// );
680    /// assert_eq!(atomic.load(), 3.0);
681    /// ```
682    #[inline]
683    pub fn try_update_and_get<F>(&self, mut f: F) -> Option<f32>
684    where
685        F: FnMut(f32) -> Option<f32>,
686    {
687        let mut current = self.load();
688        loop {
689            let new = f(current)?;
690            match self.compare_set_weak(current, new) {
691                Ok(_) => return Some(new),
692                Err(actual) => current = actual,
693            }
694        }
695    }
696
697    /// Gets a reference to the underlying standard library atomic type.
698    ///
699    /// This allows direct access to the standard library's atomic operations
700    /// for advanced use cases that require fine-grained control over memory
701    /// ordering.
702    ///
703    /// # Memory Ordering
704    ///
705    /// When using the returned reference, you have full control over memory
706    /// ordering. Remember to use `f32::to_bits()` and `f32::from_bits()` for
707    /// conversions.
708    ///
709    /// # Returns
710    ///
711    /// A reference to the underlying `std::sync::atomic::AtomicU32`.
712    ///
713    /// # Example
714    ///
715    /// ```rust
716    /// use qubit_atomic::Atomic;
717    /// use std::sync::atomic::Ordering;
718    ///
719    /// let atomic = Atomic::<f32>::new(0.0);
720    /// atomic.inner().store(3.14_f32.to_bits(), Ordering::Relaxed);
721    /// let bits = atomic.inner().load(Ordering::Relaxed);
722    /// assert_eq!(f32::from_bits(bits), 3.14);
723    /// ```
724    #[inline]
725    pub fn inner(&self) -> &AtomicU32 {
726        &self.inner
727    }
728}
729
730impl AtomicOps for AtomicF32 {
731    type Value = f32;
732
733    #[inline]
734    fn load(&self) -> f32 {
735        self.load()
736    }
737
738    #[inline]
739    fn store(&self, value: f32) {
740        self.store(value);
741    }
742
743    #[inline]
744    fn swap(&self, value: f32) -> f32 {
745        self.swap(value)
746    }
747
748    #[inline]
749    fn compare_set(&self, current: f32, new: f32) -> Result<(), f32> {
750        self.compare_set(current, new)
751    }
752
753    #[inline]
754    fn compare_set_weak(&self, current: f32, new: f32) -> Result<(), f32> {
755        self.compare_set_weak(current, new)
756    }
757
758    #[inline]
759    fn compare_exchange(&self, current: f32, new: f32) -> f32 {
760        self.compare_and_exchange(current, new)
761    }
762
763    #[inline]
764    fn compare_exchange_weak(&self, current: f32, new: f32) -> Result<f32, f32> {
765        self.compare_and_exchange_weak(current, new)
766    }
767
768    #[inline]
769    fn fetch_update<F>(&self, f: F) -> f32
770    where
771        F: FnMut(f32) -> f32,
772    {
773        self.fetch_update(f)
774    }
775
776    #[inline]
777    fn update_and_get<F>(&self, f: F) -> f32
778    where
779        F: FnMut(f32) -> f32,
780    {
781        self.update_and_get(f)
782    }
783
784    #[inline]
785    fn try_update<F>(&self, f: F) -> Option<f32>
786    where
787        F: FnMut(f32) -> Option<f32>,
788    {
789        self.try_update(f)
790    }
791
792    #[inline]
793    fn try_update_and_get<F>(&self, f: F) -> Option<f32>
794    where
795        F: FnMut(f32) -> Option<f32>,
796    {
797        self.try_update_and_get(f)
798    }
799}
800
801impl AtomicNumberOps for AtomicF32 {
802    #[inline]
803    fn fetch_add(&self, delta: f32) -> f32 {
804        self.fetch_add(delta)
805    }
806
807    #[inline]
808    fn fetch_sub(&self, delta: f32) -> f32 {
809        self.fetch_sub(delta)
810    }
811
812    #[inline]
813    fn fetch_mul(&self, factor: f32) -> f32 {
814        self.fetch_mul(factor)
815    }
816
817    #[inline]
818    fn fetch_div(&self, divisor: f32) -> f32 {
819        self.fetch_div(divisor)
820    }
821}