Skip to content

Array conversion from banded matrices might be inconsistent #1221

Open
@jishnub

Description

@jishnub

Using the example from the special tests:

struct TypeWithoutZero end
struct TypeWithZero end
Base.promote_rule(::Type{TypeWithoutZero}, ::Type{TypeWithZero}) = TypeWithZero
Base.convert(::Type{TypeWithZero}, ::TypeWithoutZero) = TypeWithZero()
Base.zero(x::Union{TypeWithoutZero, TypeWithZero}) = zero(typeof(x))
Base.zero(::Type{<:Union{TypeWithoutZero, TypeWithZero}}) = TypeWithZero()
LinearAlgebra.symmetric(::TypeWithoutZero, ::Symbol) = TypeWithoutZero()
LinearAlgebra.symmetric_type(::Type{TypeWithoutZero}) = TypeWithoutZero
Base.copy(A::TypeWithoutZero) = A
Base.transpose(::TypeWithoutZero) = TypeWithoutZero()
d  = fill(TypeWithoutZero(), 3)
D  = Diagonal(d)

With this,

julia> D
3×3 Diagonal{TypeWithoutZero, Vector{TypeWithoutZero}}:
 TypeWithoutZero()                                 
                   TypeWithoutZero()               
                                     TypeWithoutZero()

julia> Array(D) # doesn't preserve diagonal elements
3×3 Matrix{TypeWithZero}:
 TypeWithZero()  TypeWithZero()  TypeWithZero()
 TypeWithZero()  TypeWithZero()  TypeWithZero()
 TypeWithZero()  TypeWithZero()  TypeWithZero()

julia> [x for x in D] # preserves diagonal elements
3×3 Matrix{Any}:
 TypeWithoutZero()  TypeWithZero()     TypeWithZero()
 TypeWithZero()     TypeWithoutZero()  TypeWithZero()
 TypeWithZero()     TypeWithZero()     TypeWithoutZero()

julia> collect(D) # perhaps a missing method
ERROR: MethodError: Cannot `convert` an object of type TypeWithZero to an object of type TypeWithoutZero
The function `convert` exists, but no method is defined for this combination of argument types.

The Array constructor was added in JuliaLang/julia#44707 to address a breakage in JuMP, but these should probably be consistent? In particular, it seems odd that the diagonal elements are not preserved by the Array constructor, and that

julia> Array(D) == D
false

Perhaps the eltype of the Array should be a Union in this case, instead of being concrete?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions