/* Copyright (C) 2015 William Hart This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void TEMPLATE(T, mat_charpoly_danilevsky) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) M, const TEMPLATE(T, ctx_t) ctx) { slong n = M->r, i, j, k; TEMPLATE(T, struct) * V, * W, * T; TEMPLATE(T, poly_t) b; TEMPLATE(T, t) c, h; TEMPLATE(T, mat_t) A; if (n == 0) { TEMPLATE(T, poly_one) (p, ctx); return; } TEMPLATE(T, init) (c, ctx); if (n == 1) { TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (p, 1, c, ctx); TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (M, 0, 0), ctx); TEMPLATE(T, poly_set_coeff) (p, 0, c, ctx); _TEMPLATE(T, poly_set_length) (p, 2, ctx); TEMPLATE(T, clear) (c, ctx); return; } i = 1; TEMPLATE(T, init) (h, ctx); TEMPLATE(T, poly_one) (p, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, mat_init_set) (A, M, ctx); V = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); W = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); T = (TEMPLATE(T, struct) *) _TEMPLATE(T, vec_init) (n, ctx); while (i < n) { TEMPLATE(T, set) (h, TEMPLATE(T, mat_entry) (A, n - i, n - i - 1), ctx); while (TEMPLATE(T, is_zero) (h, ctx)) { k = 1; while (k < n - i && TEMPLATE(T, is_zero) (TEMPLATE(T, mat_entry) (A, n - i, n - i - k - 1), ctx)) k++; if (k == n - i) { TEMPLATE(T, poly_fit_length) (b, i + 1, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, i, c, ctx); for (k = 1; k <= i; k++) { TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, n - i, n - k), ctx); TEMPLATE(T, poly_set_coeff) (b, k - 1, c, ctx); } _TEMPLATE(T, poly_set_length) (b, i + 1, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); n -= i; i = 1; if (n == 1) { TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, 1, c, ctx); TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, 0, 0), ctx); TEMPLATE(T, poly_set_coeff) (b, 0, c, ctx); _TEMPLATE(T, poly_set_length) (b, 2, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); goto cleanup; } } else { TEMPLATE(T, struct) * ptr; ptr = A->rows[n - i - k - 1]; A->rows[n - i - k - 1] = A->rows[n - i - 1]; A->rows[n - i - 1] = ptr; for (j = 1; j <= n - i + 1; j++) { TEMPLATE(T, swap) (TEMPLATE(T, mat_entry) (A, j - 1, n - i - k - 1), TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), ctx); } } TEMPLATE(T, set) (h, TEMPLATE(T, mat_entry) (A, n - i, n - i - 1), ctx); } TEMPLATE(T, neg) (h, h, ctx); TEMPLATE(T, inv) (h, h, ctx); for (j = 1; j <= n; j++) { TEMPLATE(T, mul) (V + j - 1, TEMPLATE(T, mat_entry) (A, n - i, j - 1), h, ctx); TEMPLATE(T, set) (W + j - 1, TEMPLATE(T, mat_entry) (A, n - i, j - 1), ctx); } TEMPLATE(T, neg) (h, h, ctx); for (j = 1; j <= n - i; j++) { for (k = 1; k <= n - i - 1; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), V + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, j - 1, k - 1), TEMPLATE(T, mat_entry) (A, j - 1, k - 1), c, ctx); } for (k = n - i + 1; k <= n; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), V + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, j - 1, k - 1), TEMPLATE(T, mat_entry) (A, j - 1, k - 1), c, ctx); } TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), TEMPLATE(T, mat_entry) (A, j - 1, n - i - 1), h, ctx); } for (j = 1; j <= n - i - 1; j++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, j - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), c, ctx); } } for (j = n - i; j <= n - 1; j++) { TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, j - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), c, ctx); } TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, j - 1), W + j, ctx); } TEMPLATE(T, mul) (TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), W + n - i - 1, ctx); for (k = 1; k < n - i; k++) { TEMPLATE(T, mul) (c, TEMPLATE(T, mat_entry) (A, k - 1, n - 1), W + k - 1, ctx); TEMPLATE(T, add) (TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), TEMPLATE(T, mat_entry) (A, n - i - 1, n - 1), c, ctx); } i++; } TEMPLATE(T, poly_fit_length) (b, n + 1, ctx); TEMPLATE(T, set_ui) (c, 1, ctx); TEMPLATE(T, poly_set_coeff) (b, n, c, ctx); for (i = 1; i <= n; i++) { TEMPLATE(T, neg) (c, TEMPLATE(T, mat_entry) (A, 0, n - i), ctx); TEMPLATE(T, poly_set_coeff) (b, i - 1, c, ctx); } _TEMPLATE(T, poly_set_length) (b, n + 1, ctx); TEMPLATE(T, poly_mul) (p, p, b, ctx); cleanup: TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, clear) (c, ctx); TEMPLATE(T, clear) (h, ctx); TEMPLATE(T, poly_clear) (b, ctx); _TEMPLATE(T, vec_clear) (T, A->r, ctx); _TEMPLATE(T, vec_clear) (V, A->r, ctx); _TEMPLATE(T, vec_clear) (W, A->r, ctx); } #endif