tomstewart89 / BasicLinearAlgebra

A library for using matrices and linear algebra on Arduino
MIT License
187 stars 38 forks source link

Handling the Matrix<1,1> case #20

Closed zibrov-zlobin closed 6 years ago

zibrov-zlobin commented 6 years ago

Hi @tomstewart89, writing a generic MxN Kalman filter using your library I've encountered a problem with handling the cases when an MxN matrix is multiplied by added to a 1x1 Matrix.

do you have any pointers on how to implement fix or work around? thanks!

tomstewart89 commented 6 years ago

Hi @zibrov-zlobin,

That's awesome! A Kalman filter is one of the use cases I had in mind when I first wrote this library.

Regarding your problem, I seem to recall adding a method to cast a 1x1 matrix into its ElementType. Turns out that was a bad idea so I've since removed in the 2.3 release, can you make sure you're on this version?

Failing that, could you just attach some minimal example code to illustrate the problem?

Thanks!

zibrov-zlobin commented 6 years ago

I am using version 2.3.0. example code:

  BLA::Matrix<2, 2> A = {1, 1, 0, 1};
  BLA::Matrix<1, 1> x = {1};
  BLA::Matrix<2, 2> res;
  Multiply(A, x, res);

results in

kalmanFilter:23: error: no matching function for call to 'Multiply(BLA::Matrix<2, 2>&, BLA::Matrix<1, 1>&, BLA::Matrix<2, 2>&)'
   Multiply(A, x, res);
                     ^
/Users/shz/Documents/Arduino/kalmanFilter/kalmanFilter.ino:23:21: note: candidates are:
In file included from /Users/shz/Documents/Arduino/libraries/BasicLinearAlgebra/BasicLinearAlgebra.h:9:0,
                 from /Users/shz/Documents/Arduino/kalmanFilter/kalmanFilter.ino:1:
/Users/shz/Documents/Arduino/libraries/BasicLinearAlgebra/MemoryDelegate.hpp:47:61: note: template<int rows, int cols, int operandCols, class ElemT, class opElemT, class retElemT> BLA::Matrix<rows, operandCols, BLA::Array<rows, operandCols, retElemT> >& BLA::Multiply(const BLA::Matrix<rows, cols, BLA::Array<rows, cols, opElemT> >&, const BLA::Matrix<cols, operandCols, BLA::Array<cols, operandCols, opElemT> >&, BLA::Matrix<rows, operandCols, BLA::Array<rows, operandCols, retElemT> >&)
 Matrix<rows,operandCols,Array<rows,operandCols,retElemT> > &Multiply(const Matrix<rows,cols,Array<rows,cols,ElemT> > &A, const Matrix<cols,operandCols,Array<cols,operandCols,opElemT> > &B, Matrix<rows,operandCols,Array<rows,operandCols,retElemT> > &C)
                                                             ^
/Users/shz/Documents/Arduino/libraries/BasicLinearAlgebra/MemoryDelegate.hpp:47:61: note:   template argument deduction/substitution failed:
/Users/shz/Documents/Arduino/kalmanFilter/kalmanFilter.ino:23:21: note:   deduced conflicting values for non-type parameter 'cols' ('2' and '1')
   Multiply(A, x, res);
                     ^
In file included from /Users/shz/Documents/Arduino/kalmanFilter/kalmanFilter.ino:1:0:
/Users/shz/Documents/Arduino/libraries/BasicLinearAlgebra/BasicLinearAlgebra.h:312:35: note: template<int rows, int cols, int operandCols, class MemT, class opMemT, class retMemT> BLA::Matrix<rows, operandCols, retMemT>& BLA::Multiply(const BLA::Matrix<rows, cols, opMemT>&, const BLA::Matrix<cols, operandCols, opMemT>&, BLA::Matrix<rows, operandCols, retMemT>&)
 Matrix<rows,operandCols,retMemT> &Multiply(const Matrix<rows,cols,MemT> &A, const Matrix<cols,operandCols,opMemT> &B, Matrix<rows,operandCols,retMemT> &C)
                                   ^
/Users/shz/Documents/Arduino/libraries/BasicLinearAlgebra/BasicLinearAlgebra.h:312:35: note:   template argument deduction/substitution failed:
/Users/shz/Documents/Arduino/kalmanFilter/kalmanFilter.ino:23:21: note:   deduced conflicting values for non-type parameter 'cols' ('2' and '1')
   Multiply(A, x, res);
                     ^
exit status 1
no matching function for call to 'Multiply(BLA::Matrix<2, 2>&, BLA::Matrix<1, 1>&, BLA::Matrix<2, 2>&)'

thanks!

zibrov-zlobin commented 6 years ago

upd: I think I've tracked down an error in my code that resulted in a situation like the posted above, which at a second thought is somewhat artificial and should not appear.

tomstewart89 commented 6 years ago

Ok I see the problem. Basically Multiply does matrix multiplication so it expects the number of columns of A to match the number of rows of x. You might also be familiar with numpy which includes a feature called broadcasting which would do an elementwise multiplication of x on every element on A, but unfortunately this library doesn't support that (PRs are welcome though).

In the meantime if you'd like to do an elementwise multiplication on a BLA::Matrix you can just multiply it by an object of type ElementType. For example the following should work:

BLA::Matrix<2, 2> A = {1, 1, 0, 1};
BLA::Matrix<1, 1> x = {1};
BLA::Matrix<2, 2> res = A * x(0);

Hope that helps, I'll close this issue but if there's anything else feel free to reopen it.