//------------------------------------------------------------------------------ // SPEX_LU/spex_left_lu_back_sub: sparse REF backward substitution (x = U\x) //------------------------------------------------------------------------------ // SPEX_LU: (c) 2019-2024, Christopher Lourenco, Jinhao Chen,, // Erick Moreno-Centeno, and Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0-or-later or LGPL-3.0-or-later //------------------------------------------------------------------------------ /* Purpose: This function performs sparse REF backward substitution, solving * the system Ux = b. Note that prior to this, x is multiplied by * the determinant of A. * * U is a sparse mpz matrix, and bx is a dense mpz matrix. The diagonal entry * of U must appear as the last entry in each column. * * The input argument bx contains b on input, and it is overwritten on output * by the solution x. */ #include "spex_lu_internal.h" SPEX_info spex_left_lu_back_sub // performs sparse REF backward substitution ( const SPEX_matrix U, // input upper triangular matrix SPEX_matrix bx // right hand side matrix ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- SPEX_info info ; SPEX_REQUIRE (U, SPEX_CSC, SPEX_MPZ); SPEX_REQUIRE (bx, SPEX_DENSE, SPEX_MPZ); //-------------------------------------------------------------------------- int sgn; mpz_t *Ux = U->x.mpz; int64_t *Ui = U->i; int64_t *Up = U->p; for (int64_t k = 0; k < bx->n; k++) { // Start at bx[n] for (int64_t j = U->n-1; j >= 0; j--) { // If bx[j] is zero skip this iteration SPEX_MPZ_SGN(&sgn, SPEX_2D( bx, j, k, mpz)); if (sgn == 0) {continue;} // Obtain bx[j] SPEX_MPZ_DIVEXACT(SPEX_2D(bx, j, k, mpz), SPEX_2D(bx, j, k, mpz), Ux[Up[j+1]-1]); for (int64_t i = Up[j]; i < Up[j+1]-1; i++) { SPEX_MPZ_SGN(&sgn, Ux[i]); if (sgn == 0) {continue;} // bx[i] = bx[i] - Ux[i]*bx[j] SPEX_MPZ_SUBMUL(SPEX_2D(bx, Ui[i], k, mpz), Ux[i], SPEX_2D(bx, j, k, mpz)); } } } return (SPEX_OK); }