Description
In response to #258, the bug was traced to mean
which relies on similar
(through reducedim) to prepare an array for its output, e.g. mean
of a 4x3 matrix along dim 1 should yield a 1x3. It ends up calling something like similar(triangularmatrix, LowerTriangular, (1,3))
(the template matrix, the desired type, and the dimensions), which fails because a 1x3 triangular matrix doesn't make sense. In this context, similar
means "give me a matrix with the same eltype" not "give me another triangular just like this one."
- An easy fix (@tkelman) is to adjust
similar
so that when optional dimensions are used, it automatically drops the triangular, which results in AbstractMatrix. When no dimension is given, it could yield a lower triangular. This actually works, and even preserves sparsity automatically. I find this a bit yucky, because the return type depends implicitly on how the call is made. - Another fix is to change
similar
to always drop the triangular, again preserving sparsity where applicable. I've tried this fix and it doesn't break any existing tests (other than needing a new test forsimilar
). Downside is it is a potentially breaking change for user code wheresimilar
is intended to mean "give me another of same structure." Yucky as well. - Yet another possibility is to delve into the details of how
similar
is called and root out the problem at the level of reducedim. Where appropriate, it could be replaced bysameeltype
, meaning a more explicit version of what is meant already. In other cases, the replacement might besamecontainer
orsamestructure
or some such. Idea is to make explicit what you really want. This seems like a longer term solution, becausesimilar
occurs 600+ times in julia project (between method calls and definitions) and it may not be straightforward to know what is intended when.
Previous discussions have complained about similar
JuliaLang/julia#11574 (comment) and JuliaLang/julia#10064. The problem is that similar
is vague. Present docs say that behavior for special types should be decided case by case. Right now similar
for triangulars is undocumented, so the user must guess or look at the source code. Might be better to clarify and perhaps split off a sameeltype
or samestructure
in the long run.
There are safe, conservative ways to do option 2, such as when triangular is input, to return a matrix that's not triangular but whose off-triangle has been zeroed. This makes it safe for the user expecting a triangular back and for the most part won't blow up on them. (Triangulars store a full matrix in their .data field, so there is potential danger if things are not zeroed.)
What is the right solution?