Skip to content

Commit 90383d2

Browse files
authored
add kronecker function (useful for lots of number theory stuff) (#3)
* add kronecker function (useful for lots of number theory stuff)
1 parent ba09eef commit 90383d2

File tree

3 files changed

+54
-70
lines changed

3 files changed

+54
-70
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "IntegerMathUtils"
22
uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235"
3-
version = "0.1.1"
3+
version = "0.1.2"
44

55
[extras]
66
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

src/IntegerMathUtils.jl

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module IntegerMathUtils
2-
export iroot, ispower, rootrem, find_exponent, is_probably_prime
2+
export iroot, ispower, rootrem, find_exponent, is_probably_prime, kronecker
33

44
iroot(x::Integer, n::Integer) = iroot(x, Cint(n))
55

@@ -10,7 +10,7 @@ function iroot(x::BigInt, n::Cint)
1010
n <= 0 && throw(DomainError(n, "Exponent must be > 0"))
1111
x <= 0 && iseven(x) && throw(DomainError(n, "This is a math no-no"))
1212
ans = BigInt()
13-
ccall((:__gmpz_root, :libgmp), Cint, (Ref{BigInt}, Ref{BigInt}, Cint), ans, x, n)
13+
@ccall :libgmp.__gmpz_root(ans::Ref{BigInt}, x::Ref{BigInt}, n::Cint)::Cint
1414
ans
1515
end
1616

@@ -22,15 +22,15 @@ function rootrem(x::T, n::Integer) where {T<:Integer}
2222
x <= 0 && iseven(x) && throw(DomainError(n, "This is a math no-no"))
2323
root = BigInt()
2424
rem = BigInt()
25-
ccall((:__gmpz_rootrem, :libgmp), Nothing,(Ref{BigInt}, Ref{BigInt}, Ref{BigInt}, Int), root, rem, x, n)
25+
@ccall :libgmp.__gmpz_rootrem(root::Ref{BigInt}, rem::Ref{BigInt}, x::Ref{BigInt}, n::Int)::Nothing
2626
return (root, T(rem))
2727
end
2828

2929
# TODO: Add more efficient implimentation for smaller types
3030
ispower(x::Integer) = ispower(big(x))
3131

3232
function ispower(x::BigInt)
33-
return 0 != ccall((:__gmpz_perfect_power_p, :libgmp), Cint, (Ref{BigInt},), x)
33+
return 0 != @ccall :libgmp.__gmpz_perfect_power_p(x::Ref{BigInt})::Cint
3434
end
3535

3636
# TODO: Add more efficient implimentation for smaller types
@@ -43,7 +43,55 @@ function find_exponent(x::Integer)
4343
end
4444

4545
function is_probably_prime(x::Integer; reps=25)
46-
return ccall((:__gmpz_probab_prime_p, :libgmp), Cint, (Ref{BigInt}, Cint), x, reps) != 0
46+
if !(x isa BigInt)
47+
x = BigInt(x)
48+
end
49+
return 0 != @ccall :libgmp.__gmpz_probab_prime_p(x::Ref{BigInt}, reps::Cint)::Cint
50+
end
51+
52+
function kronecker(a::BigInt, b::Clong)
53+
return @ccall :libgmp.__gmpz_kronecker_si(a::Ref{BigInt}, b::Clong)::Cint
54+
end
55+
function kronecker(a::Clong, b::BigInt)
56+
return @ccall :libgmp.__gmpz_si_kronecker(a::Clong, b::Ref{BigInt})::Cint
57+
end
58+
function kronecker(a, n)
59+
@assert n != -n || n == 0
60+
@assert a != -a || a == 0
61+
t = 1
62+
if iszero(n)
63+
return Int(abs(a) == 1)
64+
end
65+
if n < 0
66+
n = abs(n)
67+
if a < 0
68+
t = -t
69+
end
70+
end
71+
trail = trailing_zeros(n)
72+
if trail > 0
73+
n >>= trail
74+
if iseven(a)
75+
return 0
76+
elseif isodd(trail) && a&7 in (3,5)
77+
t = -t
78+
end
79+
end
80+
a = mod(a, n)
81+
while a != 0
82+
while iseven(a)
83+
a = a >> 1
84+
if n&7 in (3, 5)
85+
t = -t
86+
end
87+
end
88+
a, n = n, a
89+
if a&3 == n&3 == 3
90+
t = -t
91+
end
92+
a = mod(a, n)
93+
end
94+
return n == 1 ? t : 0
4795
end
4896

4997
end

tests/runtests.jl

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)