1use core::{
2 cmp::PartialOrd,
3 ops::{BitAnd, Shr},
4};
5use num_traits::{
6 cast::AsPrimitive,
7 identities::Zero,
8 ops::wrapping::{WrappingAdd, WrappingSub},
9 Signed,
10};
11use serde::{Deserialize, Serialize};
12
13#[inline(always)]
23pub fn overflowing_sub<T>(y: T, x: T) -> (T, i32)
24where
25 T: WrappingSub + Zero + PartialOrd,
26{
27 let delta = y.wrapping_sub(&x);
28 let wrap = (delta >= T::zero()) as i32 - (y >= x) as i32;
29 (delta, wrap)
30}
31
32pub fn saturating_scale(lo: i32, hi: i32, shift: u32) -> i32 {
41 debug_assert!(shift > 0);
42 debug_assert!(shift <= 32);
43 let hi_range = -1 << (shift - 1);
44 if hi <= hi_range {
45 i32::MIN - hi_range
46 } else if -hi <= hi_range {
47 hi_range - i32::MIN
48 } else {
49 (lo >> shift) + (hi << (32 - shift))
50 }
51}
52
53#[derive(Copy, Clone, Default, Deserialize, Serialize)]
58pub struct Unwrapper<Q> {
59 y: Q,
61}
62
63impl<Q> Unwrapper<Q>
64where
65 Q: 'static + WrappingAdd + Copy,
66{
67 pub fn update<P>(&mut self, x: P) -> P
75 where
76 P: 'static + WrappingSub + Copy + AsPrimitive<Q>,
77 Q: AsPrimitive<P>,
78 {
79 let dx = x.wrapping_sub(&self.y.as_());
80 self.y = self.y.wrapping_add(&dx.as_());
81 dx
82 }
83
84 pub fn wraps<P, const S: u32>(&self) -> P
86 where
87 Q: AsPrimitive<P> + Shr<u32, Output = Q>,
88 P: 'static + Copy + WrappingAdd + Signed + BitAnd<u32, Output = P>,
89 {
90 (self.y >> S)
91 .as_()
92 .wrapping_add(&((self.y >> (S - 1)).as_() & 1))
93 }
94
95 pub fn phase<P>(&self) -> P
97 where
98 P: 'static + Copy,
99 Q: AsPrimitive<P>,
100 {
101 self.y.as_()
102 }
103
104 pub fn y(&self) -> Q {
106 self.y
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 #[test]
114 fn overflowing_sub_correctness() {
115 for (x0, x1, v) in [
116 (0i32, 0i32, 0i32),
117 (0, 1, 0),
118 (0, -1, 0),
119 (1, 0, 0),
120 (-1, 0, 0),
121 (0, 0x7fff_ffff, 0),
122 (-1, 0x7fff_ffff, -1),
123 (-2, 0x7fff_ffff, -1),
124 (-1, -0x8000_0000, 0),
125 (0, -0x8000_0000, 0),
126 (1, -0x8000_0000, 1),
127 (-0x6000_0000, 0x6000_0000, -1),
128 (0x6000_0000, -0x6000_0000, 1),
129 (-0x4000_0000, 0x3fff_ffff, 0),
130 (-0x4000_0000, 0x4000_0000, -1),
131 (-0x4000_0000, 0x4000_0001, -1),
132 (0x4000_0000, -0x3fff_ffff, 0),
133 (0x4000_0000, -0x4000_0000, 0),
134 (0x4000_0000, -0x4000_0001, 1),
135 ]
136 .iter()
137 {
138 let (dx, w) = overflowing_sub(*x1, *x0);
139 assert_eq!(*v, w, " = overflowing_sub({:#x}, {:#x})", *x0, *x1);
140 let (dx0, w0) = x1.overflowing_sub(*x0);
141 assert_eq!(w0, w != 0);
142 assert_eq!(dx, dx0);
143 }
144 }
145
146 #[test]
147 fn saturating_scale_correctness() {
148 let shift = 8;
149 for (lo, hi, res) in [
150 (0i32, 0i32, 0i32),
151 (0, 1, 0x0100_0000),
152 (0, -1, -0x0100_0000),
153 (0x100, 0, 1),
154 (-1 << 31, 0, -1 << 23),
155 (0x7fffffff, 0, 0x007f_ffff),
156 (0x7fffffff, 1, 0x0017f_ffff),
157 (-0x7fffffff, -1, -0x0180_0000),
158 (0x1234_5600, 0x7f, 0x7f12_3456),
159 (0x1234_5600, -0x7f, -0x7f00_0000 + 0x12_3456),
160 (0, 0x7f, 0x7f00_0000),
161 (0, 0x80, 0x7fff_ff80),
162 (0, -0x7f, -0x7f00_0000),
163 (0, -0x80, -0x7fff_ff80),
164 (0x7fff_ffff, 0x7f, 0x7f7f_ffff),
165 (-0x8000_0000, 0x7f, 0x7e80_0000),
166 (-0x8000_0000, -0x7f, -0x7f80_0000),
167 (0x7fff_ffff, -0x7f, -0x7e80_0001),
168 (0x100, 0x7f, 0x7f00_0001),
169 (0, -0x80, -0x7fff_ff80),
170 (-1 << 31, 0x80, 0x7fff_ff80),
171 (-1 << 31, -0x80, -0x7fff_ff80),
172 ]
173 .iter()
174 {
175 let s = saturating_scale(*lo, *hi, shift);
176 assert_eq!(
177 *res, s,
178 "{:#x} != {:#x} = saturating_scale({:#x}, {:#x}, {:#x})",
179 *res, s, *lo, *hi, shift
180 );
181 }
182 }
183}