ujmp / universal-java-matrix-package

A Java Library for sparse and dense matrices, linear algebra, visualization and big data
https://ujmp.org
GNU Lesser General Public License v3.0
111 stars 23 forks source link

API design #16

Open ghost opened 7 years ago

ghost commented 7 years ago

When using matrices and, in particular, large matrices, it seems like a strange API design choice to use something like:

Matrix transpose = dense.transpose(); // does this copy or is it just a view? What if dense is 1e7 x 1e7?

instead of something like:

Matrix transposeView = dense.getTransposeView(); Matrix transpose=transposeView.copy();

It's often the case that one is looping and say multiplying matrices. In this case something like:

Matrix A=createDense(m,n); for(;;) { UJM.mult(A, m1, m2); // A :=m1 x m2 // ... }

If you have to malloc and free (or at least manage a massive heap) every iteration it will impact the perf quite a bit.

Not really a classic issue but one reason I didn't use UJM, although I was quite interested in the long dim support. Interested to know why you choose this design. Cheers!

holger-arndt commented 7 years ago

You can call the method matrix.transpose(Ret.LINK) to get a view which will avoid to create a full copy.

Actually I have been thinking about a larger refactoring, which would change the API in a way similar to the one that you suggested:

matrix.transpose().copy() -- Returns new matrix with result matrix.transpose().inplace() -- Source matrix will contain the result and original data is overwritten matrix.transpose().link() -- Calculation is performed when needed, no additional storage (like a view) matrix.transpose().storeIn(targetMatrix) -- Send result to an existing matrix, data will be overwritten.

I guess that should solve all the issues that you described. However, I don't know when I will find the time to implement all this, because that's really A LOT of code to be changed.

ghost commented 7 years ago

Right. Yes I can imagine how much you'd have to do.

One decision I made in my impl is to make the Matrix interface as small as possible so that new impls will be easier. The issues with that are: 1 how does one select the say multiplication impl if the underlying classes are different 2 I use UtilMatrix.create(n,m) so again the choice of impl is difficult.

I ended up implementing stock mult(), decompLU(), etc with a mechanism to change the impl to only one other one. Not ideal but it works.

Oh well, if it was easy, someone would have done it already! Good luck!