1use std::ops::AddAssign;
4use std::ops::ShlAssign;
5use std::ops::ShrAssign;
6use std::ops::SubAssign;
7
8use crate::util::IsFloatingPoint;
9
10#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct Saturating<T>(pub T);
17
18impl<T> IsFloatingPoint for Saturating<T> {
20 const FLOATING_POINT: bool = false;
21 const MIN_EXP: i32 = 0;
22}
23
24impl<T: From<u32>> From<u32> for Saturating<T> {
25 #[inline]
26 fn from(value: u32) -> Self {
27 Self(T::from(value))
28 }
29}
30
31impl<'a> AddAssign<&'a Self> for Saturating<u64> {
32 #[inline]
33 fn add_assign(&mut self, rhs: &'a Self) {
34 self.0 = self.0.saturating_add(rhs.0);
35 }
36}
37impl<'a> AddAssign<&'a Self> for Saturating<u128> {
38 #[inline]
39 fn add_assign(&mut self, rhs: &'a Self) {
40 self.0 = self.0.saturating_add(rhs.0);
41 }
42}
43
44impl<'a> SubAssign<&'a Self> for Saturating<u64> {
45 #[inline]
46 fn sub_assign(&mut self, rhs: &'a Self) {
47 if self.0 != u64::MAX {
48 self.0 -= rhs.0;
49 }
50 }
51}
52impl<'a> SubAssign<&'a Self> for Saturating<u128> {
53 #[inline]
54 fn sub_assign(&mut self, rhs: &'a Self) {
55 if self.0 != u128::MAX {
56 self.0 -= rhs.0;
57 }
58 }
59}
60
61impl ShrAssign<u32> for Saturating<u64> {
62 #[inline]
63 fn shr_assign(&mut self, rhs: u32) {
64 if self.0 != u64::MAX {
65 self.0 >>= rhs;
66 }
67 }
68}
69impl ShrAssign<u32> for Saturating<u128> {
70 #[inline]
71 fn shr_assign(&mut self, rhs: u32) {
72 if self.0 != u128::MAX {
73 self.0 >>= rhs;
74 }
75 }
76}
77
78impl ShlAssign<u32> for Saturating<u64> {
79 #[inline]
80 fn shl_assign(&mut self, rhs: u32) {
81 self.0 = match self.0.checked_shl(rhs) {
82 Some(v) => v,
83 None => u64::MAX,
84 }
85 }
86}
87impl ShlAssign<u32> for Saturating<u128> {
88 #[inline]
89 fn shl_assign(&mut self, rhs: u32) {
90 self.0 = match self.0.checked_shl(rhs) {
91 Some(v) => v,
92 None => u128::MAX,
93 }
94 }
95}
96
97#[derive(Clone, Copy, PartialEq, PartialOrd)]
100#[repr(transparent)]
101pub struct F64(pub f64);
102
103impl From<u32> for F64 {
104 fn from(value: u32) -> Self {
105 Self(value as f64)
106 }
107}
108
109impl IsFloatingPoint for F64 {
111 const FLOATING_POINT: bool = true;
112 const MIN_EXP: i32 = f64::MIN_EXP;
113}
114
115impl<'a> AddAssign<&'a Self> for F64 {
116 fn add_assign(&mut self, rhs: &'a Self) {
117 self.0 += rhs.0;
118 }
119}
120impl<'a> SubAssign<&'a Self> for F64 {
121 fn sub_assign(&mut self, rhs: &'a Self) {
122 self.0 -= rhs.0;
123 }
124}
125
126impl ShlAssign<u32> for F64 {
127 #[allow(clippy::suspicious_op_assign_impl)]
128 fn shl_assign(&mut self, rhs: u32) {
129 self.0 *= (rhs as f64).exp2()
130 }
131}
132impl ShrAssign<u32> for F64 {
133 #[allow(clippy::suspicious_op_assign_impl)]
134 fn shr_assign(&mut self, rhs: u32) {
135 self.0 *= (-(rhs as f64)).exp2()
136 }
137}