Exemple #1
0
void SparseMat::solve_upper_triangle(const DoubleVec &rhs, DoubleVec &x)
  const
{
  // Solve an upper triangular matrix with explicit diagonal elements.
  // rhs and x can be the same vector.
  assert(is_upper_triangular(true));
  
  // x_i = (1/U_ii) (rhs_i - \sum_{n=i+1}^M U_in x_n )
  // rowno must be an int, not an unsigned int, or else rowno>=0 will
  // always be true.
  for(int rowno=int(rhs.size())-1; rowno>=0; rowno--) {
    const_row_iterator ij=begin(rowno);
    double diagterm = *ij;
    if(ij.row() != ij.col() || diagterm == 0.0)
      throw ErrSetupError("Zero divisor in solve_upper_triangle!");
    double sum = rhs[rowno];
    for(++ij; ij<end(rowno); ++ij)
      sum -= (*ij)*x[ij.col()];
    x[rowno] = sum/diagterm;
  }
}
Exemple #2
0
void SparseMat::solve_upper_triangle_trans(const DoubleVec &rhs,
					       DoubleVec &x) const
{
  // Solve the transpose of an upper triangular matrix with explicit
  // diagonal elements.  rhs and x can be the same vector.
  assert(is_upper_triangular(true));

  // x_i = (1/U_ii) (rhs_i - \sum_{j=0}^{i-1} U_ji x_j)

  // Copy rhs into x. This does all of the rhs_i terms.
  if(&x[0] != &rhs[0])
    x = rhs;
  for(unsigned int i=0; i<x.size(); i++) {
    const_row_iterator ji=begin(i); // loop over i^th col of the transpose
    // We're already done with the sums for x_i.
    if(ji.row() != ji.col() || *ji == 0.0)
      throw ErrSetupError("Zero divisor in solve_upper_triangle_trans!");
    x[i] /= *ji; 		// divide by the diagonal
    // Accumulate contributions to later x[i]'s.
    for(++ji; ji<end(i); ++ji)
      x[ji.col()] -= (*ji) * x[i];
  }
}
Exemple #3
0
void inv(A&& a, C&& c) {
    // The inverse of a permutation matrix is its transpose
    if (is_permutation_matrix(a)) {
        c = transpose(a);
        return;
    }

    const auto n = etl::dim<0>(a);

    // Use forward propagation for lower triangular matrix
    if (is_lower_triangular(a)) {
        c = 0;

        // The column in c
        for (size_t s = 0; s < n; ++s) {
            // The row in a
            for (size_t row = 0; row < n; ++row) {
                auto b = row == s ? 1.0 : 0.0;

                if (row == 0) {
                    c(0, s) = b / a(0, 0);
                } else {
                    value_t<A> acc(0);

                    // The column in a
                    for (size_t col = 0; col < row; ++col) {
                        acc += a(row, col) * c(col, s);
                    }

                    c(row, s) = (b - acc) / a(row, row);
                }
            }
        }

        return;
    }

    // Use backward propagation for upper triangular matrix
    if (is_upper_triangular(a)) {
        c = 0;

        // The column in c
        for (int64_t s = n - 1; s >= 0; --s) {
            // The row in a
            for (int64_t row = n - 1; row >= 0; --row) {
                auto b = row == s ? 1.0 : 0.0;

                if (row == int64_t(n) - 1) {
                    c(row, s) = b / a(row, row);
                } else {
                    value_t<A> acc(0);

                    // The column in a
                    for (int64_t col = n - 1; col > row; --col) {
                        acc += a(row, col) * c(col, s);
                    }

                    c(row, s) = (b - acc) / a(row, row);
                }
            }
        }

        return;
    }

    auto L = force_temporary_dim_only(a);
    auto U = force_temporary_dim_only(a);
    auto P = force_temporary_dim_only(a);

    etl::lu(a, L, U, P);

    c = inv(U) * inv(L) * P;
}