From 57ed2c24dcb2c6a698fbaae85dd779d77ad2620a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 20 Feb 2024 06:51:36 +0100 Subject: [PATCH] Add a few more ZZIdl methods (#1409) --- src/AlgAss/AbsAlgAss.jl | 2 +- src/NumField/QQ.jl | 15 ++++++++++++++- test/NumField/QQ.jl | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/AlgAss/AbsAlgAss.jl b/src/AlgAss/AbsAlgAss.jl index bf2dcd61ef..e47089fdc8 100644 --- a/src/AlgAss/AbsAlgAss.jl +++ b/src/AlgAss/AbsAlgAss.jl @@ -1212,7 +1212,7 @@ end @doc raw""" radical(A::AbstractAssociativeAlgebra) -> AbsAlgAssIdl -Returns the Jacobson-Radical of $A$. +Returns the Jacobson radical of $A$. """ function radical(A::AbstractAssociativeAlgebra{T}) where { T } #<: Union{ fpFieldElem, EuclideanRingResidueFieldElem{ZZRingElem}, fqPolyRepFieldElem, FqPolyRepFieldElem, QQFieldElem, AbsSimpleNumFieldElem } } return ideal_from_gens(A, _radical(A), :twosided) diff --git a/src/NumField/QQ.jl b/src/NumField/QQ.jl index 21a2443abc..9021abaa6a 100644 --- a/src/NumField/QQ.jl +++ b/src/NumField/QQ.jl @@ -127,7 +127,13 @@ end *(x::ZZIdl, y::ZZIdl) = ZZIdl(x.gen * y.gen) -intersect(x::ZZIdl, y::ZZIdl) = ZZIdl(lcm(x.gen, y.gen)) +function intersect(x::ZZIdl, y::ZZIdl...) + g = gen(x) + for I in y + g = lcm(g, gen(I)) + end + return ZZIdl(g) +end lcm(x::ZZIdl, y::ZZIdl) = intersect(x, y) @@ -152,6 +158,13 @@ isone(I::ZZIdl) = isone(I.gen) iszero(I::ZZIdl) = iszero(gen(I)) is_maximal(I::ZZIdl) = is_prime(gen(I)) is_prime(I::ZZIdl) = is_zero(I) || is_maximal(I) +is_primary(I::ZZIdl) = is_zero(I) || is_prime_power_with_data(gen(I))[1] + +is_subset(I::ZZIdl, J::ZZIdl) = is_divisible_by(gen(J), gen(I)) + +radical(I::ZZIdl) = iszero(I) ? I : ideal(ZZ, radical(gen(I))) +primary_decomposition(I::ZZIdl) = iszero(I) ? [ (I,I) ] : + [ (ideal(ZZ, p^k), ideal(ZZ, p)) for (p,k) in factor(gen(I)) ] maximal_order(::QQField) = ZZ diff --git a/test/NumField/QQ.jl b/test/NumField/QQ.jl index 4d777346e6..703e750ef9 100644 --- a/test/NumField/QQ.jl +++ b/test/NumField/QQ.jl @@ -1,3 +1,19 @@ +function check_primary_decomposition(J::Any) + @testset "Testing primary decomposition for $J" begin + d = primary_decomposition(J) + @test all(is_primary(Q) for (Q,P) in d) + @test all(is_prime(P) for (Q,P) in d) + @test all(is_subset(P,Q) for (Q,P) in d) + if isempty(d) + @test isone(J) + @test J == radical(J) + else + @test intersect([Q for (Q,P) in d]...) == J + @test prod([P for (Q,P) in d]) == radical(J) + end + end +end + @testset "NumField/QQ" begin @test Hecke.ideal_type(ZZ) == Hecke.ZZIdl @test Hecke.ideal_type(Hecke.ZZRing) == Hecke.ZZIdl @@ -19,6 +35,8 @@ @test !is_one(I) @test is_maximal(I) @test is_prime(I) + @test is_primary(I) + check_primary_decomposition(I) J = 4*ZZ @@ -31,18 +49,35 @@ @test !is_one(J) @test !is_maximal(J) @test !is_prime(J) + @test is_primary(J) + check_primary_decomposition(J) J = 0*ZZ @test is_zero(J) @test !is_one(J) @test !is_maximal(J) @test is_prime(J) + @test is_primary(J) + check_primary_decomposition(J) J = 1*ZZ @test !is_zero(J) @test is_one(J) @test !is_maximal(J) @test !is_prime(J) + @test !is_primary(J) + check_primary_decomposition(J) + + J = 36*ZZ + @test !is_zero(J) + @test !is_one(J) + @test !is_maximal(J) + @test !is_prime(J) + @test !is_primary(J) + @test radical(J) == 6*ZZ + check_primary_decomposition(J) + + check_primary_decomposition((2*3*5)^2*ZZ) I = QQ(1, 2)*ZZ @test I == ZZ * QQ(1, 2)