Advertisement
Guest User

Untitled

a guest
May 22nd, 2015
359
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.16 KB | None | 0 0
  1. #include <iostream>
  2. #include <sstream>
  3. #include <vector>
  4.  
  5. template <typename T> struct dense_traits;
  6. template <typename T> struct dense_traits<const T> : dense_traits<T> {};
  7. template <typename Parent, std::size_t M, std::size_t N> class Subview;
  8. template <typename Derived> class Densebase;
  9.  
  10. template <typename Derived>
  11. class Mathbase
  12. {
  13. public:
  14.   using T = typename dense_traits<Derived>::T;
  15.  
  16.   Derived& derived() { return static_cast<Derived&>(*this); }
  17.   const Derived& derived() const { return static_cast<const Derived&>(*this); }
  18.  
  19.   T& coeff(std::size_t row, std::size_t col) { return derived().coeff(row, col); }
  20.   const T& coeff(std::size_t row, std::size_t col) const { return derived().coeff(row, col); }
  21.   T& coeff(std::size_t index) { return derived().coeff(index); }
  22.   const T& coeff(std::size_t index) const { return derived().coeff(index); }
  23. };
  24.  
  25. template <typename Derived, std::size_t N>
  26. struct det_helper
  27. {
  28.   static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense)
  29.   {
  30.     typename dense_traits<Derived>::T det = 0;
  31.     // Laplace expansion
  32.     for (std::size_t i = 0; i < N; ++i)
  33.       det += ((i & 1) ? -1 : 1)*dense.coeff(0,i)*det_helper::run(dense.sub(0,i));
  34.  
  35.     return det;
  36.   }
  37. };
  38.  
  39. template <typename Derived>
  40. struct det_helper<Derived, 2>
  41. {
  42.   static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense)
  43.   {
  44.     return dense.coeff(0,0)*dense.coeff(1,1) - dense.coeff(0,1)*dense.coeff(1,0);
  45.   }
  46. };
  47.  
  48. template <typename Derived>
  49. class Densebase : public Mathbase<Derived>
  50. {
  51. public:
  52.   using base = Mathbase<Derived>;
  53.   using base::base;
  54.   using base::derived;
  55.   using base::coeff;
  56.   using typename base::T;
  57.  
  58.   using Submat = Subview<Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>;
  59.   using ConstSubmat = const Subview<const Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>;
  60.  
  61.   constexpr std::size_t rows() const { return derived().rows(); }
  62.   constexpr std::size_t cols() const { return derived().cols(); }
  63.  
  64.   constexpr std::size_t diagonalsize() const { return std::min(rows(), cols()); }
  65.  
  66.   T determinant() const
  67.   {
  68.     return det_helper<Derived, dense_traits<Derived>::M>::run(derived());
  69.   }
  70.  
  71.   Submat sub(std::size_t row, std::size_t col) { return Submat(derived(), row, col); }
  72.   ConstSubmat sub(std::size_t row, std::size_t col) const { return ConstSubmat(derived(), row, col); }
  73. };
  74.  
  75. template <typename T, std::size_t M, std::size_t N>
  76. class Matrix : public Densebase<Matrix<T,M,N>>
  77. {
  78. public:
  79.   Matrix() : data_(M*N) {}
  80.   Matrix(std::initializer_list<T> vals) : data_{vals} {}
  81.   virtual ~Matrix() {}
  82.  
  83.   T& coeff(std::size_t row, std::size_t col) { return data_[row*N + col]; }
  84.   T& coeff(std::size_t index) { return data_[index]; }
  85.  
  86.   const T& coeff(std::size_t row, std::size_t col) const { return data_[row*N + col]; }
  87.   const T& coeff(std::size_t index) const { return data_[index]; }
  88.  
  89.   constexpr std::size_t rows() const { return M; }
  90.   constexpr std::size_t cols() const { return N; }
  91.  
  92. private:
  93.   std::vector<T> data_;
  94. };
  95.  
  96. template <typename Parent, std::size_t M, std::size_t N>
  97. class Subview : public Densebase<Parent>
  98. {
  99. public:
  100.   using T = typename dense_traits<Parent>::T;
  101.  
  102.   Subview(Parent& parent, std::size_t iM, std::size_t iN) : parent_{parent}, iM_{iM}, iN_{iN} {}
  103.   T& coeff(std::size_t row, std::size_t col) { return parent_.coeff(row + (row >= iM_), col + (col >= iN_)); }
  104.   T& coeff(std::size_t index) { return parent_.coeff(index + (index >= iM_), index + (index >= iN_)); }
  105.  
  106.   const T& coeff(std::size_t row, std::size_t col) const { return parent_.coeff(row + (row >= iM_), col + (col >= iN_)); }
  107.   const T& coeff(std::size_t index) const { return parent_.coeff(index + (index >= iM_), index + (index >= iN_)); }
  108.  
  109.   constexpr std::size_t rows() const { return M; }
  110.   constexpr std::size_t cols() const { return N; }
  111.  
  112. private:
  113.   Parent& parent_;
  114.   std::size_t iM_, iN_;
  115. };
  116.  
  117. template <typename T_, std::size_t M_, std::size_t N_>
  118. struct dense_traits< Matrix<T_, M_, N_> >
  119. {
  120.   using T = T_;
  121.   enum { M = M_, N = N_ };
  122. };
  123.  
  124. template <typename Derived>
  125. inline std::ostream& operator<<(std::ostream& stream, const Densebase<Derived>& dense)
  126. {
  127.   unsigned int width = 0;
  128.   for (std::size_t i = 0; i < dense.cols(); ++i)
  129.     for (std::size_t j = 0; j < dense.rows(); ++j)
  130.     {
  131.       std::stringstream w; w.precision(3); w << std::fixed << dense.coeff(j,i);
  132.       width = std::max<unsigned int>(width, w.tellp());
  133.     }
  134.  
  135.   stream.precision(3);
  136.   stream.setf(std::ios::fixed);
  137.   for (std::size_t i = 0; i < dense.rows(); ++i)
  138.   {
  139.     stream << std::endl;
  140.     stream.width(width); stream << dense.coeff(i,0);
  141.     for (std::size_t j = 1; j < dense.cols(); ++j)
  142.     {
  143.       stream << ' ';
  144.       stream.width(width); stream << dense.coeff(i,j);
  145.     }
  146.   }
  147.  
  148.   return stream;
  149. }
  150.  
  151. int main(int argc, char* argv[])
  152. {
  153.  
  154.   Matrix<float, 3, 3> m { 2, 1, 2,
  155.                           2, 5, 4,
  156.                           5, 6, 1};
  157.  
  158.   auto t = m.sub(0,0);
  159.   std::cout << m.determinant();
  160.   t.coeff(0,0) = 10;
  161.   std::cout << m;
  162.   std::cout << t.coeff(1,0);
  163.   std::cout << m.sub(0,0);
  164.  
  165.   return EXIT_SUCCESS;
  166. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement