Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions src/generic/Misc/Localization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ base_ring(L::LocalizedEuclideanRing) = L.base_ring::base_ring_type(L)

parent(a::LocalizedEuclideanRingElem) = a.parent

characteristic(L::LocalizedEuclideanRing) = characteristic(base_ring(L))

###############################################################################
#
# Basic manipulation
Expand All @@ -136,7 +138,8 @@ iszero(a::LocalizedEuclideanRingElem) = iszero(data(a))
isone(a::LocalizedEuclideanRingElem) = isone(data(a))

function is_unit(a::LocalizedEuclideanRingElem{T}) where {T <: RingElem}
return isin(inv(a.data), parent(a))
is_unit(data(a)) || return false
return isin(inv(data(a)), parent(a))
end

deepcopy_internal(a::LocalizedEuclideanRingElem, dict::IdDict) = parent(a)(deepcopy_internal(data(a), dict))
Expand Down Expand Up @@ -221,7 +224,7 @@ If 'checked = false' the invertibility of $a$ is not checked and the correspondi
of the Fraction Field is returned.
"""
function Base.inv(a::LocalizedEuclideanRingElem{T}, checked::Bool = true) where {T}
b = inv(a.data)
b = inv(data(a))
checked && (isin(b, parent(a)) || error("no unit"))
return LocalizedEuclideanRingElem{T}(b, parent(a), false)
end
Expand Down Expand Up @@ -255,8 +258,8 @@ function Base.divrem(a::LocalizedEuclideanRingElem{T}, b::LocalizedEuclideanRing
check_parent(a, b)
L = parent(a)
if L.comp
a1, s1 = ppio(numerator(a.data), L.prime)
a2, s2 = ppio(numerator(b.data), L.prime)
a1, s1 = ppio(numerator(data(a)), L.prime)
a2, s2 = ppio(numerator(data(b)), L.prime)
b1 = denominator(a)
b2 = denominator(b)
q, r = divrem(a1 * s1 * b2, s2)
Expand All @@ -274,9 +277,9 @@ end
function euclid(a::LocalizedEuclideanRingElem{T}) where {T <: RingElem}
L = parent(a)
if L.comp
return ppio(numerator(a.data), L.prime)[1]
return ppio(numerator(data(a)), L.prime)[1]
else
return ppio(numerator(a.data), L.prime)[2]
return ppio(numerator(data(a)), L.prime)[2]
end
end

Expand All @@ -292,9 +295,9 @@ function gcd(a::LocalizedEuclideanRingElem{T}, b::LocalizedEuclideanRingElem{T})
iszero(b) && return inv(canonical_unit(a)) * a
par = parent(a)
if par.comp
elem = ppio(gcd(numerator(a.data), numerator(b.data)), parent(a).prime)[2]
elem = ppio(gcd(numerator(data(a)), numerator(data(b))), parent(a).prime)[2]
else
elem = ppio(gcd(numerator(a.data), numerator(b.data)), parent(a).prime)[1]
elem = ppio(gcd(numerator(data(a)), numerator(data(b))), parent(a).prime)[1]
end
return par(elem)
end
Expand All @@ -304,9 +307,9 @@ function lcm(a::LocalizedEuclideanRingElem{T}, b::LocalizedEuclideanRingElem{T})
par = parent(a)
(iszero(a) || iszero(b)) && return par()
if par.comp
elem = ppio(lcm(numerator(a.data), numerator(b.data)), parent(a).prime)[2]
elem = ppio(lcm(numerator(data(a)), numerator(data(b))), parent(a).prime)[2]
else
elem = ppio(lcm(numerator(a.data), numerator(b.data)), parent(a).prime)[1]
elem = ppio(lcm(numerator(data(a)), numerator(data(b))), parent(a).prime)[1]
end
return par(elem)
end
Expand All @@ -320,9 +323,9 @@ end
function gcdx(a::LocalizedEuclideanRingElem{T}, b::LocalizedEuclideanRingElem{T}) where {T <: RingElement}
check_parent(a,b)
L = parent(a)
g, u, v = gcdx(numerator(a.data), numerator(b.data))
g, u, v = gcdx(numerator(data(a)), numerator(data(b)))
c = inv(canonical_unit(L(g)))
return c*L(g), c*L(u*denominator(a.data)), c*L(v*denominator(b.data))
return c*L(g), c*L(u*denominator(data(a))), c*L(v*denominator(data(b)))
end

###############################################################################
Expand All @@ -335,6 +338,17 @@ function ^(a::LocalizedEuclideanRingElem, b::Int)
return parent(a)(data(a)^b)
end

###############################################################################
#
# Conformance test element generation
#
###############################################################################

function ConformanceTests.generate_element(R::LocalizedEuclideanRing)
# TODO: should sometimes create something with a denominator
return R(ConformanceTests.generate_element(base_ring(R)))
end

###############################################################################
#
# Promotion rules
Expand Down Expand Up @@ -398,11 +412,11 @@ Returns unit `b`::LocalizedEuclideanRingElem{T} s.th. $a$ * `b` only consists of
"""
function canonical_unit(a::LocalizedEuclideanRingElem{T}) where {T <: RingElem}
if parent(a).comp
b = ppio(numerator(a.data), parent(a).prime)[1]
b = ppio(numerator(data(a)), parent(a).prime)[1]
else
b = ppio(numerator(a.data), parent(a).prime)[2]
b = ppio(numerator(data(a)), parent(a).prime)[2]
end
return parent(a)(b//denominator(a.data))
return parent(a)(b//denominator(data(a)))
end

###############################################################################
Expand Down
1 change: 1 addition & 0 deletions test/Rings-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ include("generic/Matrix-test.jl")
include("generic/MPoly-test.jl")
include("generic/LaurentMPoly-test.jl")
include("generic/UnivPoly-test.jl")
include("generic/Localization-test.jl")
include("algorithms/MPolyEvaluate-test.jl")
include("algorithms/MPolyFactor-test.jl")
include("algorithms/MPolyNested-test.jl")
Expand Down
138 changes: 138 additions & 0 deletions test/generic/Localization-test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
@testset "Localization" begin

Qx, x = QQ["x"]

@testset "Conformance" begin
L = localization(Qx, x^2 + 1)
ConformanceTests.test_Ring_interface(L)
end

@testset "Constructor" begin

@test parent_type(LocalizedEuclideanRingElem{elem_type(Qx)}) == LocalizedEuclideanRing{elem_type(Qx)}

L = localization(Qx, x^2 + 1)
@test elem_type(L) == LocalizedEuclideanRingElem{elem_type(Qx)}
@test base_ring(L) == Qx
@test base_ring(L()) == Qx

L = localization(Qx, 4 * x^2 + x + 1)
@test elem_type(L) == LocalizedEuclideanRingElem{elem_type(Qx)}
@test base_ring(L) == Qx
@test base_ring(L()) == Qx

L = localization(Qx, [3 * x^4 + x + 18, x^9 + 3])
@test elem_type(L) == LocalizedEuclideanRingElem{elem_type(Qx)}
@test base_ring(L) == Qx
@test base_ring(L()) == Qx
end

@testset "Canonicalisation" begin

L = localization(Qx, 5x^2 + 3x + 2)
@test canonical_unit(L(5x^2 + 3x + 2)) == L(5)
@test canonical_unit(L(28)) == L(28)
@test canonical_unit(L(5 * x^4 + 3 * x^3 + 12 * x^2 + 6 * x + 4)) == L(5 * (x^2 + 2))

L = localization(Qx, [5x^2 + 3x + 2, x^16 + x + 3])
@test canonical_unit(L(x^16 + x + 3)) == one(L)
@test canonical_unit(L(89)) == L(89)
@test canonical_unit(L((5 * x^4 + 3 * x^3 + 12 * x^2 + 6 * x + 4) // (x^3 + 9))) == inv(L((1 // 5 * x^3 + 9 // 5) // (x^2 + 2)))
end

@testset "Parent object call overloading" begin

L1 = localization(Qx, 5x^2 + 3x + 2)
L2 = localization(Qx, 7x^3 + 2)
@test_throws ErrorException L1(L2(5))
@test parent(L1(4x // 7)) == L1

L = localization(Qx, [x^2 + 2, 3x^3 + 5])
@test parent(L(3x^2 + 6)) == L
@test_throws ErrorException L(15 // (3x^2 + 6))
@test_throws ErrorException L(17 // (9 * x^5 + 18 * x^3 + 15 * x^2 + 30))
@test_throws ErrorException L(19 // (9 * x^6 + 54 * x^5 + 18 * x^4 + 123 * x^3 + 90 * x^2 + 30 * x + 180))
end

@testset "GCDX" begin

L = localization(Qx, x^6 + 108)
a = L(x^10 + 2 * x^8 + 14 * x^7 + 49 * x^5 + 42 * x^3 + 294 * x^2 + 588)
b = L(x^11 + 14 * x^8 + 21 * x^6 + 294 * x^3 + 6)
(g, u, v) = gcdx(a, b)
@test g == u * a + v * b

L = localization(Qx, [x^6 + 108, x^8 + 12x^3 + 3])
a = L(x^10 + 2 * x^8 + 14 * x^7 + 49 * x^5 + 42 * x^3 + 294 * x^2 + 588)
b = L(x^11 + 14 * x^8 + 21 * x^6 + 294 * x^3 + 6)
(g, u, v) = gcdx(a, b)
@test g == u * a + v * b
end

@testset "GCD and LCM" begin

L = localization(Qx, x^6 + 108)
a = L(x^10 + 2 * x^8 + 14 * x^7 + 49 * x^5 + 42 * x^3 + 294 * x^2 + 588)
b = L(x^11 + 14 * x^8 + 21 * x^6 + 294 * x^3 + 6)
g = gcd(a, b)
@test g == L(1)
a = L(x^16 + 2 * x^14 + 14 * x^13 + 49 * x^11 + 108 * x^10 + 42 * x^9 + 510 * x^8 + 1512 * x^7 + 588 * x^6 + 5292 * x^5 + 4536 * x^3 + 31752 * x^2 + 63504)
b = L(x^17 + 14 * x^14 + 21 * x^12 + 108 * x^11 + 294 * x^9 + 1512 * x^8 + 2274 * x^6 + 31752 * x^3 + 648)
g = gcd(a, b)
@test g == L(x^6 + 108)

L = localization(Qx, [x^6 + 108, x^8 + 12x^3 + 3])
a = L(x^10 + 2 * x^8 + 14 * x^7 + 49 * x^5 + 42 * x^3 + 294 * x^2 + 588)
b = L(x^13 + 2 * x^11 + 14 * x^10 + 49 * x^8 + 42 * x^6 + 294 * x^5 + 588 * x^3 + 6 * x^2 + 12)
g = gcd(a, b)
@test g == L(1)
end

@testset "Exact division" begin
L = localization(Qx, x^6 + 108)
@test_throws ErrorException divexact(L(9), L(2x^6 + 216))
a = L(x^10 + 2 * x^8 + 14 * x^7 + 49 * x^5 + 42 * x^3 + 294 * x^2 + 588)
b = L(x^11 + 14 * x^8 + 21 * x^6 + 294 * x^3 + 6)
g = divides(a, b)
@test a == b * g[2]
@test g[1] == true
a = L(x^16 + 2 * x^14 + 14 * x^13 + 49 * x^11 + 108 * x^10 + 42 * x^9 + 510 * x^8 + 1512 * x^7 + 588 * x^6 + 5292 * x^5 + 4536 * x^3 + 31752 * x^2 + 63504)
b = L(x^17 + 14 * x^14 + 21 * x^12 + 108 * x^11 + 294 * x^9 + 1512 * x^8 + 2274 * x^6 + 31752 * x^3 + 648)
@test a == b * g[2]
@test g[1] == true
end

@testset "Inversion" begin
L = localization(Qx, x^6 + 108)
@test_throws ErrorException inv(L(2x^6 + 216))
@test inv(L(x^2 + 108)) == L(1 // (x^2 + 108))

L = localization(Qx, [x^6 + 3, x^3 + 5])
@test_throws ErrorException inv(L(2x^6 + 6))
@test inv(L(x^2 + 108)) == L(1 // (x^2 + 108))
end

@testset "Binary operators" begin
L = localization(Qx, x^6 + 108)
@test L(18x // 2) + L(2x // 1) == L(11x)
@test L(18x // 3) - L(1x) == L(5x)
@test L(32x) * L(4x) == L(128x^2)

L = localization(Qx, [x^6 + 3, x^3 + 5])
@test L(18x // 2) + L(2x // 1) == L(11x)
@test L(18x // 3) - L(1x) == L(5x)
@test L(32x) * L(4x) == L(128x^2)
end

@testset "Basic manipulation" begin
L = localization(Qx, x^6 + 108)
@test iszero(L(x^2 + x)) == false
@test isone(L(x^2 // x^2)) == true
@test is_unit(L(x)) == true

L = localization(Qx, [x^6 + 3, x^3 + 5])
@test iszero(L(x - x)) == true
@test isone(L(x^2 + 3x)) == false
@test is_unit(L((x^3 + 5) // (x^3 + 5)))
end
end
Loading