use crate::{
atomic_float_wrapper::{
Abs, Neg, UseUpdateToAdd, UseUpdateToMax, UseUpdateToMin, UseUpdateToSub,
},
AtomicNumber, IntoAtomicNumber,
};
use atomic_traits::{fetch::Update, AsPtr, Atomic, Bitwise};
use core::sync::atomic::Ordering::{self};
use num_primitive::PrimitiveFloat;
use num_traits::FromPrimitive;
pub trait AtomicFloat<F>:
Atomic<Type = F>
+ Bitwise
+ AsPtr
+ Update<Type = F>
+ Abs<Type = F>
+ Neg<Type = F>
+ UseUpdateToAdd<Type = F>
+ UseUpdateToSub<Type = F>
+ UseUpdateToMin<Type = F>
+ UseUpdateToMax<Type = F>
+ Send
+ Sync
where
F: PrimitiveFloat,
{
}
impl<AF, F> AtomicFloat<F> for AF
where
AF: Atomic<Type = F>
+ Bitwise
+ AsPtr
+ Update<Type = F>
+ Abs<Type = F>
+ Neg<Type = F>
+ UseUpdateToAdd<Type = F>
+ UseUpdateToSub<Type = F>
+ UseUpdateToMin<Type = F>
+ UseUpdateToMax<Type = F>
+ Send
+ Sync,
F: PrimitiveFloat,
{
}
pub trait IntoAtomicFloat: IntoAtomicNumber<AN = Self::AF> + PrimitiveFloat {
type AF: AtomicFloat<Self>;
fn into_atomic_float(self) -> impl AtomicFloat<Self>;
}
impl<T, A> IntoAtomicFloat for T
where
T: IntoAtomicNumber<AN = A> + PrimitiveFloat + FromPrimitive,
A: AtomicFloat<Self>,
{
type AF = T::AN;
fn into_atomic_float(self) -> impl AtomicFloat<Self> {
Self::AF::new(self)
}
}
pub trait PrimitiveAtomicFloat: PrimitiveFloat + IntoAtomicFloat {}
impl<T> PrimitiveAtomicFloat for T where T: PrimitiveFloat + IntoAtomicFloat {}
impl<T> Abs for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_abs(&self, order: Ordering) -> Self::Type {
self.atomic.fetch_abs(order)
}
}
impl<T> Neg for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_neg(&self, order: Ordering) -> Self::Type {
self.atomic.fetch_neg(order)
}
}
impl<T> UseUpdateToAdd for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_add_via_update(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_add_via_update(val, order)
}
}
impl<T> UseUpdateToSub for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_sub_via_update(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_sub_via_update(val, order)
}
}
impl<T> UseUpdateToMin for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_min_via_update(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_min_via_update(val, order)
}
}
impl<T> UseUpdateToMax for AtomicNumber<T>
where
T: PrimitiveAtomicFloat + FromPrimitive,
{
type Type = T;
#[inline]
fn fetch_max_via_update(&self, val: Self::Type, order: Ordering) -> T {
self.atomic.fetch_max_via_update(val, order)
}
}