/************************************************************************* Problem testing *************************************************************************/ static void testproblem(const ap::complex_2d_array& a, int n) { int i; int j; ap::complex_2d_array b; ap::complex_2d_array c; ap::integer_1d_array pivots; ap::complex v1; ap::complex v2; ap::complex ve; b.setbounds(1, n, 1, n); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { b(i,j) = a(i-1,j-1); } } ve = dettriangle(b, n); v1 = cmatrixdet(a, n); makeacopy(a, n, n, c); cmatrixlu(c, n, n, pivots); v2 = cmatrixludet(c, pivots, n); if( ve!=0 ) { deterrors = deterrors||ap::abscomplex((v1-ve)/ap::maxreal(ap::abscomplex(ve), double(1)))>1.0E-9; deterrors = deterrors||ap::abscomplex((v1-ve)/ap::maxreal(ap::abscomplex(ve), double(1)))>1.0E-9; } else { deterrors = deterrors||v1!=ve; deterrors = deterrors||v2!=ve; } }
/************************************************************************* Inversion of a general complex matrix. Input parameters: A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. N - size of matrix A. Output parameters: A - inverse of matrix A. Array whose indexes range within [0..N-1, 0..N-1]. Result: True, if the matrix is not singular. False, if the matrix is singular. -- ALGLIB -- Copyright 2005 by Bochkanov Sergey *************************************************************************/ bool cmatrixinverse(ap::complex_2d_array& a, int n) { bool result; ap::integer_1d_array pivots; cmatrixlu(a, n, n, pivots); result = cmatrixluinverse(a, pivots, n); return result; }
/************************************************************************* Solving a system of linear equations. The algorithm solves a system of linear equations by using the LU decomposition. The algorithm solves systems with a square matrix only. Input parameters: A - system matrix. Array whose indexes range within [0..N-1, 0..N-1]. B - right side of a system. Array whose indexes range within [0..N-1]. N - size of matrix A. Output parameters: X - solution of a system. Array whose index ranges within [0..N-1]. Result: True, if the matrix is not singular. False, if the matrix is singular. In this case, X doesn't contain a solution. -- ALGLIB -- Copyright 2005-2008 by Bochkanov Sergey *************************************************************************/ bool cmatrixsolve(ap::complex_2d_array a, ap::complex_1d_array b, int n, ap::complex_1d_array& x) { bool result; ap::integer_1d_array pivots; int i; cmatrixlu(a, n, n, pivots); result = cmatrixlusolve(a, pivots, b, n, x); return result; }
/************************************************************************* Problem testing *************************************************************************/ static void testproblem(const ap::complex_2d_array& a, int n) { ap::complex_2d_array b; ap::complex_2d_array blu; ap::complex_2d_array t1; ap::integer_1d_array p; int i; int j; ap::complex v; // // Decomposition // makeacopy(a, n, n, b); cmatrixinverse(b, n); makeacopy(a, n, n, blu); cmatrixlu(blu, n, n, p); cmatrixluinverse(blu, p, n); // // Test // t1.setbounds(0, n-1, 0, n-1); internalmatrixmatrixmultiply(a, 0, n-1, 0, n-1, false, b, 0, n-1, 0, n-1, false, t1, 0, n-1, 0, n-1); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = t1(i,j); if( i==j ) { v = v-1; } inverrors = inverrors||ap::abscomplex(v)>threshold; } } internalmatrixmatrixmultiply(a, 0, n-1, 0, n-1, false, blu, 0, n-1, 0, n-1, false, t1, 0, n-1, 0, n-1); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = t1(i,j); if( i==j ) { v = v-1; } inverrors = inverrors||ap::abscomplex(v)>threshold; } } }
/************************************************************************* Returns True for successful test, False - for failed test *************************************************************************/ static bool testcmatrixrcond(int maxn, int passcount) { bool result; ap::complex_2d_array a; ap::complex_2d_array lua; ap::integer_1d_array p; int n; int i; int j; int pass; bool err50; bool err90; bool errless; bool errspec; double erc1; double ercinf; ap::real_1d_array q50; ap::real_1d_array q90; double v; q50.setbounds(0, 3); q90.setbounds(0, 3); err50 = false; err90 = false; errless = false; errspec = false; // // process // for(n = 1; n <= maxn; n++) { // // special test for zero matrix // cmatrixgenzero(a, n); cmatrixmakeacopy(a, n, n, lua); cmatrixlu(lua, n, n, p); errspec = errspec||ap::fp_neq(cmatrixrcond1(a, n),0); errspec = errspec||ap::fp_neq(cmatrixrcondinf(a, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcond1(lua, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcondinf(lua, n),0); // // general test // a.setbounds(0, n-1, 0, n-1); for(i = 0; i <= 3; i++) { q50(i) = 0; q90(i) = 0; } for(pass = 1; pass <= passcount; pass++) { cmatrixrndcond(n, exp(ap::randomreal()*log(double(1000))), a); cmatrixmakeacopy(a, n, n, lua); cmatrixlu(lua, n, n, p); cmatrixrefrcond(a, n, erc1, ercinf); // // 1-norm, normal // v = 1/cmatrixrcond1(a, n); if( ap::fp_greater_eq(v,threshold50*erc1) ) { q50(0) = q50(0)+double(1)/double(passcount); } if( ap::fp_greater_eq(v,threshold90*erc1) ) { q90(0) = q90(0)+double(1)/double(passcount); } errless = errless||ap::fp_greater(v,erc1*1.001); // // 1-norm, LU // v = 1/cmatrixlurcond1(lua, n); if( ap::fp_greater_eq(v,threshold50*erc1) ) { q50(1) = q50(1)+double(1)/double(passcount); } if( ap::fp_greater_eq(v,threshold90*erc1) ) { q90(1) = q90(1)+double(1)/double(passcount); } errless = errless||ap::fp_greater(v,erc1*1.001); // // Inf-norm, normal // v = 1/cmatrixrcondinf(a, n); if( ap::fp_greater_eq(v,threshold50*ercinf) ) { q50(2) = q50(2)+double(1)/double(passcount); } if( ap::fp_greater_eq(v,threshold90*ercinf) ) { q90(2) = q90(2)+double(1)/double(passcount); } errless = errless||ap::fp_greater(v,ercinf*1.001); // // Inf-norm, LU // v = 1/cmatrixlurcondinf(lua, n); if( ap::fp_greater_eq(v,threshold50*ercinf) ) { q50(3) = q50(3)+double(1)/double(passcount); } if( ap::fp_greater_eq(v,threshold90*ercinf) ) { q90(3) = q90(3)+double(1)/double(passcount); } errless = errless||ap::fp_greater(v,ercinf*1.001); } for(i = 0; i <= 3; i++) { err50 = err50||ap::fp_less(q50(i),0.50); err90 = err90||ap::fp_less(q90(i),0.90); } // // degenerate matrix test // if( n>=3 ) { a.setlength(n, n); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { a(i,j) = 0.0; } } a(0,0) = 1; a(n-1,n-1) = 1; errspec = errspec||ap::fp_neq(cmatrixrcond1(a, n),0); errspec = errspec||ap::fp_neq(cmatrixrcondinf(a, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcond1(a, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcondinf(a, n),0); } // // near-degenerate matrix test // if( n>=2 ) { a.setlength(n, n); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { a(i,j) = 0.0; } } for(i = 0; i <= n-1; i++) { a(i,i) = 1; } i = ap::randominteger(n); a(i,i) = 0.1*ap::maxrealnumber; errspec = errspec||ap::fp_neq(cmatrixrcond1(a, n),0); errspec = errspec||ap::fp_neq(cmatrixrcondinf(a, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcond1(a, n),0); errspec = errspec||ap::fp_neq(cmatrixlurcondinf(a, n),0); } } // // report // result = !(err50||err90||errless||errspec); return result; }