rustfft/
math_utils.rs

1use num_traits::{One, PrimInt, Zero};
2
3pub fn primitive_root(prime: u64) -> Option<u64> {
4    let test_exponents: Vec<u64> = distinct_prime_factors(prime - 1)
5        .iter()
6        .map(|factor| (prime - 1) / factor)
7        .collect();
8    'next: for potential_root in 2..prime {
9        // for each distinct factor, if potential_root^(p-1)/factor mod p is 1, reject it
10        for exp in &test_exponents {
11            if modular_exponent(potential_root, *exp, prime) == 1 {
12                continue 'next;
13            }
14        }
15
16        // if we reach this point, it means this root was not rejected, so return it
17        return Some(potential_root);
18    }
19    None
20}
21
22/// computes base^exponent % modulo using the standard exponentiation by squaring algorithm
23pub fn modular_exponent<T: PrimInt>(mut base: T, mut exponent: T, modulo: T) -> T {
24    let one = T::one();
25
26    let mut result = one;
27
28    while exponent > Zero::zero() {
29        if exponent & one == one {
30            result = result * base % modulo;
31        }
32        exponent = exponent >> One::one();
33        base = (base * base) % modulo;
34    }
35
36    result
37}
38
39/// return all of the prime factors of n, but omit duplicate prime factors
40pub fn distinct_prime_factors(mut n: u64) -> Vec<u64> {
41    let mut result = Vec::new();
42
43    // handle 2 separately so we dont have to worry about adding 2 vs 1
44    if n % 2 == 0 {
45        while n % 2 == 0 {
46            n /= 2;
47        }
48        result.push(2);
49    }
50    if n > 1 {
51        let mut divisor = 3;
52        let mut limit = (n as f32).sqrt() as u64 + 1;
53        while divisor < limit {
54            if n % divisor == 0 {
55                // remove as many factors as possible from n
56                while n % divisor == 0 {
57                    n /= divisor;
58                }
59                result.push(divisor);
60
61                // recalculate the limit to reduce the amount of work we need to do
62                limit = (n as f32).sqrt() as u64 + 1;
63            }
64
65            divisor += 2;
66        }
67
68        if n > 1 {
69            result.push(n);
70        }
71    }
72
73    result
74}
75
76#[derive(Debug, PartialEq, Eq, Copy, Clone)]
77pub struct PrimeFactor {
78    pub value: usize,
79    pub count: u32,
80}
81
82#[derive(Clone, Debug)]
83pub struct PrimeFactors {
84    other_factors: Vec<PrimeFactor>,
85    n: usize,
86    power_two: u32,
87    power_three: u32,
88    total_factor_count: u32,
89    distinct_factor_count: u32,
90}
91impl PrimeFactors {
92    pub fn compute(mut n: usize) -> Self {
93        let mut result = Self {
94            other_factors: Vec::new(),
95            n,
96            power_two: 0,
97            power_three: 0,
98            total_factor_count: 0,
99            distinct_factor_count: 0,
100        };
101
102        // compute powers of two separately
103        result.power_two = n.trailing_zeros();
104        result.total_factor_count += result.power_two;
105        n >>= result.power_two;
106        if result.power_two > 0 {
107            result.distinct_factor_count += 1;
108        }
109
110        // also compute powers of three separately
111        while n % 3 == 0 {
112            result.power_three += 1;
113            n /= 3;
114        }
115        result.total_factor_count += result.power_three;
116        if result.power_three > 0 {
117            result.distinct_factor_count += 1;
118        }
119
120        // if we have any other factors, gather them in the "other factors" vec
121        if n > 1 {
122            let mut divisor = 5;
123            // compute divisor limit. if our divisor goes above this limit, we know we won't find any more factors. we'll revise it downwards as we discover factors.
124            let mut limit = (n as f32).sqrt() as usize + 1;
125            while divisor < limit {
126                // Count how many times this divisor divesthe remaining input
127                let mut count = 0;
128                while n % divisor == 0 {
129                    n /= divisor;
130                    count += 1;
131                }
132
133                // If this entry is actually a divisor of the given number, add it to the array
134                if count > 0 {
135                    result.other_factors.push(PrimeFactor {
136                        value: divisor,
137                        count,
138                    });
139                    result.total_factor_count += count;
140                    result.distinct_factor_count += 1;
141
142                    // recalculate the limit to reduce the amount of other factors we need to check
143                    limit = (n as f32).sqrt() as usize + 1;
144                }
145
146                divisor += 2;
147            }
148
149            // because of our limit logic, there might be one factor left
150            if n > 1 {
151                result
152                    .other_factors
153                    .push(PrimeFactor { value: n, count: 1 });
154                result.total_factor_count += 1;
155                result.distinct_factor_count += 1;
156            }
157        }
158
159        result
160    }
161
162    pub fn is_prime(&self) -> bool {
163        self.total_factor_count == 1
164    }
165    pub fn get_product(&self) -> usize {
166        self.n
167    }
168    #[allow(unused)]
169    pub fn get_total_factor_count(&self) -> u32 {
170        self.total_factor_count
171    }
172    #[allow(unused)]
173    pub fn get_distinct_factor_count(&self) -> u32 {
174        self.distinct_factor_count
175    }
176    #[allow(unused)]
177    pub fn get_power_of_two(&self) -> u32 {
178        self.power_two
179    }
180    #[allow(unused)]
181    pub fn get_power_of_three(&self) -> u32 {
182        self.power_three
183    }
184    #[allow(unused)]
185    pub fn get_other_factors(&self) -> &[PrimeFactor] {
186        &self.other_factors
187    }
188    #[allow(unused)]
189    pub fn is_power_of_three(&self) -> bool {
190        self.power_three > 0 && self.power_two == 0 && self.other_factors.len() == 0
191    }
192
193    // Divides the number by the given prime factor. Returns None if the resulting number is one.
194    #[allow(unused)]
195    pub fn remove_factors(mut self, factor: PrimeFactor) -> Option<Self> {
196        if factor.count == 0 {
197            return Some(self);
198        }
199        if factor.value == 2 {
200            self.power_two = self.power_two.checked_sub(factor.count).unwrap();
201            self.n >>= factor.count;
202            self.total_factor_count -= factor.count;
203            if self.power_two == 0 {
204                self.distinct_factor_count -= 1;
205            }
206            if self.n > 1 {
207                return Some(self);
208            }
209        } else if factor.value == 3 {
210            self.power_three = self.power_three.checked_sub(factor.count).unwrap();
211            self.n /= 3.pow(factor.count);
212            self.total_factor_count -= factor.count;
213            if self.power_two == 0 {
214                self.distinct_factor_count -= 1;
215            }
216            if self.n > 1 {
217                return Some(self);
218            }
219        } else {
220            let found_factor = self
221                .other_factors
222                .iter_mut()
223                .find(|item| item.value == factor.value)
224                .unwrap();
225            found_factor.count = found_factor.count.checked_sub(factor.count).unwrap();
226            self.n /= factor.value.pow(factor.count);
227            self.total_factor_count -= factor.count;
228            if found_factor.count == 0 {
229                self.distinct_factor_count -= 1;
230                self.other_factors.retain(|item| item.value != factor.value);
231            }
232            if self.n > 1 {
233                return Some(self);
234            }
235        }
236        None
237    }
238
239    // returns true if we have any factors whose value is less than or equal to the provided factor
240    pub fn has_factors_leq(&self, factor: usize) -> bool {
241        self.power_two > 0
242            || self.power_three > 0
243            || self
244                .other_factors
245                .first()
246                .map_or(false, |f| f.value <= factor)
247    }
248
249    // returns true if we have any factors whose value is greater than the provided factor
250    pub fn has_factors_gt(&self, factor: usize) -> bool {
251        (factor < 2 && self.power_two > 0)
252            || (factor < 3 && self.power_three > 0)
253            || self
254                .other_factors
255                .last()
256                .map_or(false, |f| f.value > factor)
257    }
258
259    // returns the product of all factors greater than the provided min_factor
260    pub fn product_above(&self, min_factor: usize) -> usize {
261        self.other_factors
262            .iter()
263            .skip_while(|f| f.value <= min_factor)
264            .map(|f| f.value.pow(f.count))
265            .product()
266    }
267
268    // Splits this set of prime factors into two different sets so that the products of the two sets are as close as possible
269    pub fn partition_factors(mut self) -> (Self, Self) {
270        // Make sure this isn't a prime number
271        assert!(!self.is_prime());
272
273        // If the given length is a perfect square, put the square root into both returned arays
274        if self.power_two % 2 == 0
275            && self.power_three % 2 == 0
276            && self
277                .other_factors
278                .iter()
279                .all(|factor| factor.count % 2 == 0)
280        {
281            let mut new_product = 1;
282
283            // cut our power of two in half
284            self.power_two /= 2;
285            new_product <<= self.power_two;
286
287            // cout our power of three in half
288            self.power_three /= 2;
289            new_product *= 3.pow(self.power_three);
290
291            // cut all our other factors in half
292            for factor in self.other_factors.iter_mut() {
293                factor.count /= 2;
294                new_product *= factor.value.pow(factor.count);
295            }
296
297            // update our cached properties and return 2 copies of ourself
298            self.total_factor_count /= 2;
299            self.n = new_product;
300            (self.clone(), self)
301        } else if self.distinct_factor_count == 1 {
302            // If there's only one factor, just split it as evenly as possible
303            let mut half = Self {
304                other_factors: Vec::new(),
305                n: self.n,
306                power_two: self.power_two / 2,
307                power_three: self.power_three / 2,
308                total_factor_count: self.total_factor_count / 2,
309                distinct_factor_count: 1,
310            };
311
312            // We computed one half via integer division -- compute the other half by subtracting the divided values fro mthe original
313            self.power_two -= half.power_two;
314            self.power_three -= half.power_three;
315            self.total_factor_count -= half.total_factor_count;
316
317            // Update the product values for each half, with different logic depending on what kind of single factor we have
318            if let Some(first_factor) = self.other_factors.first_mut() {
319                // we actualyl skipped updating the "other factor"  earlier, so cut it in half and do the subtraction now
320                assert!(first_factor.count > 1); // If this is only one, then we're prime. we passed the "is_prime" assert earlier, so that would be a contradiction
321                let half_factor = PrimeFactor {
322                    value: first_factor.value,
323                    count: first_factor.count / 2,
324                };
325                first_factor.count -= half_factor.count;
326                half.other_factors.push(half_factor);
327
328                self.n = first_factor.value.pow(first_factor.count);
329                half.n = half_factor.value.pow(half_factor.count);
330            } else if half.power_two > 0 {
331                half.n = 1 << half.power_two;
332                self.n = 1 << self.power_two;
333            } else if half.power_three > 0 {
334                half.n = 3.pow(half.power_three);
335                self.n = 3.pow(self.power_three);
336            }
337
338            (self, half)
339        } else {
340            // we have a mixed bag of products. we're going to greedily try to evenly distribute entire groups of factors in one direction or the other
341            let mut left_product = 1;
342            let mut right_product = 1;
343
344            // for each factor, put it in whichever cumulative half is smaller
345            for factor in self.other_factors {
346                let factor_product = factor.value.pow(factor.count as u32);
347                if left_product <= right_product {
348                    left_product *= factor_product;
349                } else {
350                    right_product *= factor_product;
351                }
352            }
353            if left_product <= right_product {
354                left_product <<= self.power_two;
355            } else {
356                right_product <<= self.power_two;
357            }
358            if self.power_three > 0 && left_product <= right_product {
359                left_product *= 3.pow(self.power_three);
360            } else {
361                right_product *= 3.pow(self.power_three);
362            }
363
364            // now that we have our two products, compute a prime factorization for them
365            // we could maintain factor lists internally to save some computation and an allocation, but it led to a lot of code and this is so much simpler
366            (Self::compute(left_product), Self::compute(right_product))
367        }
368    }
369}
370
371#[derive(Copy, Clone, Debug)]
372pub struct PartialFactors {
373    power2: u32,
374    power3: u32,
375    power5: u32,
376    power7: u32,
377    power11: u32,
378    other_factors: usize,
379}
380impl PartialFactors {
381    #[allow(unused)]
382    pub fn compute(len: usize) -> Self {
383        let power2 = len.trailing_zeros();
384        let mut other_factors = len >> power2;
385
386        let mut power3 = 0;
387        while other_factors % 3 == 0 {
388            power3 += 1;
389            other_factors /= 3;
390        }
391
392        let mut power5 = 0;
393        while other_factors % 5 == 0 {
394            power5 += 1;
395            other_factors /= 5;
396        }
397
398        let mut power7 = 0;
399        while other_factors % 7 == 0 {
400            power7 += 1;
401            other_factors /= 7;
402        }
403
404        let mut power11 = 0;
405        while other_factors % 11 == 0 {
406            power11 += 1;
407            other_factors /= 11;
408        }
409
410        Self {
411            power2,
412            power3,
413            power5,
414            power7,
415            power11,
416            other_factors,
417        }
418    }
419
420    #[allow(unused)]
421    pub fn get_power2(&self) -> u32 {
422        self.power2
423    }
424    #[allow(unused)]
425    pub fn get_power3(&self) -> u32 {
426        self.power3
427    }
428    #[allow(unused)]
429    pub fn get_power5(&self) -> u32 {
430        self.power5
431    }
432    #[allow(unused)]
433    pub fn get_power7(&self) -> u32 {
434        self.power7
435    }
436    #[allow(unused)]
437    pub fn get_power11(&self) -> u32 {
438        self.power11
439    }
440    #[allow(unused)]
441    pub fn get_other_factors(&self) -> usize {
442        self.other_factors
443    }
444    #[allow(unused)]
445    pub fn product(&self) -> usize {
446        (self.other_factors
447            * 3.pow(self.power3)
448            * 5.pow(self.power5)
449            * 7.pow(self.power7)
450            * 11.pow(self.power11))
451            << self.power2
452    }
453    #[allow(unused)]
454    pub fn product_power2power3(&self) -> usize {
455        3.pow(self.power3) << self.power2
456    }
457    #[allow(unused)]
458    pub fn divide_by(&self, divisor: &PartialFactors) -> Option<PartialFactors> {
459        let two_divides = self.power2 >= divisor.power2;
460        let three_divides = self.power3 >= divisor.power3;
461        let five_divides = self.power5 >= divisor.power5;
462        let seven_divides = self.power7 >= divisor.power7;
463        let eleven_divides = self.power11 >= divisor.power11;
464        let other_divides = self.other_factors % divisor.other_factors == 0;
465        if two_divides
466            && three_divides
467            && five_divides
468            && seven_divides
469            && eleven_divides
470            && other_divides
471        {
472            Some(Self {
473                power2: self.power2 - divisor.power2,
474                power3: self.power3 - divisor.power3,
475                power5: self.power5 - divisor.power5,
476                power7: self.power7 - divisor.power7,
477                power11: self.power11 - divisor.power11,
478                other_factors: if self.other_factors == divisor.other_factors {
479                    1
480                } else {
481                    self.other_factors / divisor.other_factors
482                },
483            })
484        } else {
485            None
486        }
487    }
488}
489
490#[cfg(test)]
491mod unit_tests {
492    use super::*;
493
494    #[test]
495    fn test_modular_exponent() {
496        // make sure to test something that would overflow under ordinary circumstances
497        // ie 3 ^ 416788 mod 47
498        let test_list = vec![
499            ((2, 8, 300), 256),
500            ((2, 9, 300), 212),
501            ((1, 9, 300), 1),
502            ((3, 416788, 47), 8),
503        ];
504
505        for (input, expected) in test_list {
506            let (base, exponent, modulo) = input;
507
508            let result = modular_exponent(base, exponent, modulo);
509
510            assert_eq!(result, expected);
511        }
512    }
513
514    #[test]
515    fn test_primitive_root() {
516        let test_list = vec![(3, 2), (7, 3), (11, 2), (13, 2), (47, 5), (7919, 7)];
517
518        for (input, expected) in test_list {
519            let root = primitive_root(input).unwrap();
520
521            assert_eq!(root, expected);
522        }
523    }
524
525    #[test]
526    fn test_distinct_prime_factors() {
527        let test_list = vec![
528            (46, vec![2, 23]),
529            (2, vec![2]),
530            (3, vec![3]),
531            (162, vec![2, 3]),
532        ];
533
534        for (input, expected) in test_list {
535            let factors = distinct_prime_factors(input);
536
537            assert_eq!(factors, expected);
538        }
539    }
540
541    use std::collections::HashMap;
542
543    macro_rules! map{
544        { $($key:expr => $value:expr),+ } => {
545            {
546                let mut m = HashMap::new();
547                $(
548                    m.insert($key, $value);
549                )+
550                m
551            }
552         };
553    }
554
555    fn assert_internally_consistent(prime_factors: &PrimeFactors) {
556        let mut cumulative_product = 1;
557        let mut discovered_distinct_factors = 0;
558        let mut discovered_total_factors = 0;
559
560        if prime_factors.get_power_of_two() > 0 {
561            cumulative_product <<= prime_factors.get_power_of_two();
562            discovered_distinct_factors += 1;
563            discovered_total_factors += prime_factors.get_power_of_two();
564        }
565        if prime_factors.get_power_of_three() > 0 {
566            cumulative_product *= 3.pow(prime_factors.get_power_of_three());
567            discovered_distinct_factors += 1;
568            discovered_total_factors += prime_factors.get_power_of_three();
569        }
570        for factor in prime_factors.get_other_factors() {
571            assert!(factor.count > 0);
572            cumulative_product *= factor.value.pow(factor.count);
573            discovered_distinct_factors += 1;
574            discovered_total_factors += factor.count;
575        }
576
577        assert_eq!(prime_factors.get_product(), cumulative_product);
578        assert_eq!(
579            prime_factors.get_distinct_factor_count(),
580            discovered_distinct_factors
581        );
582        assert_eq!(
583            prime_factors.get_total_factor_count(),
584            discovered_total_factors
585        );
586        assert_eq!(prime_factors.is_prime(), discovered_total_factors == 1);
587    }
588
589    #[test]
590    fn test_prime_factors() {
591        #[derive(Debug)]
592        struct ExpectedData {
593            len: usize,
594            factors: HashMap<usize, u32>,
595            total_factors: u32,
596            distinct_factors: u32,
597            is_prime: bool,
598        }
599        impl ExpectedData {
600            fn new(
601                len: usize,
602                factors: HashMap<usize, u32>,
603                total_factors: u32,
604                distinct_factors: u32,
605                is_prime: bool,
606            ) -> Self {
607                Self {
608                    len,
609                    factors,
610                    total_factors,
611                    distinct_factors,
612                    is_prime,
613                }
614            }
615        }
616
617        let test_list = vec![
618            ExpectedData::new(2, map! { 2 => 1 }, 1, 1, true),
619            ExpectedData::new(128, map! { 2 => 7 }, 7, 1, false),
620            ExpectedData::new(3, map! { 3 => 1 }, 1, 1, true),
621            ExpectedData::new(81, map! { 3 => 4 }, 4, 1, false),
622            ExpectedData::new(5, map! { 5 => 1 }, 1, 1, true),
623            ExpectedData::new(125, map! { 5 => 3 }, 3, 1, false),
624            ExpectedData::new(97, map! { 97 => 1 }, 1, 1, true),
625            ExpectedData::new(6, map! { 2 => 1, 3 => 1 }, 2, 2, false),
626            ExpectedData::new(12, map! { 2 => 2, 3 => 1 }, 3, 2, false),
627            ExpectedData::new(36, map! { 2 => 2, 3 => 2 }, 4, 2, false),
628            ExpectedData::new(10, map! { 2 => 1, 5 => 1 }, 2, 2, false),
629            ExpectedData::new(100, map! { 2 => 2, 5 => 2 }, 4, 2, false),
630            ExpectedData::new(44100, map! { 2 => 2, 3 => 2, 5 => 2, 7 => 2 }, 8, 4, false),
631        ];
632
633        for expected in test_list {
634            let factors = PrimeFactors::compute(expected.len);
635
636            assert_eq!(factors.get_product(), expected.len);
637            assert_eq!(factors.is_prime(), expected.is_prime);
638            assert_eq!(
639                factors.get_distinct_factor_count(),
640                expected.distinct_factors
641            );
642            assert_eq!(factors.get_total_factor_count(), expected.total_factors);
643            assert_eq!(
644                factors.get_power_of_two(),
645                expected.factors.get(&2).map_or(0, |i| *i)
646            );
647            assert_eq!(
648                factors.get_power_of_three(),
649                expected.factors.get(&3).map_or(0, |i| *i)
650            );
651
652            // verify that every factor in the "other factors" array matches our expected map
653            for factor in factors.get_other_factors() {
654                assert_eq!(factor.count, *expected.factors.get(&factor.value).unwrap());
655            }
656
657            // finally, verify that every factor in the "other factors" array was present in the "other factors" array
658            let mut found_factors: Vec<usize> = factors
659                .get_other_factors()
660                .iter()
661                .map(|factor| factor.value)
662                .collect();
663            if factors.get_power_of_two() > 0 {
664                found_factors.push(2);
665            }
666            if factors.get_power_of_three() > 0 {
667                found_factors.push(3);
668            }
669            for key in expected.factors.keys() {
670                assert!(found_factors.contains(key as &usize));
671            }
672        }
673
674        // in addition to our precomputed list, go through a bunch of ofther factors and just make sure they're internally consistent
675        for n in 1..200 {
676            let factors = PrimeFactors::compute(n);
677            assert_eq!(factors.get_product(), n);
678
679            assert_internally_consistent(&factors);
680        }
681    }
682
683    #[test]
684    fn test_partition_factors() {
685        // We aren't going to verify the actual return value of "partition_factors", we're justgoing to make sure each half is internally consistent
686        for n in 4..200 {
687            let factors = PrimeFactors::compute(n);
688            if !factors.is_prime() {
689                let (left_factors, right_factors) = factors.partition_factors();
690
691                assert!(left_factors.get_product() > 1);
692                assert!(right_factors.get_product() > 1);
693
694                assert_eq!(left_factors.get_product() * right_factors.get_product(), n);
695
696                assert_internally_consistent(&left_factors);
697                assert_internally_consistent(&right_factors);
698            }
699        }
700    }
701
702    #[test]
703    fn test_remove_factors() {
704        // For every possible factor of a bunch of factors, they removing each and making sure the result is internally consistent
705        for n in 2..200 {
706            let factors = PrimeFactors::compute(n);
707
708            for i in 0..=factors.get_power_of_two() {
709                if let Some(removed_factors) = factors
710                    .clone()
711                    .remove_factors(PrimeFactor { value: 2, count: i })
712                {
713                    assert_eq!(removed_factors.get_product(), factors.get_product() >> i);
714                    assert_internally_consistent(&removed_factors);
715                } else {
716                    // If the method returned None, this must be a power of two and i must be equal to the product
717                    assert!(n.is_power_of_two());
718                    assert!(i == factors.get_power_of_two());
719                }
720            }
721        }
722    }
723
724    #[test]
725    fn test_partial_factors() {
726        #[derive(Debug)]
727        struct ExpectedData {
728            len: usize,
729            power2: u32,
730            power3: u32,
731            power5: u32,
732            power7: u32,
733            power11: u32,
734            other: usize,
735        }
736
737        let test_list = vec![
738            ExpectedData {
739                len: 2,
740                power2: 1,
741                power3: 0,
742                power5: 0,
743                power7: 0,
744                power11: 0,
745                other: 1,
746            },
747            ExpectedData {
748                len: 128,
749                power2: 7,
750                power3: 0,
751                power5: 0,
752                power7: 0,
753                power11: 0,
754                other: 1,
755            },
756            ExpectedData {
757                len: 3,
758                power2: 0,
759                power3: 1,
760                power5: 0,
761                power7: 0,
762                power11: 0,
763                other: 1,
764            },
765            ExpectedData {
766                len: 81,
767                power2: 0,
768                power3: 4,
769                power5: 0,
770                power7: 0,
771                power11: 0,
772                other: 1,
773            },
774            ExpectedData {
775                len: 5,
776                power2: 0,
777                power3: 0,
778                power5: 1,
779                power7: 0,
780                power11: 0,
781                other: 1,
782            },
783            ExpectedData {
784                len: 125,
785                power2: 0,
786                power3: 0,
787                power5: 3,
788                power7: 0,
789                power11: 0,
790                other: 1,
791            },
792            ExpectedData {
793                len: 97,
794                power2: 0,
795                power3: 0,
796                power5: 0,
797                power7: 0,
798                power11: 0,
799                other: 97,
800            },
801            ExpectedData {
802                len: 6,
803                power2: 1,
804                power3: 1,
805                power5: 0,
806                power7: 0,
807                power11: 0,
808                other: 1,
809            },
810            ExpectedData {
811                len: 12,
812                power2: 2,
813                power3: 1,
814                power5: 0,
815                power7: 0,
816                power11: 0,
817                other: 1,
818            },
819            ExpectedData {
820                len: 36,
821                power2: 2,
822                power3: 2,
823                power5: 0,
824                power7: 0,
825                power11: 0,
826                other: 1,
827            },
828            ExpectedData {
829                len: 10,
830                power2: 1,
831                power3: 0,
832                power5: 1,
833                power7: 0,
834                power11: 0,
835                other: 1,
836            },
837            ExpectedData {
838                len: 100,
839                power2: 2,
840                power3: 0,
841                power5: 2,
842                power7: 0,
843                power11: 0,
844                other: 1,
845            },
846            ExpectedData {
847                len: 44100,
848                power2: 2,
849                power3: 2,
850                power5: 2,
851                power7: 2,
852                power11: 0,
853                other: 1,
854            },
855            ExpectedData {
856                len: 2310,
857                power2: 1,
858                power3: 1,
859                power5: 1,
860                power7: 1,
861                power11: 1,
862                other: 1,
863            },
864        ];
865
866        for expected in test_list {
867            let factors = PartialFactors::compute(expected.len);
868
869            assert_eq!(factors.get_power2(), expected.power2);
870            assert_eq!(factors.get_power3(), expected.power3);
871            assert_eq!(factors.get_power5(), expected.power5);
872            assert_eq!(factors.get_power7(), expected.power7);
873            assert_eq!(factors.get_power11(), expected.power11);
874            assert_eq!(factors.get_other_factors(), expected.other);
875
876            assert_eq!(
877                expected.len,
878                (1 << factors.get_power2())
879                    * 3.pow(factors.get_power3())
880                    * 5.pow(factors.get_power5())
881                    * 7.pow(factors.get_power7())
882                    * 11.pow(factors.get_power11())
883                    * factors.get_other_factors()
884            );
885            assert_eq!(expected.len, factors.product());
886            assert_eq!(
887                (1 << factors.get_power2()) * 3.pow(factors.get_power3()),
888                factors.product_power2power3()
889            );
890            assert_eq!(factors.get_other_factors().trailing_zeros(), 0);
891            assert!(factors.get_other_factors() % 3 > 0);
892        }
893
894        // in addition to our precomputed list, go through a bunch of ofther factors and just make sure they're internally consistent
895        for n in 1..200 {
896            let factors = PartialFactors::compute(n);
897
898            assert_eq!(
899                n,
900                (1 << factors.get_power2())
901                    * 3.pow(factors.get_power3())
902                    * 5.pow(factors.get_power5())
903                    * 7.pow(factors.get_power7())
904                    * 11.pow(factors.get_power11())
905                    * factors.get_other_factors()
906            );
907            assert_eq!(n, factors.product());
908            assert_eq!(
909                (1 << factors.get_power2()) * 3.pow(factors.get_power3()),
910                factors.product_power2power3()
911            );
912            assert_eq!(factors.get_other_factors().trailing_zeros(), 0);
913            assert!(factors.get_other_factors() % 3 > 0);
914        }
915    }
916
917    #[test]
918    fn test_partial_factors_divide_by() {
919        for n in 2..200 {
920            let factors = PartialFactors::compute(n);
921
922            for power2 in 0..5 {
923                for power3 in 0..4 {
924                    for power5 in 0..3 {
925                        for power7 in 0..3 {
926                            for power11 in 0..2 {
927                                for power13 in 0..2 {
928                                    let divisor_product = (3.pow(power3)
929                                        * 5.pow(power5)
930                                        * 7.pow(power7)
931                                        * 11.pow(power11)
932                                        * 13.pow(power13))
933                                        << power2;
934                                    let divisor = PartialFactors::compute(divisor_product);
935                                    if let Some(quotient) = factors.divide_by(&divisor) {
936                                        assert_eq!(quotient.product(), n / divisor_product);
937                                    } else {
938                                        assert!(n % divisor_product > 0);
939                                    }
940                                }
941                            }
942                        }
943                    }
944                }
945            }
946        }
947    }
948}