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_lu(long * P, arb_mat_t LU, const arb_mat_t A, long prec) { arb_t d, e; arb_ptr * a; long i, j, m, n, r, row, col; int result; m = arb_mat_nrows(A); n = arb_mat_ncols(A); result = 1; if (m == 0 || n == 0) return result; arb_mat_set(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; arb_init(d); arb_init(e); while (row < m && col < n) { r = arb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) arb_mat_swap_rows(LU, P, row, r); arb_set(d, a[row] + col); for (j = row + 1; j < m; j++) { arb_div(e, a[j] + col, d, prec); arb_neg(e, e); _arb_vec_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); arb_zero(a[j] + col); arb_neg(a[j] + row, e); } row++; col++; } arb_clear(d); arb_clear(e); return result; }
/* Calculate the likelihood, storing many intermediate calculations. */ void evaluate_site_lhood(arb_t lhood, arb_mat_struct *lhood_node_vectors, arb_mat_struct *lhood_edge_vectors, const arb_mat_struct *base_node_vectors, const root_prior_t r, const arb_struct *equilibrium, const arb_mat_struct *transition_matrices, const csr_graph_struct *g, const int *preorder, int node_count, slong prec) { int u, a, b, idx; int start, stop; arb_mat_struct *nmat, *nmatb, *emat; const arb_mat_struct *tmat; for (u = 0; u < node_count; u++) { a = preorder[node_count - 1 - u]; nmat = lhood_node_vectors + a; start = g->indptr[a]; stop = g->indptr[a+1]; /* initialize the state vector for node a */ arb_mat_set(nmat, base_node_vectors + a); /* create all of the state vectors on edges outgoing from this node */ for (idx = start; idx < stop; idx++) { b = g->indices[idx]; /* * At this point (a, b) is an edge from node a to node b * in a post-order traversal of edges of the tree. */ tmat = transition_matrices + idx; nmatb = lhood_node_vectors + b; /* * Update vectors on edges if requested, * otherwise avoid using temporary vectors on edges. * In either case, lhood node vectors are updated. */ if (lhood_edge_vectors) { emat = lhood_edge_vectors + idx; _arb_mat_mul_stochastic(emat, tmat, nmatb, prec); arb_mat_mul_entrywise(nmat, nmat, emat, prec); } else { _prune_update_prob(nmat, nmat, tmat, nmatb, prec); } } } /* Report the sum of state entries associated with the root. */ int root_node_index = preorder[0]; nmat = lhood_node_vectors + root_node_index; root_prior_expectation(lhood, r, nmat, equilibrium, prec); }
void cross_site_ws_update_with_edge_rates(cross_site_ws_t w, const model_and_data_t m, const arb_struct *edge_rates, slong prec) { w->prec = prec; /* update rate mixture */ rate_mixture_summarize( w->rate_mix_prior, w->rate_mix_rates, w->rate_mix_expect, m->rate_mixture, prec); /* update the equilibrium if necessary, ignoring diagonal entries */ if (model_and_data_uses_equilibrium(m)) { _arb_vec_rate_matrix_equilibrium(w->equilibrium, m->mat, prec); } /* update the unscaled rate matrix, and zero the diagonal */ arb_mat_set(w->rate_matrix, m->mat); _arb_mat_zero_diagonal(w->rate_matrix); /* update the rate divisor, optionally using the equilibrium */ _update_rate_divisor(w, m, prec); /* * Scale the rate matrix according to the rate divisor. * Each rate matrix associated with a specific rate category * and branch will need to be further scaled. */ arb_mat_scalar_div_arb(w->rate_matrix, w->rate_matrix, w->rate_divisor, prec); /* update the diagonal of the rate matrix */ _arb_update_rate_matrix_diagonal(w->rate_matrix, prec); /* optionally set edge rates */ if (edge_rates) { _arb_vec_set(w->edge_rates, edge_rates, w->edge_count); } /* update the transition probability matrices */ _update_transition_matrices(w, prec); }
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); } } }
static int _spd_inv(arb_mat_t X, const arb_mat_t A, slong prec) { slong n; arb_mat_t L; int result; n = arb_mat_nrows(A); arb_mat_init(L, n, n); arb_mat_set(L, A); if (_arb_mat_ldl_inplace(L, prec)) { arb_mat_inv_ldl_precomp(X, L, prec); result = 1; } else { result = 0; } arb_mat_clear(L); return result; }
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 }
/* evaluates the truncated Taylor series (assumes no aliasing) */ void _arb_mat_exp_taylor(arb_mat_t S, const arb_mat_t A, slong N, slong prec) { if (N == 1) { arb_mat_one(S); } else if (N == 2) { arb_mat_one(S); arb_mat_add(S, S, A, prec); } else if (N == 3) { arb_mat_t T; arb_mat_init(T, arb_mat_nrows(A), arb_mat_nrows(A)); arb_mat_mul(T, A, A, prec); arb_mat_scalar_mul_2exp_si(T, T, -1); arb_mat_add(S, A, T, prec); arb_mat_one(T); arb_mat_add(S, S, T, prec); arb_mat_clear(T); } else { slong i, lo, hi, m, w, dim; arb_mat_struct * pows; arb_mat_t T, U; fmpz_t c, f; dim = arb_mat_nrows(A); m = n_sqrt(N); w = (N + m - 1) / m; fmpz_init(c); fmpz_init(f); pows = flint_malloc(sizeof(arb_mat_t) * (m + 1)); arb_mat_init(T, dim, dim); arb_mat_init(U, dim, dim); for (i = 0; i <= m; i++) { arb_mat_init(pows + i, dim, dim); if (i == 0) arb_mat_one(pows + i); else if (i == 1) arb_mat_set(pows + i, A); else arb_mat_mul(pows + i, pows + i - 1, A, prec); } arb_mat_zero(S); fmpz_one(f); for (i = w - 1; i >= 0; i--) { lo = i * m; hi = FLINT_MIN(N - 1, lo + m - 1); arb_mat_zero(T); fmpz_one(c); while (hi >= lo) { arb_mat_scalar_addmul_fmpz(T, pows + hi - lo, c, prec); if (hi != 0) fmpz_mul_ui(c, c, hi); hi--; } arb_mat_mul(U, pows + m, S, prec); arb_mat_scalar_mul_fmpz(S, T, f, prec); arb_mat_add(S, S, U, prec); fmpz_mul(f, f, c); } arb_mat_scalar_div_fmpz(S, S, f, prec); fmpz_clear(c); fmpz_clear(f); for (i = 0; i <= m; i++) arb_mat_clear(pows + i); flint_free(pows); arb_mat_clear(T); arb_mat_clear(U); } }
int main() { slong iter; flint_rand_t state; flint_printf("mul_entrywise...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { slong m, n, qbits1, qbits2, rbits1, rbits2, rbits3; fmpq_mat_t A, B, C; arb_mat_t a, b, c, d; qbits1 = 2 + n_randint(state, 200); qbits2 = 2 + n_randint(state, 200); rbits1 = 2 + n_randint(state, 200); rbits2 = 2 + n_randint(state, 200); rbits3 = 2 + n_randint(state, 200); m = n_randint(state, 10); n = n_randint(state, 10); fmpq_mat_init(A, m, n); fmpq_mat_init(B, m, n); fmpq_mat_init(C, m, n); arb_mat_init(a, m, n); arb_mat_init(b, m, n); arb_mat_init(c, m, n); arb_mat_init(d, m, n); fmpq_mat_randtest(A, state, qbits1); fmpq_mat_randtest(B, state, qbits2); _fmpq_mat_mul_entrywise(C, A, B); arb_mat_set_fmpq_mat(a, A, rbits1); arb_mat_set_fmpq_mat(b, B, rbits2); arb_mat_mul_entrywise(c, a, b, rbits3); if (!arb_mat_contains_fmpq_mat(c, C)) { flint_printf("FAIL\n\n"); flint_printf("m = %wd, n = %wd, bits3 = %wd\n", m, n, rbits3); flint_printf("A = "); fmpq_mat_print(A); flint_printf("\n\n"); flint_printf("B = "); fmpq_mat_print(B); flint_printf("\n\n"); flint_printf("C = "); fmpq_mat_print(C); flint_printf("\n\n"); flint_printf("a = "); arb_mat_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_mat_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_mat_printd(c, 15); flint_printf("\n\n"); abort(); } /* test aliasing with a */ if (arb_mat_nrows(a) == arb_mat_nrows(c) && arb_mat_ncols(a) == arb_mat_ncols(c)) { arb_mat_set(d, a); arb_mat_mul_entrywise(d, d, b, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 1)\n\n"); abort(); } } /* test aliasing with b */ if (arb_mat_nrows(b) == arb_mat_nrows(c) && arb_mat_ncols(b) == arb_mat_ncols(c)) { arb_mat_set(d, b); arb_mat_mul_entrywise(d, a, d, rbits3); if (!arb_mat_equal(d, c)) { flint_printf("FAIL (aliasing 2)\n\n"); abort(); } } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); arb_mat_clear(a); arb_mat_clear(b); arb_mat_clear(c); arb_mat_clear(d); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }