From b7adff7de73d8994e87123e570f48216c3f51e89 Mon Sep 17 00:00:00 2001 From: Tommy Hofmann Date: Tue, 17 Sep 2024 11:48:11 +0200 Subject: [PATCH] feat: add coprime base (#1785) --- docs/src/euclidean_interface.md | 2 + src/AbstractAlgebra.jl | 1 + src/algorithms/coprime_base.jl | 68 ++++++++++++++++++++++++++++ src/exports.jl | 2 + test/Rings-test.jl | 1 + test/algorithms/coprime_base-test.jl | 17 +++++++ 6 files changed, 91 insertions(+) create mode 100644 src/algorithms/coprime_base.jl create mode 100644 test/algorithms/coprime_base-test.jl diff --git a/docs/src/euclidean_interface.md b/docs/src/euclidean_interface.md index e3cc5cf2b..5e18043ce 100644 --- a/docs/src/euclidean_interface.md +++ b/docs/src/euclidean_interface.md @@ -35,4 +35,6 @@ crt(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement crt(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement crt_with_lcm(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement crt_with_lcm(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement +coprime_base +coprime_base_push! ``` diff --git a/src/AbstractAlgebra.jl b/src/AbstractAlgebra.jl index c9e3ec280..63ef75c60 100644 --- a/src/AbstractAlgebra.jl +++ b/src/AbstractAlgebra.jl @@ -409,6 +409,7 @@ include("algorithms/MPolyEvaluate.jl") include("algorithms/MPolyFactor.jl") include("algorithms/MPolyNested.jl") include("algorithms/DensePoly.jl") +include("algorithms/coprime_base.jl") ############################################################################### # diff --git a/src/algorithms/coprime_base.jl b/src/algorithms/coprime_base.jl new file mode 100644 index 000000000..2b6586a68 --- /dev/null +++ b/src/algorithms/coprime_base.jl @@ -0,0 +1,68 @@ +################################################################################ +# +# Coprime bases +# +################################################################################ + +function augment_coprime_base(S::Vector{E}, a::E, start::Int = 1) where E + i = start + if is_unit(a) + return S + end + + g = a + new = true + + while i<=length(S) && !isone(a) + if new + g = gcd(S[i], a) + new = false + else + g = gcd!(g, S[i], a) + end + if is_unit(g) + i += 1 + continue + end + si = divexact(S[i], g) + a = divexact(a, g) + if is_unit(si) # g = S[i] and S[i] | a + continue + end + S[i] = si + if is_unit(a) # g = a and a | S[i] + a = copy(g) + continue + end + augment_coprime_base(S, copy(g), i) + continue + end + if !is_unit(a) + push!(S, a) + end + + return S +end + +@doc raw""" + coprime_base(S::Vector{RingElement}) -> Vector{RingElement} + +Returns a coprime base for $S$, i.e. the resulting array contains pairwise coprime objects that multiplicatively generate the same set as the input array. +""" +function coprime_base(S::Vector{E}) where {E <: RingElement} + @assert !isempty(S) + T = Array{E}(undef, 1) + T[1] = S[1] + for i=2:length(S) + augment_coprime_base(T, S[i]) + end + return T +end + +@doc raw""" + coprime_base_push!(S::Vector{RingElem}, a::RingElem) -> Vector{RingElem} + +Given an array $S$ of coprime elements, insert a new element, that is, find a +coprime base for `push(S, a)`. +""" +coprime_base_push!(S, a) = augment_coprime_base(S, a) diff --git a/src/exports.jl b/src/exports.jl index 0ae79e4c1..87ebc8965 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -152,6 +152,8 @@ export compose export conj! export constant_coefficient export content +export coprime_base +export coprime_base_push! export crt export crt_with_lcm export cycles diff --git a/test/Rings-test.jl b/test/Rings-test.jl index 09a686437..004a94b0e 100644 --- a/test/Rings-test.jl +++ b/test/Rings-test.jl @@ -34,6 +34,7 @@ include("algorithms/MPolyFactor-test.jl") include("algorithms/MPolyNested-test.jl") include("algorithms/DensePoly-test.jl") include("algorithms/GenericFunctions-test.jl") +include("algorithms/coprime_base-test.jl") include("generic/PolyRingHom-test.jl") @testset "Generic.Rings.broadcast" begin diff --git a/test/algorithms/coprime_base-test.jl b/test/algorithms/coprime_base-test.jl new file mode 100644 index 000000000..7b537b20c --- /dev/null +++ b/test/algorithms/coprime_base-test.jl @@ -0,0 +1,17 @@ +@testset "coprime base" begin + c = BigInt[6, 10] + d = coprime_base(c) + @test issetequal(d, BigInt[2, 3, 5]) + + c = BigInt[1] + d = coprime_base(c) + @test issetequal(d, BigInt[1]) + + c = BigInt[6, 10, 1] + d = coprime_base(c) + @test issetequal(d, BigInt[2, 3, 5]) + coprime_base_push!(d, BigInt(1)) + @test issetequal(d, BigInt[2, 3, 5]) + coprime_base_push!(d, BigInt(14)) + @test issetequal(d, BigInt[2, 3, 5, 7]) +end