diff --git a/Project.toml b/Project.toml index 90da51e47..689a44be9 100644 --- a/Project.toml +++ b/Project.toml @@ -16,7 +16,7 @@ RandomExtensions = "fb686558-2515-59ef-acaa-46db3789a887" SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" [compat] -AbstractAlgebra = "0.31" +AbstractAlgebra = "0.32.0" Antic_jll = "~0.201.500" Arb_jll = "~200.2300.000" Calcium_jll = "~0.401.100" diff --git a/src/HeckeMiscFiniteField.jl b/src/HeckeMiscFiniteField.jl index 0710a2dec..f4898600a 100644 --- a/src/HeckeMiscFiniteField.jl +++ b/src/HeckeMiscFiniteField.jl @@ -137,8 +137,6 @@ Base.length(F::FqPolyRepField) = BigInt(characteristic(F)^degree(F)) Base.IteratorSize(::Type{FqPolyRepField}) = Base.HasLength() -sub!(z::T, x::T, y::T) where {T} = x - y - function (A::fqPolyRepField)(x::fpFieldElem) @assert characteristic(A) == characteristic(parent(x)) return A(lift(x)) diff --git a/src/HeckeMiscInteger.jl b/src/HeckeMiscInteger.jl index 8f978623b..d09d15055 100644 --- a/src/HeckeMiscInteger.jl +++ b/src/HeckeMiscInteger.jl @@ -17,49 +17,6 @@ function mulmod(a::UInt, b::UInt, n::UInt, ni::UInt) ccall((:n_mulmod2_preinv, libflint), UInt, (UInt, UInt, UInt, UInt), a, b, n, ni) end -# TODO (CF): -# should be Bernstein'ed: this is slow for large valuations -# returns the maximal v s.th. z mod p^v == 0 and z div p^v -# also useful if p is not prime.... -# -# TODO: what happens to z = 0??? - -function remove(z::T, p::T) where {T<:Integer} - z == 0 && return (0, z) - v = 0 - @assert p > 1 - while mod(z, p) == 0 - z = Base.div(z, p) - v += 1 - end - return (v, z) -end - -function remove(z::Rational{T}, p::T) where {T<:Integer} - z == 0 && return (0, z) - v, d = remove(denominator(z), p) - w, n = remove(numerator(z), p) - return w - v, n // d -end - -function valuation(z::T, p::T) where {T<:Integer} - iszero(z) && error("Not yet implemented") - v = 0 - @assert p > 1 - while mod(z, p) == 0 - z = Base.div(z, p) - v += 1 - end - return v -end - -function valuation(z::Rational{T}, p::T) where {T<:Integer} - z == 0 && error("Not yet implemented") - v = valuation(denominator(z), p) - w = valuation(numerator(z), p) - return w - v -end - @inline __get_rounding_mode() = Base.MPFR.rounding_raw(BigFloat) function BigFloat(a::QQFieldElem) @@ -293,8 +250,8 @@ end /(a::BigFloat, b::ZZRingElem) = a / BigInt(b) -is_negative(n::IntegerUnion) = cmp(n, 0) < 0 -is_positive(n::IntegerUnion) = cmp(n, 0) > 0 +is_negative(n::ZZRingElem) = cmp(n, 0) < 0 +is_positive(n::ZZRingElem) = cmp(n, 0) > 0 ################################################################################ @@ -463,7 +420,6 @@ mod(i::IntegerUnion, r::fmpzUnitRange) = mod(i - first(r), length(r)) + first(r) Base.:(:)(a::ZZRingElem, b::Integer) = (:)(promote(a, b)...) Base.:(:)(a::Integer, b::ZZRingElem) = (:)(promote(a, b)...) -Base.:(:)(x::Int, y::Nothing) = 1:0 Base.:(:)(x::Int, y::ZZRingElem) = ZZRingElem(x):y # Construct StepRange{ZZRingElem, T} where +(::ZZRingElem, zero(::T)) must be defined diff --git a/src/HeckeMiscMatrix.jl b/src/HeckeMiscMatrix.jl index 51c9e9130..673575962 100644 --- a/src/HeckeMiscMatrix.jl +++ b/src/HeckeMiscMatrix.jl @@ -1,88 +1,11 @@ export is_zero_row, is_diagonal, is_lower_triangular, is_positive_entry, is_upper_triangular, diagonal -import LinearAlgebra -LinearAlgebra.dot(a::RingElem, b::RingElem) = a * b - -################################################################################ -# -# Dense matrix types -# -################################################################################ - -dense_matrix_type(::Type{T}) where {T} = Generic.MatSpaceElem{T} - -################################################################################ -# -# Unsafe functions for generic matrices -# -################################################################################ - -#function zero!(a::MatElem) -# for i in 1:nrows(a) -# for j in 1:ncols(a) -# a[i, j] = zero!(a[i, j]) -# end -# end -# return a -#end - -function mul!(c::MatElem, a::MatElem, b::MatElem) - ncols(a) != nrows(b) && error("Incompatible matrix dimensions") - nrows(c) != nrows(a) && error("Incompatible matrix dimensions") - ncols(c) != ncols(b) && error("Incompatible matrix dimensions") - - if c === a || c === b - d = parent(a)() - return mul!(d, a, b) - end - - t = base_ring(a)() - for i = 1:nrows(a) - for j = 1:ncols(b) - c[i, j] = zero!(c[i, j]) - for k = 1:ncols(a) - c[i, j] = addmul_delayed_reduction!(c[i, j], a[i, k], b[k, j], t) - end - c[i, j] = reduce!(c[i, j]) - end - end - return c -end - -function add!(c::MatElem, a::MatElem, b::MatElem) - parent(a) != parent(b) && error("Parents don't match.") - parent(c) != parent(b) && error("Parents don't match.") - for i = 1:nrows(c) - for j = 1:ncols(c) - c[i, j] = add!(c[i, j], a[i, j], b[i, j]) - end - end - return c -end - function mul!(a::zzModMatrix, b::zzModMatrix, c::zzModRingElem) ccall((:nmod_mat_scalar_mul, libflint), Nothing, (Ref{zzModMatrix}, Ref{zzModMatrix}, UInt), a, b, c.data) return a end -function mul!(c::MatElem, a::MatElem, b::RingElement) - nrows(c) != nrows(a) && error("Incompatible matrix dimensions") - - if c === a || c === b - d = parent(a)() - return mul!(d, a, b) - end - - t = base_ring(a)() - for i = 1:nrows(a) - for j = 1:ncols(a) - c[i, j] = mul!(c[i, j], a[i, j], b) - end - end - return c -end - ################################################################################ # # Denominator @@ -100,8 +23,7 @@ function denominator(M::QQMatrix) return d end -transpose!(A::Union{ZZMatrix, QQMatrix}) = is_square(A) ? transpose!(A, A) : transpose(A) -transpose!(A::MatrixElem) = transpose(A) +transpose!(A::Union{ZZMatrix,QQMatrix}) = is_square(A) ? transpose!(A, A) : transpose(A) function transpose!(A::ZZMatrix, B::ZZMatrix) ccall((:fmpz_mat_transpose, libflint), Nothing, @@ -115,48 +37,11 @@ function transpose!(A::QQMatrix, B::QQMatrix) return A end -################################################################################ -# -# Zero matrix constructors -# -################################################################################ - -function zero_matrix(::Type{MatElem}, R::Ring, n::Int) - return zero_matrix(R, n) -end - -function zero_matrix(::Type{MatElem}, R::Ring, n::Int, m::Int) - return zero_matrix(R, n, m) -end - - function matrix(A::Matrix{ZZRingElem}) m = matrix(FlintZZ, A) return m end -function matrix(A::Matrix{T}) where {T<:RingElem} - r, c = size(A) - (r < 0 || c < 0) && error("Array must be non-empty") - m = matrix(parent(A[1, 1]), A) - return m -end - -function matrix(A::Vector{T}) where {T<:RingElem} - return matrix(reshape(A, length(A), 1)) -end - -export scalar_matrix - -function scalar_matrix(R::Ring, n::Int, a::RingElement) - b = R(a) - z = zero_matrix(R, n, n) - for i in 1:n - z[i, i] = b - end - return z -end - function Array(a::ZZMatrix; S::Type{T}=ZZRingElem) where {T} A = Array{T}(undef, nrows(a), ncols(a)) for i = 1:nrows(a) @@ -188,8 +73,6 @@ function is_positive_entry(M::ZZMatrix, i::Int, j::Int) end end - - function is_zero_row(M::zzModMatrix, i::Int) zero = UInt(0) for j in 1:ncols(M) @@ -201,35 +84,8 @@ function is_zero_row(M::zzModMatrix, i::Int) return true end -function is_zero_row(M::MatElem{T}, i::Int) where {T} - for j in 1:ncols(M) - if !iszero(M[i, j]) - return false - end - end - return true -end - -function is_zero_row(M::Matrix{T}, i::Int) where {T<:Integer} - for j = 1:Base.size(M, 2) - if M[i, j] != 0 - return false - end - end - return true -end - function is_zero_row(M::Matrix{ZZRingElem}, i::Int) for j = 1:Base.size(M, 2) - if M[i, j] != 0 - return false - end - end - return true -end - -function is_zero_row(M::Matrix{T}, i::Int) where {T<:RingElem} - for j in 1:Base.size(M, 2) if !iszero(M[i, j]) return false end @@ -238,7 +94,6 @@ function is_zero_row(M::Matrix{T}, i::Int) where {T<:RingElem} end export divexact! -export mul! function divexact!(a::ZZMatrix, b::ZZMatrix, d::ZZRingElem) ccall((:fmpz_mat_scalar_divexact_fmpz, libflint), Nothing, @@ -355,22 +210,6 @@ end # ################################################################################ -@doc raw""" - kernel(a::MatElem{T}; side::Symbol = :right) -> Int, MatElem{T} - -It returns a tuple $(n, M)$, where $n$ is the rank of the kernel and $M$ is a basis for it. If side is $:right$ or not -specified, the right kernel is computed. If side is $:left$, the left kernel is computed. -""" -function kernel(A::MatElem; side::Symbol=:right) - if side == :right - return right_kernel(A) - elseif side == :left - return left_kernel(A) - else - error("Unsupported argument: :$side for side: Must be :left or :right") - end -end - function right_kernel(x::fpMatrix) z = zero_matrix(base_ring(x), ncols(x), max(nrows(x), ncols(x))) n = ccall((:nmod_mat_nullspace, libflint), Int, (Ref{fpMatrix}, Ref{fpMatrix}), z, x) @@ -407,13 +246,6 @@ function left_kernel(x::ZZMatrix) end end -right_kernel(M::MatElem) = nullspace(M) - -function left_kernel(M::MatElem) - rk, M1 = nullspace(transpose(M)) - return rk, transpose(M1) -end - function right_kernel(x::ZZMatrix) n, M = left_kernel(transpose(x)) return n, transpose(M) @@ -447,11 +279,6 @@ function right_kernel(M::zzModMatrix) return 0, zero_matrix(R, nrows(M), 0) end -function left_kernel(a::zzModMatrix) - n, M = right_kernel(transpose(a)) - return n, transpose(M) -end - function right_kernel(M::ZZModMatrix) R = base_ring(M) N = hcat(transpose(M), identity_matrix(R, ncols(M))) @@ -475,93 +302,6 @@ function right_kernel(M::ZZModMatrix) return 0, zero_matrix(R, nrows(M), 0) end -function left_kernel(a::ZZModMatrix) - n, M = right_kernel(transpose(a)) - return n, transpose(M) -end - -################################################################################ -# -# Kernel over different rings -# -################################################################################ - -@doc raw""" -kernel(a::MatrixElem{T}, R::Ring; side::Symbol = :right) -> n, MatElem{elem_type(R)} - -It returns a tuple $(n, M)$, where $n$ is the rank of the kernel over $R$ and $M$ is a basis for it. If side is $:right$ or not -specified, the right kernel is computed. If side is $:left$, the left kernel is computed. -""" -function kernel(M::MatrixElem, R::Ring; side::Symbol=:right) - MP = change_base_ring(R, M) - return kernel(MP, side=side) -end - -################################################################################ -# -# Diagonal (block) matrix creation -# -################################################################################ - -@doc raw""" - diagonal_matrix(x::T...) where T <: RingElem -> MatElem{T} - diagonal_matrix(x::Vector{T}) where T <: RingElem -> MatElem{T} - diagonal_matrix(Q, x::Vector{T}) where T <: RingElem -> MatElem{T} - -Returns a diagonal matrix whose diagonal entries are the elements of $x$. - -# Examples - -```jldoctest -julia> diagonal_matrix(QQ(1), QQ(2)) -[1 0] -[0 2] - -julia> diagonal_matrix([QQ(3), QQ(4)]) -[3 0] -[0 4] - -julia> diagonal_matrix(QQ, [5, 6]) -[5 0] -[0 6] -``` -""" -function diagonal_matrix(R::Ring, x::Vector{<:RingElement}) - x = R.(x) - M = zero_matrix(R, length(x), length(x)) - for i = 1:length(x) - M[i, i] = x[i] - end - return M -end - -function diagonal_matrix(x::T, xs::T...) where {T<:RingElem} - return diagonal_matrix(collect((x, xs...))) -end - -diagonal_matrix(x::Vector{<:RingElement}) = diagonal_matrix(parent(x[1]), x) - -@doc raw""" - diagonal_matrix(x::Vector{T}) where T <: MatElem -> MatElem - -Returns a block diagonal matrix whose diagonal blocks are the matrices in $x$. -""" -function diagonal_matrix(x::Vector{T}) where {T<:MatElem} - return cat(x..., dims=(1, 2))::T -end - -function diagonal_matrix(x::T, xs::T...) where {T<:MatElem} - return cat(x, xs..., dims=(1, 2))::T -end - -function diagonal_matrix(R::Ring, x::Vector{<:MatElem}) - if length(x) == 0 - return zero_matrix(R, 0, 0) - end - x = [change_base_ring(R, i) for i in x] - return diagonal_matrix(x) -end - ################################################################################ # # Reduce the entries of a matrix modulo p @@ -648,164 +388,6 @@ function map_entries(R::zzModRing, M::ZZMatrix) return MR end -################################################################################ -# -# Concatenation of matrices -# -################################################################################ - -@doc raw""" -vcat(A::Vector{Generic.Mat}) -> Generic.Mat -vcat(A::Vector{ZZMatrix}) -> ZZMatrix - -Forms a big matrix by vertically concatenating the matrices in $A$. -All component matrices need to have the same number of columns. -""" -function Base.vcat(A::Vector{T}) where {S<:RingElem,T<:MatElem{S}} - if any(x -> ncols(x) != ncols(A[1]), A) - error("Matrices must have same number of columns") - end - M = zero_matrix(base_ring(A[1]), sum(nrows, A), ncols(A[1])) - s = 0 - for i = A - for j = 1:nrows(i) - for k = 1:ncols(i) - M[s+j, k] = i[j, k] - end - end - s += nrows(i) - end - return M -end - -function Base.vcat(A::Vector{ZZMatrix}) - if any(x -> ncols(x) != ncols(A[1]), A) - error("Matrices must have same number of columns") - end - M = zero_matrix(base_ring(A[1]), sum(nrows, A), ncols(A[1])) - s = 0 - for i = A - for j = 1:nrows(i) - for k = 1:ncols(i) - M[s+j, k] = i[j, k] - end - end - s += nrows(i) - end - return M -end - -function Base.vcat(A::Vector{zzModMatrix}) - if any(x -> ncols(x) != ncols(A[1]), A) - error("Matrices must have same number of columns") - end - M = zero_matrix(base_ring(A[1]), sum(nrows, A), ncols(A[1])) - s = 0 - for i = A - for j = 1:nrows(i) - for k = 1:ncols(i) - M[s+j, k] = i[j, k] - end - end - s += nrows(i) - end - return M -end - -function Base.vcat(A::MatElem...) - r = nrows(A[1]) - c = ncols(A[1]) - R = base_ring(A[1]) - for i = 2:length(A) - @assert ncols(A[i]) == c - @assert base_ring(A[i]) == R - r += nrows(A[i]) - end - X = zero_matrix(R, r, c) - o = 1 - for i = 1:length(A) - for j = 1:nrows(A[i]) - X[o, :] = A[i][j, :] - o += 1 - end - end - return X -end - -function Base.hcat(A::Vector{T}) where {S<:RingElem,T<:MatElem{S}} - if any(x -> nrows(x) != nrows(A[1]), A) - error("Matrices must have same number of rows") - end - M = zero_matrix(base_ring(A[1]), nrows(A[1]), sum(ncols, A)) - s = 0 - for i = A - for j = 1:ncols(i) - for k = 1:nrows(i) - M[k, s+j] = i[k, j] - end - end - s += ncols(i) - end - return M -end - -function Base.hcat(A::MatElem...) - r = nrows(A[1]) - c = ncols(A[1]) - R = base_ring(A[1]) - for i = 2:length(A) - @assert nrows(A[i]) == r - @assert base_ring(A[i]) == R - c += ncols(A[i]) - end - X = zero_matrix(R, r, c) - o = 1 - for i = 1:length(A) - for j = 1:ncols(A[i]) - X[:, o] = A[i][:, j] - o += 1 - end - end - return X -end - -function Base.cat(A::MatElem...; dims) - @assert dims == (1, 2) || isa(dims, Int) - - if isa(dims, Int) - if dims == 1 - return hcat(A...) - elseif dims == 2 - return vcat(A...) - else - error("dims must be 1, 2, or (1,2)") - end - end - - local X - for i = 1:length(A) - if i == 1 - X = hcat(A[1], zero_matrix(base_ring(A[1]), nrows(A[1]), sum(Int[ncols(A[j]) for j = 2:length(A)]))) - else - X = vcat(X, hcat(zero_matrix(base_ring(A[1]), nrows(A[i]), sum(ncols(A[j]) for j = 1:i-1)), A[i], zero_matrix(base_ring(A[1]), nrows(A[i]), sum(Int[ncols(A[j]) for j = i+1:length(A)])))) - end - end - return X -end - -#= seems to be in AA now -function Base.hvcat(rows::Tuple{Vararg{Int}}, A::MatElem...) - B = hcat([A[i] for i=1:rows[1]]...) - o = rows[1] - for j=2:length(rows) - C = hcat([A[i+o] for i=1:rows[j]]...) - o += rows[j] - B = vcat(B, C) - end - return B -end -=# - export hnf! function hnf!(x::ZZMatrix) @@ -935,18 +517,6 @@ end # ################################################################################ -function is_upper_triangular(M::MatElem) - n = nrows(M) - for i = 2:n - for j = 1:min(i - 1, ncols(M)) - if !iszero(M[i, j]) - return false - end - end - end - return true -end - function is_upper_triangular(M::ZZMatrix) GC.@preserve M begin for i = 2:nrows(M) @@ -1155,49 +725,9 @@ function to_array(M::QQMatrix) return A end -################################################################################ -# -# Minpoly and Charpoly -# -################################################################################ - -function minpoly(M::MatElem) - k = base_ring(M) - kx, x = polynomial_ring(k, cached=false) - return minpoly(kx, M) -end - -function charpoly(M::MatElem) - k = base_ring(M) - kx, x = polynomial_ring(k, cached=false) - return charpoly(kx, M) -end -############################################################################### -# -# Sub -# -############################################################################### -function sub(M::MatElem, rows::Vector{Int}, cols::Vector{Int}) - N = zero_matrix(base_ring(M), length(rows), length(cols)) - for i = 1:length(rows) - for j = 1:length(cols) - N[i, j] = M[rows[i], cols[j]] - end - end - return N -end -function sub(M::MatElem{T}, r::AbstractUnitRange{<:Integer}, c::AbstractUnitRange{<:Integer}) where {T} - z = similar(M, length(r), length(c)) - for i in 1:length(r) - for j in 1:length(c) - z[i, j] = M[r[i], c[j]] - end - end - return z -end ################################################################################ # diff --git a/src/HeckeMiscPoly.jl b/src/HeckeMiscPoly.jl index 695e0d256..4df74fbaa 100644 --- a/src/HeckeMiscPoly.jl +++ b/src/HeckeMiscPoly.jl @@ -1,11 +1,3 @@ -function polynomial_ring(R::Ring; cached::Bool=false) - return polynomial_ring(R, "x", cached=cached) -end - -function content(a::PolyElem{<:FieldElem}) - return one(base_ring(a)) -end - function ZZRingElem(a::Generic.ResidueRingElem{ZZRingElem}) return a.data end @@ -42,15 +34,6 @@ function (::ZZRing)(a::ZZModRingElem) return a.data end -function Base.div(f::PolyElem, g::PolyElem) - q, r = divrem(f, g) - return q -end - -function Base.rem(f::PolyElem, g::PolyElem) - return mod(f, g) -end - function rem!(z::T, f::T, g::T) where {T<:PolyElem} z = rem(f, g) return z diff --git a/src/HeckeMoreStuff.jl b/src/HeckeMoreStuff.jl index acf6debb4..87d149264 100644 --- a/src/HeckeMoreStuff.jl +++ b/src/HeckeMoreStuff.jl @@ -12,10 +12,6 @@ function round(::Type{Int}, a::QQFieldElem) return round(Int, Rational{BigInt}(a)) end -function matrix(a::Vector{Vector{T}}) where {T} - return matrix(permutedims(reduce(hcat, a), (2, 1))) -end - function prime_field(_::NumField) return QQField() end @@ -86,16 +82,6 @@ for (s, f) in ((:trunc, Base.trunc), (:round, Base.round), (:ceil, Base.ceil), ( end end -export is_constant - -function is_constant(f::PolyElem) - return f.length < 2 -end - -function identity_matrix(::Type{MatElem}, R::Ring, n::Int) - return identity_matrix(R, n) -end - function norm(v::arb_mat) return sqrt(sum([a^2 for a in v])) end @@ -131,11 +117,6 @@ function mul!(z::acb, x::acb, y::arb) return z end -#TODO: should be done in Nemo/AbstractAlgebra s.w. -# needed by ^ (the generic power in Base using square and multiply) -Base.copy(f::Generic.MPoly) = deepcopy(f) -Base.copy(f::Generic.Poly) = deepcopy(f) - @doc raw""" valuation(G::QQMatrix, p) @@ -173,57 +154,9 @@ end ZZMatrix(M::Matrix{Int}) = matrix(FlintZZ, M) -zero_matrix(::Type{Int}, r, c) = zeros(Int, r, c) - -base_ring(::Vector{Int}) = Int - -function AbstractAlgebra.is_symmetric(M::MatElem) - for i in 1:nrows(M) - for j in i:ncols(M) - if M[i, j] != M[j, i] - return false - end - end - end - return true -end - -################################################################################ -# -# Create a matrix from rows -# -################################################################################ - -function matrix(K::Ring, R::Vector{<:Vector}) - if length(R) == 0 - return zero_matrix(K, 0, 0) - else - n = length(R) - m = length(R[1]) - z = zero_matrix(K, n, m) - for i in 1:n - @assert length(R[i]) == m - for j in 1:m - z[i, j] = R[i][j] - end - end - return z - end -end - order(::ZZRingElem) = FlintZZ -export neg!, rem! - -sub!(z::Rational{Int}, x::Rational{Int}, y::Int) = x - y - -neg!(z::Rational{Int}, x::Rational{Int}) = -x - -add!(z::Rational{Int}, x::Rational{Int}, y::Int) = x + y - -mul!(z::Rational{Int}, x::Rational{Int}, y::Int) = x * y - -is_negative(x::Rational) = x.num < 0 +export rem! function is_negative(x::QQFieldElem) c = ccall((:fmpq_sgn, libflint), Cint, (Ref{QQFieldElem},), x) @@ -237,35 +170,6 @@ function sub!(z::Vector{QQFieldElem}, x::Vector{QQFieldElem}, y::Vector{ZZRingEl return z end -function is_upper_triangular(A::Generic.Mat) - m = nrows(A) - n = ncols(A) - d = 0 - for r = 1:m - for c = 1:n - if !iszero(A[r, c]) - if c <= d - return false - end - d = c - break - end - end - end - return true -end - -function sub(M::Generic.Mat, rows::AbstractUnitRange{Int}, cols::AbstractUnitRange{Int}) - @assert step(rows) == 1 && step(cols) == 1 - z = zero_matrix(base_ring(M), length(rows), length(cols)) - for i in rows - for j in cols - z[i-first(rows)+1, j-first(cols)+1] = M[i, j] - end - end - return z -end - function valuation(a::UInt, b::UInt) return ccall((:n_remove, libflint), Int, (Ref{UInt}, UInt), a, b) end @@ -329,28 +233,10 @@ norm(x::ZZRingElem) = abs(x) number_field(::ZZRing) = FlintQQ -function change_base_ring(p::MPolyRingElem{T}, g, new_polynomial_ring) where {T<:RingElement} - cvzip = zip(coefficients(p), exponent_vectors(p)) - M = MPolyBuildCtx(new_polynomial_ring) - for (c, v) in cvzip - res = g(c) - if !iszero(res) - push_term!(M, g(c), v) - end - end - return finish(M)::elem_type(new_polynomial_ring) -end - -function mulmod(a::S, b::S, mod::Vector{S}) where {S<:MPolyRingElem{T}} where {T<:RingElem} - return Base.divrem(a * b, mod)[2] -end - function Base.hash(f::zzModMPolyRingElem, h::UInt) return UInt(1) # TODO: enhance or throw error end -@inline ngens(R::AbstractAlgebra.Generic.MPolyRing) = R.num_vars - #to make the MPoly module happy, divrem needs it... function Base.div(a::nf_elem, b::nf_elem) return a // b @@ -523,31 +409,6 @@ end base_field(_::AnticNumberField) = FlintQQ -#trivia to make life easier - -gens(L::SimpleNumField{T}) where {T} = [gen(L)] - -function gen(L::SimpleNumField{T}, i::Int) where {T} - i == 1 || error("index must be 1") - return gen(L) -end - -function Base.getindex(L::SimpleNumField{T}, i::Int) where {T} - if i == 0 - return one(L) - elseif i == 1 - return gen(L) - else - error("index has to be 0 or 1") - end -end - -ngens(L::SimpleNumField{T}) where {T} = 1 - -is_unit(a::NumFieldElem) = !iszero(a) - -canonical_unit(a::NumFieldElem) = a - ################################################################################ # # Base case for dot products @@ -629,10 +490,6 @@ function evaluate(f::QQPolyRingElem, r::T) where {T<:RingElem} return s end -function neg!(w::Vector{Int}) - w .*= -1 -end - function neg!(w::ZZMatrix) ccall((:fmpz_mat_neg, libflint), Nothing, (Ref{ZZMatrix}, Ref{ZZMatrix}), w, w) return w @@ -676,23 +533,6 @@ function shift_left(a::qadic, n::Int) return b end -export set_precision, set_precision! - -function set_precision(f::PolyElem{T}, n::Int) where {T<:SeriesElem} - g = parent(f)() - for i = 0:length(f) - setcoeff!(g, i, set_precision(coeff(f, i), n)) - end - return g -end - -function set_precision!(f::PolyElem{T}, n::Int) where {T<:SeriesElem} - for i = 0:length(f) - setcoeff!(f, i, set_precision!(coeff(f, i), n)) - end - return f -end - #Assuming that the denominator of a is one, reduces all the coefficients modulo p # non-symmetric (positive) residue system function mod!(a::nf_elem, b::ZZRingElem) @@ -766,12 +606,6 @@ function lift(R::ZZAbsPowerSeriesRing, f::ZZModAbsPowerSeriesRingElem) return r end -function addmul!(z::T, x::T, y::T) where {T<:RingElement} - zz = parent(z)() - zz = mul!(zz, x, y) - return addeq!(z, zz) -end - function evaluate(f::fpPolyRingElem, v::Vector{fpFieldElem}) F = base_ring(f) v1 = UInt[x.data for x in v] @@ -985,19 +819,9 @@ function order(x::Generic.ResidueRingElem{ZZRingElem}, fp::Dict{ZZRingElem,Int64 error("missing") end -Base.copy(a::PolyElem) = deepcopy(a) -Base.copy(a::SeriesElem) = deepcopy(a) - fit!(::QQRelPowerSeriesRingElem, Int) = nothing fit!(::QQAbsPowerSeriesRingElem, Int) = nothing -function Base.minimum(::typeof(precision), a::Vector{<:SeriesElem}) - return minimum(map(precision, a)) -end - -function Base.maximum(::typeof(precision), a::Vector{<:SeriesElem}) - return maximum(map(precision, a)) -end Base.length(a::qadic) = a.length function setcoeff!(z::ZZPolyRingElem, n::Int, x::Ptr{ZZRingElem}) @@ -1014,73 +838,6 @@ function iszero(a::Ref{ZZRingElem}) return unsafe_load(reinterpret(Ptr{Int}, a)) == 0 end -function canonical_unit(a::SeriesElem) - iszero(a) && return one(parent(a)) - v = valuation(a) - v == 0 && return a - v > 0 && return shift_right(a, v) - return shift_left(a, -v) -end - -#TODO: this is for rings, not for fields, maybe different types? -function Base.gcd(a::T, b::T) where {T<:SeriesElem} - iszero(a) && iszero(b) && return a - iszero(a) && return gen(parent(a))^valuation(b) - iszero(b) && return gen(parent(a))^valuation(a) - return gen(parent(a))^min(valuation(a), valuation(b)) -end - -function Base.lcm(a::T, b::T) where {T<:SeriesElem} - iszero(a) && iszero(b) && return a - iszero(a) && return a - iszero(b) && return b - return gen(parent(a))^max(valuation(a), valuation(b)) -end - -# should be Nemo/AA -# TODO: symbols vs strings -# lift(PolyRing, Series) -# lift(FracField, Series) -# (to be in line with lift(ZZ, padic) and lift(QQ, padic) -#TODO: some of this would only work for Abs, not Rel, however, this should be fine here -function map_coefficients(f, a::RelPowerSeriesRingElem; parent::SeriesRing) - c = typeof(f(coeff(a, 0)))[] - for i = 0:pol_length(a)-1 - push!(c, f(polcoeff(a, i))) - end - b = parent(c, length(c), precision(a), valuation(a)) - return b -end - -#= -function map_coefficients(f, a::RelPowerSeriesRingElem) - d = f(coeff(a, 0)) - T = parent(a) - if parent(d) == base_ring(T) - S = T - else - S = power_series_ring(parent(d), max_precision(T), string(var(T)), cached = false)[1] - end - c = typeof(d)[d] - for i=1:pol_length(a)-1 - push!(c, f(polcoeff(a, i))) - end - b = S(c, length(c), precision(a), valuation(a)) - return b -end -=# -function lift(R::PolyRing{S}, s::SeriesElem{S}) where {S} - t = R() - for x = 0:pol_length(s) - setcoeff!(t, x, polcoeff(s, x)) - end - return shift_left(t, valuation(s)) -end - -function gen(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:PolyElem} - return R(gen(base_ring(R))) -end - function gen(R::Union{Generic.ResidueRing{fqPolyRepPolyRingElem},Generic.ResidueField{fqPolyRepPolyRingElem}}) ## this is not covered by above return R(gen(base_ring(R))) ## and I don't know why end @@ -1097,27 +854,15 @@ function characteristic(R::Union{Generic.ResidueRing{zzModPolyRingElem},Generic. return characteristic(base_ring(base_ring(R))) end -function characteristic(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:PolyElem} - return characteristic(base_ring(base_ring(R))) -end - # discuss: size = order? order = size? function size(R::Union{Generic.ResidueRing{zzModPolyRingElem},Generic.ResidueField{zzModPolyRingElem}}) return characteristic(R)^degree(modulus(R)) end -function size(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:ResElem} - return size(base_ring(base_ring(R)))^degree(modulus(R)) -end - function size(R::Union{Generic.ResidueRing{ZZRingElem},Generic.ResidueField{ZZRingElem}}) return modulus(R) end -function size(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:PolyElem} - return size(base_ring(base_ring(R)))^degree(R.modulus) -end - function size(R::Union{Generic.ResidueRing{fqPolyRepPolyRingElem},Generic.ResidueField{fqPolyRepPolyRingElem}}) return size(base_ring(base_ring(R)))^degree(R.modulus) end @@ -1182,15 +927,6 @@ function rand(R::Generic.ResidueField{ZZRingElem}) return R(rand(ZZRingElem(0):(order(R)-1))) end -function rand(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:PolyElem} - r = rand(base_ring(base_ring(R))) - g = gen(R) - for i = 1:degree(R.modulus) - r = r * g + rand(base_ring(base_ring(R))) - end - return r -end - function rand(R::Union{Generic.ResidueRing{fqPolyRepPolyRingElem},Generic.ResidueField{fqPolyRepPolyRingElem}}) r = rand(base_ring(base_ring(R))) g = gen(R) @@ -1218,35 +954,6 @@ function rand(R::Union{Generic.ResidueRing{zzModPolyRingElem},Generic.ResidueFie return r end -function gens(R::Union{Generic.ResidueRing{T},Generic.ResidueField{T}}) where {T<:PolyElem} ## probably needs more cases - ## as the other residue functions - g = gen(R) - r = Vector{typeof(g)}() - push!(r, one(R)) - if degree(R.modulus) == 1 - return r - end - push!(r, g) - for i = 2:degree(R.modulus)-1 - push!(r, r[end] * g) - end - return r -end - -function gens(R::Union{Generic.ResidueRing{zzModPolyRingElem},Generic.ResidueField{zzModPolyRingElem}}) - g = gen(R) - r = Vector{typeof(g)}() - push!(r, one(R)) - if degree(R.modulus) == 1 - return r - end - push!(r, g) - for i = 2:degree(R.modulus)-1 - push!(r, r[end] * g) - end - return r -end - function rem!(f::zzModPolyRingElem, g::zzModPolyRingElem, h::zzModPolyRingElem) ccall((:nmod_poly_rem, libflint), Nothing, (Ref{zzModPolyRingElem}, Ref{zzModPolyRingElem}, Ref{zzModPolyRingElem}), f, g, h) return f @@ -1262,19 +969,10 @@ function gcd!(f::fpPolyRingElem, g::fpPolyRingElem, h::fpPolyRingElem) return f end - function divexact(a::ZZModRingElem, y::ZZRingElem; check::Bool=true) return divexact(a, parent(a)(y), check=check) end -function lift(a::Generic.ResidueRingElem) - return a.data -end - -function lift(a::Generic.ResidueFieldElem) - return a.data -end - function ^(a::ResElem, f::ZZRingElem) f == 0 && return one(parent(a)) f == 1 && return a @@ -1301,23 +999,6 @@ end characteristic(F::Generic.ResidueField{ZZRingElem}) = abs(F.modulus) -function leading_monomial(f::Generic.MPoly) - R = parent(f) - l = length(f) - if l == 0 - return f - end - A = f.exps - r, c = size(A) - e = A[1:r, 1:1] - return R([one(base_ring(R))], e) -end - -function leading_coefficient(f::Generic.MPoly) - return f.coeffs[1] -end - - function is_prime(x::Integer) return is_prime(ZZRingElem(x)) end @@ -1417,48 +1098,6 @@ function (R::ZZMPolyRing)(f::QQMPolyRingElem) return map_coefficients(ZZ, f, parent=R) end -ngens(R::ZZMPolyRing) = length(gens(R)) - -#check with Nemo/ Dan if there are better solutions -#the block is also not used here I think -#functionality to view mpoly as upoly in variable `i`, so the -#coefficients are mpoly's without variable `i`. -function leading_coefficient(f::MPolyRingElem, i::Int) - g = MPolyBuildCtx(parent(f)) - d = degree(f, i) - for (c, e) = zip(coefficients(f), exponent_vectors(f)) - if e[i] == d - e[i] = 0 - push_term!(g, c, e) - end - end - return finish(g) -end - -#not used here -""" -`content` as a polynomial in the variable `i`, i.e. the gcd of all the -coefficients when viewed as univariate polynomial in `i`. -""" -function content(f::MPolyRingElem, i::Int) - return reduce(gcd, coefficients(f, i)) -end - -""" -The coefficients of `f` when viewed as a univariate polynomial in the `i`-th -variable. -""" -function coefficients(f::MPolyRingElem, i::Int) - d = degree(f, i) - cf = [MPolyBuildCtx(parent(f)) for j = 0:d] - for (c, e) = zip(coefficients(f), exponent_vectors(f)) - a = e[i] - e[i] = 0 - push_term!(cf[a+1], c, e) - end - return map(finish, cf) -end - # mainly for testing function rand(L::Loc{T}, num_scale=(1:1000), den_scale=(1:1000)) where {T<:ZZRingElem} num = rand(num_scale) @@ -1478,8 +1117,6 @@ function rand(L::Loc{T}, num_scale::Vector, den_scale::Integer) where {T<:ZZRing return L(num // den) end -AbstractAlgebra.promote_rule(::Type{LocElem{T}}, ::Type{T}) where {T} = LocElem{T} - function cmpabs(a::Int, b::Int) a = abs(a) b = abs(b) @@ -1538,22 +1175,6 @@ function rem!(z::fpPolyRingElem, a::fpPolyRingElem, b::fpPolyRingElem) return z end -function show(io::IO, M::Map) - @show_name(io, M) - if get(io, :compact, false) - print(io, domain(M), " --> ", codomain(M), "\n") - return - end - io = Base.IOContext(io, :compact => true) - print(io, "Map with following data\n") - print(io, "Domain:\n") - print(io, "=======\n") - print(io, domain(M)) - print(io, "\nCodomain:\n") - print(io, "=========\n") - print(io, codomain(M)) -end - function preimage(M::Map{D,C}, a) where {D,C} if isdefined(M.header, :preimage) p = M.header.preimage(a)::elem_type(D) @@ -1575,14 +1196,6 @@ function image(M::Map{D,C}, a) where {D,C} end end -\(f::Map, x) = preimage(f, x) - -function preimage(f::AbstractAlgebra.Generic.CompositeMap, a) - return preimage(f.map1, preimage(f.map2, a)) -end - - - function Base.setprecision(q::qadic, N::Int) r = parent(q)() r.N = N @@ -1707,9 +1320,6 @@ end Base.precision(Q::FlintPadicField) = Q.prec_max Base.precision(Q::FlintQadicField) = Q.prec_max -nrows(A::Matrix{T}) where {T} = size(A)[1] -ncols(A::Matrix{T}) where {T} = size(A)[2] - import Base.^ ^(a::qadic, b::qadic) = exp(b * log(a)) ^(a::padic, b::padic) = exp(b * log(a)) @@ -1771,6 +1381,7 @@ end function root(a::FinFieldElem, n::ZZRingElem) return root(a, Int(n)) end + function root(a::FinFieldElem, n::Integer) k = parent(a) kt, t = polynomial_ring(k, "t", cached=false) @@ -1830,8 +1441,6 @@ function divexact!(A::Generic.Mat{nf_elem}, p::ZZRingElem) end end -elem_type(::Type{Generic.ResidueRing{T}}) where {T} = Generic.ResidueRingElem{T} - # # Lifts a matrix from F_p to Z/p^nZ # @@ -1968,10 +1577,6 @@ AbstractAlgebra.promote_rule(::Type{S}, ::Type{QQFieldElem}) where {S<:NumFieldE AbstractAlgebra.promote_rule(::Type{QQFieldElem}, ::Type{S}) where {S<:NumFieldElem} = S -AbstractAlgebra.promote_rule(::Type{T}, ::Type{S}) where {S<:NumFieldElem,T<:Integer} = S - -AbstractAlgebra.promote_rule(::Type{S}, ::Type{T}) where {S<:NumFieldElem,T<:Integer} = S - function is_positive(x::ZZRingElem, ::Union{PosInf,Vector{PosInf}}) return sign(x) == 1 end @@ -2114,14 +1719,6 @@ function _power(x::NumFieldElem, y::ZZRingElem) return res end -#TODO: in Nemo, rename to setprecision -# fix/report series add for different length -function set_precision(a::SeriesElem, i::Int) - b = deepcopy(a) - set_precision!(b, i) - return b -end - function (Rx::fpPolyRing)(a::fqPolyRepFieldElem) el = Rx() for i = 0:degree(parent(a)) @@ -2208,24 +1805,6 @@ function setprecision!(a::padic, n::Int) return setprecision(a, n) end -ngens(R::MPolyRing) = nvars(R) - -function (R::Generic.PolyRing{T})(x::AbstractAlgebra.Generic.RationalFunctionFieldElem{T,U}) where {T<:RingElem,U} - @assert isone(denominator(x)) - @assert parent(numerator(x)) === R - return numerator(x) -end - -function (R::PolyRing{T})(x::AbstractAlgebra.Generic.RationalFunctionFieldElem{T,U}) where {T<:RingElem,U} - @assert isone(denominator(x)) - @assert parent(numerator(x)) === R - return numerator(x) -end - -export base_ring_type - -base_ring_type(::Type{AbstractAlgebra.Generic.PolyRing{T}}) where {T} = parent_type(T) - base_ring_type(::Type{AcbPolyRing}) = AcbField base_ring_type(::Type{ArbPolyRing}) = ArbField diff --git a/src/flint/fq.jl b/src/flint/fq.jl index 3883a2497..67702511e 100644 --- a/src/flint/fq.jl +++ b/src/flint/fq.jl @@ -504,29 +504,6 @@ function add!(z::FqPolyRepFieldElem, x::FqPolyRepFieldElem, y::FqPolyRepFieldEle return z end -############################################################################### -# -# Random functions -# -############################################################################### - -Random.Sampler(::Type{RNG}, K::FinField, n::Random.Repetition) where {RNG<:AbstractRNG} = - Random.SamplerSimple(K, Random.Sampler(RNG, BigInt(0):BigInt(characteristic(K) - 1), n)) - -function rand(rng::AbstractRNG, Ksp::Random.SamplerSimple{<:FinField}) - K = Ksp[] - r = degree(K) - alpha = gen(K) - res = zero(K) - for i = 0 : (r-1) - c = rand(rng, Ksp.data) - res += c * alpha^i - end - return res -end - -Random.gentype(::Type{T}) where {T<:FinField} = elem_type(T) - ################################################################################ # # fqPolyRepField Modulus