Broadcasting like a Matrix

broadcast

#1

I have a custom type that behaves like an AbstractMatrix but cannot be <: AbstractMatrix. Is it possible in 0.6 to have it broadcast like a matrix?

Right now I get an error:

julia> immutable MyMatrix end

julia> Base.size(::MyMatrix) = (3,3)

julia> Base.IndexStyle(::Type{MyMatrix}) = Base.IndexCartesian()

julia> Base.getindex(::MyMatrix,k::Int,j::Int) = 5

julia> A=zeros(3,3);

julia> A .= MyMatrix()
ERROR: MethodError: Cannot `convert` an object of type MyMatrix to an object of type Float64
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Stacktrace:
 [1] setindex! at ./multidimensional.jl:247 [inlined]
 [2] macro expansion at ./broadcast.jl:152 [inlined]
 [3] macro expansion at ./simdloop.jl:72 [inlined]
 [4] macro expansion at ./broadcast.jl:0 [inlined]
 [5] _broadcast!(::Base.#identity, ::Array{Float64,2}, ::Tuple{Tuple{}}, ::Tuple{Tuple{}}, ::MyMatrix, ::Tuple{}, ::Type{Val{0}}, ::CartesianRange{CartesianIndex{2}}) at ./broadcast.jl:138
 [6] broadcast_c! at ./broadcast.jl:210 [inlined]
 [7] broadcast!(::Function, ::Array{Float64,2}, ::MyMatrix) at ./broadcast.jl:203

#2

Ah, I figured it out: you need to define a containertype and getindex for CartesianIndex:

julia> Base.getindex(A::MyMatrix,kj::CartesianIndex{2}) = A[kj[1],kj[2]]

julia> Base.Broadcast.containertype(::MyMatrix) = Array

julia> A .= MyMatrix()
3×3 Array{Float64,2}:
 5.0  5.0  5.0
 5.0  5.0  5.0
 5.0  5.0  5.0