Checking for various Matrix types

I have a few related questions about checking for various matrix types to get Boolean values. Any help would be appreciated.
Q1) Suppose I have a function function f( ..., A ,...) where the type of A is unspecified. Inside the body of the function, I want to check whether A is a Matrix. But typeof(A) == AbstractMatrix does not work, for example

julia> A = rand(3,3);
julia> typeof(A)==AbstractMatrix
false

Q2) I also want to check for various formats, such as Diagonal or upper Triangular. But attempts similar to the following do not work.

julia> B = LowerTriangular(A)
3Ă—3 LowerTriangular{Float64,Array{Float64,2}}:
 0.660393     â‹…         â‹…
 0.00534751  0.697988   â‹…
 0.660567    0.967677  0.0742839
julia> typeof(B) == LowerTriangular
false

I have purposefully not mentioned the storage type, as it might not be known apriori in a code.

Somehting like that:

julia> typeof(A) <: AbstractMatrix
true

julia> typeof(B) <: LowerTriangular
true

help?> <:
search: <:

  <:(T1, T2)

  Subtype operator: returns true if and only if all values of type T1 are also of type T2.
3 Likes

You need to check for subtypes:

julia> rand(2,2) isa AbstractMatrix
true

julia> typeof(rand(2,2)) <: AbstractMatrix
true
7 Likes

If you’re envisioning the function looking something like

function matrixstuff(..., A, ...)
  if A isa LowerTriangular

  elseif A isa UpperTriangular

  elseif A isa ...

  ...

  else
    # generic thing for AbstractMatrix or whatever
  end
end

then you might also consider using dispatch, which is a nice code pattern:

function matrixstuff(..., A::LowerTriangular, ...)
  ... # now you can be sure that A is a LowerTriangular
end

function matrixstuff(..., A::UpperTriangular, ...)
  ... #ditto here for UpperTriangular
end

Organizing your code like that may have some nice benefits—the dispatch will automatically use the most specialized version of matrixstuff possible for the inputs, so it ostensibly takes at least a little pressure off of you to get type hierarchies right. It also is arguably cleaner in the sense that if you accidentally put an if A isa AbstractMatrix or something at the top of your long ifelse in the first form of the function, then you’d actually have unreachable branches, because many more specialized matrix types are subtypes of AbstractMatrix. That certainly doesn’t make anything wrong and maybe dispatching like this isn’t right for your problem. Just food for thought.

1 Like

@oheil @hendri54 @cgeoga Thanks a lot ! This is exactly what I was looking for.

1 Like