diff src/DLD-FUNCTIONS/balance.cc @ 3181:3f6a813eb09e

[project @ 1998-09-25 02:50:29 by jwe]
author jwe
date Fri, 25 Sep 1998 02:53:39 +0000
parents f657159c8152
children 9580887dd160
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/balance.cc	Thu Sep 24 19:00:19 1998 +0000
+++ b/src/DLD-FUNCTIONS/balance.cc	Fri Sep 25 02:53:39 1998 +0000
@@ -32,14 +32,32 @@
 #include "CmplxAEPBAL.h"
 #include "dbleAEPBAL.h"
 #include "dbleAEPBAL.h"
-#include "dbleGEPBAL.h"
 
 #include "defun-dld.h"
 #include "error.h"
+#include "f77-fcn.h"
 #include "gripes.h"
 #include "oct-obj.h"
 #include "utils.h"
 
+extern "C"
+{
+  int F77_FCN( dggbal, DGGBAL) (const char* JOB,  const int& N,
+        double* A, const int& LDA, double* B, const int& LDB,
+        int& ILO, int & IHI, double* LSCALE,
+        double* RSCALE, double* WORK, int& INFO, long );
+
+  int F77_FCN( dggbak, DGGBAK) (const char* JOB, const char* SIDE,
+        const int& N, const int& ILO, const int& IHI,
+        double* LSCALE, double* RSCALE, int& M,
+        double* V, const int& LDV, int& INFO, long, long);
+
+  int F77_FCN( zggbal, ZGGBAL) ( const char* JOB,  const int& N,
+        Complex* A, const int& LDA, Complex* B, const int& LDB,
+        int& ILO, int & IHI, double* LSCALE,
+        double* RSCALE, double* WORK, int& INFO, long );
+}
+
 DEFUN_DLD (balance, args, nargout,
   "AA = balance (A [, OPT]) or [[DD,] AA] =  balance (A [, OPT])\n\
 \n\
@@ -55,10 +73,11 @@
   B: (default) permute and scale, in that order.  Rows/columns\n\
      of a (and b) that are isolated by permutation are not scaled\n\
 \n\
-[DD, AA] = balance (A, OPT) returns aa = inv(dd)*a*dd,\n\
+[DD, AA] = balance (A, OPT) returns aa = dd*a*dd,\n\
 \n\
 [CC, DD, AA, BB] = balance (A, B, OPT) returns AA (BB) = CC*A*DD (CC*B*DD)")
 {
+
   octave_value_list retval;
 
   int nargin = args.length ();
@@ -69,212 +88,192 @@
       return retval;
     }
 
+  // determine if it's AEP or GEP
+  int AEPcase = (nargin == 1 ? 1 : args(1).is_string() );
   string bal_job;
-  int my_nargin;		// # args w/o optional string arg
-
-  // Determine if balancing option is listed.  Set my_nargin to the
-  // number of matrix inputs.
 
-  if (args(nargin-1).is_string ())
-    {
-      bal_job = args(nargin-1).string_value ();
-      my_nargin = nargin-1;
-    }
-  else
-    {
-      bal_job = "B";
-      my_nargin = nargin;
-    }
+  // problem dimension
+  int nn = args(0).rows ();
 
-  octave_value arg_a = args(0);
-
-  int a_nr = arg_a.rows ();
-  int a_nc = arg_a.columns ();
-
-  // Check argument 1 dimensions.
-
-  int arg_is_empty = empty_arg ("balance", a_nr, a_nc);
+  int arg_is_empty = empty_arg ("balance", nn, args(0).columns());
 
   if (arg_is_empty < 0)
     return retval;
   if (arg_is_empty > 0)
     return octave_value_list (2, Matrix ());
 
-  if (a_nr != a_nc)
-    {
-      gripe_square_matrix_required ("balance");
-      return retval;
-    }
+  if (nn != args(0).columns())
+  {
+    gripe_square_matrix_required ("balance");
+    return retval;
+  }
 
   // Extract argument 1 parameter for both AEP and GEP.
-
   Matrix aa;
   ComplexMatrix caa;
-  if (arg_a.is_complex_type ())
-    caa = arg_a.complex_matrix_value ();
-  else
-    aa = arg_a.matrix_value ();
-
-  if (error_state)
-    return retval;
+  if (args(0).is_complex_type ()) caa = args(0).complex_matrix_value ();
+  else                            aa = args(0).matrix_value ();
+  if (error_state)                return retval;
 
   // Treat AEP/GEP cases.
+  if(AEPcase)
+  {   
+    // Algebraic eigenvalue problem.
+    if(nargin == 1)
+      bal_job = "B";
+    else if(args(1).is_string())
+      bal_job = args(1).string_value();
+    // the next line should never execute, but better safe than sorry.
+    else error("balance: AEP argument 2 must be a string");
 
-  switch (my_nargin)
+    // balance the AEP
+    if (args(0).is_complex_type ())
+    {
+      ComplexAEPBALANCE result (caa, bal_job);
+
+      if (nargout == 0 || nargout == 1)
+        retval(0) = result.balanced_matrix ();
+      else
+      {
+        retval(1) = result.balanced_matrix ();
+        retval(0) = result.balancing_matrix ();
+      }
+    }
+    else
     {
-    case 1:
-      
-      // Algebraic eigenvalue problem.
+      AEPBALANCE result (aa, bal_job);
 
-      if (arg_a.is_complex_type ())
-	{
-	  ComplexAEPBALANCE result (caa, bal_job);
+      if (nargout == 0 || nargout == 1)
+        retval(0) = result.balanced_matrix ();
+      else
+      {
+        retval(1) = result.balanced_matrix ();
+        retval(0) = result.balancing_matrix ();
+       }
+    }
+  }
+  //
+  // end of AEP case, now do GEP case
+  else
+  {
+    // Generalized eigenvalue problem.
+    if(nargin == 2)
+      bal_job = "B";
+    else if(args(2).is_string())
+      bal_job = args(2).string_value();
+    else error("balance: GEP argument 3 must be a string");
+
+    if( (nn != args(1).columns()) || (nn != args(1).rows() ) )
+    {
+      gripe_nonconformant ();
+      return retval;
+    }
+    Matrix bb;
+    ComplexMatrix cbb;
+    if (args(1).is_complex_type ()) cbb = args(1).complex_matrix_value ();
+    else                            bb = args(1).matrix_value ();
+    if (error_state) return retval;
 
-	  if (nargout == 0 || nargout == 1)
-	    retval(0) = result.balanced_matrix ();
-	  else
-	    {
-	      retval(1) = result.balanced_matrix ();
-	      retval(0) = result.balancing_matrix ();
-	    }
-	}
+    //
+    // Both matrices loaded, now let's check what kind of arithmetic:
+    // first, declare variables used in both the real and complex case
+    int ilo, ihi, info;
+    RowVector lscale(nn), rscale(nn), work(6*nn);
+    char job = bal_job[0];
+    static int complex_case = (args(0).is_complex_type() 
+                       || args(1).is_complex_type());
+
+    // now balance
+    if (complex_case)
+    {
+      if (args(0).is_real_type ()) caa = aa;
+      if (args(1).is_real_type ()) cbb = bb;
+  
+      F77_XFCN( zggbal, ZGGBAL, ( &job, nn, caa.fortran_vec(), nn,
+          cbb.fortran_vec(), nn, ilo, ihi, lscale.fortran_vec(),
+          rscale.fortran_vec(), work.fortran_vec(), info, 1L));
+    }
+    else          // real matrices case
+    {
+      F77_XFCN( dggbal, DGGBAL, (&job,  nn, aa.fortran_vec(),
+          nn, bb.fortran_vec() , nn, ilo, ihi, lscale.fortran_vec(),
+          rscale.fortran_vec(), work.fortran_vec(), info , 1L));
+      
+      if(f77_exception_encountered)
+        (*current_liboctave_error_handler) 
+         ("unrecoverable error in balance GEP");
+    }
+      
+    // Since we just want the balancing matrices, we can use dggbal
+    // for both the real and complex cases;
+    Matrix Pl(nn,nn), Pr(nn,nn);
+    for(int ii=0; ii < nn ; ii++)
+      for( int jj=0; jj < nn ; jj++)
+        Pl(ii,jj) = Pr(ii,jj) = (ii == jj ? 1.0 : 0.0);
+  
+    // left first
+    F77_XFCN( dggbak, DGGBAK, (&job, "L",
+          nn, ilo, ihi, lscale.fortran_vec(),
+          rscale.fortran_vec(), nn, Pl.fortran_vec(),
+          nn, info, 1L, 1L));
+      
+    if(f77_exception_encountered)
+      (*current_liboctave_error_handler) 
+        ("unrecoverable error in balance GEP(L)");
+      
+    // then right
+    F77_XFCN(dggbak, DGGBAK, (&job, "R",
+          nn, ilo, ihi, lscale.fortran_vec(),
+          rscale.fortran_vec(), nn, Pr.fortran_vec(),
+          nn, info, 1L, 1L));
+    if(f77_exception_encountered)
+      (*current_liboctave_error_handler) 
+        ("unrecoverable error in balance GEP(R)");
+
+    switch (nargout)
+    {
+    case 0:
+    case 1:
+      warning ("balance: used GEP, should have two output arguments");
+      if(complex_case)
+        retval(0) = caa;
       else
-	{
-	  AEPBALANCE result (aa, bal_job);
-
-	  if (nargout == 0 || nargout == 1)
-	    retval(0) = result.balanced_matrix ();
-	  else
-	    {
-	      retval(1) = result.balanced_matrix ();
-	      retval(0) = result.balancing_matrix ();
-	    }
-	}
+        retval(0) = aa;
       break;
 
     case 2:
+      if(complex_case)
       {
-	// Generalized eigenvalue problem.
-
-	// 1st we have to check argument 2 dimensions and type...
-
-	octave_value arg_b = args(1);
-
-	int b_nr = arg_b.rows ();
-	int b_nc = arg_b.columns ();
-      
-	// Check argument 2 dimensions -- must match arg 1.
-
-	if (b_nr != b_nc || b_nr != a_nr)
-	  {
-	    gripe_nonconformant ();
-	    return retval;
-	  }
-      
-	// Now, extract the second matrix...
-	// Extract argument 1 parameter for both AEP and GEP.
-
-	Matrix bb;
-	ComplexMatrix cbb;
-	if (arg_b.is_complex_type ())
-	  cbb = arg_b.complex_matrix_value ();
-	else
-	  bb = arg_b.matrix_value ();
-
-	if (error_state)
-	  return retval;
-
-	// Both matrices loaded, now let's check what kind of arithmetic:
-
-	if (arg_a.is_complex_type () || arg_b.is_complex_type ())
-	  {
-	    if (arg_a.is_real_type ())
-	      caa = aa;
-
-	    if (arg_b.is_real_type ())
-	      cbb = bb;
-
-	    // Compute magnitudes of elements for balancing purposes.
-	    // Surely there's a function I can call someplace!
-
-	    for (int i = 0; i < a_nr; i++)
-	      for (int j = 0; j < a_nc; j++)
-		{
-		  aa (i, j) = abs (caa (i, j));
-		  bb (i, j) = abs (cbb (i, j));
-		}
-	  }
-
-	GEPBALANCE result (aa, bb, bal_job);
-
-	if (arg_a.is_complex_type () || arg_b.is_complex_type ())
-	  {
-	    caa = result.left_balancing_matrix () * caa
-	      * result.right_balancing_matrix ();
-
-	    cbb = result.left_balancing_matrix () * cbb
-	      * result.right_balancing_matrix ();
-
-	    switch (nargout)
-	      {
-	      case 0:
-	      case 1:
-		warning ("balance: should use two output arguments");
-		retval(0) = caa;
-		break;
-
-	      case 2:
-		retval(1) = cbb;
-		retval(0) = caa;
-		break;
-
-	      case 4:
-		retval(3) = cbb;
-		retval(2) = caa;
-		retval(1) = result.right_balancing_matrix ();
-		retval(0) = result.left_balancing_matrix ();
-		break;
-
-	      default:
-		error ("balance: invalid number of output arguments");
-		break;
-	      }
-	  }
-	else
-	  {
-	    switch (nargout)
-	      {
-	      case 0:
-	      case 1:
-		warning ("balance: should use two output arguments");
-		retval(0) = result.balanced_a_matrix ();
-		break;
-
-	      case 2:
-		retval(1) = result.balanced_b_matrix ();
-		retval(0) = result.balanced_a_matrix ();
-		break;
-
-	      case 4:
-		retval(3) = result.balanced_b_matrix ();
-		retval(2) = result.balanced_a_matrix ();
-		retval(1) = result.right_balancing_matrix ();
-		retval(0) = result.left_balancing_matrix ();
-		break;
-
-	      default:
-		error ("balance: invalid number of output arguments");
-		break;
-	      }
-	  }
+        retval(1) = cbb;
+        retval(0) = caa;
+      }
+      else
+      {
+        retval(1) = bb;
+        retval(0) = aa;
       }
       break;
 
+    case 4:
+      if(complex_case)
+      {
+        retval(3) = cbb;
+        retval(2) = caa;
+      }
+      else
+      {
+        retval(3) = bb;
+        retval(2) = aa;
+      }
+      retval(1) = Pr;
+      retval(0) = Pl.transpose();  // so that aa_bal = cc*aa*dd, etc.
+      break;
+
     default:
-      error ("balance requires one (AEP) or two (GEP) numeric arguments");
+      error ("balance: invalid number of output arguments");
       break;
     }
-
+  }
   return retval;
 }