Note that
BlockMatrix{S,TA<:AbstractMatrix{S},TB<:AbstractMatrix{S},TC<:
AbstractMatrix{S},TD<:AbstractMatrix{S}}
is a syntax that (1) has come to be called "triangular dispatch" and (2) is
not actually supported by julia yet, although neither does it throw an error.
It just won't always do what you think it will do.
There are more indirect strategies to achieve this; see one here:
http://docs.julialang.org/en/release-0.3/manual/faq/#how-should-i-declare-abstract-container-type-fields
(the part about the inner constructor).
--Tim
On Thursday, March 12, 2015 07:20:45 PM Greg Plowman wrote:
> I don't really understand how this works, but this might point someone in
> the right direction.
> It seems Julia can't fully infer types, in particular the element type S.
> So we get further if we give a hint:
>
> type BlockMatrix{S,TA<:AbstractMatrix{S},TB<:AbstractMatrix{S},TC<:
> AbstractMatrix{S},TD<:AbstractMatrix{S}} <: AbstractMatrix{S}
> A::TA
> B::TB
> C::TC
> D::TD
> end
>
> typealias Block{S} BlockMatrix{S,AbstractMatrix{S},AbstractMatrix{S},
> AbstractMatrix{S},AbstractMatrix{S}}
>
> # not really sure what size() should be, but need to define for output
> Base.size(x::BlockMatrix) = (size(x.A,1) + size(x.C,1), size(x.A,2) + size(x
> .B,2))
>
> N = Block{Float64}(A,A,A,B)
>
>
> julia> N.A
> 4x4 Array{Float64,2}:
> 0.805914 0.473687 0.721984 0.464178
> 0.306 0.728015 0.148804 0.776728
> 0.439048 0.566558 0.72709 0.524761
> 0.255731 0.16528 0.331941 0.167353
> julia> N.B
> 4x4 Array{Float64,2}:
> 0.805914 0.473687 0.721984 0.464178
> 0.306 0.728015 0.148804 0.776728
> 0.439048 0.566558 0.72709 0.524761
> 0.255731 0.16528 0.331941 0.167353
> julia> N.C
> 4x4 Array{Float64,2}:
> 0.805914 0.473687 0.721984 0.464178
> 0.306 0.728015 0.148804 0.776728
> 0.439048 0.566558 0.72709 0.524761
> 0.255731 0.16528 0.331941 0.167353
> julia> N.D
> 4x4 Diagonal{Float64}:
> 1.0 0.0 0.0 0.0
> 0.0 2.0 0.0 0.0
> 0.0 0.0 3.0 0.0
> 0.0 0.0 0.0 4.0
>
> On Friday, March 13, 2015 at 8:49:41 AM UTC+11, Gabriel Mitchell wrote:
> > @ggggg Sorry, I guess I didn't state my intent that clearly. While your
> > example does enforce the Matrix/eltype constraint that is only part of
> > what
> > I am after. Having a type parameter for each block is a main thing that I
> > am interested in. The reason is that I can write methods that dispatch on
> > those types. An example of such a method with an explicit 4-ary structure
> > would be
> >
> > #generic fallback
> > det(A::Matrix,B::Matrix,C::Matrix,D::Matrix) = det([A B; C D])
> >
> > #specialized method, should actually, check for A invertible, but you get
> > the idea
> > det(A::Diagonal,B::Diagonal,C::Diagonal,D::Diagonal) =
> > det(A)*det(D-C*inv(A)*B)
> >
> > #etc...
> >
> > In my applications there are at least a dozen situations where certain
> > block structure allow for significantly more efficient implementations
> > than
> > the generic fallback. One would like to make the calls to these methods
> > (det,inv,trace, and so on) with the normal 1-ary argument, that matrix M
> > itself. This would be possible if the type information of the blocks could
> > be read out of the type of M. I hope this clear up my motivation for the
> > above question.
> >
> > On Thursday, March 12, 2015 at 8:49:05 PM UTC+1, ggggg wrote:
> >> BlockMatrix only needs one type parameter to fully specify the type, so
> >> you should probably only use one type parameter. Like so:
> >>
> >> *type BlockMatrix{S} <: AbstractMatrix{S}*
> >>
> >>> * A::AbstractMatrix{S}*
> >>>
> >>> * B::AbstractMatrix{S}*
> >>>
> >>> * C::AbstractMatrix{S}*
> >>>
> >>> * D::AbstractMatrix{S}*
> >>>
> >>> *end*
> >>
> >> I'm sure someone else can explain in more detail why yours didn't work.