int fmpz_mat_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_mat_t LU; long dim, *perm; int result; if (fmpz_mat_is_empty(A) || fmpz_mat_is_empty(B)) { fmpz_one(den); return 1; } dim = fmpz_mat_nrows(A); perm = _perm_init(dim); fmpz_mat_init_set(LU, A); result = (fmpz_mat_fflu(LU, den, perm, LU, 1) == dim); if (result) fmpz_mat_solve_fflu_precomp(X, perm, LU, B); else fmpz_zero(den); _perm_clear(perm); fmpz_mat_clear(LU); return result; }
void fmpz_mat_det_bareiss(fmpz_t det, const fmpz_mat_t A) { fmpz_mat_t tmp; if (A->r < 1) { fmpz_one(det); return; } fmpz_mat_init_set(tmp, A); _fmpz_mat_det_bareiss(det, tmp); fmpz_mat_clear(tmp); }
dgsl_mp_t *dgsl_mp_init(const fmpz_mat_t B, mpfr_t sigma, mpfr_t *c, const dgsl_alg_t algorithm) { assert(mpfr_cmp_ui(sigma, 0) > 0); dgsl_mp_t *self = (dgsl_mp_t*)calloc(1, sizeof(dgsl_mp_t)); if(!self) dgs_die("out of memory"); dgsl_alg_t alg = algorithm; long m = fmpz_mat_nrows(B); long n = fmpz_mat_ncols(B); const mpfr_prec_t prec = mpfr_get_prec(sigma); fmpz_mat_init_set(self->B, B); self->c_z = _fmpz_vec_init(n); self->c = _mpfr_vec_init(n, prec); mpfr_init2(self->sigma, prec); mpfr_set(self->sigma, sigma, MPFR_RNDN); if (alg == DGSL_DETECT) { if (fmpz_mat_is_one(self->B)) { alg = DGSL_IDENTITY; } else if (_mpfr_vec_is_zero(c, n)) alg = DGSL_INLATTICE; else alg = DGSL_COSET; //TODO: we could test for lattice membership here } mpfr_t c_; mpfr_init2(c_, prec); size_t tau = 3; if (2*ceil(sqrt(log2((double)n))) > tau) tau = 2*ceil(sqrt(log2((double)n))); switch(alg) { case DGSL_IDENTITY: self->D = (dgs_disc_gauss_mp_t**)calloc(1, sizeof(dgs_disc_gauss_mp_t*)); mpfr_set_d(c_, 0.0, MPFR_RNDN); self->D[0] = dgs_disc_gauss_mp_init(self->sigma, c_, tau, DGS_DISC_GAUSS_DEFAULT); self->call = dgsl_mp_call_identity; break; case DGSL_INLATTICE: self->D = (dgs_disc_gauss_mp_t**)calloc(m, sizeof(dgs_disc_gauss_mp_t*)); if (c) _fmpz_vec_set_mpfr_vec(self->c_z, c, n); mpfr_mat_t G; mpfr_mat_init(G, m, n, prec); mpfr_mat_set_fmpz_mat(G, B); mpfr_mat_gso(G, MPFR_RNDN); mpfr_t sigma_; mpfr_init2(sigma_, prec); mpfr_t norm; mpfr_init2(norm, prec); mpfr_set_d(c_, 0.0, MPFR_RNDN); for(long i=0; i<m; i++) { _mpfr_vec_2norm(norm, G->rows[i], n, MPFR_RNDN); assert(mpfr_cmp_d(norm, 0.0) > 0); mpfr_div(sigma_, self->sigma, norm, MPFR_RNDN); assert(mpfr_cmp_d(sigma_, 0.0) > 0); self->D[i] = dgs_disc_gauss_mp_init(sigma_, c_, tau, DGS_DISC_GAUSS_DEFAULT); } mpfr_clear(sigma_); mpfr_clear(norm); mpfr_mat_clear(G); self->call = dgsl_mp_call_inlattice; break; case DGSL_COSET: mpfr_mat_init(self->G, m, n, prec); mpfr_mat_set_fmpz_mat(self->G, B); mpfr_mat_gso(self->G, MPFR_RNDN); self->call = dgsl_mp_call_coset; break; default: dgs_die("not implemented"); } mpfr_clear(c_); return self; }
DMat(const DMat<ACoeffRing>& M) : mRing(&M.ring()) { fmpz_mat_init_set(mArray, M.mArray); }
long fmpz_mat_nullspace(fmpz_mat_t res, const fmpz_mat_t mat) { long i, j, k, m, n, rank, nullity; long * pivots; long * nonpivots; fmpz_mat_t tmp; fmpz_t den; m = mat->r; n = mat->c; fmpz_mat_init_set(tmp, mat); fmpz_init(den); rank = fmpz_mat_rref(tmp, den, NULL, mat); nullity = n - rank; fmpz_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) fmpz_one(res->rows[i] + i); } else if (nullity) { pivots = flint_malloc(rank * sizeof(long)); nonpivots = flint_malloc(nullity * sizeof(long)); for (i = j = k = 0; i < rank; i++) { while (fmpz_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } fmpz_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) fmpz_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); fmpz_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } fmpz_clear(den); fmpz_mat_clear(tmp); return nullity; }