Skip to main content

malachite_base/num/factorization/
is_power.rs

1// Copyright © 2026 William Youmans
2//
3// Uses code adopted from the FLINT Library.
4//
5//      Copyright © 2009 William Hart
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::num::arithmetic::traits::{
14    CheckedRoot, DivAssignMod, DivMod, GcdAssign, Parity, RootRem, SqrtRem,
15};
16use crate::num::basic::integers::USIZE_IS_U32;
17use crate::num::conversion::traits::{ExactFrom, WrappingFrom};
18use crate::num::factorization::primes::SMALL_PRIMES;
19use crate::num::factorization::traits::{
20    ExpressAsPower, Factor, IsPower, IsPrime, IsSquare, Primes,
21};
22use crate::num::logic::traits::{SignificantBits, TrailingZeros};
23
24// The following arrays are bitmasks indicating whether an integer is a 2, 3, or 5th power residue.
25// For example, modulo 31 we have:
26// - squares:    {0, 1, 2, 4, 5, 7, 8, 9, 10, 14, 16, 18, 19, 20, 25, 28}
27// - cubes:      {0, 1, 2, 4, 8, 15, 16, 23, 27, 29, 30}
28// - 5th powers: {0, 1, 5, 6, 25, 26, 30}
29// Since 2 is a square, cube, but not a 5th power mod 31, we encode it as 011 = 3. Then MOD31[2] =
30// 3.
31
32const MOD63: [u8; 63] = [
33    7, 7, 4, 0, 5, 4, 0, 5, 6, 5, 4, 4, 0, 4, 4, 0, 5, 4, 5, 4, 4, 0, 5, 4, 0, 5, 4, 6, 7, 4, 0, 4,
34    4, 0, 4, 6, 7, 5, 4, 0, 4, 4, 0, 5, 4, 4, 5, 4, 0, 5, 4, 0, 4, 4, 4, 6, 4, 0, 5, 4, 0, 4, 6,
35];
36
37const MOD61: [u8; 61] = [
38    7, 7, 0, 3, 1, 1, 0, 0, 2, 3, 0, 6, 1, 5, 5, 1, 1, 0, 0, 1, 3, 4, 1, 2, 2, 1, 0, 3, 2, 4, 0, 0,
39    4, 2, 3, 0, 1, 2, 2, 1, 4, 3, 1, 0, 0, 1, 1, 5, 5, 1, 6, 0, 3, 2, 0, 0, 1, 1, 3, 0, 7,
40];
41
42const MOD44: [u8; 44] = [
43    7, 7, 0, 2, 3, 3, 0, 2, 2, 3, 0, 6, 7, 2, 0, 2, 3, 2, 0, 2, 3, 6, 0, 6, 2, 3, 0, 2, 2, 2, 0, 2,
44    6, 7, 0, 2, 3, 3, 0, 2, 2, 2, 0, 6,
45];
46
47const MOD31: [u8; 31] =
48    [7, 7, 3, 0, 3, 5, 4, 1, 3, 1, 1, 0, 0, 0, 1, 2, 3, 0, 1, 1, 1, 0, 0, 2, 0, 5, 4, 2, 1, 2, 6];
49
50const MOD72: [u8; 72] = [
51    7, 7, 0, 0, 0, 7, 0, 7, 7, 7, 0, 7, 0, 7, 0, 0, 7, 7, 0, 7, 0, 0, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7,
52    7, 0, 0, 7, 0, 7, 0, 0, 7, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 0, 0, 7, 0, 7, 7, 0, 0, 7, 0, 7, 0, 7,
53    7, 7, 0, 7, 0, 0, 0, 7,
54];
55
56const MOD49: [u8; 49] = [
57    1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
58    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
59];
60
61const MOD67: [u8; 67] = [
62    2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0,
63    0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64    0, 0, 2,
65];
66
67const MOD79: [u8; 79] = [
68    4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0,
69    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0,
70    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
71];
72
73// This is n_is_power when FLINT64 is false, from ulong_extras/is_power.c, FLINT 3.1.2.
74fn get_perfect_power_u32(n: u32) -> Option<(u32, u64)> {
75    // Check for powers 2, 3, 5
76    let mut t = MOD31[(n % 31) as usize];
77    t &= MOD44[(n % 44) as usize];
78    t &= MOD61[(n % 61) as usize];
79    t &= MOD63[(n % 63) as usize];
80    // Check for perfect square
81    if t.odd() {
82        let (rt, rem) = n.sqrt_rem();
83        if rem == 0 {
84            return Some((rt, 2));
85        }
86    }
87    // Check for perfect cube
88    if t & 2 != 0 {
89        let (rt, rem) = n.root_rem(3);
90        if rem == 0 {
91            return Some((rt, 3));
92        }
93    }
94    // Check for perfect fifth power
95    if t & 4 != 0 {
96        let (rt, rem) = n.root_rem(5);
97        if rem == 0 {
98            return Some((rt, 5));
99        }
100    }
101    // Check for powers 7, 11, 13
102    t = MOD49[(n % 49) as usize];
103    t |= MOD67[(n % 67) as usize];
104    t |= MOD79[(n % 79) as usize];
105    t &= MOD72[(n % 72) as usize];
106
107    // Check for perfect 7th power
108    if t.odd() {
109        let (rt, rem) = n.root_rem(7);
110        if rem == 0 {
111            return Some((rt, 7));
112        }
113    }
114    // Check for perfect 11th power
115    if t & 2 != 0 {
116        let (rt, rem) = n.root_rem(11);
117        if rem == 0 {
118            return Some((rt, 11));
119        }
120    }
121    // Check for perfect 13th power
122    if t & 13 != 0 {
123        let (rt, rem) = n.root_rem(13);
124        if rem == 0 {
125            return Some((rt, 13));
126        }
127    }
128    // Handle powers of 2
129    let count = u64::from(n.trailing_zeros());
130    let mut n = n >> count;
131    if n == 1 {
132        return if count == 1 {
133            None // Just 2^1 = 2, not a perfect power
134        } else {
135            Some((2, count))
136        };
137    }
138    // Check other powers (exp >= 17, root <= 13 and odd)
139    let mut exp = 0;
140    while n.is_multiple_of(3) {
141        n /= 3;
142        exp += 1;
143    }
144    if exp > 0 {
145        if n == 1 && exp > 1 {
146            if count == 0 {
147                return Some((3, exp));
148            } else if count == exp {
149                return Some((6, exp));
150            } else if count == exp << 1 {
151                return Some((12, exp));
152            }
153        }
154        return None;
155    }
156    None
157}
158
159// This is n_is_power when FLINT64 is false, from ulong_extras/is_power.c, FLINT 3.1.2, returning
160// only whether n can be expressed as a nontrivial perfect power.
161fn get_perfect_power_u32_bool(n: u32) -> bool {
162    // Check for powers 2, 3, 5
163    let mut t = MOD31[(n % 31) as usize];
164    t &= MOD44[(n % 44) as usize];
165    t &= MOD61[(n % 61) as usize];
166    t &= MOD63[(n % 63) as usize];
167    // Check for perfect squares, cubes, and fifth powers
168    if (t.odd() && n.is_square())
169        || (t & 2 != 0 && n.root_rem(3).1 == 0)
170        || (t & 4 != 0 && n.root_rem(5).1 == 0)
171    {
172        return true;
173    }
174    // Check for powers 7, 11, 13
175    t = MOD49[(n % 49) as usize];
176    t |= MOD67[(n % 67) as usize];
177    t |= MOD79[(n % 79) as usize];
178    t &= MOD72[(n % 72) as usize];
179    // Check for perfect 7th, 11th, and 13th powers
180    if (t.odd() && n.root_rem(7).1 == 0)
181        || (t & 2 != 0 && n.root_rem(11).1 == 0)
182        || (t & 13 != 0 && n.root_rem(13).1 == 0)
183    {
184        return true;
185    }
186    // Handle powers of 2
187    let count = n.trailing_zeros();
188    let mut n = n >> n.trailing_zeros();
189    if n == 1 {
190        return count != 1;
191    }
192    // Check other powers (exp >= 17, root <= 13 and odd)
193    let mut exp = 0;
194    while n.is_multiple_of(3) {
195        n /= 3;
196        exp += 1;
197    }
198    exp > 0 && n == 1 && exp > 1 && (count == 0 || count == exp || count == exp << 1)
199}
200
201// This is n_is_power when FLINT64 is true, from ulong_extras/is_power.c, FLINT 3.1.2.
202fn get_perfect_power_u64(n: u64) -> Option<(u64, u64)> {
203    // Check for powers 2, 3, 5
204    let mut t = MOD31[(n % 31) as usize];
205    t &= MOD44[(n % 44) as usize];
206    t &= MOD61[(n % 61) as usize];
207    t &= MOD63[(n % 63) as usize];
208    // Check for perfect square
209    if t.odd() {
210        let (rt, rem) = n.sqrt_rem();
211        if rem == 0 {
212            return Some((rt, 2));
213        }
214    }
215    // Check for perfect cube
216    if t & 2 != 0 {
217        let (rt, rem) = n.root_rem(3);
218        if rem == 0 {
219            return Some((rt, 3));
220        }
221    }
222    // Check for perfect fifth power
223    if t & 4 != 0 {
224        let (rt, rem) = n.root_rem(5);
225        if rem == 0 {
226            return Some((rt, 5));
227        }
228    }
229    // Check for powers 7, 11, 13
230    t = MOD49[(n % 49) as usize];
231    t |= MOD67[(n % 67) as usize];
232    t |= MOD79[(n % 79) as usize];
233    t &= MOD72[(n % 72) as usize];
234    // Check for perfect 7th power
235    if t.odd() {
236        let (rt, rem) = n.root_rem(7);
237        if rem == 0 {
238            return Some((rt, 7));
239        }
240    }
241    // Check for perfect 11th power
242    if t & 2 != 0 {
243        let (rt, rem) = n.root_rem(11);
244        if rem == 0 {
245            return Some((rt, 11));
246        }
247    }
248    // Check for perfect 13th power
249    if t & 13 != 0 {
250        let (rt, rem) = n.root_rem(13);
251        if rem == 0 {
252            return Some((rt, 13));
253        }
254    }
255    // Handle powers of 2
256    let count = u64::from(n.trailing_zeros());
257    let mut n = n >> count;
258    if n == 1 {
259        return if count == 1 {
260            None // Just 2^1 = 2, not a perfect power
261        } else {
262            Some((2, count))
263        };
264    }
265    // Check other powers (exp >= 17, root <= 13 and odd)
266    let mut exp = 0;
267    while n.is_multiple_of(3) {
268        n /= 3;
269        exp += 1;
270    }
271    if exp > 0 {
272        if n == 1 && exp > 1 {
273            if count == 0 {
274                return Some((3, exp));
275            } else if count == exp {
276                return Some((6, exp));
277            } else if count == exp << 1 {
278                return Some((12, exp));
279            }
280        }
281        return None;
282    }
283    // Check powers of 5
284    exp = 0;
285    while n.is_multiple_of(5) {
286        n /= 5;
287        exp += 1;
288    }
289    if exp > 0 {
290        if n == 1 && exp > 1 {
291            if count == 0 {
292                return Some((5, exp));
293            } else if count == exp {
294                return Some((10, exp));
295            }
296        }
297        return None;
298    }
299    if count > 0 {
300        return None;
301    }
302    // Check powers of 7
303    exp = 0;
304    while n.is_multiple_of(7) {
305        n /= 7;
306        exp += 1;
307    }
308    if exp > 0 {
309        if n == 1 && exp > 1 {
310            return Some((7, exp));
311        }
312        return None;
313    }
314    // Check powers of 11
315    exp = 0;
316    while n.is_multiple_of(11) {
317        n /= 11;
318        exp += 1;
319    }
320    if exp > 0 {
321        if n == 1 && exp > 1 {
322            return Some((11, exp));
323        }
324        return None;
325    }
326    // Check powers of 13
327    exp = 0;
328    while n.is_multiple_of(13) {
329        n /= 13;
330        exp += 1;
331    }
332    if exp > 0 {
333        if n == 1 && exp > 1 {
334            return Some((13, exp));
335        }
336        return None;
337    }
338    None
339}
340
341// This is n_is_power when FLINT64 is true, from ulong_extras/is_power.c, FLINT 3.1.2, returning
342// only whether n can be expressed as a nontrivial perfect power.
343fn get_perfect_power_u64_bool(n: u64) -> bool {
344    // Check for powers 2, 3, 5
345    let mut t = MOD31[(n % 31) as usize];
346    t &= MOD44[(n % 44) as usize];
347    t &= MOD61[(n % 61) as usize];
348    t &= MOD63[(n % 63) as usize];
349    // Check for perfect squares, cubes, and fifth powers
350    if (t.odd() && n.is_square())
351        || (t & 2 != 0 && n.root_rem(3).1 == 0)
352        || (t & 4 != 0 && n.root_rem(5).1 == 0)
353    {
354        return true;
355    }
356    // Check for powers 7, 11, 13
357    t = MOD49[(n % 49) as usize];
358    t |= MOD67[(n % 67) as usize];
359    t |= MOD79[(n % 79) as usize];
360    t &= MOD72[(n % 72) as usize];
361    // Check for perfect 7th, 11th, and 13th powers
362    if (t.odd() && n.root_rem(7).1 == 0)
363        || (t & 2 != 0 && n.root_rem(11).1 == 0)
364        || (t & 13 != 0 && n.root_rem(13).1 == 0)
365    {
366        return true;
367    }
368    // Handle powers of 2
369    let count = u64::from(n.trailing_zeros());
370    let mut n = n >> count;
371    if n == 1 {
372        return count != 1;
373    }
374    // Check other powers (exp >= 17, root <= 13 and odd)
375    let mut exp = 0;
376    while n.is_multiple_of(3) {
377        n /= 3;
378        exp += 1;
379    }
380    if exp > 0 {
381        return n == 1 && exp > 1 && (count == 0 || count == exp || count == exp << 1);
382    }
383    // Check powers of 5
384    exp = 0;
385    while n.is_multiple_of(5) {
386        n /= 5;
387        exp += 1;
388    }
389    if exp > 0 {
390        return n == 1 && exp > 1 && (count == 0 || count == exp);
391    }
392    if count > 0 {
393        return false;
394    }
395    // Check powers of 7
396    exp = 0;
397    while n.is_multiple_of(7) {
398        n /= 7;
399        exp += 1;
400    }
401    if exp > 0 {
402        return n == 1 && exp > 1;
403    }
404    // Check powers of 11
405    exp = 0;
406    while n.is_multiple_of(11) {
407        n /= 11;
408        exp += 1;
409    }
410    if exp > 0 {
411        return n == 1 && exp > 1;
412    }
413    // Check powers of 13
414    exp = 0;
415    while n.is_multiple_of(13) {
416        n /= 13;
417        exp += 1;
418    }
419    n == 1 && exp > 1
420}
421
422fn get_perfect_power_u128(n: u128) -> Option<(u128, u64)> {
423    if let Ok(n) = u64::try_from(n) {
424        return get_perfect_power_u64(n).map(|(p, e)| (u128::from(p), e));
425    }
426    // Find largest power of 2 dividing n
427    let mut pow_2 = TrailingZeros::trailing_zeros(n);
428    // Two divides exactly once - not a perfect power
429    if pow_2 == 1 {
430        return None;
431    }
432    // If pow_2 is prime, just check if n is a perfect pow_2-th power
433    if pow_2.is_prime() {
434        return n.checked_root(pow_2).map(|root| (root, pow_2));
435    }
436    // Divide out 2^pow_2 to get the odd part
437    let mut q = n >> pow_2;
438    // Factor out powers of small primes
439    for &prime in SMALL_PRIMES[..168].iter().skip(1) {
440        let prime = u128::from(prime);
441        let (new_q, r) = q.div_mod(prime);
442        if r == 0 {
443            q = new_q;
444            if q.div_assign_mod(prime) != 0 {
445                return None; // prime divides exactly once, reject
446            }
447            let mut pow_p = 2u64;
448            loop {
449                let (new_q, r) = q.div_mod(prime);
450                if r == 0 {
451                    q = new_q;
452                    pow_p += 1;
453                } else {
454                    break;
455                }
456            }
457            pow_2.gcd_assign(pow_p);
458            if pow_2 == 1 {
459                return None; // we have multiplicity 1 of some factor
460            }
461            // As soon as pow_2 becomes prime, stop factoring
462            if q == 1 || pow_2.is_prime() {
463                return n.checked_root(pow_2).map(|root| (root, pow_2));
464            }
465        }
466    }
467    // After factoring, check remaining cases
468    if pow_2 == 0 {
469        // No factors found above; exhaustively check all prime exponents
470        let bits = n.significant_bits();
471        for nth in u64::primes() {
472            // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits)
473            if nth > bits {
474                return None;
475            }
476            if let Some(root) = n.checked_root(nth) {
477                return Some((root, nth));
478            }
479        }
480    } else {
481        // Found some factors; only check prime divisors of pow_2
482        for (nth, _) in pow_2.factor() {
483            if let Some(root) = n.checked_root(nth) {
484                return Some((root, nth));
485            }
486        }
487    }
488    None
489}
490
491fn get_perfect_power_u128_bool(n: u128) -> bool {
492    if let Ok(n) = u64::try_from(n) {
493        return get_perfect_power_u64_bool(n);
494    }
495    // Find largest power of 2 dividing n
496    let mut pow_2 = TrailingZeros::trailing_zeros(n);
497    // Two divides exactly once - not a perfect power
498    if pow_2 == 1 {
499        return false;
500    }
501    // If pow_2 is prime, check if n is a perfect pow_2-th power
502    if pow_2.is_prime() {
503        return n.checked_root(pow_2).is_some();
504    }
505    // Divide out 2^pow_2 to get the odd part
506    let mut q = n >> pow_2;
507    // Factor out powers of small primes
508    for &prime in SMALL_PRIMES[..168].iter().skip(1) {
509        let prime = u128::from(prime);
510        let (new_q, r) = q.div_mod(prime);
511        if r == 0 {
512            q = new_q;
513            if q.div_assign_mod(prime) != 0 {
514                return false; // prime divides exactly once, reject
515            }
516            let mut pow_p = 2u64;
517            loop {
518                let (new_q, r) = q.div_mod(prime);
519                if r == 0 {
520                    q = new_q;
521                    pow_p += 1;
522                } else {
523                    break;
524                }
525            }
526            pow_2.gcd_assign(pow_p);
527            if pow_2 == 1 {
528                return false; // we have multiplicity 1 of some factor
529            }
530            // As soon as pow_2 becomes prime, stop factoring
531            if q == 1 || pow_2.is_prime() {
532                return n.checked_root(pow_2).is_some();
533            }
534        }
535    }
536    // After factoring, check remaining cases
537    if pow_2 == 0 {
538        // No factors found above; exhaustively check all prime exponents
539        let bits = n.significant_bits();
540        for nth in u64::primes() {
541            // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits)
542            if nth > bits {
543                return false;
544            }
545            if n.checked_root(nth).is_some() {
546                return true;
547            }
548        }
549    } else {
550        // Found some factors; only check prime divisors of pow_2
551        for (nth, _) in pow_2.factor() {
552            if n.checked_root(nth).is_some() {
553                return true;
554            }
555        }
556    }
557    false
558}
559
560fn express_as_power_u32(n: u32) -> Option<(u32, u64)> {
561    if n <= 1 {
562        return Some((n, 2));
563    }
564    // continue until we have largest possible exponent
565    let (mut base, mut exp) = get_perfect_power_u32(n)?;
566    while base > 3 {
567        match get_perfect_power_u32(base) {
568            Some((base2, exp2)) => {
569                base = base2;
570                exp *= exp2;
571            }
572            None => {
573                return Some((base, exp));
574            }
575        }
576    }
577    Some((base, exp))
578}
579
580fn express_as_power_u64(n: u64) -> Option<(u64, u64)> {
581    if n <= 1 {
582        return Some((n, 2));
583    }
584    // continue until we have largest possible exponent
585    let (mut base, mut exp) = get_perfect_power_u64(n)?;
586    while base > 3 {
587        match get_perfect_power_u64(base) {
588            Some((base2, exp2)) => {
589                base = base2;
590                exp *= exp2;
591            }
592            None => {
593                return Some((base, exp));
594            }
595        }
596    }
597    Some((base, exp))
598}
599
600fn express_as_power_u128(n: u128) -> Option<(u128, u64)> {
601    if n <= 1 {
602        return Some((n, 2));
603    }
604    // continue until we have largest possible exponent
605    let (mut base, mut exp) = get_perfect_power_u128(n)?;
606    while base > 3 {
607        match get_perfect_power_u128(base) {
608            Some((base2, exp2)) => {
609                base = base2;
610                exp *= exp2;
611            }
612            None => {
613                return Some((base, exp));
614            }
615        }
616    }
617    Some((base, exp))
618}
619
620fn express_as_power_i32(n: i32) -> Option<(i32, u64)> {
621    if n == 0 || n == 1 {
622        return Some((n, 2));
623    }
624    // continue until we have largest possible exponent
625    let (mut base, mut exp) = get_perfect_power_u32(n.unsigned_abs())?;
626    while base > 3 {
627        match get_perfect_power_u32(base) {
628            Some((base2, exp2)) => {
629                base = base2;
630                exp *= exp2;
631            }
632            None => break,
633        }
634    }
635    // handle negative input
636    if n < 0 && exp.even() {
637        while exp.even() {
638            base *= base;
639            exp >>= 1;
640        }
641        if exp == 1 {
642            return None;
643        }
644    }
645    let ibase = i32::exact_from(base);
646    Some((if n >= 0 { ibase } else { -ibase }, exp))
647}
648
649fn express_as_power_i64(n: i64) -> Option<(i64, u64)> {
650    if n == 0 || n == 1 {
651        return Some((n, 2));
652    }
653    // continue until we have largest possible exponent
654    let (mut base, mut exp) = get_perfect_power_u64(n.unsigned_abs())?;
655    while base > 3 {
656        match get_perfect_power_u64(base) {
657            Some((base2, exp2)) => {
658                base = base2;
659                exp *= exp2;
660            }
661            None => break,
662        }
663    }
664    // handle negative input
665    if n < 0 && exp.even() {
666        while exp.even() {
667            base *= base;
668            exp >>= 1;
669        }
670        if exp == 1 {
671            return None;
672        }
673    }
674    let ibase = i64::exact_from(base);
675    Some((if n >= 0 { ibase } else { -ibase }, exp))
676}
677
678fn express_as_power_i128(n: i128) -> Option<(i128, u64)> {
679    if n == 0 || n == 1 {
680        return Some((n, 2));
681    }
682    // continue until we have largest possible exponent
683    let (mut base, mut exp) = get_perfect_power_u128(n.unsigned_abs())?;
684    while base > 3 {
685        match get_perfect_power_u128(base) {
686            Some((base2, exp2)) => {
687                base = base2;
688                exp *= exp2;
689            }
690            None => break,
691        }
692    }
693    // handle negative input
694    if n < 0 && exp.even() {
695        while exp.even() {
696            base *= base;
697            exp >>= 1;
698        }
699        if exp == 1 {
700            return None;
701        }
702    }
703    let ibase = i128::exact_from(base);
704    Some((if n >= 0 { ibase } else { -ibase }, exp))
705}
706
707#[inline]
708fn is_power_u32(n: u32) -> bool {
709    n <= 1 || get_perfect_power_u32_bool(n)
710}
711
712#[inline]
713fn is_power_u64(n: u64) -> bool {
714    n <= 1 || get_perfect_power_u64_bool(n)
715}
716
717fn is_power_i32(n: i32) -> bool {
718    if n == 0 || n == 1 {
719        return true;
720    }
721    if n > 0 {
722        // For positive numbers, just check if it's a perfect power
723        return get_perfect_power_u32_bool(n.unsigned_abs());
724    }
725    // For negative numbers, we need to check if there's an odd exponent representation
726    //
727    // continue until we have largest possible exponent
728    let Some((mut base, mut exp)) = get_perfect_power_u32(n.unsigned_abs()) else {
729        return false;
730    };
731    while base > 3 {
732        match get_perfect_power_u32(base) {
733            Some((base2, exp2)) => {
734                base = base2;
735                exp *= exp2;
736            }
737            None => break,
738        }
739    }
740    // Check if we can make the exponent odd
741    !exp.is_power_of_two()
742}
743
744fn is_power_i64(n: i64) -> bool {
745    if n == 0 || n == 1 {
746        return true;
747    }
748    if n > 0 {
749        // For positive numbers, just check if it's a perfect power
750        return get_perfect_power_u64_bool(n.unsigned_abs());
751    }
752    // For negative numbers, we need to check if there's an odd exponent representation
753    //
754    // continue until we have largest possible exponent
755    let Some((mut base, mut exp)) = get_perfect_power_u64(n.unsigned_abs()) else {
756        return false;
757    };
758    while base > 3 {
759        match get_perfect_power_u64(base) {
760            Some((base2, exp2)) => {
761                base = base2;
762                exp *= exp2;
763            }
764            None => break,
765        }
766    }
767    // Check if we can make the exponent odd
768    !exp.is_power_of_two()
769}
770
771fn is_power_i128(n: i128) -> bool {
772    if n == 0 || n == 1 {
773        return true;
774    }
775    if n > 0 {
776        // For positive numbers, just check if it's a perfect power
777        return get_perfect_power_u128_bool(n.unsigned_abs());
778    }
779    // For negative numbers, we need to check if there's an odd exponent representation
780    //
781    // continue until we have largest possible exponent
782    let Some((mut base, mut exp)) = get_perfect_power_u128(n.unsigned_abs()) else {
783        return false;
784    };
785    while base > 3 {
786        match get_perfect_power_u128(base) {
787            Some((base2, exp2)) => {
788                base = base2;
789                exp *= exp2;
790            }
791            None => break,
792        }
793    }
794    // Check if we can make the exponent odd
795    !exp.is_power_of_two()
796}
797
798impl ExpressAsPower for u64 {
799    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
800    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
801    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
802    /// representation as a power, the representation with the smallest base is returned. For
803    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
804    ///
805    /// # Worst-case complexity
806    /// $T(n) = O(n)$
807    ///
808    /// $M(n) = O(1)$
809    ///
810    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
811    /// division strips small prime factors, each division removing at least one bit, and a bounded
812    /// number of root extractions follow, each at worst $O(n)$.
813    ///
814    /// # Examples
815    /// See [here](super::is_power#express_as_power).
816    ///
817    /// # Notes
818    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
819    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
820    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
821    #[inline]
822    fn express_as_power(&self) -> Option<(u64, u64)> {
823        express_as_power_u64(*self)
824    }
825}
826
827impl ExpressAsPower for u128 {
828    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
829    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
830    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
831    /// representation as a power, the representation with the smallest base is returned. For
832    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
833    ///
834    /// # Worst-case complexity
835    /// $T(n) = O(n)$
836    ///
837    /// $M(n) = O(1)$
838    ///
839    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
840    /// division strips small prime factors, each division removing at least one bit, and a bounded
841    /// number of root extractions follow, each at worst $O(n)$.
842    ///
843    /// # Examples
844    /// See [here](super::is_power#express_as_power).
845    ///
846    /// # Notes
847    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
848    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
849    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
850    #[inline]
851    fn express_as_power(&self) -> Option<(Self, u64)> {
852        express_as_power_u128(*self)
853    }
854}
855
856impl ExpressAsPower for usize {
857    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
858    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
859    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
860    /// representation as a power, the representation with the smallest base is returned. For
861    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
862    ///
863    /// # Worst-case complexity
864    /// $T(n) = O(n)$
865    ///
866    /// $M(n) = O(1)$
867    ///
868    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
869    /// division strips small prime factors, each division removing at least one bit, and a bounded
870    /// number of root extractions follow, each at worst $O(n)$.
871    ///
872    /// # Examples
873    /// See [here](super::is_power#express_as_power).
874    ///
875    /// # Notes
876    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
877    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
878    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
879    fn express_as_power(&self) -> Option<(Self, u64)> {
880        if USIZE_IS_U32 {
881            match express_as_power_u32(u32::wrapping_from(*self)) {
882                Some((base, exp)) => Some((Self::wrapping_from(base), exp)),
883                _ => None,
884            }
885        } else {
886            match express_as_power_u64(u64::wrapping_from(*self)) {
887                Some((base, exp)) => Some((Self::wrapping_from(base), exp)),
888                _ => None,
889            }
890        }
891    }
892}
893
894impl IsPower for u64 {
895    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
896    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
897    /// considered perfect powers.
898    ///
899    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
900    ///
901    /// # Worst-case complexity
902    /// $T(n) = O(n)$
903    ///
904    /// $M(n) = O(1)$
905    ///
906    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
907    /// division strips small prime factors, each division removing at least one bit, and a bounded
908    /// number of root extractions follow, each at worst $O(n)$.
909    ///
910    /// # Examples
911    /// See [here](super::is_power#is_power).
912    #[inline]
913    fn is_power(&self) -> bool {
914        is_power_u64(*self)
915    }
916}
917
918impl IsPower for u128 {
919    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
920    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
921    /// considered perfect powers.
922    ///
923    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
924    ///
925    /// # Worst-case complexity
926    /// $T(n) = O(n)$
927    ///
928    /// $M(n) = O(1)$
929    ///
930    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
931    /// division strips small prime factors, each division removing at least one bit, and a bounded
932    /// number of root extractions follow, each at worst $O(n)$.
933    ///
934    /// # Examples
935    /// See [here](super::is_power#is_power).
936    #[inline]
937    fn is_power(&self) -> bool {
938        get_perfect_power_u128_bool(*self)
939    }
940}
941
942impl IsPower for usize {
943    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
944    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
945    /// considered perfect powers.
946    ///
947    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
948    ///
949    /// # Worst-case complexity
950    /// $T(n) = O(n)$
951    ///
952    /// $M(n) = O(1)$
953    ///
954    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
955    /// division strips small prime factors, each division removing at least one bit, and a bounded
956    /// number of root extractions follow, each at worst $O(n)$.
957    ///
958    /// # Examples
959    /// See [here](super::is_power#is_power).
960    fn is_power(&self) -> bool {
961        if USIZE_IS_U32 {
962            is_power_u32(u32::wrapping_from(*self))
963        } else {
964            is_power_u64(u64::wrapping_from(*self))
965        }
966    }
967}
968
969macro_rules! impl_unsigned_32 {
970    ($t: ident) => {
971        impl ExpressAsPower for $t {
972            /// Expresses a number as a perfect power, if such a representation exists. We define a
973            /// perfect power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both
974            /// integers. In particular, 0 and 1 are considered perfect powers. If a number has more
975            /// than one representation as a power, the representation with the smallest base is
976            /// returned. For example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather
977            /// than `(4,3)` or `(8,2)`.
978            ///
979            /// # Worst-case complexity
980            /// $T(n) = O(n)$
981            ///
982            /// $M(n) = O(1)$
983            ///
984            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`:
985            /// trial division strips small prime factors, each division removing at least one bit,
986            /// and a bounded number of root extractions follow, each at worst $O(n)$.
987            ///
988            /// # Examples
989            /// See [here](super::is_power#express_as_power).
990            ///
991            /// # Notes
992            /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a
993            ///   perfect power equal to $\text{base}^\text{exp}$, otherwise `None`.
994            /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
995            fn express_as_power(&self) -> Option<($t, u64)> {
996                match express_as_power_u32(u32::from(*self)) {
997                    Some((base, exp)) => Some(($t::exact_from(base), exp)),
998                    _ => None,
999                }
1000            }
1001        }
1002
1003        impl IsPower for $t {
1004            /// Determines whether an integer is a perfect power. We define a perfect power as any
1005            /// number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
1006            /// particular 0 and 1 are considered perfect powers.
1007            ///
1008            /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
1009            ///
1010            /// # Worst-case complexity
1011            /// $T(n) = O(n)$
1012            ///
1013            /// $M(n) = O(1)$
1014            ///
1015            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`:
1016            /// trial division strips small prime factors, each division removing at least one bit,
1017            /// and a bounded number of root extractions follow, each at worst $O(n)$.
1018            ///
1019            /// # Examples
1020            /// See [here](super::is_power#is_power).
1021            #[inline]
1022            fn is_power(&self) -> bool {
1023                is_power_u32(u32::from(*self))
1024            }
1025        }
1026    };
1027}
1028impl_unsigned_32!(u8);
1029impl_unsigned_32!(u16);
1030impl_unsigned_32!(u32);
1031
1032impl ExpressAsPower for i64 {
1033    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
1034    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
1035    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
1036    /// representation as a power, the representation with the smallest base is returned. For
1037    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
1038    ///
1039    /// # Worst-case complexity
1040    /// $T(n) = O(n)$
1041    ///
1042    /// $M(n) = O(1)$
1043    ///
1044    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1045    /// division strips small prime factors, each division removing at least one bit, and a bounded
1046    /// number of root extractions follow, each at worst $O(n)$.
1047    ///
1048    /// # Examples
1049    /// See [here](super::is_power#express_as_power).
1050    ///
1051    /// # Notes
1052    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
1053    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
1054    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
1055    #[inline]
1056    fn express_as_power(&self) -> Option<(Self, u64)> {
1057        express_as_power_i64(*self)
1058    }
1059}
1060
1061impl ExpressAsPower for i128 {
1062    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
1063    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
1064    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
1065    /// representation as a power, the representation with the smallest base is returned. For
1066    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
1067    ///
1068    /// # Worst-case complexity
1069    /// $T(n) = O(n)$
1070    ///
1071    /// $M(n) = O(1)$
1072    ///
1073    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1074    /// division strips small prime factors, each division removing at least one bit, and a bounded
1075    /// number of root extractions follow, each at worst $O(n)$.
1076    ///
1077    /// # Examples
1078    /// See [here](super::is_power#express_as_power).
1079    ///
1080    /// # Notes
1081    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
1082    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
1083    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
1084    #[inline]
1085    fn express_as_power(&self) -> Option<(Self, u64)> {
1086        express_as_power_i128(*self)
1087    }
1088}
1089
1090impl ExpressAsPower for isize {
1091    /// Expresses a number as a perfect power, if such a representation exists. We define a perfect
1092    /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
1093    /// particular, 0 and 1 are considered perfect powers. If a number has more than one
1094    /// representation as a power, the representation with the smallest base is returned. For
1095    /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`.
1096    ///
1097    /// # Worst-case complexity
1098    /// $T(n) = O(n)$
1099    ///
1100    /// $M(n) = O(1)$
1101    ///
1102    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1103    /// division strips small prime factors, each division removing at least one bit, and a bounded
1104    /// number of root extractions follow, each at worst $O(n)$.
1105    ///
1106    /// # Examples
1107    /// See [here](super::is_power#express_as_power).
1108    ///
1109    /// # Notes
1110    /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect
1111    ///   power equal to $\text{base}^\text{exp}$, otherwise `None`.
1112    /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
1113    fn express_as_power(&self) -> Option<(Self, u64)> {
1114        if USIZE_IS_U32 {
1115            match express_as_power_i32(i32::wrapping_from(*self)) {
1116                Some((base, exp)) => Some((Self::wrapping_from(base), exp)),
1117                _ => None,
1118            }
1119        } else {
1120            match express_as_power_i64(i64::wrapping_from(*self)) {
1121                Some((base, exp)) => Some((Self::wrapping_from(base), exp)),
1122                _ => None,
1123            }
1124        }
1125    }
1126}
1127
1128impl IsPower for i64 {
1129    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
1130    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
1131    /// considered perfect powers.
1132    ///
1133    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
1134    ///
1135    /// # Worst-case complexity
1136    /// $T(n) = O(n)$
1137    ///
1138    /// $M(n) = O(1)$
1139    ///
1140    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1141    /// division strips small prime factors, each division removing at least one bit, and a bounded
1142    /// number of root extractions follow, each at worst $O(n)$.
1143    ///
1144    /// # Examples
1145    /// See [here](super::is_power#is_power).
1146    #[inline]
1147    fn is_power(&self) -> bool {
1148        is_power_i64(*self)
1149    }
1150}
1151
1152impl IsPower for i128 {
1153    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
1154    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
1155    /// considered perfect powers.
1156    ///
1157    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
1158    ///
1159    /// # Worst-case complexity
1160    /// $T(n) = O(n)$
1161    ///
1162    /// $M(n) = O(1)$
1163    ///
1164    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1165    /// division strips small prime factors, each division removing at least one bit, and a bounded
1166    /// number of root extractions follow, each at worst $O(n)$.
1167    ///
1168    /// # Examples
1169    /// See [here](super::is_power#is_power).
1170    #[inline]
1171    fn is_power(&self) -> bool {
1172        is_power_i128(*self)
1173    }
1174}
1175
1176impl IsPower for isize {
1177    /// Determines whether an integer is a perfect power. We define a perfect power as any number of
1178    /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are
1179    /// considered perfect powers.
1180    ///
1181    /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
1182    ///
1183    /// # Worst-case complexity
1184    /// $T(n) = O(n)$
1185    ///
1186    /// $M(n) = O(1)$
1187    ///
1188    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`: trial
1189    /// division strips small prime factors, each division removing at least one bit, and a bounded
1190    /// number of root extractions follow, each at worst $O(n)$.
1191    ///
1192    /// # Examples
1193    /// See [here](super::is_power#is_power).
1194    fn is_power(&self) -> bool {
1195        if USIZE_IS_U32 {
1196            is_power_i32(i32::wrapping_from(*self))
1197        } else {
1198            is_power_i64(i64::wrapping_from(*self))
1199        }
1200    }
1201}
1202
1203macro_rules! impl_signed_32 {
1204    ($t: ident) => {
1205        impl ExpressAsPower for $t {
1206            /// Expresses a number as a perfect power, if such a representation exists. We define a
1207            /// perfect power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both
1208            /// integers. In particular, 0 and 1 are considered perfect powers. If a number has more
1209            /// than one representation as a power, the representation with the smallest base is
1210            /// returned. For example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather
1211            /// than `(4,3)` or `(8,2)`.
1212            ///
1213            /// # Worst-case complexity
1214            /// $T(n) = O(n)$
1215            ///
1216            /// $M(n) = O(1)$
1217            ///
1218            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`:
1219            /// trial division strips small prime factors, each division removing at least one bit,
1220            /// and a bounded number of root extractions follow, each at worst $O(n)$.
1221            ///
1222            /// # Examples
1223            /// See [here](super::is_power#express_as_power).
1224            ///
1225            /// # Notes
1226            /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a
1227            ///   perfect power equal to $\text{base}^\text{exp}$, otherwise `None`.
1228            /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`.
1229            fn express_as_power(&self) -> Option<($t, u64)> {
1230                match express_as_power_i32(i32::from(*self)) {
1231                    Some((base, exp)) => Some(($t::exact_from(base), exp)),
1232                    _ => None,
1233                }
1234            }
1235        }
1236
1237        impl IsPower for $t {
1238            /// Determines whether an integer is a perfect power. We define a perfect power as any
1239            /// number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In
1240            /// particular 0 and 1 are considered perfect powers.
1241            ///
1242            /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$.
1243            ///
1244            /// # Worst-case complexity
1245            /// $T(n) = O(n)$
1246            ///
1247            /// $M(n) = O(1)$
1248            ///
1249            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`:
1250            /// trial division strips small prime factors, each division removing at least one bit,
1251            /// and a bounded number of root extractions follow, each at worst $O(n)$.
1252            ///
1253            /// # Examples
1254            /// See [here](super::is_power#is_power).
1255            #[inline]
1256            fn is_power(&self) -> bool {
1257                is_power_i32(i32::from(*self))
1258            }
1259        }
1260    };
1261}
1262impl_signed_32!(i8);
1263impl_signed_32!(i16);
1264impl_signed_32!(i32);