Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029
00030 #include <string>
00031
00032 #include "CmplxAEPBAL.h"
00033 #include "fCmplxAEPBAL.h"
00034 #include "dbleAEPBAL.h"
00035 #include "floatAEPBAL.h"
00036 #include "CmplxGEPBAL.h"
00037 #include "fCmplxGEPBAL.h"
00038 #include "dbleGEPBAL.h"
00039 #include "floatGEPBAL.h"
00040 #include "quit.h"
00041
00042 #include "defun-dld.h"
00043 #include "error.h"
00044 #include "f77-fcn.h"
00045 #include "gripes.h"
00046 #include "oct-obj.h"
00047 #include "utils.h"
00048
00049 DEFUN_DLD (balance, args, nargout,
00050 "-*- texinfo -*-\n\
00051 @deftypefn {Loadable Function} {@var{AA} =} balance (@var{A})\n\
00052 @deftypefnx {Loadable Function} {@var{AA} =} balance (@var{A}, @var{opt})\n\
00053 @deftypefnx {Loadable Function} {[@var{DD}, @var{AA}] =} balance (@var{A}, @var{opt})\n\
00054 @deftypefnx {Loadable Function} {[@var{D}, @var{P}, @var{AA}] =} balance (@var{A}, @var{opt})\n\
00055 @deftypefnx {Loadable Function} {[@var{CC}, @var{DD}, @var{AA}, @var{BB}] =} balance (@var{A}, @var{B}, @var{opt})\n\
00056 \n\
00057 Compute @code{@var{AA} = @var{DD} \\ @var{A} * @var{DD}} in which @var{AA}\n\
00058 is a matrix whose row and column norms are roughly equal in magnitude, and\n\
00059 @code{@var{DD} = @var{P} * @var{D}}, in which @var{P} is a permutation\n\
00060 matrix and @var{D} is a diagonal matrix of powers of two. This allows the\n\
00061 equilibration to be computed without round-off. Results of eigenvalue\n\
00062 calculation are typically improved by balancing first.\n\
00063 \n\
00064 If two output values are requested, @code{balance} returns\n\
00065 the diagonal @var{D} and the permutation @var{P} separately as vectors.\n\
00066 In this case, @code{@var{DD} = eye(n)(:,@var{P}) * diag (@var{D})}, where\n\
00067 @math{n} is the matrix size.\n\
00068 \n\
00069 If four output values are requested, compute @code{@var{AA} =\n\
00070 @var{CC}*@var{A}*@var{DD}} and @code{@var{BB} = @var{CC}*@var{B}*@var{DD}},\n\
00071 in which @var{AA} and @var{BB} have non-zero elements of approximately the\n\
00072 same magnitude and @var{CC} and @var{DD} are permuted diagonal matrices as\n\
00073 in @var{DD} for the algebraic eigenvalue problem.\n\
00074 \n\
00075 The eigenvalue balancing option @var{opt} may be one of:\n\
00076 \n\
00077 @table @asis\n\
00078 @item \"noperm\", \"S\"\n\
00079 Scale only; do not permute.\n\
00080 \n\
00081 @item \"noscal\", \"P\"\n\
00082 Permute only; do not scale.\n\
00083 @end table\n\
00084 \n\
00085 Algebraic eigenvalue balancing uses standard @sc{lapack} routines.\n\
00086 \n\
00087 Generalized eigenvalue problem balancing uses Ward's algorithm\n\
00088 (SIAM Journal on Scientific and Statistical Computing, 1981).\n\
00089 @end deftypefn")
00090 {
00091 octave_value_list retval;
00092
00093 int nargin = args.length ();
00094
00095 if (nargin < 1 || nargin > 3 || nargout < 0 || nargout > 4)
00096 {
00097 print_usage ();
00098 return retval;
00099 }
00100
00101
00102 bool AEPcase = nargin == 1 || args(1).is_string ();
00103
00104
00105 octave_idx_type nn = args(0).rows ();
00106
00107 if (nn != args(0).columns())
00108 {
00109 gripe_square_matrix_required ("balance");
00110 return retval;
00111 }
00112
00113 bool isfloat = args(0).is_single_type () ||
00114 (! AEPcase && args(1).is_single_type());
00115
00116 bool complex_case = (args(0).is_complex_type () ||
00117 (! AEPcase && args(1).is_complex_type ()));
00118
00119
00120 Matrix aa;
00121 ComplexMatrix caa;
00122 FloatMatrix faa;
00123 FloatComplexMatrix fcaa;
00124
00125 if (isfloat)
00126 {
00127 if (complex_case)
00128 fcaa = args(0).float_complex_matrix_value ();
00129 else
00130 faa = args(0).float_matrix_value ();
00131 }
00132 else
00133 {
00134 if (complex_case)
00135 caa = args(0).complex_matrix_value ();
00136 else
00137 aa = args(0).matrix_value ();
00138 }
00139
00140 if (error_state)
00141 return retval;
00142
00143
00144 if (AEPcase)
00145 {
00146
00147 bool noperm = false, noscal = false;
00148 if (nargin > 1)
00149 {
00150 std::string a1s = args(1).string_value ();
00151 noperm = a1s == "noperm" || a1s == "S";
00152 noscal = a1s == "noscal" || a1s == "P";
00153 }
00154
00155
00156 if (isfloat)
00157 {
00158 if (complex_case)
00159 {
00160 FloatComplexAEPBALANCE result (fcaa, noperm, noscal);
00161
00162 if (nargout == 0 || nargout == 1)
00163 retval(0) = result.balanced_matrix ();
00164 else if (nargout == 2)
00165 {
00166 retval(1) = result.balanced_matrix ();
00167 retval(0) = result.balancing_matrix ();
00168 }
00169 else
00170 {
00171 retval(2) = result.balanced_matrix ();
00172 retval(1) = result.permuting_vector ();
00173 retval(0) = result.scaling_vector ();
00174 }
00175
00176 }
00177 else
00178 {
00179 FloatAEPBALANCE result (faa, noperm, noscal);
00180
00181 if (nargout == 0 || nargout == 1)
00182 retval(0) = result.balanced_matrix ();
00183 else if (nargout == 2)
00184 {
00185 retval(1) = result.balanced_matrix ();
00186 retval(0) = result.balancing_matrix ();
00187 }
00188 else
00189 {
00190 retval(2) = result.balanced_matrix ();
00191 retval(1) = result.permuting_vector ();
00192 retval(0) = result.scaling_vector ();
00193 }
00194 }
00195 }
00196 else
00197 {
00198 if (complex_case)
00199 {
00200 ComplexAEPBALANCE result (caa, noperm, noscal);
00201
00202 if (nargout == 0 || nargout == 1)
00203 retval(0) = result.balanced_matrix ();
00204 else if (nargout == 2)
00205 {
00206 retval(1) = result.balanced_matrix ();
00207 retval(0) = result.balancing_matrix ();
00208 }
00209 else
00210 {
00211 retval(2) = result.balanced_matrix ();
00212 retval(1) = result.permuting_vector ();
00213 retval(0) = result.scaling_vector ();
00214 }
00215 }
00216 else
00217 {
00218 AEPBALANCE result (aa, noperm, noscal);
00219
00220 if (nargout == 0 || nargout == 1)
00221 retval(0) = result.balanced_matrix ();
00222 else if (nargout == 2)
00223 {
00224 retval(1) = result.balanced_matrix ();
00225 retval(0) = result.balancing_matrix ();
00226 }
00227 else
00228 {
00229 retval(2) = result.balanced_matrix ();
00230 retval(1) = result.permuting_vector ();
00231 retval(0) = result.scaling_vector ();
00232 }
00233 }
00234 }
00235 }
00236 else
00237 {
00238 std::string bal_job;
00239 if (nargout == 1)
00240 warning ("balance: used GEP, should have two output arguments");
00241
00242
00243 if (nargin == 2)
00244 bal_job = "B";
00245 else if (args(2).is_string ())
00246 bal_job = args(2).string_value ();
00247 else
00248 {
00249 error ("balance: OPT argument must be a string");
00250 return retval;
00251 }
00252
00253 if ((nn != args(1).columns ()) || (nn != args(1).rows ()))
00254 {
00255 gripe_nonconformant ();
00256 return retval;
00257 }
00258
00259 Matrix bb;
00260 ComplexMatrix cbb;
00261 FloatMatrix fbb;
00262 FloatComplexMatrix fcbb;
00263
00264 if (isfloat)
00265 {
00266 if (complex_case)
00267 fcbb = args(1).float_complex_matrix_value ();
00268 else
00269 fbb = args(1).float_matrix_value ();
00270 }
00271 else
00272 {
00273 if (complex_case)
00274 cbb = args(1).complex_matrix_value ();
00275 else
00276 bb = args(1).matrix_value ();
00277 }
00278
00279
00280 if (isfloat)
00281 {
00282 if (complex_case)
00283 {
00284 FloatComplexGEPBALANCE result (fcaa, fcbb, bal_job);
00285
00286 switch (nargout)
00287 {
00288 case 4:
00289 retval(3) = result.balanced_matrix2 ();
00290
00291 case 3:
00292 retval(2) = result.balanced_matrix ();
00293 retval(1) = result.balancing_matrix2 ();
00294 retval(0) = result.balancing_matrix ();
00295 break;
00296 case 2:
00297 retval(1) = result.balancing_matrix2 ();
00298
00299 case 1:
00300 retval(0) = result.balancing_matrix ();
00301 break;
00302 default:
00303 error ("balance: invalid number of output arguments");
00304 break;
00305 }
00306 }
00307 else
00308 {
00309 FloatGEPBALANCE result (faa, fbb, bal_job);
00310
00311 switch (nargout)
00312 {
00313 case 4:
00314 retval(3) = result.balanced_matrix2 ();
00315
00316 case 3:
00317 retval(2) = result.balanced_matrix ();
00318 retval(1) = result.balancing_matrix2 ();
00319 retval(0) = result.balancing_matrix ();
00320 break;
00321 case 2:
00322 retval(1) = result.balancing_matrix2 ();
00323
00324 case 1:
00325 retval(0) = result.balancing_matrix ();
00326 break;
00327 default:
00328 error ("balance: invalid number of output arguments");
00329 break;
00330 }
00331 }
00332 }
00333 else
00334 {
00335 if (complex_case)
00336 {
00337 ComplexGEPBALANCE result (caa, cbb, bal_job);
00338
00339 switch (nargout)
00340 {
00341 case 4:
00342 retval(3) = result.balanced_matrix2 ();
00343
00344 case 3:
00345 retval(2) = result.balanced_matrix ();
00346 retval(1) = result.balancing_matrix2 ();
00347 retval(0) = result.balancing_matrix ();
00348 break;
00349 case 2:
00350 retval(1) = result.balancing_matrix2 ();
00351
00352 case 1:
00353 retval(0) = result.balancing_matrix ();
00354 break;
00355 default:
00356 error ("balance: invalid number of output arguments");
00357 break;
00358 }
00359 }
00360 else
00361 {
00362 GEPBALANCE result (aa, bb, bal_job);
00363
00364 switch (nargout)
00365 {
00366 case 4:
00367 retval(3) = result.balanced_matrix2 ();
00368
00369 case 3:
00370 retval(2) = result.balanced_matrix ();
00371 retval(1) = result.balancing_matrix2 ();
00372 retval(0) = result.balancing_matrix ();
00373 break;
00374 case 2:
00375 retval(1) = result.balancing_matrix2 ();
00376
00377 case 1:
00378 retval(0) = result.balancing_matrix ();
00379 break;
00380 default:
00381 error ("balance: invalid number of output arguments");
00382 break;
00383 }
00384 }
00385 }
00386 }
00387
00388 return retval;
00389 }