mzd_t *mzd_kernel_left_pluq(mzd_t *A, int const cutoff) { mzp_t *P = mzp_init(A->nrows); mzp_t *Q = mzp_init(A->ncols); rci_t r = mzd_pluq(A, P, Q, cutoff); if (r == A->ncols) { mzp_free(P); mzp_free(Q); __M4RI_DD_MZD(A); return NULL; } mzd_t *U = mzd_init_window(A, 0, 0, r, r); mzd_t *B = mzd_init_window(A, 0, r, r, A->ncols); mzd_trsm_upper_left(U, B, cutoff); mzd_t *R = mzd_init(A->ncols, A->ncols - r); mzd_t *RU = mzd_init_window(R, 0, 0, r, R->ncols); mzd_copy(RU, B); for(rci_t i = 0; i < R->ncols; ++i) { mzd_write_bit(R, r + i, i, 1); } mzd_apply_p_left_trans(R, Q); mzp_free(P); mzp_free(Q); mzd_free_window(RU); mzd_free_window(U); mzd_free_window(B); __M4RI_DD_MZD(A); __M4RI_DD_MZD(R); return R; }
int test_trsm_upper_left (int m, int n, int offsetU, int offsetB, const char *description) { printf("upper_left: %s m: %4d n: %4d offset: %4d ... ",description, m, n, offsetU); mzd_t* Ubase = mzd_init (2048,2048); mzd_t* Bbase = mzd_init (2048,2048); mzd_randomize (Ubase); mzd_randomize (Bbase); mzd_t* Bbasecopy = mzd_copy (NULL, Bbase); mzd_t* U = mzd_init_window (Ubase, 0, offsetU, m, offsetU + m); mzd_t* B = mzd_init_window (Bbase, 0, offsetB, m, offsetB + n); mzd_t* W = mzd_copy (NULL, B); size_t i,j; for (i=0; i<m; ++i){ for (j=0; j<i;++j) mzd_write_bit(U,i,j, 0); mzd_write_bit(U,i,i, 1); } mzd_trsm_upper_left(U, B, 2048); mzd_addmul(W, U, B, 2048); int status = 0; for ( i=0; i<m; ++i) for ( j=0; j<n; ++j){ if (mzd_read_bit (W,i,j)){ status = 1; } } // Verifiying that nothing has been changed around the submatrices mzd_addmul(W, U, B, 2048); mzd_copy (B, W); for ( i=0; i<2048; ++i) for ( j=0; j<2048/RADIX; ++j){ if (Bbase->rows[i][j] != Bbasecopy->rows[i][j]){ status = 1; } } mzd_free_window (U); mzd_free_window (B); mzd_free_window (W); mzd_free(Ubase); mzd_free(Bbase); mzd_free(Bbasecopy); if (!status) printf("passed\n"); else printf("FAILED\n"); return status; }
int _mzd_pluq_solve_left(mzd_t const *A, rci_t rank, mzp_t const *P, mzp_t const *Q, mzd_t *B, int const cutoff, int const inconsistency_check) { /** A is supposed to store L lower triangular and U upper triangular * B is modified in place * (Bi's in the comments are just modified versions of B) * PLUQ = A * 1) P B2 = B1 * 2) L B3 = B2 * 3) U B4 = B3 * 4) Q B5 = B4 */ int retval = 0; /* P B2 = B1 or B2 = P^T B1 */ mzd_apply_p_left(B, P); /* L B3 = B2 */ /* view on the upper part of L */ mzd_t const *LU = mzd_init_window_const(A, 0, 0, rank, rank); mzd_t *Y1 = mzd_init_window(B, 0, 0, rank, B->ncols); mzd_trsm_lower_left(LU, Y1, cutoff); if (inconsistency_check) { /* Check for inconsistency */ /** FASTER without this check; update with the lower part of L */ mzd_t const *H = mzd_init_window_const(A, rank, 0, A->nrows, rank); mzd_t *Y2 = mzd_init_window(B, rank, 0, A->nrows, B->ncols); if(A->nrows < B->nrows) { mzd_t *Y3 = mzd_init_window(B, A->nrows, 0, B->nrows, B->ncols); mzd_set_ui(Y3, 0); mzd_free_window(Y3); } mzd_addmul(Y2, H, Y1, cutoff); /* * test whether Y2 is the zero matrix */ if(!mzd_is_zero(Y2)) { retval = -1; } mzd_free_window((mzd_t*)H); mzd_free_window(Y2); } /* U B4 = B3 */ mzd_trsm_upper_left(LU, Y1, cutoff); mzd_free_window((mzd_t*)LU); mzd_free_window(Y1); if (!inconsistency_check) { /** Default is to set the undefined bits to zero if inconsistency * has been checked then Y2 bits are already all zeroes thus this * clearing is not needed */ for(rci_t i = rank; i < B->nrows; ++i) { for(rci_t j = 0; j < B->ncols; j += m4ri_radix) { mzd_clear_bits(B, i, j, MIN(m4ri_radix, B->ncols - j)); } } } /* Q B5 = B4 or B5 = Q^T B4 */ mzd_apply_p_left_trans(B, Q); /* P L U Q B5 = B1 */ __M4RI_DD_MZD(B); __M4RI_DD_INT(retval); return retval; }