|
| 1 | +export iroot, ispower, rootrem find_exponent, is_probably_prime |
| 2 | + |
| 3 | +module IntegerMathUtils |
| 4 | + |
| 5 | +iroot(x::Integer, n::Integer) = iroot(x, Cint(n)) |
| 6 | + |
| 7 | +# TODO: Add more efficient implimentation |
| 8 | +iroot(x::T, n::Cint) where {T<:Integer} = T(iroot(big(x), Cint(n))) |
| 9 | + |
| 10 | +function iroot(x::BigInt, n::Cint) |
| 11 | + n <= 0 && throw(DomainError(n, "Exponent must be > 0")) |
| 12 | + x <= 0 && iseven(x) && throw(DomainError(n, "This is a math no-no")) |
| 13 | + ans = BigInt() |
| 14 | + ccall((:__gmpz_root, :libgmp), Cint, (Ref{BigInt}, Ref{BigInt}, Cint), ans, x, n) |
| 15 | + ans |
| 16 | +end |
| 17 | + |
| 18 | +# TODO: Add more efficient implimentation for smaller types |
| 19 | +function rootrem(x::T, n::Integer) where {T<:Integer} |
| 20 | + x = big(x) |
| 21 | + n = Cint(n) |
| 22 | + n <= 0 && throw(DomainError(n, "Exponent must be > 0")) |
| 23 | + x <= 0 && iseven(x) && throw(DomainError(n, "This is a math no-no")) |
| 24 | + root = BigInt() |
| 25 | + rem = BigInt() |
| 26 | + ccall((:__gmpz_rootrem, :libgmp), Nothing,(Ref{BigInt}, Ref{BigInt}, Ref{BigInt}, Int), root, rem, x, n) |
| 27 | + return (root, T(rem)) |
| 28 | +end |
| 29 | + |
| 30 | +# TODO: Add more efficient implimentation for smaller types |
| 31 | +ispower(x::Integer) = ispower(big(x)) |
| 32 | + |
| 33 | +function ispower(x::BigInt) |
| 34 | + return 0 != ccall((:__gmpz_perfect_power_p, :libgmp), Cint, (Ref{BigInt},), x) |
| 35 | +end |
| 36 | + |
| 37 | +# TODO: Add more efficient implimentation for smaller types |
| 38 | +function find_exponent(x::Integer) |
| 39 | + x <= 1 && return 1 |
| 40 | + for exponent in ndigits(x, base=2):-1:2 |
| 41 | + rootrem(x, exponent)[2] == 0 && return exponent |
| 42 | + end |
| 43 | + 1 |
| 44 | +end |
| 45 | + |
| 46 | +function is_probably_prime(x::Integer; reps=25) |
| 47 | + return ccall((:__gmpz_probab_prime_p, :libgmp), Cint, (Ref{BigInt}, Cint), x, reps) != 0 |
| 48 | +end |
| 49 | + |
| 50 | +end |
0 commit comments