bool generalizedsymmetricdefiniteevdreduce(ap::real_2d_array& a, int n, bool isuppera, const ap::real_2d_array& b, bool isupperb, int problemtype, ap::real_2d_array& r, bool& isupperr) { bool result; ap::real_2d_array t; ap::real_1d_array w1; ap::real_1d_array w2; ap::real_1d_array w3; int i; int j; double v; ap::ap_error::make_assertion(n>0, "GeneralizedSymmetricDefiniteEVDReduce: N<=0!"); ap::ap_error::make_assertion(problemtype==1||problemtype==2||problemtype==3, "GeneralizedSymmetricDefiniteEVDReduce: incorrect ProblemType!"); result = true; // // Problem 1: A*x = lambda*B*x // // Reducing to: // C*y = lambda*y // C = L^(-1) * A * L^(-T) // x = L^(-T) * y // if( problemtype==1 ) { // // Factorize B in T: B = LL' // t.setbounds(1, n, 1, n); if( isupperb ) { for(i = 1; i <= n; i++) { ap::vmove(t.getcolumn(i, i, n), b.getrow(i, i, n)); } } else { for(i = 1; i <= n; i++) { ap::vmove(&t(i, 1), &b(i, 1), ap::vlen(1,i)); } } if( !choleskydecomposition(t, n, false) ) { result = false; return result; } // // Invert L in T // if( !invtriangular(t, n, false, false) ) { result = false; return result; } // // Build L^(-1) * A * L^(-T) in R // w1.setbounds(1, n); w2.setbounds(1, n); r.setbounds(1, n, 1, n); for(j = 1; j <= n; j++) { // // Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T)) // ap::vmove(&w1(1), &t(j, 1), ap::vlen(1,j)); symmetricmatrixvectormultiply(a, isuppera, 1, j, w1, 1.0, w2); if( isuppera ) { matrixvectormultiply(a, 1, j, j+1, n, true, w1, 1, j, 1.0, w2, j+1, n, 0.0); } else { matrixvectormultiply(a, j+1, n, 1, j, false, w1, 1, j, 1.0, w2, j+1, n, 0.0); } // // Form l(i)*w2 (here l(i) is i-th row of L^(-1)) // for(i = 1; i <= n; i++) { v = ap::vdotproduct(&t(i, 1), &w2(1), ap::vlen(1,i)); r(i,j) = v; } } // // Copy R to A // for(i = 1; i <= n; i++) { ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n)); } // // Copy L^(-1) from T to R and transpose // isupperr = true; for(i = 1; i <= n; i++) { for(j = 1; j <= i-1; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(r.getrow(i, i, n), t.getcolumn(i, i, n)); } return result; } // // Problem 2: A*B*x = lambda*x // or // problem 3: B*A*x = lambda*x // // Reducing to: // C*y = lambda*y // C = U * A * U' // B = U'* U // if( problemtype==2||problemtype==3 ) { // // Factorize B in T: B = U'*U // t.setbounds(1, n, 1, n); if( isupperb ) { for(i = 1; i <= n; i++) { ap::vmove(&t(i, i), &b(i, i), ap::vlen(i,n)); } } else { for(i = 1; i <= n; i++) { ap::vmove(t.getrow(i, i, n), b.getcolumn(i, i, n)); } } if( !choleskydecomposition(t, n, true) ) { result = false; return result; } // // Build U * A * U' in R // w1.setbounds(1, n); w2.setbounds(1, n); w3.setbounds(1, n); r.setbounds(1, n, 1, n); for(j = 1; j <= n; j++) { // // Form w2 = A * u'(j) (here u'(j) is j-th column of U') // ap::vmove(&w1(1), &t(j, j), ap::vlen(1,n-j+1)); symmetricmatrixvectormultiply(a, isuppera, j, n, w1, 1.0, w3); ap::vmove(&w2(j), &w3(1), ap::vlen(j,n)); ap::vmove(&w1(j), &t(j, j), ap::vlen(j,n)); if( isuppera ) { matrixvectormultiply(a, 1, j-1, j, n, false, w1, j, n, 1.0, w2, 1, j-1, 0.0); } else { matrixvectormultiply(a, j, n, 1, j-1, true, w1, j, n, 1.0, w2, 1, j-1, 0.0); } // // Form u(i)*w2 (here u(i) is i-th row of U) // for(i = 1; i <= n; i++) { v = ap::vdotproduct(&t(i, i), &w2(i), ap::vlen(i,n)); r(i,j) = v; } } // // Copy R to A // for(i = 1; i <= n; i++) { ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n)); } if( problemtype==2 ) { // // Invert U in T // if( !invtriangular(t, n, true, false) ) { result = false; return result; } // // Copy U^-1 from T to R // isupperr = true; for(i = 1; i <= n; i++) { for(j = 1; j <= i-1; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(&r(i, i), &t(i, i), ap::vlen(i,n)); } } else { // // Copy U from T to R and transpose // isupperr = false; for(i = 1; i <= n; i++) { for(j = i+1; j <= n; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(r.getcolumn(i, i, n), t.getrow(i, i, n)); } } } return result; }
//************************************************************************ //Обращение матрицы, заданной LU-разложением // //Входные параметры: // A - LU-разложение матрицы (результат работы подпрограммы // LUDecomposition). // Pivots - таблица перестановок, произведенных в ходе LU-разложения. // (результат работы подпрограммы LUDecomposition). // N - размерность матрицы // //Выходные параметры: // A - матрица, обратная к исходной. Массив с нумерацией // элементов [1..N, 1..N] // //Результат: // True, если исходная матрица невырожденная. // False, если исходная матрица вырожденная. // // -- LAPACK routine (version 3.0) -- // Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., // Courant Institute, Argonne National Lab, and Rice University // February 29, 1992 //************************************************************************ bool inverselu(ap::real_2d_array& a, const ap::integer_1d_array& pivots, int n) { bool result; ap::real_1d_array work; int i; int iws; int j; int jb; int jj; int jp; int jp1; double v; result = true; // // Quick return if possible // if( n==0 ) { return result; } work.setbounds(1, n); // // Form inv(U) // if( !invtriangular(a, n, true, false) ) { result = false; return result; } // // Solve the equation inv(A)*L = inv(U) for inv(A). // for(j = n; j >= 1; j--) { // // Copy current column of L to WORK and replace with zeros. // for(i = j+1; i <= n; i++) { work(i) = a(i,j); a(i,j) = 0; } // // Compute current column of inv(A). // if( j<n ) { jp1 = j+1; for(i = 1; i <= n; i++) { v = ap::vdotproduct(a.getrow(i, jp1, n), work.getvector(jp1, n)); a(i,j) = a(i,j)-v; } } } // // Apply column interchanges. // for(j = n-1; j >= 1; j--) { jp = pivots(j); if( jp!=j ) { ap::vmove(work.getvector(1, n), a.getcolumn(j, 1, n)); ap::vmove(a.getcolumn(j, 1, n), a.getcolumn(jp, 1, n)); ap::vmove(a.getcolumn(jp, 1, n), work.getvector(1, n)); } } return result; }