Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 131 additions & 9 deletions src/MatRing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,8 @@ base_ring_type(::Type{<:MatRingElem{T}}) where T <: NCRingElement = parent_type(
###############################################################################

function Base.hash(a::MatRingElem, h::UInt)
b = 0x6413942b83a26c65%UInt
for i in 1:nrows(a)
for j in 1:ncols(a)
b = xor(b, xor(hash(a[i, j], h), h))
b = (b << 1) | (b >> (sizeof(Int)*8 - 1))
end
end
return b
# b = 0x6413942b83a26c65 % UInt # FIXME: comment in once `isequal(::MatRingElem, ::MatElem)` is removed.
return xor(b, hash(matrix(a), h))
end

vector_space_dim(a::MatRing{T}) where {T <: Union{FieldElem, Rational{BigInt}}} = nrows(a)^2
Expand Down Expand Up @@ -250,8 +244,92 @@ end

^(a::MatRingElem{T}, b::Int) where T <: NCRingElement = Generic.MatRingElem(matrix(a)^b)

==(x::MatRingElem{T}, y::MatRingElem{T}) where {T <: NCRingElement} = matrix(x) == matrix(y)
==(x::T, y::T) where {T <: MatRingElem} = matrix(x) == matrix(y)

isequal(x::T, y::T) where {T <: MatRingElem} = isequal(matrix(x), matrix(y))

# FIXME: maybe remove the below methods, or comment the errors in
function ==(x::MatElem{T}, y::MatRingElem{T}) where {T <: NCRingElement}
# error("Equality comparison of MatElem with MatRingElem unsupported")
return x == matrix(y)
end

function ==(x::MatRingElem{T}, y::MatElem{T}) where {T <: NCRingElement}
# error("Equality comparison of MatRingElem with MatElem unsupported")
return matrix(x) == y
end

function isequal(x::MatElem{T}, y::MatRingElem{T}) where {T <: NCRingElement}
# error("Equality comparison of MatElem with MatRingElem unsupported")
return isequal(x, matrix(y))
end

function isequal(x::MatRingElem{T}, y::MatElem{T}) where {T <: NCRingElement}
# error("Equality comparison of MatRingElem with MatElem unsupported")
return isequal(matrix(x), y)
end

###############################################################################
#
# Ad hoc binary operators
#
###############################################################################

function *(x::JuliaRingElement, y::MatRingElem{T}) where T <: NCRingElement
return Generic.MatRingElem(x * matrix(y))
end

function *(x::T, y::MatRingElem{T}) where {T <: NCRingElem}
return Generic.MatRingElem(x * matrix(y))
end

function *(x::MatRingElem{T}, y::JuliaRingElement) where T <: NCRingElement
return Generic.MatRingElem(matrix(x) * y)
end

function *(x::MatRingElem{T}, y::T) where {T <: NCRingElem}
return Generic.MatRingElem(matrix(x) * y)
end

function +(x::JuliaRingElement, y::MatRingElem{T}) where T <: NCRingElement
return Generic.MatRingElem(x + matrix(y))
end

function +(x::MatRingElem{T}, y::JuliaRingElement) where T <: NCRingElement
return Generic.MatRingElem(matrix(x) + y)
end

function +(x::T, y::MatRingElem{T}) where {T <: NCRingElem}
return Generic.MatRingElem(x + matrix(y))
end

function +(x::MatRingElem{T}, y::T) where {T <: NCRingElem}
return Generic.MatRingElem(matrix(x) + y)
end

function -(x::JuliaRingElement, y::MatRingElem{T}) where T <: NCRingElement
return Generic.MatRingElem(x - matrix(y))
end

function -(x::MatRingElem{T}, y::JuliaRingElement) where T <: NCRingElement
return Generic.MatRingElem(matrix(x) - y)
end

function -(x::T, y::MatRingElem{T}) where {T <: NCRingElem}
return Generic.MatRingElem(x - matrix(y))
end

function -(x::MatRingElem{T}, y::T) where {T <: NCRingElem}
return Generic.MatRingElem(matrix(x) - y)
end

function *(x::MatRingElem{T}, y::Vector{T}) where T <: NCRingElement
return matrix(x) * y
end

function *(x::Vector{T}, y::MatRingElem{T}) where T <: NCRingElement
return x * matrix(y)
end

###############################################################################
#
Expand Down Expand Up @@ -498,6 +576,50 @@ end
randmat_with_rank(S::MatRing{T}, rank::Int, v...) where {T <: RingElement} =
randmat_with_rank(Random.default_rng(), S, rank, v...)

################################################################################
#
# Promotion
#
################################################################################

function Base.promote(x::MatRingElem{S},
y::MatRingElem{T}) where {S <: NCRingElement,
T <: NCRingElement}
U = promote_rule_sym(S, T)
if U === S
return x, change_base_ring(base_ring(x), y)
elseif U === T
return change_base_ring(base_ring(y), x), y
else
error("Cannot promote to common type")
end
end

# matrix * vec and vec * matrx
function Base.promote(x::MatRingElem{S},
y::Vector{T}) where {S <: NCRingElement,
T <: NCRingElement}
U = promote_rule_sym(S, T)
if U === S
return x, map(base_ring(x), y)::Vector{S} # Julia needs help here
elseif U === T && length(y) != 0
return change_base_ring(parent(y[1]), x), y
else
error("Cannot promote to common type")
end
end

function Base.promote(x::Vector{S},
y::MatRingElem{T}) where {S <: NCRingElement,
T <: NCRingElement}
yy, xx = promote(y, x)
return xx, yy
end

*(x::MatRingElem, y::Vector) = *(promote(x, y)...)

*(x::Vector, y::MatRingElem) = *(promote(x, y)...)

###############################################################################
#
# Conformance test element generation
Expand Down
58 changes: 29 additions & 29 deletions src/Matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ end
#
###############################################################################

function *(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
function *(x::JuliaRingElement, y::MatElem{T}) where T <: NCRingElement
z = similar(y)
for i = 1:nrows(y)
for j = 1:ncols(y)
Expand All @@ -963,7 +963,7 @@ function *(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
return z
end

function *(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
function *(x::T, y::MatElem{T}) where {T <: NCRingElem}
z = similar(y)
for i = 1:nrows(y)
for j = 1:ncols(y)
Expand All @@ -973,7 +973,7 @@ function *(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
return z
end

function *(x::MatrixElem{T}, y::JuliaRingElement) where T <: NCRingElement
function *(x::MatElem{T}, y::JuliaRingElement) where T <: NCRingElement
z = similar(x)
for i = 1:nrows(x)
for j = 1:ncols(x)
Expand All @@ -983,7 +983,7 @@ function *(x::MatrixElem{T}, y::JuliaRingElement) where T <: NCRingElement
return z
end

function *(x::MatrixElem{T}, y::T) where {T <: NCRingElem}
function *(x::MatElem{T}, y::T) where {T <: NCRingElem}
z = similar(x)
for i = 1:nrows(x)
for j = 1:ncols(x)
Expand All @@ -993,7 +993,7 @@ function *(x::MatrixElem{T}, y::T) where {T <: NCRingElem}
return z
end

function +(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
function +(x::JuliaRingElement, y::MatElem{T}) where T <: NCRingElement
z = similar(y)
R = base_ring(y)
for i = 1:nrows(y)
Expand All @@ -1008,14 +1008,14 @@ function +(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
return z
end

+(x::MatrixElem{T}, y::JuliaRingElement) where T <: NCRingElement = y + x
+(x::MatElem{T}, y::JuliaRingElement) where T <: NCRingElement = y + x

@doc raw"""
+(x::NCRingElement, y::MatrixElem{<:NCRingElement})
+(x::NCRingElement, y::MatElem{<:NCRingElement})

Return $S(x) + y$ where $S$ is the parent of $y$.
"""
function +(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
function +(x::T, y::MatElem{T}) where {T <: NCRingElem}
z = similar(y)
for i = 1:nrows(y)
for j = 1:ncols(y)
Expand All @@ -1030,13 +1030,13 @@ function +(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
end

@doc raw"""
+(x::MatrixElem{<:NCRingElement}, y::NCRingElement)
+(x::MatElem{<:NCRingElement}, y::NCRingElement)

Return $x + S(y)$, where $S$ is the parent of $a$.
"""
+(x::MatrixElem{T}, y::T) where {T <: NCRingElem} = y + x
+(x::MatElem{T}, y::T) where {T <: NCRingElem} = y + x

function -(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
function -(x::JuliaRingElement, y::MatElem{T}) where T <: NCRingElement
z = similar(y)
R = base_ring(y)
for i = 1:nrows(y)
Expand All @@ -1051,7 +1051,7 @@ function -(x::JuliaRingElement, y::MatrixElem{T}) where T <: NCRingElement
return z
end

function -(x::MatrixElem{T}, y::JuliaRingElement) where T <: NCRingElement
function -(x::MatElem{T}, y::JuliaRingElement) where T <: NCRingElement
z = similar(x)
R = base_ring(x)
for i = 1:nrows(x)
Expand All @@ -1067,11 +1067,11 @@ function -(x::MatrixElem{T}, y::JuliaRingElement) where T <: NCRingElement
end

@doc raw"""
-(x::NCRingElement, y::MatrixElem{<:NCRingElement})
-(x::NCRingElement, y::MatElem{<:NCRingElement})

Return $S(x) - y$ where $S$ is the parent of $y$.
"""
function -(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
function -(x::T, y::MatElem{T}) where {T <: NCRingElem}
z = similar(y)
R = base_ring(y)
for i = 1:nrows(y)
Expand All @@ -1087,11 +1087,11 @@ function -(x::T, y::MatrixElem{T}) where {T <: NCRingElem}
end

@doc raw"""
-(x::MatrixElem{<:NCRingElem}, y::NCRingElement)
-(x::MatElem{<:NCRingElem}, y::NCRingElement)

Return $x - S(y)$, where $S$ is the parent of $a$.
"""
function -(x::MatrixElem{T}, y::T) where {T <: NCRingElem}
function -(x::MatElem{T}, y::T) where {T <: NCRingElem}
z = similar(x)
R = base_ring(x)
for i = 1:nrows(x)
Expand Down Expand Up @@ -1123,7 +1123,7 @@ function mul!(z::Vector{T}, x::MatrixElem{T}, y::Vector{T}) where T <: NCRingEle
return z
end

function *(x::MatrixElem{T}, y::Vector{T}) where T <: NCRingElement
function *(x::MatElem{T}, y::Vector{T}) where T <: NCRingElement
ncols(x) == length(y) || error("Incompatible dimensions")
return mul!(T[base_ring(x)() for i in 1:nrows(x)], x, y)
end
Expand All @@ -1145,7 +1145,7 @@ function mul!(z::Vector{T}, x::Vector{T}, y::MatrixElem{T}) where T <: NCRingEle
return z
end

function *(x::Vector{T}, y::MatrixElem{T}) where T <: NCRingElement
function *(x::Vector{T}, y::MatElem{T}) where T <: NCRingElement
length(x) == nrows(y) || error("Incompatible dimensions")
return mul!(T[base_ring(y)() for j in 1:ncols(y)], x, y)
end
Expand Down Expand Up @@ -1175,9 +1175,9 @@ end
#
################################################################################

function Base.promote(x::MatrixElem{S},
y::MatrixElem{T}) where {S <: NCRingElement,
T <: NCRingElement}
function Base.promote(x::MatElem{S},
y::MatElem{T}) where {S <: NCRingElement,
T <: NCRingElement}
U = promote_rule_sym(S, T)
if U === S
return x, change_base_ring(base_ring(x), y)
Expand All @@ -1197,7 +1197,7 @@ end
==(x::MatElem, y::MatElem) = ==(promote(x, y)...)

# matrix * vec and vec * matrx
function Base.promote(x::MatrixElem{S},
function Base.promote(x::MatElem{S},
y::Vector{T}) where {S <: NCRingElement,
T <: NCRingElement}
U = promote_rule_sym(S, T)
Expand All @@ -1211,15 +1211,15 @@ function Base.promote(x::MatrixElem{S},
end

function Base.promote(x::Vector{S},
y::MatrixElem{T}) where {S <: NCRingElement,
y::MatElem{T}) where {S <: NCRingElement,
T <: NCRingElement}
yy, xx = promote(y, x)
return xx, yy
end

*(x::MatrixElem, y::Vector) = *(promote(x, y)...)
*(x::MatElem, y::Vector) = *(promote(x, y)...)

*(x::Vector, y::MatrixElem) = *(promote(x, y)...)
*(x::Vector, y::MatElem) = *(promote(x, y)...)

function Base.promote(x::MatElem{S}, y::T) where {S <: NCRingElement, T <: NCRingElement}
U = promote_rule_sym(S, T)
Expand Down Expand Up @@ -1306,13 +1306,13 @@ end
###############################################################################

@doc raw"""
==(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement}
==(x::MatElem{T}, y::MatElem{T}) where {T <: NCRingElement}

Return `true` if $x == y$ arithmetically, otherwise return `false`. Recall
that power series to different precisions may still be arithmetically
equal to the minimum of the two precisions.
"""
function ==(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement}
function ==(x::MatElem{T}, y::MatElem{T}) where {T <: NCRingElement}
b = check_parent(x, y, false)
!b && return false
for i = 1:nrows(x)
Expand All @@ -1326,14 +1326,14 @@ function ==(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement}
end

@doc raw"""
isequal(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement}
isequal(x::MatElem{T}, y::MatElem{T}) where {T <: NCRingElement}

Return `true` if $x == y$ exactly, otherwise return `false`. This function is
useful in cases where the entries of the matrices are inexact, e.g. power
series. Only if the power series are precisely the same, to the same precision,
are they declared equal by this function.
"""
function isequal(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement}
function isequal(x::MatElem{T}, y::MatElem{T}) where {T <: NCRingElement}
b = check_parent(x, y, false)
!b && return false
for i = 1:nrows(x)
Expand Down
11 changes: 11 additions & 0 deletions test/generic/MatRing-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1448,3 +1448,14 @@ end
@test v isa Vector{elem_type(M)}
@test all(x -> parent(x) == M, v)
end

@testset "Generic.MatRing.adhoc_equality" begin
# FIXME: may be removed, depending on how we decide to handle equality between MatRingElem and MatElem.
# Test equality comparison between MatRingElem & MatElem
R = matrix_ring(ZZ, 2)
M = R(matrix(ZZ, 2,2, [1,2,3,4]))
@test M == matrix(M)
@test matrix(M) == M
@test M == matrix(QQ, M)
@test matrix(QQ, M) == M
end
Loading