mirror of
https://github.com/vale981/arb
synced 2025-03-06 01:41:39 -05:00
255 lines
8.3 KiB
C
255 lines
8.3 KiB
C
/*
|
|
Copyright (C) 2012 Fredrik Johansson
|
|
|
|
This file is part of Arb.
|
|
|
|
Arb 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "arb_mat.h"
|
|
|
|
void
|
|
_fmpq_mul_si_frac(fmpq_t res, const fmpq_t x, slong p, slong q)
|
|
{
|
|
fmpq_t r;
|
|
fmpq_init(r);
|
|
fmpq_set_si(r, p, q);
|
|
fmpq_mul(res, x, r);
|
|
fmpq_clear(r);
|
|
}
|
|
|
|
void
|
|
_fmpq_max(fmpq_t p, const fmpq_t q, const fmpq_t r)
|
|
{
|
|
if (fmpq_cmp(q, r) < 0)
|
|
fmpq_set(p, r);
|
|
else
|
|
fmpq_set(p, q);
|
|
}
|
|
|
|
void
|
|
_fmpq_mat_scalar_mul_fmpq(fmpq_mat_t res,
|
|
const fmpq_mat_t mat, const fmpq_t x)
|
|
{
|
|
slong i, j;
|
|
for (i = 0; i < mat->r; i++)
|
|
for (j = 0; j < mat->c; j++)
|
|
fmpq_mul(fmpq_mat_entry(res, i, j),
|
|
fmpq_mat_entry(mat, i, j), x);
|
|
}
|
|
|
|
void
|
|
_fmpq_mat_inf_norm(fmpq_t res, const fmpq_mat_t mat)
|
|
{
|
|
fmpq_t s, q;
|
|
slong i, j;
|
|
|
|
fmpq_init(s);
|
|
fmpq_init(q);
|
|
|
|
fmpq_zero(res);
|
|
for (i = 0; i < mat->r; i++)
|
|
{
|
|
fmpq_zero(s);
|
|
for (j = 0; j < mat->c; j++)
|
|
{
|
|
fmpq_abs(q, fmpq_mat_entry(mat, i, j));
|
|
fmpq_add(s, s, q);
|
|
}
|
|
_fmpq_max(res, res, s);
|
|
}
|
|
|
|
fmpq_clear(s);
|
|
fmpq_clear(q);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
slong iter;
|
|
flint_rand_t state;
|
|
|
|
flint_printf("solve_preapprox....");
|
|
fflush(stdout);
|
|
|
|
flint_randinit(state);
|
|
|
|
for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++)
|
|
{
|
|
fmpq_mat_t QA, QB, QR, QT, QE, QX;
|
|
arb_mat_t A, B, R, T, X;
|
|
slong n, m, qbits, prec;
|
|
int q_invertible, r_approximable, r_approximable2;
|
|
|
|
n = n_randint(state, 8);
|
|
m = n_randint(state, 8);
|
|
qbits = 1 + n_randint(state, 30);
|
|
prec = 2 + n_randint(state, 200);
|
|
|
|
fmpq_mat_init(QA, n, n);
|
|
fmpq_mat_init(QB, n, m);
|
|
fmpq_mat_init(QR, n, n);
|
|
fmpq_mat_init(QT, n, m);
|
|
fmpq_mat_init(QE, n, n);
|
|
fmpq_mat_init(QX, n, m);
|
|
|
|
arb_mat_init(A, n, n);
|
|
arb_mat_init(B, n, m);
|
|
arb_mat_init(R, n, n);
|
|
arb_mat_init(T, n, m);
|
|
arb_mat_init(X, n, m);
|
|
|
|
/* Sample a square matrix QE with inf-norm less than 1. */
|
|
{
|
|
fmpq_t m;
|
|
fmpq_init(m);
|
|
fmpq_mat_randtest(QE, state, qbits);
|
|
_fmpq_mat_inf_norm(m, QE);
|
|
if (!fmpq_is_zero(m))
|
|
{
|
|
slong p, q;
|
|
q = 64;
|
|
p = n_randint(state, q);
|
|
fmpq_inv(m, m);
|
|
_fmpq_mul_si_frac(m, m, p, q);
|
|
_fmpq_mat_scalar_mul_fmpq(QE, QE, m);
|
|
}
|
|
fmpq_clear(m);
|
|
}
|
|
|
|
/* Sample an unrestricted square matrix QR. */
|
|
fmpq_mat_randtest(QR, state, qbits);
|
|
|
|
/* Construct QA := inv(QR)(I - QE), so that I - QR*QA = QE */
|
|
fmpq_mat_one(QA);
|
|
fmpq_mat_sub(QA, QA, QE);
|
|
q_invertible = fmpq_mat_solve_fraction_free(QA, QR, QA);
|
|
|
|
/* Sample unrestricted matrices QB and QT. */
|
|
fmpq_mat_randtest(QB, state, qbits);
|
|
fmpq_mat_randtest(QT, state, qbits);
|
|
|
|
arb_mat_set_fmpq_mat(A, QA, prec);
|
|
arb_mat_set_fmpq_mat(B, QB, prec);
|
|
arb_mat_set_fmpq_mat(R, QR, prec);
|
|
arb_mat_set_fmpq_mat(T, QT, prec);
|
|
|
|
if (q_invertible)
|
|
{
|
|
/* Construct QX := inv(QA)QB */
|
|
fmpq_mat_solve_fraction_free(QX, QA, QB);
|
|
|
|
r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec);
|
|
if (r_approximable)
|
|
{
|
|
if (!arb_mat_contains_fmpq_mat(X, QX))
|
|
{
|
|
flint_printf("FAIL (containment, iter = %wd)\n", iter);
|
|
flint_printf("n = %wd, prec = %wd\n", n, prec);
|
|
flint_printf("\n");
|
|
|
|
flint_printf("QA = \n"); fmpq_mat_print(QA); flint_printf("\n\n");
|
|
flint_printf("QB = \n"); fmpq_mat_print(QB); flint_printf("\n\n");
|
|
flint_printf("QR = \n"); fmpq_mat_print(QR); flint_printf("\n\n");
|
|
flint_printf("QT = \n"); fmpq_mat_print(QT); flint_printf("\n\n");
|
|
flint_printf("QE = \n"); fmpq_mat_print(QE); flint_printf("\n\n");
|
|
flint_printf("QX = \n"); fmpq_mat_print(QX); flint_printf("\n\n");
|
|
|
|
flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n");
|
|
flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n");
|
|
flint_printf("R = \n"); arb_mat_printd(R, 15); flint_printf("\n\n");
|
|
flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n");
|
|
flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n");
|
|
|
|
flint_abort();
|
|
}
|
|
}
|
|
|
|
/* test aliasing */
|
|
if (n_randint(state, 2))
|
|
{
|
|
r_approximable2 = arb_mat_solve_preapprox(T, A, B, R, T, prec);
|
|
if ((r_approximable != r_approximable2) ||
|
|
(r_approximable && !arb_mat_equal(X, T)))
|
|
{
|
|
flint_printf("FAIL (aliasing (X, T))\n");
|
|
flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n");
|
|
flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n");
|
|
flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n");
|
|
flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n");
|
|
flint_abort();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r_approximable2 = arb_mat_solve_preapprox(B, A, B, R, T, prec);
|
|
if ((r_approximable != r_approximable2) ||
|
|
(r_approximable && !arb_mat_equal(X, B)))
|
|
{
|
|
flint_printf("FAIL (aliasing (X, B))\n");
|
|
flint_printf("A = \n"); arb_mat_printd(A, 15); flint_printf("\n\n");
|
|
flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n");
|
|
flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n");
|
|
flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n");
|
|
flint_abort();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* test a simplified case where A = R = I */
|
|
{
|
|
arb_mat_one(A);
|
|
arb_mat_one(R);
|
|
fmpq_mat_randtest(QB, state, qbits);
|
|
fmpq_mat_randtest(QT, state, qbits);
|
|
arb_mat_set_fmpq_mat(B, QB, prec);
|
|
arb_mat_set_fmpq_mat(T, QT, prec);
|
|
arb_mat_zero(X);
|
|
r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec);
|
|
if (!r_approximable || !arb_mat_contains(X, B))
|
|
{
|
|
flint_printf("FAIL (special values A = R = I))\n");
|
|
flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n");
|
|
flint_printf("T = \n"); arb_mat_printd(T, 15); flint_printf("\n\n");
|
|
flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n");
|
|
}
|
|
}
|
|
|
|
/* test a simplified case where A = R = I and T = B */
|
|
{
|
|
arb_mat_one(A);
|
|
arb_mat_one(R);
|
|
fmpq_mat_randtest(QB, state, qbits);
|
|
arb_mat_set_fmpq_mat(B, QB, prec);
|
|
arb_mat_set(T, B);
|
|
arb_mat_zero(X);
|
|
r_approximable = arb_mat_solve_preapprox(X, A, B, R, T, prec);
|
|
if (!r_approximable || !arb_mat_contains(X, B))
|
|
{
|
|
flint_printf("FAIL (special values A = R = I, T = B))\n");
|
|
flint_printf("B = \n"); arb_mat_printd(B, 15); flint_printf("\n\n");
|
|
flint_printf("X = \n"); arb_mat_printd(X, 15); flint_printf("\n\n");
|
|
}
|
|
}
|
|
|
|
fmpq_mat_clear(QA);
|
|
fmpq_mat_clear(QB);
|
|
fmpq_mat_clear(QR);
|
|
fmpq_mat_clear(QT);
|
|
fmpq_mat_clear(QE);
|
|
fmpq_mat_clear(QX);
|
|
|
|
arb_mat_clear(A);
|
|
arb_mat_clear(B);
|
|
arb_mat_clear(R);
|
|
arb_mat_clear(T);
|
|
arb_mat_clear(X);
|
|
}
|
|
|
|
flint_randclear(state);
|
|
flint_cleanup();
|
|
flint_printf("PASS\n");
|
|
return EXIT_SUCCESS;
|
|
}
|