Double dispatch was the wrong term. I should have said double argument polymorphism. Double dispatch is a sub-optimal answer to the problem of double polymorphism.
Apologies for polluting the discussion with a silly error. On Fri, Jul 1, 2011 at 2:35 PM, Greg Sterijevski <gsterijev...@gmail.com>wrote: > Ted, > > I am not sure why you think there will be double dispatch. If we remove the > multiplication method from the interface then there can only be one call to > multiply. If we want to keep the interface as is and also have a MatrixOps > class, then perhaps that is where we might have such a case. I am either > for > the status quo, or the elimination of the operations I noted in my feature > request. Supporting both would be a disaster... > > My request stems from attempting to build a SymmetricRealMatrix which > stores > its contents in a packed format. I began implementing multiply and so forth > and did not relish having a bunch of case statements. This lead me to the > idea of removing all operations involving other matrices to a separate > class. > > I am not clear about why using java's type system is such a bad thing. A > diagonal is different from a symmetric. Both fall under the "is a" > condition. Each is an example of a matrix-but different enough to merit its > own class. > > As for the second "MatrixOps" class. The utility of such a class is that > the > multiply routine is added when there is a need for it. I may have > GregsZigZagMatrix, whose only user is Greg. If I only multiply > GregsZigZagMatrix matrix with a diagonal, then that's the only method we > would implement. In the current schema, I would need to either support all > existing matrix patterns, support a few and throw exceptions on others, or > have a default case which is unoptimized and uses the element getter > method. > > > I will look at Mahout's solution for this. I guess a better question to the > list would have been: "What is the best way to implement a symmetric matrix > where only the lower (or upper) triangular portion is kept?" > > Thank you, > > -Greg > > > On Fri, Jul 1, 2011 at 12:45 PM, Ted Dunning <ted.dunn...@gmail.com> > wrote: > > > Getting double dispatch this way leads to a pretty ugly API interface. > > > > There is no reason why Matrix.times can't delegate to > MatrixOp.times(this, > > other), though. That gives you your double dispatch. > > > > The real problem with this design is that adding a new matrix type is no > > longer something that a user can do and all of your dispatch almost has > to > > be done based on Java type structure. That isn't really what you want. > In > > Mahout, for instance, we have a fair bit of special purpose code that > uses > > special indicator methods like isSparse(). In retrospect, I think we > might > > have missed a bet and should have used indicator interfaces instead, but > > the > > differences aren't huge. > > > > The cost is that most of our cleverness lives in AbstractMatrix in the > form > > of cascaded if statements rather than nice stylish polymorphism. This > > design does, however, allow user written classes to add a layer of their > > own > > special casing before delegating to the super class. > > > > The question of whether users ever really need to write their own matrix > > class is difficult to answer. In Mahout, the answer was thought to be > no, > > because users hadn't. On the other hand, now that users can, they do. > > This > > is partly because Mahout lives on the edge of new parallel paradigms and > > users need to experiment a lot to get things right before contributing > > back. > > I suspect that they same is true of Commons Math, just on a longer time > > scale. The needs for experimentation are less dire than with Mahout, but > > the pace of change is also glacial. In my mind, this leads to a similar > > ratio of need / change-rate and may indicate that a similar solution > would > > be a good idea. > > > > On Fri, Jul 1, 2011 at 7:36 AM, Greg Sterijevski <gsterijev...@gmail.com > > >wrote: > > > > > Hello All, > > > > > > Luc suggested that I move this discussion to the list. Luc posed the > > > question: > > > > > > "I don't understand how you intend to separate the API. > > > Would that mean users would always have to know beforehand the shape of > > the > > > matrix they use and manage both the matrix, the data store and the > > > operators > > > in sync ?" > > > > > > I think my longwinded report was not as clear as it should have been. I > > > want > > > to simplify the RealMatrix interface and implementing classes. In my > > mind's > > > eye, I see the real matrix interface as describing the shape of the > data, > > > holding that data and giving the user an indexing scheme to get at an > > > element. > > > > > > My concern with the current interface is that if different shapes of > > > matrices are allowed (Diagonal, Symmetric, Triangular, Banded) the > matrix > > > manipulation routines (add, subtract, mult, ...) become very > complicated. > > > > > > In my proposal, I argue that we might have another class, say > > > MatrixOperations. > > > > > > It would have routines for Mutlitplication that depend on type. A small > > > subset of the interface might look like: > > > > > > public interface MatrixOpsIface{ > > > public SymmetricMatrix selfTimesTranspose( SymmetricMatrix sm ); > > > public SymmetricMatrix selfTimesTranspose( GeneralMatrix sm ); > > > public SymmetricMatrix sandwichProduct( SymmetricMatrix sm, > > > GeneralMatrix gm); > > > public SymmetricMatrix sandwichProduct( SymmetricMatrix sm, > > > SymmericMatrix sm2); > > > public SymmetricMatrix sandwichProduct( SymmetricMatrix sm, > > > SymmetricMatrix gm); > > > public GeneralMatrix multipy( DiagonalMatrix dm, GeneralMatrix gm); > > > public GeneralMatrix multiply( SymmetricMatrix sm, GeneralMatrix > gm); > > > public DiagonalMatrix multiply( DiagonalMatrix dm, DiagonalMatrix > dm); > > > } > > > > > > The benefit of doing this would be that you could write highly > optimized > > > multiplication routines dependent on the shape of the matrices. All of > > the > > > complexity would be handled by the compiler. The user would simply > > > instantiate the operations object (maybe these could be static > methods), > > > and > > > call multiply. Adding a new matrix shape would be require an two check > > ins, > > > the code for the new matrix as well as a new set of methods for > handling > > > multiplication, etc, with the other types. > > > > > > -Greg > > > > > >