arb/arb_mat/test/t-solve_preapprox.c
2018-04-10 17:52:06 +02:00

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;
}