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}