1use serde::{Deserialize, Serialize};
25
26pub const RESIDUE_CLASSES: usize = 96;
28
29pub const PRIME_RESIDUE_CLASSES: [u16; RESIDUE_CLASSES] = [
32 1, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59,
33 61, 67, 71, 73, 77, 79, 83, 89, 91, 97, 101, 103, 107, 109, 113, 119,
34 121, 127, 131, 133, 137, 139, 143, 149, 151, 157, 161, 163, 167, 169, 173, 179,
35 181, 187, 191, 193, 197, 199, 203, 209, 211, 217, 221, 223, 227, 229, 233, 239,
36 241, 247, 251, 253, 257, 259, 263, 269, 271, 277, 281, 283, 287, 289, 293, 299,
37 301, 307, 311, 313, 317, 319, 323, 329, 331, 337, 341, 343, 347, 349, 353, 359,
38];
39
40pub const FACTOR_COVERED: [u16; 48] = [
42 1, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59,
43 61, 67, 71, 73, 77, 79, 83, 89, 271, 277, 281, 283, 287, 289, 293, 299,
44 301, 307, 311, 313, 317, 319, 323, 329, 331, 337, 341, 343, 347, 349, 353, 359,
45];
46
47pub const SEQUENCE_COVERED: [u16; 46] = [
49 91, 97, 101, 103, 107, 109, 113, 119, 121, 127, 131, 133, 137, 139, 143, 149,
50 151, 157, 161, 163, 167, 169, 173, 179, 181, 187, 191, 193, 197, 199, 203, 209,
51 211, 217, 221, 223, 227, 229, 233, 239, 241, 247, 251, 253, 257, 259,
52];
53
54pub const SCALE_DEPENDENT: [u16; 2] = [261, 269];
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
59pub enum ExtendedPrime {
60 SignPrime,
62 MagnitudePrime(u32),
64}
65
66impl ExtendedPrime {
67 pub fn is_prime(n: i32) -> bool {
69 if n == -1 {
70 return true; }
72 if n < 2 {
73 return false;
74 }
75 if n == 2 || n == 3 {
76 return true;
77 }
78 if n % 2 == 0 || n % 3 == 0 {
79 return false;
80 }
81
82 let mut i = 5;
83 while i * i <= n {
84 if n % i == 0 || n % (i + 2) == 0 {
85 return false;
86 }
87 i += 6;
88 }
89 true
90 }
91
92 pub fn value(&self) -> i32 {
94 match self {
95 ExtendedPrime::SignPrime => -1,
96 ExtendedPrime::MagnitudePrime(p) => *p as i32,
97 }
98 }
99}
100
101#[derive(Debug, Clone)]
103pub struct QuantizationTable {
104 pub base_q: u16,
106 pub weights: [f32; RESIDUE_CLASSES],
108}
109
110impl QuantizationTable {
111 pub fn new(base_q: u16) -> Self {
113 let mut weights = [1.0f32; RESIDUE_CLASSES];
114
115 for &residue in &FACTOR_COVERED {
118 if let Some(idx) = PRIME_RESIDUE_CLASSES.iter().position(|&r| r == residue) {
119 weights[idx] = 0.9; }
121 }
122
123 for &residue in &SEQUENCE_COVERED {
125 if let Some(idx) = PRIME_RESIDUE_CLASSES.iter().position(|&r| r == residue) {
126 weights[idx] = 1.0;
127 }
128 }
129
130 for &residue in &SCALE_DEPENDENT {
132 if let Some(idx) = PRIME_RESIDUE_CLASSES.iter().position(|&r| r == residue) {
133 weights[idx] = 1.1; }
135 }
136
137 QuantizationTable { base_q, weights }
138 }
139
140 pub fn get_step(&self, x: usize, y: usize) -> u16 {
142 let residue = ((x + y * 360) % 360) as u16;
144
145 let idx = self.find_closest_residue(residue);
147
148 let weighted_q = self.base_q as f32 * self.weights[idx];
150 weighted_q.round() as u16
151 }
152
153 fn find_closest_residue(&self, residue: u16) -> usize {
155 let mut min_dist = u16::MAX;
156 let mut min_idx = 0;
157
158 for (idx, &prime_residue) in PRIME_RESIDUE_CLASSES.iter().enumerate() {
159 let dist = if residue > prime_residue {
160 residue - prime_residue
161 } else {
162 prime_residue - residue
163 };
164
165 let wraparound_dist = 360 - dist;
167 let effective_dist = dist.min(wraparound_dist);
168
169 if effective_dist < min_dist {
170 min_dist = effective_dist;
171 min_idx = idx;
172 }
173 }
174
175 min_idx
176 }
177}
178
179pub struct PpfHash {
181 seed: u32,
183}
184
185impl PpfHash {
186 pub fn new(seed: u32) -> Self {
188 PpfHash { seed }
189 }
190
191 pub fn hash(&self, x: u32, y: u32) -> f32 {
193 let combined = self.combine_coords(x, y);
195
196 let hash = combined.wrapping_mul(2654435761u32);
198
199 let residue = (hash % 360) as usize;
201
202 let idx = self.find_prime_residue(residue);
204
205 PRIME_RESIDUE_CLASSES[idx] as f32 / 360.0
207 }
208
209 fn combine_coords(&self, x: u32, y: u32) -> u32 {
211 let x_prime = self.prime_factorize_approx(x);
214 let y_prime = self.prime_factorize_approx(y);
215 x_prime ^ y_prime ^ self.seed
216 }
217
218 fn prime_factorize_approx(&self, n: u32) -> u32 {
221 if n == 0 {
222 return 0;
223 }
224
225 let mut residue = n;
227 let mut factor_hash = 1u32;
228
229 while residue % 2 == 0 {
230 factor_hash = factor_hash.wrapping_mul(2);
231 residue /= 2;
232 }
233 while residue % 3 == 0 {
234 factor_hash = factor_hash.wrapping_mul(3);
235 residue /= 3;
236 }
237 while residue % 5 == 0 {
238 factor_hash = factor_hash.wrapping_mul(5);
239 residue /= 5;
240 }
241
242 factor_hash.wrapping_add(residue)
244 }
245
246 fn find_prime_residue(&self, residue: usize) -> usize {
248 let residue = residue as u16;
249 let mut min_dist = u16::MAX;
250 let mut min_idx = 0;
251
252 for (idx, &prime_residue) in PRIME_RESIDUE_CLASSES.iter().enumerate() {
253 let dist = if residue > prime_residue {
254 residue - prime_residue
255 } else {
256 prime_residue - residue
257 };
258
259 let wraparound_dist = 360 - dist;
260 let effective_dist = dist.min(wraparound_dist);
261
262 if effective_dist < min_dist {
263 min_dist = effective_dist;
264 min_idx = idx;
265 }
266 }
267
268 min_idx
269 }
270}
271
272pub struct RecursiveSequence {
274 scale: u32,
276 index: u32,
278 value: u32,
280}
281
282impl RecursiveSequence {
283 pub fn new(scale: u32) -> Self {
285 let value = (scale - 1) * 360 + 181;
287 RecursiveSequence {
288 scale,
289 index: 1,
290 value,
291 }
292 }
293
294 pub fn value(&self) -> u32 {
296 self.value
297 }
298
299 pub fn next(&mut self) -> u32 {
301 self.index += 1;
302 self.value += self.index;
303 self.value
304 }
305
306 pub fn in_range(&self) -> bool {
308 self.value <= self.scale * 360 + 180
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315
316 #[test]
317 fn test_residue_classes() {
318 assert_eq!(PRIME_RESIDUE_CLASSES.len(), RESIDUE_CLASSES);
320
321 for &residue in &PRIME_RESIDUE_CLASSES {
323 assert_eq!(gcd(residue as u32, 360), 1);
324 }
325 }
326
327 #[test]
328 fn test_category_distribution() {
329 assert_eq!(
331 FACTOR_COVERED.len() + SEQUENCE_COVERED.len() + SCALE_DEPENDENT.len(),
332 RESIDUE_CLASSES
333 );
334 }
335
336 #[test]
337 fn test_extended_prime() {
338 assert!(ExtendedPrime::is_prime(-1)); assert!(ExtendedPrime::is_prime(2));
340 assert!(ExtendedPrime::is_prime(3));
341 assert!(ExtendedPrime::is_prime(5));
342 assert!(ExtendedPrime::is_prime(7));
343
344 assert!(!ExtendedPrime::is_prime(0));
345 assert!(!ExtendedPrime::is_prime(1));
346 assert!(!ExtendedPrime::is_prime(4));
347 assert!(!ExtendedPrime::is_prime(6));
348
349 assert!(!ExtendedPrime::is_prime(-2));
351 assert!(!ExtendedPrime::is_prime(-3));
352 }
353
354 #[test]
355 fn test_quantization_table() {
356 let table = QuantizationTable::new(10);
357
358 assert_eq!(table.base_q, 10);
360
361 assert_eq!(table.weights.len(), RESIDUE_CLASSES);
363
364 let step1 = table.get_step(0, 0);
366 let step2 = table.get_step(100, 100);
367
368 assert!(step1 >= 8 && step1 <= 12);
370 assert!(step2 >= 8 && step2 <= 12);
371 }
372
373 #[test]
374 fn test_ppf_hash_determinism() {
375 let hash = PpfHash::new(42);
376
377 let h1 = hash.hash(10, 20);
379 let h2 = hash.hash(10, 20);
380 assert_eq!(h1, h2);
381
382 let h3 = hash.hash(10, 21);
384 assert_ne!(h1, h3);
385
386 assert!(h1 >= 0.0 && h1 < 1.0);
388 }
389
390 #[test]
391 fn test_recursive_sequence() {
392 let mut seq = RecursiveSequence::new(1);
394 assert_eq!(seq.value(), 181); assert_eq!(seq.next(), 183); assert_eq!(seq.next(), 186); assert_eq!(seq.next(), 190); let mut seq2 = RecursiveSequence::new(2);
402 assert_eq!(seq2.value(), 541); }
404
405 #[test]
406 fn test_sequence_coverage() {
407 let mut seq = RecursiveSequence::new(1);
409 let mut count = 0;
410
411 while seq.in_range() && count < 1000 {
412 seq.next();
413 count += 1;
414 }
415
416 assert!(count > 10);
418 assert!(count < 1000); }
420
421 fn gcd(mut a: u32, mut b: u32) -> u32 {
423 while b != 0 {
424 let temp = b;
425 b = a % b;
426 a = temp;
427 }
428 a
429 }
430}