Dukales

hh check

Nov 3rd, 2015
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.12 KB | None | 0 0
  1. #include <valarray>
  2. #include <vector>
  3. #include <utility>
  4. #include <valarray>
  5. #include <random>
  6.  
  7. #include <cmath>
  8. #include <cstddef>
  9. #include <cassert>
  10.  
  11. template< typename value_type >
  12. struct math
  13. {
  14.  
  15.     using size_type = std::size_t;
  16.    
  17.     size_type const dimension_;
  18.     value_type const & eps;
  19.    
  20.     value_type const zero = value_type(0);
  21.     value_type const one = value_type(1);
  22.    
  23. private :
  24.    
  25.     using vector = std::valarray< value_type >;
  26.     using matrix = std::vector< vector >;
  27.  
  28.     matrix matrix_;
  29.    
  30.     value_type
  31.     det(matrix & _matrix,
  32.         size_type const _dimension) // hottest function
  33.     { // calculates lower unit triangular matrix and upper triangular
  34.         assert(0 < _dimension);
  35.         value_type det_ = one;
  36.         for (size_type i = 0; i < _dimension; ++i) {
  37.             vector & mi_ = _matrix[i];
  38.             size_type pivot = i;
  39.             {
  40.                 using std::abs;
  41.                 value_type max_ = abs(mi_[i]);
  42.                 size_type j = i;
  43.                 while (++j < _dimension) {
  44.                     value_type y_ = abs(_matrix[j][i]);
  45.                     if (max_ < y_) {
  46.                         max_ = std::move(y_);
  47.                         pivot = j;
  48.                     }
  49.                 }
  50.                 if (!(eps < max_)) { // regular?
  51.                     return zero; // singular
  52.                 }
  53.             }
  54.             if (pivot != i) {
  55.                 det_ = -det_; // each permutation flips sign of det
  56.                 mi_.swap(_matrix[pivot]);
  57.             }
  58.             value_type const & dia_ = mi_[i];
  59.             det_ *= dia_; // det is multiple of diagonal elements
  60.             size_type j = i;
  61.             while (++j < _dimension) {
  62.                 vector & mj_ = _matrix[j];
  63.                 value_type & mji_ = mj_[i];
  64.                 mji_ /= dia_;
  65.                 size_type k = i;
  66.                 while (++k < _dimension) {
  67.                     mj_[k] -= mji_ * mi_[k];
  68.                 }
  69.             }
  70.         }
  71.         return det_;
  72.     }
  73.    
  74. public :
  75.  
  76.     math(size_type const _dimension,
  77.          value_type const & _eps)
  78.         : dimension_(_dimension)
  79.         , eps(_eps)
  80.         , matrix_(dimension_)
  81.     {
  82.         assert(1 < dimension_);
  83.         assert(!(eps < zero));
  84.         for (size_type r = 0; r < dimension_; ++r) {
  85.             matrix_[r].resize(dimension_);
  86.         }
  87.     }
  88.    
  89.     template< typename rhs = matrix >
  90.     void
  91.     operator = (rhs const & _rhs)
  92.     {
  93.         auto irow = std::begin(matrix_);
  94.         for (auto const & row_ : _rhs) {
  95.             auto icol = std::begin(*irow);
  96.             for (auto const & v : row_) {
  97.                 *icol = v;
  98.                 ++icol;
  99.             }
  100.             ++irow;
  101.         }
  102.     }
  103.    
  104.     template< typename output, typename input >
  105.     void
  106.     mul(output & _output, input const & _input) const
  107.     {
  108.         for (size_type i = 0; i < dimension_; ++i) {
  109.             for (size_type j = 0; j < dimension_; ++j) {
  110.                 value_type & result_ = _output[i][j];
  111.                 result_ = zero;
  112.                 for (size_type k = 0; k < dimension_; ++k) {
  113.                     result_ += _input[i][k] * matrix_[k][j];
  114.                 }
  115.             }
  116.         }
  117.     }
  118.  
  119.     value_type
  120.     det()
  121.     {
  122.         return det(matrix_, dimension_);
  123.     }
  124.    
  125.     template< typename output >
  126.     bool
  127.     orthonormalize(output & _output,
  128.                    size_type const _rank)
  129.     {
  130.         assert(!(dimension_ < _rank));
  131.         for (size_type i = 0; i < _rank; ++i) { // Householder transformation
  132.             value_type sum_ = zero;
  133.             vector & qri_ = matrix_[i];
  134.             for (size_type j = i; j < dimension_; ++j) {
  135.                 value_type const & qrij_ = qri_[j];
  136.                 sum_ += qrij_ * qrij_;
  137.             }
  138.             using std::sqrt;
  139.             value_type norm_ = sqrt(sum_);
  140.             if (!(eps < norm_)) {
  141.                 return false;
  142.             }
  143.             value_type & qrii_ = qri_[i];
  144.             if (qrii_ < zero) {
  145.                 qrii_ = -qrii_;
  146.             }
  147.             value_type const factor_ = sqrt(std::move(sum_) + norm_ * qrii_);
  148.             if (!(eps < factor_)) {
  149.                 return false;
  150.             }
  151.             qrii_ += std::move(norm_);
  152.             for (size_type k = i; k < dimension_; ++k) {
  153.                 qri_[k] /= factor_;
  154.             }
  155.             size_type j = i;
  156.             while (++j < _rank) {
  157.                 vector & qrj_ = matrix_[j];
  158.                 value_type s_ = zero;
  159.                 for (size_type k = i; k < dimension_; ++k) {
  160.                     s_ += qri_[k] * qrj_[k];
  161.                 }
  162.                 for (size_type k = i; k < dimension_; ++k) {
  163.                     qrj_[k] -= qri_[k] * s_;
  164.                 }
  165.             }
  166.         } // matrix_ is packed QR
  167.         for (size_type i = 0; i < _rank; ++i) {
  168.             vector & qi_ = _output[i];
  169.             qi_ = zero;
  170.             qi_[i] = one;
  171.             size_type j = _rank;
  172.             while (0 < j) {
  173.                 --j;
  174.                 vector const & qrj_ = matrix_[j]; // containing packed QR
  175.                 value_type s_ = zero;
  176.                 for (size_type k = j; k < dimension_; ++k) {
  177.                     s_ += qrj_[k] * qi_[k];
  178.                 }
  179.                 for (size_type k = j; k < dimension_; ++k) {
  180.                     qi_[k] -= qrj_[k] * s_;
  181.                 }
  182.             }
  183.         } // _output is Q
  184.         return true;
  185.     }
  186.    
  187.     template< typename output >
  188.     bool
  189.     orthonormalize(output & _output)
  190.     {
  191.         return orthonormalize(_output, dimension_);
  192.     }
  193.    
  194.     template< typename input >
  195.     void
  196.     matrix_transpose(input & _input)
  197.     {
  198.         for (size_type r = 0; r < dimension_; ++r) {
  199.             for (size_type c = 0; c < dimension_; ++c) {
  200.                 std::swap(_input[c][r], _input[r][c]);
  201.             }
  202.         }
  203.     }
  204.    
  205.     void
  206.     matrix_transpose()
  207.     {
  208.         return matrix_transpose(matrix_);
  209.     }
  210.  
  211.     template< typename output >
  212.     void
  213.     matrix_sqr(output & _output) const
  214.     {
  215.         for (size_type r = 0; r < dimension_; ++r) {
  216.             vector & lhs_ = _output[r];
  217.             vector const & row_ = matrix_[r];
  218.             for (size_type c = 0; c < dimension_; ++c) {
  219.                 lhs_[c] = std::inner_product(std::cbegin(row_), std::cend(row_), std::cbegin(matrix_[c]), zero);
  220.             }
  221.         }
  222.     }
  223.    
  224.     operator matrix const & () const
  225.     {
  226.         return matrix_;
  227.     }
  228.    
  229. };
  230.  
  231. // main.cpp
  232. #include <iostream>
  233.  
  234. #include <cstdlib>
  235.  
  236. using value_type = double;
  237. using vector = std::valarray< value_type >;
  238. using matrix = std::vector< vector >;
  239.  
  240. inline
  241. std::ostream &
  242. operator << (std::ostream & _out, matrix const & _matrix)
  243. {
  244.     for (vector const & vector_ : _matrix) {
  245.         for (value_type const & value_ : vector_) {
  246.             if (value_ < 10 * std::numeric_limits< value_type >::epsilon()) {
  247.                 _out << 0 << ' ';
  248.             } else {
  249.                 _out << value_ << ' ';
  250.             }
  251.         }
  252.         _out << std::endl;
  253.     }
  254.     return _out;
  255. }
  256.  
  257. int
  258. main()
  259. {
  260.     value_type const eps = std::numeric_limits< value_type >::epsilon();
  261.     std::size_t const dimension_ = 5;
  262.     math< value_type > m(dimension_, eps);    
  263.     std::random_device rd;
  264.     std::default_random_engine e(rd());
  265.     std::normal_distribution< value_type > d(m.one, m.one);
  266.     matrix input_;
  267.     input_.resize(dimension_);
  268.     for (vector & vector_ : input_) {
  269.         vector_.resize(dimension_);
  270.         for (value_type & value_ : vector_) {
  271.             value_ = d(e);
  272.         }
  273.     }
  274.     std::cout << "input = \n" << input_ << std::endl;
  275.     matrix output_;
  276.     output_.resize(dimension_);
  277.     for (vector & vector_ : output_) {
  278.         vector_.resize(dimension_, m.zero);
  279.     }
  280.     m = input_;
  281.     assert(m.orthonormalize(output_));
  282.     std::cout << "output = \n" << output_ << std::endl;
  283.     m = output_;
  284.     m.matrix_sqr(output_);
  285.     std::cout << "output = \n" << output_ << std::endl;
  286.     return EXIT_SUCCESS;
  287. }
Advertisement
Add Comment
Please, Sign In to add comment