diff --git a/src/Matrix.jl b/src/Matrix.jl index b5fc74af47..b269b0a959 100644 --- a/src/Matrix.jl +++ b/src/Matrix.jl @@ -48,13 +48,42 @@ function _check_bases(a, b) return nothing end -function (s::MatSpace{T})(a::M) where {T, M <: MatrixElem{T}} +# create a zero matrix +function (s::MatSpace{T})() where {T <: NCRingElement} + return zero_matrix(base_ring(s), nrows(s), ncols(s))::eltype(s) +end + +function (s::MatSpace{T})(a::MatrixElem{T}) where {T <: NCRingElement} _check_dim(nrows(s), ncols(s), a) _check_bases(s, a) a isa eltype(s) && return a - b = eltype(s)(a) - b.base_ring = base_ring(s) - return b + M = s() # zero matrix + R = base_ring(s) + if R == base_ring(a) + for i = 1:nrows(s) + for j = 1:ncols(s) + M[i, j] = a[i, j] + end + end + else + for i = 1:nrows(s) + for j = 1:ncols(s) + M[i, j] = R(a[i, j]) + end + end + end + return M +end + +# create a matrix with b on the diagonal +function (s::MatSpace)(b::NCRingElement) + M = s() # zero matrix + R = base_ring(s) + rb = R(b) + for i in 1:min(nrows(s), ncols(s)) + M[i, i] = rb + end + return M end _checkbounds(i::Int, j::Int) = 1 <= j <= i @@ -6577,10 +6606,18 @@ function matrix(R::NCRing, arr::AbstractMatrix{T}) where {T} end function matrix(R::NCRing, arr::MatElem) - return map_entries(R, arr) + return map_entries(R, arr) +end + +function matrix(R::NCRing, arr::MatRingElem) + return matrix_space(R, nrows(arr), ncols(arr))(arr) +end + +function matrix(mat::MatrixElem{T}) where {T<:NCRingElement} + return matrix(base_ring(mat), mat) end -function matrix(arr::AbstractMatrix{T}) where {T<:NCRingElem} +function matrix(arr::AbstractMatrix{T}) where {T<:NCRingElement} r, c = size(arr) (r < 0 || c < 0) && error("Array must be non-empty") R = parent(arr[1, 1]) @@ -6588,11 +6625,11 @@ function matrix(arr::AbstractMatrix{T}) where {T<:NCRingElem} return matrix(R, arr) end -function matrix(arr::AbstractVector{T}) where {T<:NCRingElem} +function matrix(arr::AbstractVector{T}) where {T<:NCRingElement} return matrix(reshape(arr, length(arr), 1)) end -function matrix(arr::Vector{Vector{T}}) where {T<:NCRingElem} +function matrix(arr::Vector{Vector{T}}) where {T<:NCRingElement} return matrix(permutedims(reduce(hcat, arr), (2, 1))) end diff --git a/src/generic/MatRing.jl b/src/generic/MatRing.jl index 67c68142af..23c18760ee 100644 --- a/src/generic/MatRing.jl +++ b/src/generic/MatRing.jl @@ -146,11 +146,42 @@ function (a::MatRing{T})(b::S) where {S <: NCRingElement, T <: NCRingElement} return z end +# to resolve ambiguity for MatRing{MatRing{...}} +function (a::MatRing{T})(b::T) where {S <: NCRingElement, T <: MatRingElem{S}} + R = base_ring(a) + entries = Matrix{T}(undef, a.n, a.n) + rb = R(b) + for i = 1:a.n + for j = 1:a.n + if i != j + entries[i, j] = zero(R) + else + entries[i, j] = rb + end + end + end + z = MatRingElem{T}(R, entries) + return z +end + function (a::MatRing{T})(b::MatRingElem{T}) where {T <: NCRingElement} parent(b) != a && error("Unable to coerce matrix") return b end +function (a::MatRing{T})(b::MatrixElem{S}) where {S <: NCRingElement, T <: NCRingElement} + R = base_ring(a) + _check_dim(nrows(a), ncols(a), b) + entries = Matrix{T}(undef, nrows(a), ncols(a)) + for i = 1:nrows(a) + for j = 1:ncols(a) + entries[i, j] = R(b[i, j]) + end + end + z = MatRingElem{T}(R, entries) + return z +end + function (a::MatRing{T})(b::Matrix{S}) where {S <: NCRingElement, T <: NCRingElement} R = base_ring(a) _check_dim(a.n, a.n, b) diff --git a/src/generic/Matrix.jl b/src/generic/Matrix.jl index 800564ea22..844924d50e 100644 --- a/src/generic/Matrix.jl +++ b/src/generic/Matrix.jl @@ -148,21 +148,7 @@ end # ############################################################################### -# create a zero matrix -function (a::Generic.MatSpace{T})() where {T <: NCRingElement} - return zero_matrix(base_ring(a), nrows(a), ncols(a))::dense_matrix_type(T) -end -# create a matrix with b on the diagonal -function (a::Generic.MatSpace)(b::NCRingElement) - M = a() # zero matrix - R = base_ring(a) - rb = R(b) - for i in 1:min(nrows(a), ncols(a)) - M[i, i] = rb - end - return M -end # convert a Julia matrix function (a::Generic.MatSpace{T})(b::AbstractMatrix{S}) where {T <: NCRingElement, S} diff --git a/test/Matrix-test.jl b/test/Matrix-test.jl index dd206c6118..e9d24f536b 100644 --- a/test/Matrix-test.jl +++ b/test/Matrix-test.jl @@ -112,6 +112,26 @@ end @test T == matrix(QQ, [42 0 0; 0 42 0; 0 0 42]) end +@testset "Matrix.conversion" begin + U, t = polynomial_ring(QQ, "t") + + R = matrix_ring(U, 2) + S = matrix_space(U, 2, 2) + a = U.([1 2; t^2 (t-1)]) # Matrix + Ra = R(a) # MatRingElem + Sa = S(a) # MatElem + @test Ra == R(Ra) + @test Ra == R(Sa) + @test Sa == S(Sa) + @test Sa == S(Ra) + @test matrix(Ra) == Sa + @test matrix(U, Ra) == Ra + @test matrix(Sa) == Sa + @test matrix(U, Sa) == Sa + @test Matrix(Ra) == a + @test Matrix(Sa) == a +end + @testset "Strassen" begin S = matrix(QQ, rand(-10:10, 100, 100)) T = S*S