Skip to content

Commit 28e0e5a

Browse files
authored
feat: add sqrtmod_pk (#2155)
- only for units for now
1 parent 25dc778 commit 28e0e5a

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

src/flint/fmpz.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,41 @@ function sqrtmod(x::ZZRingElem, m::ZZRingElem)
10781078
return z
10791079
end
10801080

1081+
function sqrtmod_pk(a::IntegerUnion, p::IntegerUnion, k::Int)
1082+
@req a != 0 && valuation(a, p) == 0 "Element must be a unit modulo p^k"
1083+
return _sqrtmod_pk_big(ZZ(a), ZZ(p), k)
1084+
end
1085+
1086+
function _sqrtmod_pk_big(a::ZZRingElem, p::ZZRingElem, k::Int)
1087+
# must be unit modulo p
1088+
r = ZZ()
1089+
fl = @ccall libflint._padic_sqrt(r::Ref{ZZRingElem}, a::Ref{ZZRingElem}, p::Ref{ZZRingElem}, k::Int)::Bool
1090+
if !fl
1091+
error("No square root exists")
1092+
end
1093+
return r
1094+
end
1095+
1096+
function _sqrtmod_pk_small(a::Int, p::Int, k::Int)
1097+
# this is too expensive to check
1098+
#@req k < @ccall Nemo.libflint.n_flog((UInt(1) << 63)::UInt, p::Int)::Int
1099+
if a < 0
1100+
a = mod(a, p)
1101+
end
1102+
# must be unit modulo p
1103+
res = Ref(Ptr{UInt}())
1104+
n = @ccall libflint.n_sqrtmod_primepow(res::Ref{Ptr{UInt}}, a::Int, p::Int, k::Int)::Int
1105+
1106+
if n == 0
1107+
error("No square root exists")
1108+
end
1109+
1110+
ptr = res[]
1111+
b = unsafe_load(ptr, 1)
1112+
@ccall libflint.flint_free(ptr::Ptr{UInt})::Nothing
1113+
return b % Int
1114+
end
1115+
10811116
function _normalize_crt(r::ZZRingElem, m::ZZRingElem, signed)
10821117
s = sign(Int, m)
10831118
if s > 0

test/flint/fmpz-test.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,21 @@ end
958958
@test mod_sym(ZZ(4), ZZ(-5)) == ZZ(-1)
959959
@test mod_sym(ZZ(-4), ZZ(5)) == ZZ(1)
960960
@test mod_sym(ZZ(-4), ZZ(-5)) == ZZ(1)
961+
962+
for (p, k) in [(2, 4), (2, 5), (5, 1), (5, 5)]
963+
b = rand(1:p^k - 1) % p^k
964+
while gcd(b, p) != 1
965+
b = rand(1:p^k - 1) % p^k
966+
end
967+
a = powermod(b, 2, p^k)
968+
c = Nemo.sqrtmod_pk(a, p, k)
969+
@test c^2 % p^k == a
970+
c = Nemo._sqrtmod_pk_small(a, p, k)
971+
@test c^2 % p^k == a
972+
end
973+
974+
@test_throws ArgumentError Nemo.sqrtmod_pk(2, 2, 5)
975+
@test_throws ErrorException Nemo.sqrtmod_pk(3, 5, 10)
961976
end
962977

963978
@testset "ZZRingElem.crt" begin

0 commit comments

Comments
 (0)