jeudi 21 mai 2015

CRTP and Expression template Linear algebra

I'm trying to modify my linear algebra module to avoid the virtual vtable things.. Trying to use CRTP and expression template. I went with something basic that should test the whole thing, and I can't get it work.

I have 4 classes, say: The base CRTP class, here Mathbase

template <typename Derived>
class Mathbase
{
 public:
 using T = typename dense_traits<Derived>::T;

  Derived& derived() { return static_cast<Derived&>(*this); }
  const Derived& derived() const { return static_cast<const Derived&>(*this); }

  T& coeff(std::size_t row, std::size_t col) { return derived().coeff(row, col); }
  const T& coeff(std::size_t row, std::size_t col) const { return derived().coeff(row, col); }
  T& coeff(std::size_t index) { return derived().coeff(index); }
  const T& coeff(std::size_t index) const { return derived().coeff(index); }
};

Then, a Densebase in which I implements functions like transpose, determinant, etc:

template <typename Derived>
class Densebase : public Mathbase<Derived>
{
 public:

 using Submat = Subview<Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>;
 using ConstSubmat = const Subview<const Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>;

  Submat sub(std::size_t row, std::size_t col) { return Submat(derived(), row, col); }
  ConstSubmat sub(std::size_t row, std::size_t col) const { return ConstSubmat(derived(), row, col); }
};

Note that it declares two types that makes a references on a parent matrix (co-matrix) Then I have the Matrix class, that implements coeff functions by accessing its storage:

template <typename T, std::size_t M, std::size_t N>
class Matrix : public Densebase<Matrix<T,M,N>>
{
  // nothing fancy
};

Now, two things aren't working:

  • I implemented a determinant helper which uses laplace expansion (calculating co-matrix determinants and summing them up, sadly it failed to compile

    template <typename Derived, std::size_t N>
    struct det_helper
    {
       static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense)
       {
         typename dense_traits<Derived>::T det = 0;
         // Laplace expansion
         for (std::size_t i = 0; i < N; ++i)
           det += ((i & 1) ? -1 : 1)*dense.coeff(0,i)*det_helper::run(dense.sub(0,i));
    
         return det;
       }
     };
    
     template <typename Derived>
     struct det_helper<Derived, 2>
     {
       static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense)
       {
         return dense.coeff(0,0)*dense.coeff(1,1) - dense.coeff(0,1)*dense.coeff(1,0);
       }
     };
    
    

And called like this:

T determinant() const
{
  return det_helper<Derived, dense_traits<Derived>::M>::run(derived());
}

  • The 2nd problem is when I implemented an overload on << stream operator which works fine on Matrix but crash on stream << matrix.sub(0,0); without even entering in the function.

Aucun commentaire:

Enregistrer un commentaire