static void _update_aggregated_state_frechet_matrices( cross_site_ws_t csw, model_and_data_t m, nd_axis_struct *edge_axis, nd_axis_struct *trans_axis, const int *first_idx, const int *second_idx, slong prec) { arb_mat_t P, L, Q; arb_t rate; slong first_state, second_state; slong cat, trans_idx; slong state_count = model_and_data_state_count(m); slong edge_count = model_and_data_edge_count(m); slong rate_category_count = model_and_data_rate_category_count(m); arb_init(rate); arb_mat_init(P, state_count, state_count); arb_mat_init(L, state_count, state_count); arb_mat_init(Q, state_count, state_count); /* set entries of L to the requested transition weights */ for (trans_idx = 0; trans_idx < trans_axis->n; trans_idx++) { first_state = first_idx[trans_idx]; second_state = second_idx[trans_idx]; arb_add(arb_mat_entry(L, first_state, second_state), arb_mat_entry(L, first_state, second_state), trans_axis->agg_weights + trans_idx, prec); } /* multiply entries of L by the rate matrix entries */ arb_mat_mul_entrywise(L, L, csw->rate_matrix, prec); /* divide L by the global weight divisor */ arb_mat_scalar_div_arb(L, L, trans_axis->agg_weight_divisor, prec); for (cat = 0; cat < rate_category_count; cat++) { slong edge; const arb_struct * cat_rate = csw->rate_mix_rates + cat; for (edge = 0; edge < edge_count; edge++) { slong idx = m->edge_map->order[edge]; const arb_struct * edge_rate = csw->edge_rates + idx; arb_mat_struct *fmat; if (!edge_axis->request_update[edge]) continue; fmat = cross_site_ws_trans_frechet_matrix(csw, cat, idx); arb_mul(rate, edge_rate, cat_rate, prec); arb_mat_scalar_mul_arb(Q, csw->rate_matrix, rate, prec); _arb_mat_exp_frechet(P, fmat, Q, L, prec); } } arb_clear(rate); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(Q); }
void arb_mat_L2norm(arb_t out, const arb_mat_t in, slong prec) { int nrows = arb_mat_nrows(in); int ncols = arb_mat_ncols(in); arb_zero(out); for(int i = 0; i < nrows; i++) { for(int j = 0; j < ncols; j++) { arb_addmul(out, arb_mat_entry(in, i, j), arb_mat_entry(in, i, j), prec); } } arb_sqrtpos(out, out, prec); }
void arb_mat_sub(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) arb_sub(arb_mat_entry(res, i, j), arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j), prec); }
void arb_mat_randtest(arb_mat_t mat, flint_rand_t state, slong prec, slong mag_bits) { slong i, j; if (n_randint(state, 2)) for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) arb_randtest(arb_mat_entry(mat, i, j), state, prec, mag_bits); else for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) arb_randtest_precise(arb_mat_entry(mat, i, j), state, prec, mag_bits); }
void arb_mat_pow_ui(arb_mat_t B, const arb_mat_t A, ulong exp, slong prec) { slong d = arb_mat_nrows(A); if (exp <= 2 || d <= 1) { if (exp == 0 || d == 0) { arb_mat_one(B); } else if (d == 1) { arb_pow_ui(arb_mat_entry(B, 0, 0), arb_mat_entry(A, 0, 0), exp, prec); } else if (exp == 1) { arb_mat_set(B, A); } else if (exp == 2) { arb_mat_sqr(B, A, prec); } } else { arb_mat_t T, U; slong i; arb_mat_init(T, d, d); arb_mat_set(T, A); arb_mat_init(U, d, d); for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--) { arb_mat_sqr(U, T, prec); if (exp & (WORD(1) << i)) arb_mat_mul(T, U, A, prec); else arb_mat_swap(T, U); } arb_mat_swap(B, T); arb_mat_clear(T); arb_mat_clear(U); } }
int arb_mat_contains(const arb_mat_t mat1, const arb_mat_t mat2) { slong i, j; if ((arb_mat_nrows(mat1) != arb_mat_nrows(mat2)) || (arb_mat_ncols(mat1) != arb_mat_ncols(mat2))) return 0; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) if (!arb_contains(arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j))) return 0; return 1; }
void arb_mat_bound_inf_norm(mag_t b, const arb_mat_t A) { slong i, j, r, c; mag_t s, t; r = arb_mat_nrows(A); c = arb_mat_ncols(A); mag_zero(b); if (r == 0 || c == 0) return; mag_init(s); mag_init(t); for (i = 0; i < r; i++) { mag_zero(s); for (j = 0; j < c; j++) { arb_get_mag(t, arb_mat_entry(A, i, j)); mag_add(s, s, t); } mag_max(b, b, s); } mag_clear(s); mag_clear(t); }
void arb_mat_cholesky(arb_mat_t out, const arb_mat_t in, slong prec) { int nrows = arb_mat_nrows(in); for(int j = 0; j < nrows; j++) { for(int i = j; i < nrows; i++) { arb_set(arb_mat_entry(out, i, j), arb_mat_entry(in, i, j)); for(int k = 0; k < j; k++) { arb_submul(arb_mat_entry(out, i, j), arb_mat_entry(out, i, k), arb_mat_entry(out, j, k), prec); } if(i == j) { arb_sqrt(arb_mat_entry(out, i, j), arb_mat_entry(out, i, j), prec); } else { arb_div(arb_mat_entry(out, i, j), arb_mat_entry(out, i, j), arb_mat_entry(out, j, j), prec); } } } }
void arb_mat_zero(arb_mat_t mat) { slong i, j; for (i = 0; i < arb_mat_nrows(mat); i++) for (j = 0; j < arb_mat_ncols(mat); j++) arb_zero(arb_mat_entry(mat, i, j)); }
void arb_mat_set_exact(arb_mat_t A) { int nrows = arb_mat_nrows(A); int ncols = arb_mat_nrows(A); for(int i = 0; i < nrows; i++) { for(int j = 0; j < ncols; j++) { arb_set_exact(arb_mat_entry(A, i, j)); } } }
/* * Update the frechet matrix for each rate category and edge. * At this point the rate matrix has been normalized * to have zero row sums, but it has not been scaled * by the edge rate coefficients. * The frechet matrices must already have been initialized. */ static void _update_state_pair_frechet_matrices( cross_site_ws_t csw, model_and_data_t m, nd_axis_struct *edge_axis, slong first_state, slong second_state, slong prec) { arb_mat_t P, L, Q; slong cat; arb_t rate; slong state_count = model_and_data_state_count(m); slong edge_count = model_and_data_edge_count(m); slong rate_category_count = model_and_data_rate_category_count(m); arb_init(rate); arb_mat_init(P, state_count, state_count); arb_mat_init(L, state_count, state_count); arb_mat_init(Q, state_count, state_count); arb_set(arb_mat_entry(L, first_state, second_state), arb_mat_entry(csw->rate_matrix, first_state, second_state)); for (cat = 0; cat < rate_category_count; cat++) { slong edge; const arb_struct * cat_rate = csw->rate_mix_rates + cat; for (edge = 0; edge < edge_count; edge++) { slong idx = m->edge_map->order[edge]; const arb_struct * edge_rate = csw->edge_rates + idx; arb_mat_struct *fmat; if (!edge_axis->request_update[edge]) continue; fmat = cross_site_ws_trans_frechet_matrix(csw, cat, idx); arb_mul(rate, edge_rate, cat_rate, prec); arb_mat_scalar_mul_arb(Q, csw->rate_matrix, rate, prec); _arb_mat_exp_frechet(P, fmat, Q, L, prec); } } arb_clear(rate); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(Q); }
void arb_mat_ones(arb_mat_t mat) { slong R, C, i, j; R = arb_mat_nrows(mat); C = arb_mat_ncols(mat); for (i = 0; i < R; i++) for (j = 0; j < C; j++) arb_one(arb_mat_entry(mat, i, j)); }
void evaluate_site_frechet( arb_struct *lhood_scaled_edge_expectations, const arb_mat_struct *lhood_node_vectors, const arb_mat_struct *forward_edge_vectors, const arb_mat_struct *frechet_matrices, const csr_graph_t g, int *preorder, int node_count, int state_count, slong prec) { slong u, idx, state; arb_mat_t fvec; arb_mat_init(fvec, state_count, 1); for (u = 0; u < node_count; u++) { slong a = preorder[u]; slong start = g->indptr[a]; slong stop = g->indptr[a+1]; for (idx = start; idx < stop; idx++) { slong b = g->indices[idx]; const arb_mat_struct *lvec = lhood_node_vectors + b; const arb_mat_struct *evec = forward_edge_vectors + idx; arb_zero(lhood_scaled_edge_expectations + idx); arb_mat_mul(fvec, frechet_matrices + idx, lvec, prec); for (state = 0; state < state_count; state++) { arb_addmul(lhood_scaled_edge_expectations + idx, arb_mat_entry(fvec, state, 0), arb_mat_entry(evec, state, 0), prec); } } } arb_mat_clear(fvec); }
void arb_mat_set_round_fmpz_mat(arb_mat_t dest, const fmpz_mat_t src, slong prec) { slong i, j; if (arb_mat_ncols(dest) != 0) { for (i = 0; i < arb_mat_nrows(dest); i++) for (j = 0; j < arb_mat_ncols(dest); j++) arb_set_round_fmpz(arb_mat_entry(dest, i, j), fmpz_mat_entry(src, i, j), prec); } }
void arb_mat_trace(arb_t trace, const arb_mat_t mat, slong prec) { slong i; if (!arb_mat_is_square(mat)) { flint_printf("arb_mat_trace: a square matrix is required!\n"); abort(); } if (arb_mat_is_empty(mat)) { arb_zero(trace); return; } arb_set(trace, arb_mat_entry(mat, 0, 0)); for (i = 1; i < arb_mat_nrows(mat); i++) { arb_add(trace, trace, arb_mat_entry(mat, i, i), prec); } }
int arb_mat_is_triu(const arb_mat_t A) { slong i, j, n, m; n = arb_mat_nrows(A); m = arb_mat_ncols(A); for (i = 1; i < n; i++) for (j = 0; j < FLINT_MIN(i, m); j++) if (!arb_is_zero(arb_mat_entry(A, i, j))) return 0; return 1; }
void arb_mat_approx_solve_triu_classical(arb_mat_t X, const arb_mat_t U, const arb_mat_t B, int unit, slong prec) { slong i, j, n, m; arb_ptr tmp; arb_t s; n = U->r; m = B->c; arb_init(s); tmp = flint_malloc(sizeof(arb_struct) * n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = *arb_mat_entry(X, j, i); for (j = n - 1; j >= 0; j--) { arb_approx_dot(s, arb_mat_entry(B, j, i), 1, U->rows[j] + j + 1, 1, tmp + j + 1, 1, n - j - 1, prec); if (!unit) arb_approx_div(tmp + j, s, arb_mat_entry(U, j, j), prec); else arb_swap(tmp + j, s); } for (j = 0; j < n; j++) *arb_mat_entry(X, j, i) = tmp[j]; } flint_free(tmp); arb_clear(s); }
void arb_mat_print_sage_float(const arb_mat_t A) { int nrows = arb_mat_nrows(A); int ncols = arb_mat_ncols(A); printf("["); for(int j = 0; j < nrows; j++) { printf("["); for(int k = 0; k < ncols; k++) { double x = arf_get_d(arb_midref(arb_mat_entry(A, j, k)), ARF_RND_NEAR); printf("%e", x); if(k < nrows - 1) printf(", "); } printf("],\n"); } printf("]\n"); }
void arb_mat_mul_classical(arb_mat_t C, const arb_mat_t A, const arb_mat_t B, long prec) { long ar, ac, br, bc, i, j, k; ar = arb_mat_nrows(A); ac = arb_mat_ncols(A); br = arb_mat_nrows(B); bc = arb_mat_ncols(B); if (ac != br || ar != arb_mat_nrows(C) || bc != arb_mat_ncols(C)) { printf("arb_mat_mul: incompatible dimensions\n"); abort(); } if (br == 0) { arb_mat_zero(C); return; } if (A == C || B == C) { arb_mat_t T; arb_mat_init(T, ar, bc); arb_mat_mul(T, A, B, prec); arb_mat_swap(T, C); arb_mat_clear(T); return; } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { arb_mul(arb_mat_entry(C, i, j), arb_mat_entry(A, i, 0), arb_mat_entry(B, 0, j), prec); for (k = 1; k < br; k++) { arb_addmul(arb_mat_entry(C, i, j), arb_mat_entry(A, i, k), arb_mat_entry(B, k, j), prec); } } } }
void arb_mat_frobenius_norm(arb_t res, const arb_mat_t A, slong prec) { slong i, j, r, c; r = arb_mat_nrows(A); c = arb_mat_ncols(A); arb_zero(res); if (r == 0 || c == 0) return; for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { arb_srcptr x = arb_mat_entry(A, i, j); arb_addmul(res, x, x, prec); } } arb_sqrtpos(res, res, prec); }
int main() { slong iter; flint_rand_t state; flint_printf("lu...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { fmpq_mat_t Q; arb_mat_t A, LU, P, L, U, T; slong i, j, n, qbits, prec, *perm; int q_invertible, r_invertible; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(LU, n, n); arb_mat_init(P, n, n); arb_mat_init(L, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); perm = _perm_init(n); fmpq_mat_randtest(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu(perm, LU, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_lu(perm, LU, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); abort(); } prec *= 2; } } arb_mat_one(L); for (i = 0; i < n; i++) for (j = 0; j < i; j++) arb_set(arb_mat_entry(L, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) for (j = i; j < n; j++) arb_set(arb_mat_entry(U, i, j), arb_mat_entry(LU, i, j)); for (i = 0; i < n; i++) arb_one(arb_mat_entry(P, perm[i], i)); arb_mat_mul(T, P, L, prec); arb_mat_mul(T, T, U, prec); if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("LU = \n"); arb_mat_printd(LU, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("P*L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(LU); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(U); arb_mat_clear(T); _perm_clear(perm); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("ldl...."); fflush(stdout); flint_randinit(state); /* check special matrices */ { slong n; for (n = 1; n < 10; n++) { slong lprec; arb_mat_t L, A; arb_mat_init(L, n, n); arb_mat_init(A, n, n); for (lprec = 2; lprec < 10; lprec++) { int result; slong prec; prec = 1 << lprec; /* zero */ arb_mat_zero(A); result = arb_mat_ldl(L, A, prec); if (result) { flint_printf("FAIL (zero):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* negative identity */ arb_mat_one(A); arb_mat_neg(A, A); result = arb_mat_ldl(L, A, prec); if (result) { flint_printf("FAIL (negative identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } /* identity */ arb_mat_one(A); result = arb_mat_ldl(L, A, prec); if (!result || !arb_mat_equal(L, A)) { flint_printf("FAIL (identity):\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } arb_mat_clear(L); arb_mat_clear(A); } } for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { fmpq_mat_t Q; arb_mat_t A, L, D, U, T; slong n, qbits, prec; int q_invertible, r_invertible; n = n_randint(state, 8); qbits = 1 + n_randint(state, 100); prec = 2 + n_randint(state, 202); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(L, n, n); arb_mat_init(D, n, n); arb_mat_init(U, n, n); arb_mat_init(T, n, n); _fmpq_mat_randtest_positive_semidefinite(Q, state, qbits); q_invertible = fmpq_mat_is_invertible(Q); if (!q_invertible) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_ldl(L, A, prec); if (r_invertible) { flint_printf("FAIL: matrix is singular over Q but not over R\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); } } else { /* now this must converge */ while (1) { arb_mat_set_fmpq_mat(A, Q, prec); r_invertible = arb_mat_ldl(L, A, prec); if (r_invertible) { break; } else { if (prec > 10000) { flint_printf("FAIL: failed to converge at 10000 bits\n"); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); abort(); } prec *= 2; } } /* multiply out the decomposition */ { slong i; arb_mat_zero(D); arb_mat_transpose(U, L); for (i = 0; i < n; i++) { arb_set(arb_mat_entry(D, i, i), arb_mat_entry(L, i, i)); arb_one(arb_mat_entry(L, i, i)); arb_one(arb_mat_entry(U, i, i)); } arb_mat_mul(T, L, D, prec); arb_mat_mul(T, T, U, prec); } if (!arb_mat_contains_fmpq_mat(T, Q)) { flint_printf("FAIL (containment, iter = %wd)\n", iter); flint_printf("n = %wd, prec = %wd\n", n, prec); flint_printf("\n"); flint_printf("Q = \n"); fmpq_mat_print(Q); flint_printf("\n\n"); flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n"); flint_printf("L = \n"); arb_mat_printd(L, 15); flint_printf("\n\n"); flint_printf("U = \n"); arb_mat_printd(U, 15); flint_printf("\n\n"); flint_printf("L*U = \n"); arb_mat_printd(T, 15); flint_printf("\n\n"); abort(); } } fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(L); arb_mat_clear(D); arb_mat_clear(U); arb_mat_clear(T); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void arb_mat_solve_cho_precomp(arb_mat_t X, const arb_mat_t L, const arb_mat_t B, slong prec) { slong i, j, c, n, m; n = arb_mat_nrows(X); m = arb_mat_ncols(X); arb_mat_set(X, B); for (c = 0; c < m; c++) { /* solve Ly = b */ for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, i, j), arb_mat_entry(X, j, c), prec); } arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(L, i, i), prec); } /* solve Ux = y */ for (i = n - 1; i >= 0; i--) { for (j = i + 1; j < n; j++) { arb_submul(arb_mat_entry(X, i, c), arb_mat_entry(L, j, i), arb_mat_entry(X, j, c), prec); } arb_div(arb_mat_entry(X, i, c), arb_mat_entry(X, i, c), arb_mat_entry(L, i, i), prec); } } }
void arb_mat_inv_cho_precomp(arb_mat_t X, const arb_mat_t L, slong prec) { slong n; if (arb_mat_nrows(X) != arb_mat_nrows(L) || arb_mat_ncols(X) != arb_mat_ncols(L)) { flint_printf("arb_mat_inv_cho_precomp: incompatible dimensions\n"); abort(); } if (arb_mat_is_empty(L)) return; n = arb_mat_nrows(L); if (n == 1) { arb_inv(arb_mat_entry(X, 0, 0), arb_mat_entry(L, 0, 0), prec); _arb_sqr(arb_mat_entry(X, 0, 0), arb_mat_entry(X, 0, 0), prec); return; } if (X == L) { flint_printf("arb_mat_inv_cho_precomp: unsupported aliasing\n"); abort(); } /* invert a 2x2 or larger matrix given its L * L^T decomposition */ { slong i, j, k; arb_struct *s; arb_mat_zero(X); s = _arb_vec_init(n); for (i = 0; i < n; i++) { arb_inv(s + i, arb_mat_entry(L, i, i), prec); } for (j = n-1; j >= 0; j--) { for (i = j; i >= 0; i--) { if (i == j) { arb_set(arb_mat_entry(X, i, j), s + i); } else { arb_zero(arb_mat_entry(X, i, j)); } for (k = i + 1; k < n; k++) { arb_submul(arb_mat_entry(X, i, j), arb_mat_entry(L, k, i), arb_mat_entry(X, k, j), prec); } arb_div(arb_mat_entry(X, i, j), arb_mat_entry(X, i, j), arb_mat_entry(L, i, i), prec); arb_set(arb_mat_entry(X, j, i), arb_mat_entry(X, i, j)); } } _arb_vec_clear(s, n); } }
int arb_mat_jacobi(arb_mat_t D, arb_mat_t P, const arb_mat_t A, slong prec) { // // Given a d x d real symmetric matrix A, compute an orthogonal matrix // P and a diagonal D such that A = P D P^t = P D P^(-1). // // D should have already been initialized as a d x 1 matrix, and Pp // should have already been initialized as a d x d matrix. // // If the eigenvalues can be certified as unique, then a nonzero int is // returned, and the eigenvectors should have reasonable error bounds. If // the eigenvalues cannot be certified as unique, then some of the // eigenvectors will have infinite error radius. #define B(i,j) arb_mat_entry(B, i, j) #define D(i) arb_mat_entry(D, i, 0) #define P(i,j) arb_mat_entry(P, i, j) int dim = arb_mat_nrows(A); if(dim == 1) { arb_mat_set(D, A); arb_mat_one(P); return 0; } arb_mat_t B; arb_mat_init(B, dim, dim); arf_t * B1 = (arf_t*)malloc(dim * sizeof(arf_t)); arf_t * B2 = (arf_t*)malloc(dim * sizeof(arf_t)); arf_t * row_max = (arf_t*)malloc((dim - 1) * sizeof(arf_t)); int * row_max_indices = (int*)malloc((dim - 1) * sizeof(int)); for(int k = 0; k < dim; k++) { arf_init(B1[k]); arf_init(B2[k]); } for(int k = 0; k < dim - 1; k++) { arf_init(row_max[k]); } arf_t x1, x2; arf_init(x1); arf_init(x2); arf_t Gii, Gij, Gji, Gjj; arf_init(Gii); arf_init(Gij); arf_init(Gji); arf_init(Gjj); arb_mat_set(B, A); arb_mat_one(P); for(int i = 0; i < dim - 1; i++) { for(int j = i + 1; j < dim; j++) { arf_abs(x1, arb_midref(B(i,j))); if(arf_cmp(row_max[i], x1) < 0) { arf_set(row_max[i], x1); row_max_indices[i] = j; } } } int finished = 0; while(!finished) { arf_zero(x1); int i = 0; int j = 0; for(int k = 0; k < dim - 1; k++) { if(arf_cmp(x1, row_max[k]) < 0) { arf_set(x1, row_max[k]); i = k; } } j = row_max_indices[i]; slong bound = arf_abs_bound_lt_2exp_si(x1); if(bound < -prec * .9) { finished = 1; break; } else { //printf("%ld\n", arf_abs_bound_lt_2exp_si(x1)); //arb_mat_printd(B, 10); //printf("\n"); } arf_twobytwo_diag(Gii, Gij, arb_midref(B(i,i)), arb_midref(B(i,j)), arb_midref(B(j,j)), 2*prec); arf_neg(Gji, Gij); arf_set(Gjj, Gii); //printf("%d %d\n", i, j); //arf_printd(Gii, 100); //printf(" "); //arf_printd(Gij, 100); //printf("\n"); if(arf_is_zero(Gij)) { // If this happens, we're finished = 1; // not going to do any better break; // without increasing the precision. } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(B(i,k)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(B(j,k)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(B(i,k)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(B(j,k)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(B(i,k)), B1[k]); arf_set(arb_midref(B(j,k)), B2[k]); } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(B(k,i)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(B(k,j)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(B(k,i)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(B(k,j)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(B(k,i)), B1[k]); arf_set(arb_midref(B(k,j)), B2[k]); } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(P(k,i)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(P(k,j)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(P(k,i)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(P(k,j)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(P(k,i)), B1[k]); arf_set(arb_midref(P(k,j)), B2[k]); } if(i < dim - 1) arf_set_ui(row_max[i], 0); if(j < dim - 1) arf_set_ui(row_max[j], 0); // Update the max in any row where the maximum // was in a column that changed. for(int k = 0; k < dim - 1; k++) { if(row_max_indices[k] == j || row_max_indices[k] == i) { arf_abs(row_max[k], arb_midref(B(k,k+1))); row_max_indices[k] = k+1; for(int l = k+2; l < dim; l++) { arf_abs(x1, arb_midref(B(k,l))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = l; } } } } // Update the max in the ith row. for(int k = i + 1; k < dim; k++) { arf_abs(x1, arb_midref(B(i, k))); if(arf_cmp(row_max[i], x1) < 0) { arf_set(row_max[i], x1); row_max_indices[i] = k; } } // Update the max in the jth row. for(int k = j + 1; k < dim; k++) { arf_abs(x1, arb_midref(B(j, k))); if(arf_cmp(row_max[j], x1) < 0) { arf_set(row_max[j], x1); row_max_indices[j] = k; } } // Go through column i to see if any of // the new entries are larger than the // max of their row. for(int k = 0; k < i; k++) { if(k == dim) continue; arf_abs(x1, arb_midref(B(k, i))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = i; } } // And then column j. for(int k = 0; k < j; k++) { if(k == dim) continue; arf_abs(x1, arb_midref(B(k, j))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = j; } } } for(int k = 0; k < dim; k++) { arb_set(D(k), B(k,k)); arb_set_exact(D(k)); } // At this point we've done that diagonalization and all that remains is // to certify the correctness and compute error bounds. arb_mat_t e; arb_t error_norms[dim]; for(int k = 0; k < dim; k++) arb_init(error_norms[k]); arb_mat_init(e, dim, 1); arb_t z1, z2; arb_init(z1); arb_init(z2); for(int j = 0; j < dim; j++) { arb_mat_set(B, A); for(int k = 0; k < dim; k++) { arb_sub(B(k, k), B(k, k), D(j), prec); } for(int k = 0; k < dim; k++) { arb_set(arb_mat_entry(e, k, 0), P(k, j)); } arb_mat_L2norm(z2, e, prec); arb_mat_mul(e, B, e, prec); arb_mat_L2norm(error_norms[j], e, prec); arb_div(z2, error_norms[j], z2, prec); // and now z1 is an upper bound for the // error in the eigenvalue arb_add_error(D(j), z2); } int unique_eigenvalues = 1; for(int j = 0; j < dim; j++) { if(j == 0) { arb_sub(z1, D(j), D(1), prec); } else { arb_sub(z1, D(j), D(0), prec); } arb_get_abs_lbound_arf(x1, z1, prec); for(int k = 1; k < dim; k++) { if(k == j) continue; arb_sub(z1, D(j), D(k), prec); arb_get_abs_lbound_arf(x2, z1, prec); if(arf_cmp(x2, x1) < 0) { arf_set(x1, x2); } } if(arf_is_zero(x1)) { unique_eigenvalues = 0; } arb_div_arf(z1, error_norms[j], x1, prec); for(int k = 0; k < dim; k++) { arb_add_error(P(k, j), z1); } } arb_mat_clear(e); arb_clear(z1); arb_clear(z2); for(int k = 0; k < dim; k++) arb_clear(error_norms[k]); arf_clear(x1); arf_clear(x2); arb_mat_clear(B); for(int k = 0; k < dim; k++) { arf_clear(B1[k]); arf_clear(B2[k]); } for(int k = 0; k < dim - 1; k++) { arf_clear(row_max[k]); } arf_clear(Gii); arf_clear(Gij); arf_clear(Gji); arf_clear(Gjj); free(B1); free(B2); free(row_max); free(row_max_indices); if(unique_eigenvalues) return 0; else return 1; #undef B #undef D #undef P }
int main() { slong iter; flint_rand_t state; flint_printf("solve_tril...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++) { arb_mat_t A, X, B, Y; slong rows, cols, prec, i, j; int unit; prec = 2 + n_randint(state, 200); if (n_randint(state, 10) == 0) { rows = n_randint(state, 60); cols = n_randint(state, 60); } else { rows = n_randint(state, 10); cols = n_randint(state, 10); } unit = n_randint(state, 2); arb_mat_init(A, rows, rows); arb_mat_init(B, rows, cols); arb_mat_init(X, rows, cols); arb_mat_init(Y, rows, cols); arb_mat_randtest(A, state, prec, 10); arb_mat_randtest(X, state, prec, 10); arb_mat_randtest(Y, state, prec, 10); for (i = 0; i < rows; i++) { if (unit) arb_one(arb_mat_entry(A, i, i)); else arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); for (j = i + 1; j < rows; j++) arb_zero(arb_mat_entry(A, i, j)); } arb_mat_mul(B, A, X, prec); if (unit) /* check that diagonal entries are ignored */ { for (i = 0; i < rows; i++) arb_set_ui(arb_mat_entry(A, i, i), 1 + n_randint(state, 100)); } /* Check Y = A^(-1) * (A * X) = X */ arb_mat_solve_tril(Y, A, B, unit, prec); if (!arb_mat_overlaps(Y, X)) { flint_printf("FAIL\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } /* Check aliasing */ arb_mat_solve_tril(B, A, B, unit, prec); if (!arb_mat_equal(B, Y)) { flint_printf("FAIL (aliasing)\n"); flint_printf("A = \n"); arb_mat_printd(A, 10); flint_printf("\n\n"); flint_printf("B = \n"); arb_mat_printd(B, 10); flint_printf("\n\n"); flint_printf("X = \n"); arb_mat_printd(X, 10); flint_printf("\n\n"); flint_printf("Y = \n"); arb_mat_printd(Y, 10); flint_printf("\n\n"); flint_abort(); } arb_mat_clear(A); arb_mat_clear(B); arb_mat_clear(X); arb_mat_clear(Y); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void arb_mat_exp(arb_mat_t B, const arb_mat_t A, slong prec) { slong i, j, dim, wp, N, q, r; mag_t norm, err; arb_mat_t T; dim = arb_mat_nrows(A); if (dim != arb_mat_ncols(A)) { flint_printf("arb_mat_exp: a square matrix is required!\n"); abort(); } if (dim == 0) { return; } else if (dim == 1) { arb_exp(arb_mat_entry(B, 0, 0), arb_mat_entry(A, 0, 0), prec); return; } wp = prec + 3 * FLINT_BIT_COUNT(prec); mag_init(norm); mag_init(err); arb_mat_init(T, dim, dim); arb_mat_bound_inf_norm(norm, A); if (mag_is_zero(norm)) { arb_mat_one(B); } else { q = pow(wp, 0.25); /* wanted magnitude */ if (mag_cmp_2exp_si(norm, 2 * wp) > 0) /* too big */ r = 2 * wp; else if (mag_cmp_2exp_si(norm, -q) < 0) /* tiny, no need to reduce */ r = 0; else r = FLINT_MAX(0, q + MAG_EXP(norm)); /* reduce to magnitude 2^(-r) */ arb_mat_scalar_mul_2exp_si(T, A, -r); mag_mul_2exp_si(norm, norm, -r); N = _arb_mat_exp_choose_N(norm, wp); mag_exp_tail(err, norm, N); _arb_mat_exp_taylor(B, T, N, wp); for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) arb_add_error_mag(arb_mat_entry(B, i, j), err); for (i = 0; i < r; i++) { arb_mat_mul(T, B, B, wp); arb_mat_swap(T, B); } for (i = 0; i < dim; i++) for (j = 0; j < dim; j++) arb_set_round(arb_mat_entry(B, i, j), arb_mat_entry(B, i, j), prec); } mag_clear(norm); mag_clear(err); arb_mat_clear(T); }
void Lib_Arb_Mat_Set_Ui(ArbMatPtr A, int32_t i, int32_t j, int32_t u) { arb_set_ui ( arb_mat_entry ((arb_mat_struct*)A, i, j), u); }