Skip to content

Commit

Permalink
add special case for N_GField(p, 1) (oscar-system#391)
Browse files Browse the repository at this point in the history
  • Loading branch information
tthsqe12 committed Mar 16, 2021
1 parent 64a6140 commit f38f01e
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 11 deletions.
27 changes: 22 additions & 5 deletions src/number/NumberTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,29 @@ mutable struct N_GField <: Field
if cached && haskey(N_GFieldID, (p, n, S))
d = N_GFieldID[p, n, S]::N_GField
else
gfinfo = GFInfo(Cint(p), Cint(n), pointer(Base.Vector{UInt8}(string(S)*"\0")))
GC.@preserve gfinfo begin
ptr = libSingular.nInitChar(libSingular.n_GF, pointer_from_objref(gfinfo))
d = new(ptr, n, libSingular.n_SetMap(ZZ.ptr, ptr),
libSingular.n_SetMap(ptr, ZZ.ptr), 1, S)
# NOTE: degree 1 special case
# A N_GField with n = 1 - when passed through Singular and to
# create_ring_from_singular_ring - will be recognized as a N_ZpField.
# This could cause some identity issue since we have the non identity
# N_GField(p, 1, ) != N_ZpField(p). There are two solutions:
# (1) accept this and discourage use of N_GField(p, 1, )
# (2) Get singular to return distinct pointers for these two fields
# In any case, Singular as of Singular_jll v402.0.104+0 is still buggy
# in its treatment of N_GField(p, 1, ). Namely, if the n == 1
# special treatment is removed here, the last test in caller.LibNormal
# fails because Singular returns the wrong coefficient field. This
# has nothing to do per se with the identity issue, it is a separate
# Singular bug.
if n == 1
ptr = libSingular.nInitChar(libSingular.n_Zp, Ptr{Nothing}(p))
else
gfinfo = GFInfo(Cint(p), Cint(n), pointer(Base.Vector{UInt8}(string(S)*"\0")))
GC.@preserve gfinfo begin
ptr = libSingular.nInitChar(libSingular.n_GF, pointer_from_objref(gfinfo))
end
end
d = new(ptr, n, libSingular.n_SetMap(ZZ.ptr, ptr),
libSingular.n_SetMap(ptr, ZZ.ptr), 1, S)
finalizer(_Ring_finalizer, d)
if cached
N_GFieldID[p, n, S] = d
Expand Down
19 changes: 13 additions & 6 deletions src/number/n_GF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ one(R::N_GField) = R(1)

zero(R::N_GField) = R(0)

gen(R::N_GField) = R(libSingular.n_Param(Cint(1), R.ptr))
function gen(R::N_GField)
if degree(R) == 1
# NOTE: degree 1 special case
return zero(R)
else
return R(libSingular.n_Param(Cint(1), R.ptr))
end
end

function isone(n::n_GF)
c = parent(n)
Expand All @@ -62,10 +69,6 @@ function iszero(n::n_GF)
return libSingular.n_IsZero(n.ptr, c.ptr)
end

@doc Markdown.doc"""
isunit(n::n_GF)
Return `true` if $n$ is a unit in the field, i.e. nonzero.
"""
isunit(n::n_GF) = !iszero(n)

###############################################################################
Expand Down Expand Up @@ -93,7 +96,11 @@ end
function AbstractAlgebra.expressify(a::n_GF; context = nothing)::Any
F = parent(a)
i = reinterpret(Int, a.ptr.cpp_object)
if 1 < i < characteristic(F)^degree(F)
p = Int(characteristic(parent(a)))
if degree(F) == 1
# NOTE: degree 1 special case
return i > p - i ? i - p : i
elseif 1 < i < p^degree(F)
return Expr(:call, :^, F.S, i)
elseif i == 1
return F.S
Expand Down
90 changes: 90 additions & 0 deletions test/number/n_GF-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
@test F != F2
@test F1 != F2

F, x = FiniteField(7, 1, "x")
F1, x = FiniteField(7, 1, "x")
F2, x = FiniteField(7, 1, "x", cached = false)

@test isa(x, n_GF)

@test F isa Singular.Field
@test F1 isa Singular.Field
@test F2 isa Singular.Field
@test F == F1
@test F != F2
@test F1 != F2

@test_throws DomainError FiniteField(257, 1, "a")
@test_throws DomainError FiniteField(2, 16, "a")
@test_throws DomainError FiniteField(2, 64, "a") # errors even if 2^64 == 0
Expand All @@ -31,6 +44,21 @@ end
@test sprint(show, "text/plain", x) == "x"
@test sprint(show, "text/plain", x^2) == "x^2"
@test sprint(show, "text/plain", x^11) == "x^11"
R, x = FiniteField(5, 1, "x")

@test string(zero(R)) == "0"
@test string(one(R)) == "1"
@test string(R(2)) == "2"
@test occursin(r"\A\d+\Z", string(x))
@test occursin(r"\A\d+\Z", string(x^2))
@test occursin(r"\A\d+\Z", string(x^11))

@test sprint(show, "text/plain", zero(R)) == "0"
@test sprint(show, "text/plain", one(R)) == "1"
@test sprint(show, "text/plain", R(2)) == "2"
@test occursin(r"\A\d+\Z", sprint(show, "text/plain", x))
@test occursin(r"\A\d+\Z", sprint(show, "text/plain", x^2))
@test occursin(r"\A\d+\Z", sprint(show, "text/plain", x^11))
end

@testset "n_GF.manipulation" begin
Expand All @@ -47,6 +75,20 @@ end
@test degree(R) == 2

@test deepcopy(R(2)) == R(2)

R, x = FiniteField(5, 1, "x")

@test isone(one(R))
@test iszero(zero(R))
@test isunit(R(1)) && isunit(R(2))
@test !isunit(R(0))

@test gen(R) == x

@test characteristic(R) == 5
@test degree(R) == 1

@test deepcopy(R(2)) == R(2)
end

@testset "n_GF.unary_ops" begin
Expand All @@ -57,6 +99,14 @@ end
@test -R(3) == R(2)
@test -R() == R()
@test -a == 2x - 1

R, x = FiniteField(5, 1, "x")

a = 3x + 1

@test -R(3) == R(2)
@test -R() == R()
@test -a == 2x - 1
end

@testset "n_GF.binary_ops" begin
Expand All @@ -68,6 +118,15 @@ end
@test a + b == R(3)
@test a - b == -x - 1
@test a*b == x^19

R, x = FiniteField(5, 1, "x")

a = 2x + 1
b = 3x + 2

@test a + b == R(3)
@test a - b == -x - 1
@test a*b == 6*x^2 + 2*x + 2
end

@testset "n_GF.comparison" begin
Expand All @@ -77,6 +136,13 @@ end

@test a == deepcopy(a)
@test isequal(a, a)

R, x = FiniteField(5, 1, "x")

a = 2x + 3

@test a == deepcopy(a)
@test isequal(a, a)
end

@testset "n_GF.ad_hoc_comparison" begin
Expand All @@ -88,13 +154,27 @@ end
@test 2 != x
@test isequal(R(2), 2)
@test isequal(2, R(2))

R, x = FiniteField(5, 1, "x")

@test R(2) == 2
@test x != 2 || x == 2
@test 2 == R(2)
@test 2 != x || 2 == x
@test isequal(R(2), 2)
@test isequal(2, R(2))
end

@testset "n_GF.powering" begin
R, x = FiniteField(5, 2, "x")

@test (x + 1)^2 == x^20
@test_throws DomainError x^-rand(1:99)

R, x = FiniteField(5, 1, "x")
@test x^3 == x*x*x
@test R(2)^2 == 2^2
@test R(2)^3 == 2^3
end

@testset "n_GF.exact_division" begin
Expand All @@ -105,6 +185,11 @@ end

@test inv(a) == x^2
@test divexact(a, b) == x^14

R, x = FiniteField(5, 1, "x")

@test 2*inv(R(2)) == 1
@test divexact(R(2), R(3)) == R(4)
end

@testset "n_GF.gcd_lcm" begin
Expand All @@ -115,6 +200,11 @@ end

@test gcd(a, b) == R(1)
@test gcd(R(0), R(0)) == R(0)

R, x = FiniteField(5, 1, "x")

@test gcd(R(0), R(0)) == R(0)
@test gcd(R(2), R(3)) == R(1)
end

@testset "n_GF.Polynomials" begin
Expand Down

0 comments on commit f38f01e

Please sign in to comment.