1#[derive(Copy, Clone, Default)]
9pub struct RPLL {
10 dt2: u32, x: i32, ff: u32, f: u32, y: i32, }
16
17impl RPLL {
18 pub fn new(dt2: u32) -> Self {
26 Self {
27 dt2,
28 ..Default::default()
29 }
30 }
31
32 pub fn update(
47 &mut self,
48 input: Option<i32>,
49 shift_frequency: u32,
50 shift_phase: u32,
51 ) -> (i32, u32) {
52 debug_assert!(shift_frequency >= self.dt2);
53 debug_assert!(shift_phase >= self.dt2);
54 self.y = self.y.wrapping_add(self.f as i32);
56 if let Some(x) = input {
57 let dx = x.wrapping_sub(self.x);
59 self.x = x;
61 let p_sig_64 = self.ff as u64 * dx as u64;
63 let p_sig =
65 ((p_sig_64 + (1u32 << (shift_frequency - 1)) as u64) >> shift_frequency) as u32;
66 let p_ref = 1u32 << (32 + self.dt2 - shift_frequency);
68 self.ff = self.ff.wrapping_add(p_ref.wrapping_sub(p_sig));
70 let dt = (x.wrapping_neg() & ((1 << self.dt2) - 1)) as u32;
72 let y_ref = (self.f >> self.dt2).wrapping_mul(dt) as i32;
74 let dy = y_ref.wrapping_sub(self.y) >> (shift_phase - self.dt2);
76 self.f = self.ff.wrapping_add(dy as u32);
78 }
79 (self.y, self.f)
80 }
81
82 pub fn phase(&self) -> i32 {
84 self.y
85 }
86
87 pub fn frequency(&self) -> u32 {
89 self.f
90 }
91}
92
93#[cfg(test)]
94mod test {
95 use super::RPLL;
96 use rand::{prelude::*, rngs::StdRng};
97 use std::vec::Vec;
98
99 #[test]
100 fn make() {
101 let _ = RPLL::new(8);
102 }
103
104 struct Harness {
105 rpll: RPLL,
106 shift_frequency: u32,
107 shift_phase: u32,
108 noise: i32,
109 period: i32,
110 next: i32,
111 next_noisy: i32,
112 time: i32,
113 rng: StdRng,
114 }
115
116 impl Harness {
117 fn default() -> Self {
118 Self {
119 rpll: RPLL::new(8),
120 shift_frequency: 9,
121 shift_phase: 8,
122 noise: 0,
123 period: 333,
124 next: 111,
125 next_noisy: 111,
126 time: 0,
127 rng: StdRng::seed_from_u64(42),
128 }
129 }
130
131 fn run(&mut self, n: usize) -> (Vec<f32>, Vec<f32>) {
132 assert!(self.period >= 1 << self.rpll.dt2);
133 assert!(self.period < 1 << self.shift_frequency);
134 assert!(self.period < 1 << self.shift_phase + 1);
135
136 let mut y = Vec::<f32>::new();
137 let mut f = Vec::<f32>::new();
138 for _ in 0..n {
139 let timestamp = if self.time - self.next_noisy >= 0 {
140 assert!(self.time - self.next_noisy < 1 << self.rpll.dt2);
141 self.next = self.next.wrapping_add(self.period);
142 let timestamp = self.next_noisy;
143 let p_noise = self.rng.random_range(-self.noise..=self.noise);
144 self.next_noisy = self.next.wrapping_add(p_noise);
145 Some(timestamp)
146 } else {
147 None
148 };
149 let (yi, fi) = self
150 .rpll
151 .update(timestamp, self.shift_frequency, self.shift_phase);
152
153 let y_ref = (self.time.wrapping_sub(self.next) as i64 * (1i64 << 32)
154 / self.period as i64) as i32;
155 y.push(yi.wrapping_sub(y_ref) as f32 / 2f32.powi(32));
157
158 let p_ref = 1 << 32 + self.rpll.dt2;
159 let p_sig = fi as u64 * self.period as u64;
160 f.push(
162 p_sig.wrapping_sub(p_ref) as i64 as f32 / 2f32.powi(32 + self.rpll.dt2 as i32),
163 );
164
165 self.time = self.time.wrapping_add(1 << self.rpll.dt2);
167 }
168 (y, f)
169 }
170
171 fn measure(&mut self, n: usize, limits: [f32; 4]) {
172 let t_settle = (1 << self.shift_frequency - self.rpll.dt2 + 4)
173 + (1 << self.shift_phase - self.rpll.dt2 + 4);
174 self.run(t_settle);
175
176 let (y, f) = self.run(n);
177 let fm = f.iter().copied().sum::<f32>() / f.len() as f32;
180 let fs = f.iter().map(|f| (*f - fm).powi(2)).sum::<f32>().sqrt() / f.len() as f32;
181 let ym = y.iter().copied().sum::<f32>() / y.len() as f32;
182 let ys = y.iter().map(|y| (*y - ym).powi(2)).sum::<f32>().sqrt() / y.len() as f32;
183
184 println!("f: {:.2e}±{:.2e}; y: {:.2e}±{:.2e}", fm, fs, ym, ys);
185
186 let m = [fm, fs, ym, ys];
187
188 print!("relative: ");
189 for i in 0..m.len() {
190 let rel = m[i].abs() / limits[i].abs();
191 print!("{:.2e} ", rel);
192 assert!(
193 rel <= 1.,
194 "idx {}, have |{:.2e}| > limit {:.2e}",
195 i,
196 m[i],
197 limits[i]
198 );
199 }
200 println!();
201 }
202 }
203
204 #[test]
205 fn default() {
206 let mut h = Harness::default();
207
208 h.measure(1 << 16, [1e-11, 4e-8, 2e-8, 2e-8]);
209 }
210
211 #[test]
212 fn noisy() {
213 let mut h = Harness::default();
214 h.noise = 10;
215 h.shift_frequency = 23;
216 h.shift_phase = 22;
217
218 h.measure(1 << 16, [3e-9, 3e-6, 5e-4, 2e-4]);
219 }
220
221 #[test]
222 fn narrow_fast() {
223 let mut h = Harness::default();
224 h.period = 990;
225 h.next = 351;
226 h.next_noisy = h.next;
227 h.noise = 5;
228 h.shift_frequency = 23;
229 h.shift_phase = 22;
230
231 h.measure(1 << 16, [2e-9, 2e-6, 1e-3, 1e-4]);
232 }
233
234 #[test]
235 fn narrow_slow() {
236 let mut h = Harness::default();
237 h.period = 1818181;
238 h.next = 35281;
239 h.next_noisy = h.next;
240 h.noise = 1000;
241 h.shift_frequency = 23;
242 h.shift_phase = 22;
243
244 h.measure(1 << 16, [2e-5, 6e-4, 2e-4, 2e-4]);
245 }
246
247 #[test]
248 fn wide_fast() {
249 let mut h = Harness::default();
250 h.period = 990;
251 h.next = 351;
252 h.next_noisy = h.next;
253 h.noise = 5;
254 h.shift_frequency = 10;
255 h.shift_phase = 9;
256
257 h.measure(1 << 16, [2e-6, 3e-2, 2e-5, 2e-2]);
258 }
259
260 #[test]
261 fn wide_slow() {
262 let mut h = Harness::default();
263 h.period = 1818181;
264 h.next = 35281;
265 h.next_noisy = h.next;
266 h.noise = 1000;
267 h.shift_frequency = 21;
268 h.shift_phase = 20;
269
270 h.measure(1 << 16, [2e-4, 6e-3, 2e-4, 2e-3]);
271 }
272
273 #[test]
274 fn batch_fast_narrow() {
275 let mut h = Harness::default();
276 h.rpll.dt2 = 8 + 3;
277 h.period = 2431;
278 h.next = 35281;
279 h.next_noisy = h.next;
280 h.noise = 100;
281 h.shift_frequency = 23;
282 h.shift_phase = 23;
283
284 h.measure(1 << 16, [1e-8, 2e-5, 6e-4, 6e-4]);
285 }
286}