nag_zgetrs (f07asc) routine - solving a complex system of linear equations AX=B, ATX=B or AHX=B, where A has been factorized by nag_zgetrf (f07arc). |
#include <nag.h> #include <nagf07.h> void nag_zgetrf(Nag_OrderType order, Integer m, Integer n, Complex a[], Integer pda, Integer ipiv[], NagError *fail);And for f07asc:
#include <nag.h> #include <nagf07.h> void nag_zgetrs(Nag_OrderType order, Nag_TransType trans, Integer n, Integer nrhs, const Complex a[], Integer pda, const Integer ipiv[], Complex b[], Integer pdb, NagError *fail);For argument descriptions consult f07arc and f07asc documents in the NAG C Library Manual [6]. To keep things simple, we are going to call f07arc from within our C++ function. This means that we will not need to pass the ipiv array to and from the function.
#undef Complex #define Complex OctComplex #include <octave/oct.h> #undef Complex #define Complex NagComplex #define MatrixType NagMatrixType #include <nag.h> #include <nag_stdlib.h> #include <nagf07.h> DEFUN_DLD (nag_cmplx_lineqn, args, , "Calls nag_zgetrf (f07arc) followed by \n\ nag_zgetrs (f07asc).\n\ nag_zgetrs solves a complex system of linear equations with multiple \n\ right-hand sides, AX=B, A^TX=B or A^HX=B, where A has been factorized \n\ by nag_zgetrf.\n") { // Variable to store function output values octave_value_list retval; // Retrieve input arguments from args std::string transpose = args(0).string_value (); Integer n = args(1).int_value(); Integer nrhs = args(2).int_value(); ComplexMatrix a(args(3).complex_matrix_value()); Integer pda = args(4).int_value(); ComplexMatrix b(args(5).complex_matrix_value()); Integer pdb = args(6).int_value(); if (! error_state) { // Declare local variables #define A(I,J) a_nag[I*pda + J] #define B(I,J) b_nag[I*pdb + J] int i, j; NagComplex *a_nag=0, *b_nag=0; Integer *ipiv=0; Nag_TransType trans; NagError fail; INIT_FAIL(fail); // Assign the appropriate value of trans if (transpose.compare("Nag_NoTrans") == 0) trans=Nag_NoTrans; else if (transpose.compare("Nag_Trans") == 0) trans=Nag_Trans; else if (transpose.compare("Nag_ConjTrans") == 0) trans=Nag_ConjTrans; else error ("transpose not Nag_NoTrans, Nag_Trans or Nag_ConjTrans"); if ( !( ipiv = NAG_ALLOC(n, Integer)) || !( a_nag = NAG_ALLOC(n*pda, NagComplex)) || !( b_nag = NAG_ALLOC(n*pdb, NagComplex)) ) { error ("Allocation failure\n"); } // Copy the input OctComplex matrices into NagComplex arrays for (i = 0; i < n; i++) for (j = 0; j < pda; j++) { A(i,j).re = a.checkelem(i,j).real(); A(i,j).im = a.checkelem(i,j).imag(); } for (i = 0; i < n; i++) for (j = 0; j < pdb; j++) { B(i,j).re = b.checkelem(i,j).real(); B(i,j).im = b.checkelem(i,j).imag(); } // Call NAG routines nag_zgetrf(Nag_RowMajor,n,n,a_nag,pda,ipiv,&fail); nag_zgetrs(Nag_RowMajor,trans,n,nrhs,a_nag,pda,ipiv,b_nag,pdb,&fail); // Copy the output NagComplex array back into OctComplex matrix for (i = 0; i < n; i++) for (j = 0; j < pdb; j++) { b.checkelem(i,j).real() = B(i,j).re; b.checkelem(i,j).imag() = B(i,j).im; } if (a_nag) NAG_FREE(a_nag); if (b_nag) NAG_FREE(b_nag); if (ipiv) NAG_FREE(ipiv); // Assign output arguments to retval retval(0) = b; retval(1) = fail.code; } return retval; }
Points to note about this code:
To compile the C++ function into oct-files, we use the mkoctfile script supplied with Octave:
% mkoctfile nag_cmplx_lineqn.cc -L/opt/NAG/cll6a08dg/lib -lnagc_nag -I/opt/NAG/cll6a08dg/includewhere:
octave:1> a = [-1.3400+2.5500i 0.2800+3.1700i -6.3900-2.2000i 0.7200-0.9200i; -0.1700-1.4100i 3.3100-0.1500i -0.1500+1.3400i 1.2900+1.3800i; -3.2900-2.3900i -1.9100+4.4200i -0.1400-1.3500i 1.7200+1.3500i; 2.4100+0.3900i -0.5600+1.4700i -0.8300-0.6900i -1.9600+0.6700i] a = Columns 1 through 3: -1.34000 + 2.55000i 0.28000 + 3.17000i -6.39000 - 2.20000i -0.17000 - 1.41000i 3.31000 - 0.15000i -0.15000 + 1.34000i -3.29000 - 2.39000i -1.91000 + 4.42000i -0.14000 - 1.35000i 2.41000 + 0.39000i -0.56000 + 1.47000i -0.83000 - 0.69000i Column 4: 0.72000 - 0.92000i 1.29000 + 1.38000i 1.72000 + 1.35000i -1.96000 + 0.67000i octave:2> b=[26.2600+51.7800i 31.3200-6.7000i; 6.4300-8.6800i 15.8600-1.4200i; -5.7500+25.3100i -2.1500+30.1900i; 1.1600+2.5700i -2.5600+7.5500i] b = 26.2600 + 51.7800i 31.3200 - 6.7000i 6.4300 - 8.6800i 15.8600 - 1.4200i -5.7500 + 25.3100i -2.1500 + 30.1900i 1.1600 + 2.5700i -2.5600 + 7.5500i octave:3> [b,ifail]=nag_cmplx_lineqn("Nag_NoTrans",4,2,a,4,b,2) b = 1.0000 + 1.0000i -1.0000 - 2.0000i 2.0000 - 3.0000i 5.0000 + 1.0000i -4.0000 - 5.0000i -3.0000 + 4.0000i 0.0000 + 6.0000i 2.0000 - 3.0000i ifail = 0
(If you get an error message saying that a library cannot be located, see the tip given in Example 1).