Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and fix similar and zero for our matrix types #1890

Merged
merged 9 commits into from
Nov 12, 2024
11 changes: 9 additions & 2 deletions src/MatRing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,23 @@ is_finite(R::MatRing) = iszero(nrows(a)) || is_finite(base_ring(R))
###############################################################################

@doc raw"""
similar(x::Generic.MatrixElem, R::NCRing=base_ring(x))
similar(x::Generic.MatrixElem, R::NCRing, r::Int, c::Int)
similar(x::Generic.MatrixElem, R::NCRing)
similar(x::Generic.MatrixElem, r::Int, c::Int)
similar(x::Generic.MatrixElem)
fingolfin marked this conversation as resolved.
Show resolved Hide resolved
similar(x::MatRingElem, R::NCRing, n::Int)
similar(x::MatRingElem, R::NCRing)
similar(x::MatRingElem, n::Int)
similar(x::MatRingElem)

Create an uninitialized matrix over the given ring and dimensions,
with defaults based upon the given source matrix `x`.
"""
similar(x::MatRingElem, R::NCRing, n::Int) = _similar(x, R, n, n)
function similar(x::MatRingElem, R::NCRing, n::Int)
TT = elem_type(R)
M = Matrix{TT}(undef, (n, n))
return Generic.MatRingElem{TT}(R, M)
end

similar(x::MatRingElem, R::NCRing=base_ring(x)) = similar(x, R, degree(x))

Expand Down
21 changes: 9 additions & 12 deletions src/Matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,17 @@ zero(a::MatSpace) = a()

@doc raw"""
zero(x::MatrixElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement
zero(x::MatrixElem{T}, R::NCRing=base_ring(x)) where T <: NCRingElement
zero(x::MatrixElem{T}, r::Int, c::Int) where T <: NCRingElement
zero(x::MatrixElem{T}, R::NCRing) where T <: NCRingElement
zero(x::MatrixElem{T}) where T <: NCRingElement

Return a zero matrix similar to the given matrix, with optionally different
base ring or dimensions.
"""
zero(x::MatrixElem{T}, R::NCRing=base_ring(x)) where T <: NCRingElement = zero(x, R, nrows(x), ncols(x))
zero(x::MatrixElem{T}, R::NCRing) where T <: NCRingElement = zero(x, R, nrows(x), ncols(x))
zero(x::MatrixElem{T}) where T <: NCRingElement = zero(x, nrows(x), ncols(x))
zero(x::MatrixElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement = zero!(similar(x, R, r, c))
zero(x::MatrixElem{T}, r::Int, c::Int) where T <: NCRingElement = zero(x, base_ring(x), r, c)
zero(x::MatrixElem{T}, r::Int, c::Int) where T <: NCRingElement = zero!(similar(x, r, c))

@doc raw"""
one(a::MatSpace)
Expand Down Expand Up @@ -398,19 +400,14 @@ end
#
###############################################################################

function _similar(x::MatrixElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement
TT = elem_type(R)
M = Matrix{TT}(undef, (r, c))
z = x isa MatElem ? Generic.MatSpaceElem{TT}(R, M) : Generic.MatRingElem{TT}(R, M)
return z
end
similar(x::MatElem, R::NCRing, r::Int, c::Int) = zero_matrix(R, r, c)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be changed in the future to use the UndefInitializer, right? (but not needed right now)
so something like dense_matrix_type(R)(R, undef, r, c)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the plan (but we can't change it now because that'd be a breaking change and wouldn't work with older Nemo versions.


similar(x::MatElem, R::NCRing, r::Int, c::Int) = _similar(x, R, r, c)

similar(x::MatElem, R::NCRing=base_ring(x)) = similar(x, R, nrows(x), ncols(x))
similar(x::MatElem, R::NCRing) = similar(x, R, nrows(x), ncols(x))

similar(x::MatElem, r::Int, c::Int) = similar(x, base_ring(x), r, c)

similar(x::MatElem) = similar(x, nrows(x), ncols(x))

###############################################################################
#
# Canonicalisation
Expand Down
5 changes: 5 additions & 0 deletions src/generic/Matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ Base.isassigned(a::Union{Mat,MatRingElem}, i, j) = isassigned(a.entries, i, j)
#
################################################################################

function similar(x::MatSpaceElem{T}, r::Int, c::Int) where T <: NCRingElement
M = Matrix{T}(undef, (r, c))
return MatSpaceElem{T}(base_ring(x), M)
end
Comment on lines +61 to +64
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method would go if we agree on the proposal to forbid MatSpaceElem{T} instances if dense_matrix_type(T) != MatSpaceElem{T}.

But in the meantime it is necessary to preserve Nemo tests.


function copy(d::MatSpaceElem{T}) where T <: NCRingElement
z = similar(d)
for i = 1:nrows(d)
Expand Down
37 changes: 36 additions & 1 deletion test/Rings-conformance-tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,10 @@ function test_MatSpace_interface(S::MatSpace; reps = 20)
R = base_ring(S)
T = elem_type(R)

@test base_ring_type(S) == typeof(R)
@test parent_type(ST) == typeof(S)
@test dense_matrix_type(R) == ST

@testset "MatSpace interface for $(S) of type $(typeof(S))" begin

@testset "Constructors" begin
Expand All @@ -715,6 +719,29 @@ function test_MatSpace_interface(S::MatSpace; reps = 20)
@test a == matrix(R, T[a[i, j] for i in 1:nrows(a), j in 1:ncols(a)])
@test a == matrix(R, nrows(S), ncols(S),
T[a[i, j] for i in 1:nrows(a) for j in 1:ncols(a)])

b = similar(a)
@test b isa ST
@test nrows(b) == nrows(S)
@test ncols(b) == ncols(S)

b = similar(a, nrows(S)+1, ncols(S)+1)
@test b isa ST
@test nrows(b) == nrows(S)+1
@test ncols(b) == ncols(S)+1

b = similar(a, R)
@test b isa MatElem
#@test b isa ST # undefined
@test nrows(b) == nrows(S)
@test ncols(b) == ncols(S)

b = similar(a, R, nrows(S)+1, ncols(S)+1)
@test b isa MatElem
#@test b isa ST # undefined
@test nrows(b) == nrows(S)+1
@test ncols(b) == ncols(S)+1

end
@test iszero(zero_matrix(R, nrows(S), ncols(S)))
end
Expand All @@ -730,12 +757,20 @@ function test_MatSpace_interface(S::MatSpace; reps = 20)
for k in 1:reps
a = test_elem(S)::ST
A = deepcopy(a)
@test A isa ST

b = zero_matrix(R, nrows(a), ncols(a))
@test b isa ST
for i in 1:nrows(a), j in 1:ncols(a)
b[i, j] = a[i, j]
end
@test b == a
@test transpose(transpose(a)) == a

t = transpose(a)
@test t isa ST
@test nrows(t) == ncols(S)
@test ncols(t) == nrows(S)
@test transpose(t) == a
@test a == A
end
end
Expand Down
1 change: 0 additions & 1 deletion test/generic/Matrix-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ AbstractAlgebra.base_ring(::F2Matrix) = F2()

Base.getindex(a::F2Matrix, r::Int64, c::Int64) = a.m[r, c]
Base.setindex!(a::F2Matrix, x::F2Elem, r::Int64, c::Int64) = a.m[r, c] = x
Base.similar(x::F2Matrix, R::F2, r::Int, c::Int) = F2Matrix(similar(x.m, r, c))

function AbstractAlgebra.zero_matrix(R::F2, r::Int, c::Int)
mat = Matrix{F2Elem}(undef, r, c)
Expand Down
Loading