libQZ.neardist
changeset 17 4b7486d77b39
equal deleted inserted replaced
15:ebd8a4ddd7f2 17:4b7486d77b39
       
     1 #======================================================================
       
     2 #                    L I B Q Z . P L 
       
     3 #                    doc: Thu Mar 12 15:23:15 2015
       
     4 #                    dlm: Thu Mar 12 20:52:43 2015
       
     5 #                    (c) 2015 A.M. Thurnherr
       
     6 #                    uE-Info: 36 0 NIL 0 0 72 2 2 4 NIL ofnI
       
     7 #======================================================================
       
     8 
       
     9 # adaptation of EISPACK routines
       
    10 
       
    11 # www.netlib.org/eispack
       
    12 
       
    13 sub eig($$)
       
    14 {
       
    15 	my($aR,$bR) = @_;							# args passed as refs
       
    16 
       
    17 	my($N) = scalar(@{aR});
       
    18 	croak("eig(A,B): A & B must be matching square matrices\n")
       
    19 		unless (@{bR} == $N) && (@{$aR->[0]} == $N) && (@{$bR->[0]} == $N);
       
    20 
       
    21 		ar = new double[n];
       
    22 		ai = new double[n];
       
    23 		beta = new double[n];
       
    24 		var A = (double[,])a.Clone();
       
    25 		var B = (double[,])b.Clone();
       
    26 
       
    27 	my($matZ) = 1;
       
    28 	my($iErr) = 0;
       
    29 
       
    30 	my(@Z);
       
    31 	QZhes($aR,$bR,\@Z);								# reduce A/B to upper Hessenberg/triangular forms
       
    32 	QZit($aR,$bR,\@Z,\$iErr);						# reduce Hess A to quasi-triangular form
       
    33 	QZval($aR,$bR,\@Z,\@alphaR,\@alphaI,\@beta);	# reduce A further
       
    34 	QZvec($aR,$bR,\@Z,\@alphaR,\@alphaI,\@beta);	# compute eigenvectors & eigenvalues
       
    35 }
       
    36 
       
    37 
       
    38 	/// <summary>Returns the real parts of the alpha values.</summary>
       
    39 	public double[] RealAlphas
       
    40 	{
       
    41 		get { return ar; }
       
    42 	}
       
    43 
       
    44 	/// <summary>Returns the imaginary parts of the alpha values.</summary>
       
    45 	public double[] ImaginaryAlphas
       
    46 	{
       
    47 		get { return ai; }
       
    48 	}
       
    49 
       
    50 	/// <summary>Returns the beta values.</summary>
       
    51 	public double[] Betas
       
    52 	{
       
    53 		get { return beta; }
       
    54 	}
       
    55 
       
    56 	/// <summary>
       
    57 	///   Returns true if matrix B is singular.
       
    58 	/// </summary>
       
    59 	/// <remarks>
       
    60 	///   This method checks if any of the generated betas is zero. It
       
    61 	///   does not says that the problem is singular, but only that one
       
    62 	///   of the matrices of the pencil (A,B) is singular.
       
    63 	/// </remarks>
       
    64 	public bool IsSingular
       
    65 	{
       
    66 		get
       
    67 		{
       
    68 			for (int i = 0; i < n; i++)
       
    69 				if (beta[i] == 0)
       
    70 					return true;
       
    71 			return false;
       
    72 		}
       
    73 	}
       
    74 
       
    75 	/// <summary>
       
    76 	///   Returns true if the eigenvalue problem is degenerate (ill-posed).
       
    77 	/// </summary>
       
    78 	public bool IsDegenerate
       
    79 	{
       
    80 		get
       
    81 		{
       
    82 			for (int i = 0; i < n; i++)
       
    83 				if (beta[i] == 0 && ar[i] == 0)
       
    84 					return true;
       
    85 			return false;
       
    86 		}
       
    87 	}
       
    88 
       
    89 	/// <summary>Returns the real parts of the eigenvalues.</summary>
       
    90 	/// <remarks>
       
    91 	///   The eigenvalues are computed using the ratio alpha[i]/beta[i],
       
    92 	///   which can lead to valid, but infinite eigenvalues.
       
    93 	/// </remarks>
       
    94 	public double[] RealEigenvalues
       
    95 	{
       
    96 		get
       
    97 		{
       
    98 			// ((alfr+i*alfi)/beta)
       
    99 			double[] eval = new double[n];
       
   100 			for (int i = 0; i < n; i++)
       
   101 				eval[i] = ar[i] / beta[i];
       
   102 			return eval;
       
   103 		}
       
   104 	}
       
   105 
       
   106 	/// <summary>Returns the imaginary parts of the eigenvalues.</summary>  
       
   107 	/// <remarks>
       
   108 	///   The eigenvalues are computed using the ratio alpha[i]/beta[i],
       
   109 	///   which can lead to valid, but infinite eigenvalues.
       
   110 	/// </remarks>
       
   111 	public double[] ImaginaryEigenvalues
       
   112 	{
       
   113 		get
       
   114 		{
       
   115 			// ((alfr+i*alfi)/beta)
       
   116 			double[] eval = new double[n];
       
   117 			for (int i = 0; i < n; i++)
       
   118 				eval[i] = ai[i] / beta[i];
       
   119 			return eval;
       
   120 		}
       
   121 	}
       
   122 
       
   123 	/// <summary>Returns the eigenvector matrix.</summary>
       
   124 	public double[,] Eigenvectors
       
   125 	{
       
   126 		get
       
   127 		{
       
   128 			return Z;
       
   129 		}
       
   130 	}
       
   131 
       
   132 	/// <summary>Returns the block diagonal eigenvalue matrix.</summary>
       
   133 	public double[,] DiagonalMatrix
       
   134 	{
       
   135 		get
       
   136 		{
       
   137 			double[,] x = new double[n, n];
       
   138 
       
   139 			for (int i = 0; i < n; i++)
       
   140 			{
       
   141 				for (int j = 0; j < n; j++)
       
   142 					x[i, j] = 0.0;
       
   143 
       
   144 				x[i, i] = ar[i] / beta[i];
       
   145 				if (ai[i] > 0)
       
   146 					x[i, i + 1] = ai[i] / beta[i];
       
   147 				else if (ai[i] < 0)
       
   148 					x[i, i - 1] = ai[i] / beta[i];
       
   149 			}
       
   150 
       
   151 			return x;
       
   152 		}
       
   153 	}
       
   154 
       
   155 
       
   156 
       
   157 	#region EISPACK Routines
       
   158 	/// <summary>
       
   159 	///   Adaptation of the original Fortran QZHES routine from EISPACK.
       
   160 	/// </summary>
       
   161 	/// <remarks>
       
   162 	///   This subroutine is the first step of the qz algorithm
       
   163 	///   for solving generalized matrix eigenvalue problems,
       
   164 	///   siam j. numer. anal. 10, 241-256(1973) by moler and stewart.
       
   165 	///
       
   166 	///   This subroutine accepts a pair of real general matrices and
       
   167 	///   reduces one of them to upper hessenberg form and the other
       
   168 	///   to upper triangular form using orthogonal transformations.
       
   169 	///   it is usually followed by  qzit,	qzval  and, possibly,  qzvec.
       
   170 	///  
       
   171 	///   For the full documentation, please check the original function.
       
   172 	/// </remarks>
       
   173 	private static int qzhes(int n, double[,] a, double[,] b, bool matz, double[,] z)
       
   174 	{
       
   175 		int i, j, k, l;
       
   176 		double r, s, t;
       
   177 		int l1;
       
   178 		double u1, u2, v1, v2;
       
   179 		int lb, nk1;
       
   180 		double rho;
       
   181 
       
   182 
       
   183 		if (matz)
       
   184 		{
       
   185 			// If we are interested in computing the
       
   186 			//	eigenvectors, set Z to identity(n,n)
       
   187 			for (j = 0; j < n; ++j)
       
   188 			{
       
   189 				for (i = 0; i < n; ++i)
       
   190 					z[i, j] = 0.0;
       
   191 				z[j, j] = 1.0;
       
   192 			}
       
   193 		}
       
   194 
       
   195 		// Reduce b to upper triangular form
       
   196 		if (n <= 1) return 0;
       
   197 		for (l = 0; l < n - 1; ++l)
       
   198 		{
       
   199 			l1 = l + 1;
       
   200 			s = 0.0;
       
   201 
       
   202 			for (i = l1; i < n; ++i)
       
   203 				s += (System.Math.Abs(b[i, l]));
       
   204 
       
   205 			if (s == 0.0) continue;
       
   206 			s += (System.Math.Abs(b[l, l]));
       
   207 			r = 0.0;
       
   208 
       
   209 			for (i = l; i < n; ++i)
       
   210 			{
       
   211 				// Computing 2nd power
       
   212 				b[i, l] /= s;
       
   213 				r += b[i, l] * b[i, l];
       
   214 			}
       
   215 
       
   216 			r = Special.Sign(System.Math.Sqrt(r), b[l, l]);
       
   217 			b[l, l] += r;
       
   218 			rho = r * b[l, l];
       
   219 
       
   220 			for (j = l1; j < n; ++j)
       
   221 			{
       
   222 				t = 0.0;
       
   223 				for (i = l; i < n; ++i)
       
   224 					t += b[i, l] * b[i, j];
       
   225 				t = -t / rho;
       
   226 				for (i = l; i < n; ++i)
       
   227 					b[i, j] += t * b[i, l];
       
   228 			}
       
   229 
       
   230 			for (j = 0; j < n; ++j)
       
   231 			{
       
   232 				t = 0.0;
       
   233 				for (i = l; i < n; ++i)
       
   234 					t += b[i, l] * a[i, j];
       
   235 				t = -t / rho;
       
   236 				for (i = l; i < n; ++i)
       
   237 					a[i, j] += t * b[i, l];
       
   238 			}
       
   239 
       
   240 			b[l, l] = -s * r;
       
   241 			for (i = l1; i < n; ++i)
       
   242 				b[i, l] = 0.0;
       
   243 		}
       
   244 
       
   245 		// Reduce a to upper hessenberg form, while keeping b triangular
       
   246 		if (n == 2) return 0;
       
   247 		for (k = 0; k < n - 2; ++k)
       
   248 		{
       
   249 			nk1 = n - 2 - k;
       
   250 
       
   251 			// for l=n-1 step -1 until k+1 do
       
   252 			for (lb = 0; lb < nk1; ++lb)
       
   253 			{
       
   254 				l = n - lb - 2;
       
   255 				l1 = l + 1;
       
   256 
       
   257 				// Zero a(l+1,k)
       
   258 				s = (System.Math.Abs(a[l, k])) + (System.Math.Abs(a[l1, k]));
       
   259 
       
   260 				if (s == 0.0) continue;
       
   261 				u1 = a[l, k] / s;
       
   262 				u2 = a[l1, k] / s;
       
   263 				r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   264 				v1 = -(u1 + r) / r;
       
   265 				v2 = -u2 / r;
       
   266 				u2 = v2 / v1;
       
   267 
       
   268 				for (j = k; j < n; ++j)
       
   269 				{
       
   270 					t = a[l, j] + u2 * a[l1, j];
       
   271 					a[l, j] += t * v1;
       
   272 					a[l1, j] += t * v2;
       
   273 				}
       
   274 
       
   275 				a[l1, k] = 0.0;
       
   276 
       
   277 				for (j = l; j < n; ++j)
       
   278 				{
       
   279 					t = b[l, j] + u2 * b[l1, j];
       
   280 					b[l, j] += t * v1;
       
   281 					b[l1, j] += t * v2;
       
   282 				}
       
   283 
       
   284 				// Zero b(l+1,l)
       
   285 				s = (System.Math.Abs(b[l1, l1])) + (System.Math.Abs(b[l1, l]));
       
   286 
       
   287 				if (s == 0.0) continue;
       
   288 				u1 = b[l1, l1] / s;
       
   289 				u2 = b[l1, l] / s;
       
   290 				r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   291 				v1 = -(u1 + r) / r;
       
   292 				v2 = -u2 / r;
       
   293 				u2 = v2 / v1;
       
   294 
       
   295 				for (i = 0; i <= l1; ++i)
       
   296 				{
       
   297 					t = b[i, l1] + u2 * b[i, l];
       
   298 					b[i, l1] += t * v1;
       
   299 					b[i, l] += t * v2;
       
   300 				}
       
   301 
       
   302 				b[l1, l] = 0.0;
       
   303 
       
   304 				for (i = 0; i < n; ++i)
       
   305 				{
       
   306 					t = a[i, l1] + u2 * a[i, l];
       
   307 					a[i, l1] += t * v1;
       
   308 					a[i, l] += t * v2;
       
   309 				}
       
   310 
       
   311 				if (matz)
       
   312 				{
       
   313 					for (i = 0; i < n; ++i)
       
   314 					{
       
   315 						t = z[i, l1] + u2 * z[i, l];
       
   316 						z[i, l1] += t * v1;
       
   317 						z[i, l] += t * v2;
       
   318 					}
       
   319 				}
       
   320 			}
       
   321 		}
       
   322 
       
   323 		return 0;
       
   324 	}
       
   325 
       
   326 	/// <summary>
       
   327 	///   Adaptation of the original Fortran QZIT routine from EISPACK.
       
   328 	/// </summary>
       
   329 	/// <remarks>
       
   330 	///   This subroutine is the second step of the qz algorithm
       
   331 	///   for solving generalized matrix eigenvalue problems,
       
   332 	///   siam j. numer. anal. 10, 241-256(1973) by moler and stewart,
       
   333 	///   as modified in technical note nasa tn d-7305(1973) by ward.
       
   334 	///  
       
   335 	///   This subroutine accepts a pair of real matrices, one of them
       
   336 	///   in upper hessenberg form and the other in upper triangular form.
       
   337 	///   it reduces the hessenberg matrix to quasi-triangular form using
       
   338 	///   orthogonal transformations while maintaining the triangular form
       
   339 	///   of the other matrix.	it is usually preceded by  qzhes  and
       
   340 	///   followed by  qzval  and, possibly,  qzvec.
       
   341 	///  
       
   342 	///   For the full documentation, please check the original function.
       
   343 	/// </remarks>
       
   344 	private static int qzit(int n, double[,] a, double[,] b, double eps1, bool matz, double[,] z, ref int ierr)
       
   345 	{
       
   346 
       
   347 		int i, j, k, l = 0;
       
   348 		double r, s, t, a1, a2, a3 = 0;
       
   349 		int k1, k2, l1, ll;
       
   350 		double u1, u2, u3;
       
   351 		double v1, v2, v3;
       
   352 		double a11, a12, a21, a22, a33, a34, a43, a44;
       
   353 		double b11, b12, b22, b33, b34, b44;
       
   354 		int na, en, ld;
       
   355 		double ep;
       
   356 		double sh = 0;
       
   357 		int km1, lm1 = 0;
       
   358 		double ani, bni;
       
   359 		int ish, itn, its, enm2, lor1;
       
   360 		double epsa, epsb, anorm = 0, bnorm = 0;
       
   361 		int enorn;
       
   362 		bool notlas;
       
   363 
       
   364 
       
   365 		ierr = 0;
       
   366 
       
   367 		#region Compute epsa and epsb
       
   368 		for (i = 0; i < n; ++i)
       
   369 		{
       
   370 			ani = 0.0;
       
   371 			bni = 0.0;
       
   372 
       
   373 			if (i != 0)
       
   374 				ani = (Math.Abs(a[i, (i - 1)]));
       
   375 
       
   376 			for (j = i; j < n; ++j)
       
   377 			{
       
   378 				ani += Math.Abs(a[i, j]);
       
   379 				bni += Math.Abs(b[i, j]);
       
   380 			}
       
   381 
       
   382 			if (ani > anorm) anorm = ani;
       
   383 			if (bni > bnorm) bnorm = bni;
       
   384 		}
       
   385 
       
   386 		if (anorm == 0.0) anorm = 1.0;
       
   387 		if (bnorm == 0.0) bnorm = 1.0;
       
   388 
       
   389 		ep = eps1;
       
   390 		if (ep == 0.0)
       
   391 		{
       
   392 			// Use roundoff level if eps1 is zero
       
   393 			ep = Special.Epslon(1.0);
       
   394 		}
       
   395 
       
   396 		epsa = ep * anorm;
       
   397 		epsb = ep * bnorm;
       
   398 		#endregion
       
   399 
       
   400 
       
   401 		// Reduce a to quasi-triangular form, while keeping b triangular
       
   402 		lor1 = 0;
       
   403 		enorn = n;
       
   404 		en = n - 1;
       
   405 		itn = n * 30;
       
   406 
       
   407 	// Begin QZ step
       
   408 	L60:
       
   409 		if (en <= 1) goto L1001;
       
   410 		if (!matz) enorn = en + 1;
       
   411 
       
   412 		its = 0;
       
   413 		na = en - 1;
       
   414 		enm2 = na;
       
   415 
       
   416 	L70:
       
   417 		ish = 2;
       
   418 		// Check for convergence or reducibility.
       
   419 		for (ll = 0; ll <= en; ++ll)
       
   420 		{
       
   421 			lm1 = en - ll - 1;
       
   422 			l = lm1 + 1;
       
   423 
       
   424 			if (l + 1 == 1)
       
   425 				goto L95;
       
   426 
       
   427 			if ((Math.Abs(a[l, lm1])) <= epsa)
       
   428 				break;
       
   429 		}
       
   430 
       
   431 	L90:
       
   432 		a[l, lm1] = 0.0;
       
   433 		if (l < na) goto L95;
       
   434 
       
   435 		// 1-by-1 or 2-by-2 block isolated
       
   436 		en = lm1;
       
   437 		goto L60;
       
   438 
       
   439 	// Check for small top of b
       
   440 	L95:
       
   441 		ld = l;
       
   442 
       
   443 	L100:
       
   444 		l1 = l + 1;
       
   445 		b11 = b[l, l];
       
   446 
       
   447 		if (Math.Abs(b11) > epsb) goto L120;
       
   448 
       
   449 		b[l, l] = 0.0;
       
   450 		s = (Math.Abs(a[l, l]) + Math.Abs(a[l1, l]));
       
   451 		u1 = a[l, l] / s;
       
   452 		u2 = a[l1, l] / s;
       
   453 		r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   454 		v1 = -(u1 + r) / r;
       
   455 		v2 = -u2 / r;
       
   456 		u2 = v2 / v1;
       
   457 
       
   458 		for (j = l; j < enorn; ++j)
       
   459 		{
       
   460 			t = a[l, j] + u2 * a[l1, j];
       
   461 			a[l, j] += t * v1;
       
   462 			a[l1, j] += t * v2;
       
   463 
       
   464 			t = b[l, j] + u2 * b[l1, j];
       
   465 			b[l, j] += t * v1;
       
   466 			b[l1, j] += t * v2;
       
   467 		}
       
   468 
       
   469 		if (l != 0)
       
   470 			a[l, lm1] = -a[l, lm1];
       
   471 
       
   472 		lm1 = l;
       
   473 		l = l1;
       
   474 		goto L90;
       
   475 
       
   476 	L120:
       
   477 		a11 = a[l, l] / b11;
       
   478 		a21 = a[l1, l] / b11;
       
   479 		if (ish == 1) goto L140;
       
   480 
       
   481 		// Iteration strategy
       
   482 		if (itn == 0) goto L1000;
       
   483 		if (its == 10) goto L155;
       
   484 
       
   485 		// Determine type of shift
       
   486 		b22 = b[l1, l1];
       
   487 		if (Math.Abs(b22) < epsb) b22 = epsb;
       
   488 		b33 = b[na, na];
       
   489 		if (Math.Abs(b33) < epsb) b33 = epsb;
       
   490 		b44 = b[en, en];
       
   491 		if (Math.Abs(b44) < epsb) b44 = epsb;
       
   492 		a33 = a[na, na] / b33;
       
   493 		a34 = a[na, en] / b44;
       
   494 		a43 = a[en, na] / b33;
       
   495 		a44 = a[en, en] / b44;
       
   496 		b34 = b[na, en] / b44;
       
   497 		t = (a43 * b34 - a33 - a44) * .5;
       
   498 		r = t * t + a34 * a43 - a33 * a44;
       
   499 		if (r < 0.0) goto L150;
       
   500 
       
   501 		// Determine single shift zeroth column of a
       
   502 		ish = 1;
       
   503 		r = Math.Sqrt(r);
       
   504 		sh = -t + r;
       
   505 		s = -t - r;
       
   506 		if (Math.Abs(s - a44) < Math.Abs(sh - a44))
       
   507 			sh = s;
       
   508 
       
   509 		// Look for two consecutive small sub-diagonal elements of a.
       
   510 		for (ll = ld; ll + 1 <= enm2; ++ll)
       
   511 		{
       
   512 			l = enm2 + ld - ll - 1;
       
   513 
       
   514 			if (l == ld)
       
   515 				goto L140;
       
   516 
       
   517 			lm1 = l - 1;
       
   518 			l1 = l + 1;
       
   519 			t = a[l + 1, l + 1];
       
   520 
       
   521 			if (Math.Abs(b[l, l]) > epsb)
       
   522 				t -= sh * b[l, l];
       
   523 
       
   524 			if (Math.Abs(a[l, lm1]) <= (Math.Abs(t / a[l1, l])) * epsa)
       
   525 				goto L100;
       
   526 		}
       
   527 
       
   528 	L140:
       
   529 		a1 = a11 - sh;
       
   530 		a2 = a21;
       
   531 		if (l != ld)
       
   532 			a[l, lm1] = -a[l, lm1];
       
   533 		goto L160;
       
   534 
       
   535 	// Determine double shift zeroth column of a
       
   536 	L150:
       
   537 		a12 = a[l, l1] / b22;
       
   538 		a22 = a[l1, l1] / b22;
       
   539 		b12 = b[l, l1] / b22;
       
   540 		a1 = ((a33 - a11) * (a44 - a11) - a34 * a43 + a43 * b34 * a11) / a21 + a12 - a11 * b12;
       
   541 		a2 = a22 - a11 - a21 * b12 - (a33 - a11) - (a44 - a11) + a43 * b34;
       
   542 		a3 = a[l1 + 1, l1] / b22;
       
   543 		goto L160;
       
   544 
       
   545 	// Ad hoc shift
       
   546 	L155:
       
   547 		a1 = 0.0;
       
   548 		a2 = 1.0;
       
   549 		a3 = 1.1605;
       
   550 
       
   551 	L160:
       
   552 		++its;
       
   553 		--itn;
       
   554 
       
   555 		if (!matz) lor1 = ld;
       
   556 
       
   557 		// Main loop
       
   558 		for (k = l; k <= na; ++k)
       
   559 		{
       
   560 			notlas = k != na && ish == 2;
       
   561 			k1 = k + 1;
       
   562 			k2 = k + 2;
       
   563 
       
   564 			km1 = Math.Max(k, l + 1) - 1; // Computing MAX
       
   565 			ll = Math.Min(en, k1 + ish);  // Computing MIN
       
   566 
       
   567 			if (notlas) goto L190;
       
   568 
       
   569 			// Zero a(k+1,k-1)
       
   570 			if (k == l) goto L170;
       
   571 			a1 = a[k, km1];
       
   572 			a2 = a[k1, km1];
       
   573 
       
   574 		L170:
       
   575 			s = Math.Abs(a1) + Math.Abs(a2);
       
   576 			if (s == 0.0) goto L70;
       
   577 			u1 = a1 / s;
       
   578 			u2 = a2 / s;
       
   579 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   580 			v1 = -(u1 + r) / r;
       
   581 			v2 = -u2 / r;
       
   582 			u2 = v2 / v1;
       
   583 
       
   584 			for (j = km1; j < enorn; ++j)
       
   585 			{
       
   586 				t = a[k, j] + u2 * a[k1, j];
       
   587 				a[k, j] += t * v1;
       
   588 				a[k1, j] += t * v2;
       
   589 
       
   590 				t = b[k, j] + u2 * b[k1, j];
       
   591 				b[k, j] += t * v1;
       
   592 				b[k1, j] += t * v2;
       
   593 			}
       
   594 
       
   595 			if (k != l)
       
   596 				a[k1, km1] = 0.0;
       
   597 			goto L240;
       
   598 
       
   599 			// Zero a(k+1,k-1) and a(k+2,k-1)
       
   600 		L190:
       
   601 			if (k == l) goto L200;
       
   602 			a1 = a[k, km1];
       
   603 			a2 = a[k1, km1];
       
   604 			a3 = a[k2, km1];
       
   605 
       
   606 		L200:
       
   607 			s = Math.Abs(a1) + Math.Abs(a2) + Math.Abs(a3);
       
   608 			if (s == 0.0) goto L260;
       
   609 			u1 = a1 / s;
       
   610 			u2 = a2 / s;
       
   611 			u3 = a3 / s;
       
   612 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2 + u3 * u3), u1);
       
   613 			v1 = -(u1 + r) / r;
       
   614 			v2 = -u2 / r;
       
   615 			v3 = -u3 / r;
       
   616 			u2 = v2 / v1;
       
   617 			u3 = v3 / v1;
       
   618 
       
   619 			for (j = km1; j < enorn; ++j)
       
   620 			{
       
   621 				t = a[k, j] + u2 * a[k1, j] + u3 * a[k2, j];
       
   622 				a[k, j] += t * v1;
       
   623 				a[k1, j] += t * v2;
       
   624 				a[k2, j] += t * v3;
       
   625 
       
   626 				t = b[k, j] + u2 * b[k1, j] + u3 * b[k2, j];
       
   627 				b[k, j] += t * v1;
       
   628 				b[k1, j] += t * v2;
       
   629 				b[k2, j] += t * v3;
       
   630 			}
       
   631 
       
   632 			if (k == l) goto L220;
       
   633 			a[k1, km1] = 0.0;
       
   634 			a[k2, km1] = 0.0;
       
   635 
       
   636 		// Zero b(k+2,k+1) and b(k+2,k)
       
   637 		L220:
       
   638 			s = (Math.Abs(b[k2, k2])) + (Math.Abs(b[k2, k1])) + (Math.Abs(b[k2, k]));
       
   639 			if (s == 0.0) goto L240;
       
   640 			u1 = b[k2, k2] / s;
       
   641 			u2 = b[k2, k1] / s;
       
   642 			u3 = b[k2, k] / s;
       
   643 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2 + u3 * u3), u1);
       
   644 			v1 = -(u1 + r) / r;
       
   645 			v2 = -u2 / r;
       
   646 			v3 = -u3 / r;
       
   647 			u2 = v2 / v1;
       
   648 			u3 = v3 / v1;
       
   649 
       
   650 			for (i = lor1; i < ll + 1; ++i)
       
   651 			{
       
   652 				t = a[i, k2] + u2 * a[i, k1] + u3 * a[i, k];
       
   653 				a[i, k2] += t * v1;
       
   654 				a[i, k1] += t * v2;
       
   655 				a[i, k] += t * v3;
       
   656 
       
   657 				t = b[i, k2] + u2 * b[i, k1] + u3 * b[i, k];
       
   658 				b[i, k2] += t * v1;
       
   659 				b[i, k1] += t * v2;
       
   660 				b[i, k] += t * v3;
       
   661 			}
       
   662 
       
   663 			b[k2, k] = 0.0;
       
   664 			b[k2, k1] = 0.0;
       
   665 
       
   666 			if (matz)
       
   667 			{
       
   668 				for (i = 0; i < n; ++i)
       
   669 				{
       
   670 					t = z[i, k2] + u2 * z[i, k1] + u3 * z[i, k];
       
   671 					z[i, k2] += t * v1;
       
   672 					z[i, k1] += t * v2;
       
   673 					z[i, k] += t * v3;
       
   674 				}
       
   675 			}
       
   676 
       
   677 		// Zero b(k+1,k)
       
   678 		L240:
       
   679 			s = (Math.Abs(b[k1, k1])) + (Math.Abs(b[k1, k]));
       
   680 			if (s == 0.0) goto L260;
       
   681 			u1 = b[k1, k1] / s;
       
   682 			u2 = b[k1, k] / s;
       
   683 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   684 			v1 = -(u1 + r) / r;
       
   685 			v2 = -u2 / r;
       
   686 			u2 = v2 / v1;
       
   687 
       
   688 			for (i = lor1; i < ll + 1; ++i)
       
   689 			{
       
   690 				t = a[i, k1] + u2 * a[i, k];
       
   691 				a[i, k1] += t * v1;
       
   692 				a[i, k] += t * v2;
       
   693 
       
   694 				t = b[i, k1] + u2 * b[i, k];
       
   695 				b[i, k1] += t * v1;
       
   696 				b[i, k] += t * v2;
       
   697 			}
       
   698 
       
   699 			b[k1, k] = 0.0;
       
   700 
       
   701 			if (matz)
       
   702 			{
       
   703 				for (i = 0; i < n; ++i)
       
   704 				{
       
   705 					t = z[i, k1] + u2 * z[i, k];
       
   706 					z[i, k1] += t * v1;
       
   707 					z[i, k] += t * v2;
       
   708 				}
       
   709 			}
       
   710 
       
   711 		L260:
       
   712 			;
       
   713 		}
       
   714 
       
   715 		goto L70; // End QZ step
       
   716 
       
   717 	// Set error -- all eigenvalues have not converged after 30*n iterations
       
   718 	L1000:
       
   719 		ierr = en + 1;
       
   720 
       
   721 	// Save epsb for use by qzval and qzvec
       
   722 	L1001:
       
   723 		if (n > 1)
       
   724 			b[n - 1, 0] = epsb;
       
   725 		return 0;
       
   726 	}
       
   727 
       
   728 	/// <summary>
       
   729 	///   Adaptation of the original Fortran QZVAL routine from EISPACK.
       
   730 	/// </summary>
       
   731 	/// <remarks>
       
   732 	///   This subroutine is the third step of the qz algorithm
       
   733 	///   for solving generalized matrix eigenvalue problems,
       
   734 	///   siam j. numer. anal. 10, 241-256(1973) by moler and stewart.
       
   735 	///  
       
   736 	///   This subroutine accepts a pair of real matrices, one of them
       
   737 	///   in quasi-triangular form and the other in upper triangular form.
       
   738 	///   it reduces the quasi-triangular matrix further, so that any
       
   739 	///   remaining 2-by-2 blocks correspond to pairs of complex
       
   740 	///   eigenvalues, and returns quantities whose ratios give the
       
   741 	///   generalized eigenvalues.	it is usually preceded by  qzhes
       
   742 	///   and  qzit  and may be followed by  qzvec.
       
   743 	///  
       
   744 	///   For the full documentation, please check the original function.
       
   745 	/// </remarks>
       
   746 	private static int qzval(int n, double[,] a, double[,] b, double[] alfr, double[] alfi, double[] beta, bool matz, double[,] z)
       
   747 	{
       
   748 		int i, j;
       
   749 		int na, en, nn;
       
   750 		double c, d, e = 0;
       
   751 		double r, s, t;
       
   752 		double a1, a2, u1, u2, v1, v2;
       
   753 		double a11, a12, a21, a22;
       
   754 		double b11, b12, b22;
       
   755 		double di, ei;
       
   756 		double an = 0, bn;
       
   757 		double cq, dr;
       
   758 		double cz, ti, tr;
       
   759 		double a1i, a2i, a11i, a12i, a22i, a11r, a12r, a22r;
       
   760 		double sqi, ssi, sqr, szi, ssr, szr;
       
   761 
       
   762 		double epsb = b[n - 1, 0];
       
   763 		int isw = 1;
       
   764 
       
   765 
       
   766 		// Find eigenvalues of quasi-triangular matrices.
       
   767 		for (nn = 0; nn < n; ++nn)
       
   768 		{
       
   769 			en = n - nn - 1;
       
   770 			na = en - 1;
       
   771 
       
   772 			if (isw == 2) goto L505;
       
   773 			if (en == 0) goto L410;
       
   774 			if (a[en, na] != 0.0) goto L420;
       
   775 
       
   776 		// 1-by-1 block, one real root
       
   777 		L410:
       
   778 			alfr[en] = a[en, en];
       
   779 			if (b[en, en] < 0.0)
       
   780 			{
       
   781 				alfr[en] = -alfr[en];
       
   782 			}
       
   783 			beta[en] = (Math.Abs(b[en, en]));
       
   784 			alfi[en] = 0.0;
       
   785 			goto L510;
       
   786 
       
   787 		// 2-by-2 block
       
   788 		L420:
       
   789 			if (Math.Abs(b[na, na]) <= epsb) goto L455;
       
   790 			if (Math.Abs(b[en, en]) > epsb) goto L430;
       
   791 			a1 = a[en, en];
       
   792 			a2 = a[en, na];
       
   793 			bn = 0.0;
       
   794 			goto L435;
       
   795 
       
   796 		L430:
       
   797 			an = Math.Abs(a[na, na]) + Math.Abs(a[na, en]) + Math.Abs(a[en, na]) + Math.Abs(a[en, en]);
       
   798 			bn = Math.Abs(b[na, na]) + Math.Abs(b[na, en]) + Math.Abs(b[en, en]);
       
   799 			a11 = a[na, na] / an;
       
   800 			a12 = a[na, en] / an;
       
   801 			a21 = a[en, na] / an;
       
   802 			a22 = a[en, en] / an;
       
   803 			b11 = b[na, na] / bn;
       
   804 			b12 = b[na, en] / bn;
       
   805 			b22 = b[en, en] / bn;
       
   806 			e = a11 / b11;
       
   807 			ei = a22 / b22;
       
   808 			s = a21 / (b11 * b22);
       
   809 			t = (a22 - e * b22) / b22;
       
   810 
       
   811 			if (Math.Abs(e) <= Math.Abs(ei))
       
   812 				goto L431;
       
   813 
       
   814 			e = ei;
       
   815 			t = (a11 - e * b11) / b11;
       
   816 
       
   817 		L431:
       
   818 			c = (t - s * b12) * .5;
       
   819 			d = c * c + s * (a12 - e * b12);
       
   820 			if (d < 0.0) goto L480;
       
   821 
       
   822 			// Two real roots. Zero both a(en,na) and b(en,na)
       
   823 			e += c + Special.Sign(Math.Sqrt(d), c);
       
   824 			a11 -= e * b11;
       
   825 			a12 -= e * b12;
       
   826 			a22 -= e * b22;
       
   827 
       
   828 			if (Math.Abs(a11) + Math.Abs(a12) < Math.Abs(a21) + Math.Abs(a22))
       
   829 				goto L432;
       
   830 
       
   831 			a1 = a12;
       
   832 			a2 = a11;
       
   833 			goto L435;
       
   834 
       
   835 		L432:
       
   836 			a1 = a22;
       
   837 			a2 = a21;
       
   838 
       
   839 		// Choose and apply real z
       
   840 		L435:
       
   841 			s = Math.Abs(a1) + Math.Abs(a2);
       
   842 			u1 = a1 / s;
       
   843 			u2 = a2 / s;
       
   844 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   845 			v1 = -(u1 + r) / r;
       
   846 			v2 = -u2 / r;
       
   847 			u2 = v2 / v1;
       
   848 
       
   849 			for (i = 0; i <= en; ++i)
       
   850 			{
       
   851 				t = a[i, en] + u2 * a[i, na];
       
   852 				a[i, en] += t * v1;
       
   853 				a[i, na] += t * v2;
       
   854 
       
   855 				t = b[i, en] + u2 * b[i, na];
       
   856 				b[i, en] += t * v1;
       
   857 				b[i, na] += t * v2;
       
   858 			}
       
   859 
       
   860 			if (matz)
       
   861 			{
       
   862 				for (i = 0; i < n; ++i)
       
   863 				{
       
   864 					t = z[i, en] + u2 * z[i, na];
       
   865 					z[i, en] += t * v1;
       
   866 					z[i, na] += t * v2;
       
   867 				}
       
   868 			}
       
   869 
       
   870 			if (bn == 0.0) goto L475;
       
   871 			if (an < System.Math.Abs(e) * bn) goto L455;
       
   872 			a1 = b[na, na];
       
   873 			a2 = b[en, na];
       
   874 			goto L460;
       
   875 
       
   876 		L455:
       
   877 			a1 = a[na, na];
       
   878 			a2 = a[en, na];
       
   879 
       
   880 		// Choose and apply real q
       
   881 		L460:
       
   882 			s = System.Math.Abs(a1) + System.Math.Abs(a2);
       
   883 			if (s == 0.0) goto L475;
       
   884 			u1 = a1 / s;
       
   885 			u2 = a2 / s;
       
   886 			r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
       
   887 			v1 = -(u1 + r) / r;
       
   888 			v2 = -u2 / r;
       
   889 			u2 = v2 / v1;
       
   890 
       
   891 			for (j = na; j < n; ++j)
       
   892 			{
       
   893 				t = a[na, j] + u2 * a[en, j];
       
   894 				a[na, j] += t * v1;
       
   895 				a[en, j] += t * v2;
       
   896 
       
   897 				t = b[na, j] + u2 * b[en, j];
       
   898 				b[na, j] += t * v1;
       
   899 				b[en, j] += t * v2;
       
   900 			}
       
   901 
       
   902 		L475:
       
   903 			a[en, na] = 0.0;
       
   904 			b[en, na] = 0.0;
       
   905 			alfr[na] = a[na, na];
       
   906 			alfr[en] = a[en, en];
       
   907 
       
   908 			if (b[na, na] < 0.0)
       
   909 				alfr[na] = -alfr[na];
       
   910 
       
   911 			if (b[en, en] < 0.0)
       
   912 				alfr[en] = -alfr[en];
       
   913 
       
   914 			beta[na] = (System.Math.Abs(b[na, na]));
       
   915 			beta[en] = (System.Math.Abs(b[en, en]));
       
   916 			alfi[en] = 0.0;
       
   917 			alfi[na] = 0.0;
       
   918 			goto L505;
       
   919 
       
   920 			// Two complex roots
       
   921 		L480:
       
   922 			e += c;
       
   923 			ei = System.Math.Sqrt(-d);
       
   924 			a11r = a11 - e * b11;
       
   925 			a11i = ei * b11;
       
   926 			a12r = a12 - e * b12;
       
   927 			a12i = ei * b12;
       
   928 			a22r = a22 - e * b22;
       
   929 			a22i = ei * b22;
       
   930 
       
   931 			if (System.Math.Abs(a11r) + System.Math.Abs(a11i) +
       
   932 				System.Math.Abs(a12r) + System.Math.Abs(a12i) <
       
   933 				System.Math.Abs(a21) + System.Math.Abs(a22r)
       
   934 				+ System.Math.Abs(a22i))
       
   935 				goto L482;
       
   936 
       
   937 			a1 = a12r;
       
   938 			a1i = a12i;
       
   939 			a2 = -a11r;
       
   940 			a2i = -a11i;
       
   941 			goto L485;
       
   942 
       
   943 		L482:
       
   944 			a1 = a22r;
       
   945 			a1i = a22i;
       
   946 			a2 = -a21;
       
   947 			a2i = 0.0;
       
   948 
       
   949 		// Choose complex z
       
   950 		L485:
       
   951 			cz = System.Math.Sqrt(a1 * a1 + a1i * a1i);
       
   952 			if (cz == 0.0) goto L487;
       
   953 			szr = (a1 * a2 + a1i * a2i) / cz;
       
   954 			szi = (a1 * a2i - a1i * a2) / cz;
       
   955 			r = System.Math.Sqrt(cz * cz + szr * szr + szi * szi);
       
   956 			cz /= r;
       
   957 			szr /= r;
       
   958 			szi /= r;
       
   959 			goto L490;
       
   960 
       
   961 		L487:
       
   962 			szr = 1.0;
       
   963 			szi = 0.0;
       
   964 
       
   965 		L490:
       
   966 			if (an < (System.Math.Abs(e) + ei) * bn) goto L492;
       
   967 			a1 = cz * b11 + szr * b12;
       
   968 			a1i = szi * b12;
       
   969 			a2 = szr * b22;
       
   970 			a2i = szi * b22;
       
   971 			goto L495;
       
   972 
       
   973 		L492:
       
   974 			a1 = cz * a11 + szr * a12;
       
   975 			a1i = szi * a12;
       
   976 			a2 = cz * a21 + szr * a22;
       
   977 			a2i = szi * a22;
       
   978 
       
   979 		// Choose complex q
       
   980 		L495:
       
   981 			cq = System.Math.Sqrt(a1 * a1 + a1i * a1i);
       
   982 			if (cq == 0.0) goto L497;
       
   983 			sqr = (a1 * a2 + a1i * a2i) / cq;
       
   984 			sqi = (a1 * a2i - a1i * a2) / cq;
       
   985 			r = System.Math.Sqrt(cq * cq + sqr * sqr + sqi * sqi);
       
   986 			cq /= r;
       
   987 			sqr /= r;
       
   988 			sqi /= r;
       
   989 			goto L500;
       
   990 
       
   991 		L497:
       
   992 			sqr = 1.0;
       
   993 			sqi = 0.0;
       
   994 
       
   995 		// Compute diagonal elements that would result if transformations were applied
       
   996 		L500:
       
   997 			ssr = sqr * szr + sqi * szi;
       
   998 			ssi = sqr * szi - sqi * szr;
       
   999 			i = 0;
       
  1000 			tr = cq * cz * a11 + cq * szr * a12 + sqr * cz * a21 + ssr * a22;
       
  1001 			ti = cq * szi * a12 - sqi * cz * a21 + ssi * a22;
       
  1002 			dr = cq * cz * b11 + cq * szr * b12 + ssr * b22;
       
  1003 			di = cq * szi * b12 + ssi * b22;
       
  1004 			goto L503;
       
  1005 
       
  1006 		L502:
       
  1007 			i = 1;
       
  1008 			tr = ssr * a11 - sqr * cz * a12 - cq * szr * a21 + cq * cz * a22;
       
  1009 			ti = -ssi * a11 - sqi * cz * a12 + cq * szi * a21;
       
  1010 			dr = ssr * b11 - sqr * cz * b12 + cq * cz * b22;
       
  1011 			di = -ssi * b11 - sqi * cz * b12;
       
  1012 
       
  1013 		L503:
       
  1014 			t = ti * dr - tr * di;
       
  1015 			j = na;
       
  1016 
       
  1017 			if (t < 0.0)
       
  1018 				j = en;
       
  1019 
       
  1020 			r = Math.Sqrt(dr * dr + di * di);
       
  1021 			beta[j] = bn * r;
       
  1022 			alfr[j] = an * (tr * dr + ti * di) / r;
       
  1023 			alfi[j] = an * t / r;
       
  1024 			if (i == 0) goto L502;
       
  1025 
       
  1026 		L505:
       
  1027 			isw = 3 - isw;
       
  1028 
       
  1029 		L510:
       
  1030 			;
       
  1031 		}
       
  1032 
       
  1033 		b[n - 1, 0] = epsb;
       
  1034 
       
  1035 		return 0;
       
  1036 	}
       
  1037 
       
  1038 	/// <summary>
       
  1039 	///   Adaptation of the original Fortran QZVEC routine from EISPACK.
       
  1040 	/// </summary>
       
  1041 	/// <remarks>
       
  1042 	///   This subroutine is the optional fourth step of the qz algorithm
       
  1043 	///   for solving generalized matrix eigenvalue problems,
       
  1044 	///   siam j. numer. anal. 10, 241-256(1973) by moler and stewart.
       
  1045 	///  
       
  1046 	///   This subroutine accepts a pair of real matrices, one of them in
       
  1047 	///   quasi-triangular form (in which each 2-by-2 block corresponds to
       
  1048 	///   a pair of complex eigenvalues) and the other in upper triangular
       
  1049 	///   form.  It computes the eigenvectors of the triangular problem and
       
  1050 	///   transforms the results back to the original coordinate system.
       
  1051 	///   it is usually preceded by  qzhes,  qzit, and	qzval.
       
  1052 	///  
       
  1053 	///   For the full documentation, please check the original function.
       
  1054 	/// </remarks>
       
  1055 	private static int qzvec(int n, double[,] a, double[,] b, double[] alfr, double[] alfi, double[] beta, double[,] z)
       
  1056 	{
       
  1057 		int i, j, k, m;
       
  1058 		int na, ii, en, jj, nn, enm2;
       
  1059 		double d, q;
       
  1060 		double r = 0, s = 0, t, w, x = 0, y, t1, t2, w1, x1 = 0, z1 = 0, di;
       
  1061 		double ra, dr, sa;
       
  1062 		double ti, rr, tr, zz = 0;
       
  1063 		double alfm, almi, betm, almr;
       
  1064 
       
  1065 		double epsb = b[n - 1, 0];
       
  1066 		int isw = 1;
       
  1067 
       
  1068 
       
  1069 		// for en=n step -1 until 1 do --
       
  1070 		for (nn = 0; nn < n; ++nn)
       
  1071 		{
       
  1072 			en = n - nn - 1;
       
  1073 			na = en - 1;
       
  1074 			if (isw == 2) goto L795;
       
  1075 			if (alfi[en] != 0.0) goto L710;
       
  1076 
       
  1077 			// Real vector
       
  1078 			m = en;
       
  1079 			b[en, en] = 1.0;
       
  1080 			if (na == -1) goto L800;
       
  1081 			alfm = alfr[m];
       
  1082 			betm = beta[m];
       
  1083 
       
  1084 			// for i=en-1 step -1 until 1 do --
       
  1085 			for (ii = 0; ii <= na; ++ii)
       
  1086 			{
       
  1087 				i = en - ii - 1;
       
  1088 				w = betm * a[i, i] - alfm * b[i, i];
       
  1089 				r = 0.0;
       
  1090 
       
  1091 				for (j = m; j <= en; ++j)
       
  1092 					r += (betm * a[i, j] - alfm * b[i, j]) * b[j, en];
       
  1093 
       
  1094 				if (i == 0 || isw == 2)
       
  1095 					goto L630;
       
  1096 
       
  1097 				if (betm * a[i, i - 1] == 0.0)
       
  1098 					goto L630;
       
  1099 
       
  1100 				zz = w;
       
  1101 				s = r;
       
  1102 				goto L690;
       
  1103 
       
  1104 			L630:
       
  1105 				m = i;
       
  1106 				if (isw == 2) goto L640;
       
  1107 
       
  1108 				// Real 1-by-1 block
       
  1109 				t = w;
       
  1110 				if (w == 0.0)
       
  1111 					t = epsb;
       
  1112 				b[i, en] = -r / t;
       
  1113 				goto L700;
       
  1114 
       
  1115 			// Real 2-by-2 block
       
  1116 			L640:
       
  1117 				x = betm * a[i, i + 1] - alfm * b[i, i + 1];
       
  1118 				y = betm * a[i + 1, i];
       
  1119 				q = w * zz - x * y;
       
  1120 				t = (x * s - zz * r) / q;
       
  1121 				b[i, en] = t;
       
  1122 				if (Math.Abs(x) <= Math.Abs(zz)) goto L650;
       
  1123 				b[i + 1, en] = (-r - w * t) / x;
       
  1124 				goto L690;
       
  1125 
       
  1126 			L650:
       
  1127 				b[i + 1, en] = (-s - y * t) / zz;
       
  1128 
       
  1129 			L690:
       
  1130 				isw = 3 - isw;
       
  1131 
       
  1132 			L700:
       
  1133 				;
       
  1134 			}
       
  1135 			// End real vector
       
  1136 			goto L800;
       
  1137 
       
  1138 		// Complex vector
       
  1139 		L710:
       
  1140 			m = na;
       
  1141 			almr = alfr[m];
       
  1142 			almi = alfi[m];
       
  1143 			betm = beta[m];
       
  1144 
       
  1145 			// last vector component chosen imaginary so that eigenvector matrix is triangular
       
  1146 			y = betm * a[en, na];
       
  1147 			b[na, na] = -almi * b[en, en] / y;
       
  1148 			b[na, en] = (almr * b[en, en] - betm * a[en, en]) / y;
       
  1149 			b[en, na] = 0.0;
       
  1150 			b[en, en] = 1.0;
       
  1151 			enm2 = na;
       
  1152 			if (enm2 == 0) goto L795;
       
  1153 
       
  1154 			// for i=en-2 step -1 until 1 do --
       
  1155 			for (ii = 0; ii < enm2; ++ii)
       
  1156 			{
       
  1157 				i = na - ii - 1;
       
  1158 				w = betm * a[i, i] - almr * b[i, i];
       
  1159 				w1 = -almi * b[i, i];
       
  1160 				ra = 0.0;
       
  1161 				sa = 0.0;
       
  1162 
       
  1163 				for (j = m; j <= en; ++j)
       
  1164 				{
       
  1165 					x = betm * a[i, j] - almr * b[i, j];
       
  1166 					x1 = -almi * b[i, j];
       
  1167 					ra = ra + x * b[j, na] - x1 * b[j, en];
       
  1168 					sa = sa + x * b[j, en] + x1 * b[j, na];
       
  1169 				}
       
  1170 
       
  1171 				if (i == 0 || isw == 2) goto L770;
       
  1172 				if (betm * a[i, i - 1] == 0.0) goto L770;
       
  1173 
       
  1174 				zz = w;
       
  1175 				z1 = w1;
       
  1176 				r = ra;
       
  1177 				s = sa;
       
  1178 				isw = 2;
       
  1179 				goto L790;
       
  1180 
       
  1181 			L770:
       
  1182 				m = i;
       
  1183 				if (isw == 2) goto L780;
       
  1184 
       
  1185 				// Complex 1-by-1 block
       
  1186 				tr = -ra;
       
  1187 				ti = -sa;
       
  1188 
       
  1189 			L773:
       
  1190 				dr = w;
       
  1191 				di = w1;
       
  1192 
       
  1193 				// Complex divide (t1,t2) = (tr,ti) / (dr,di)
       
  1194 			L775:
       
  1195 				if (Math.Abs(di) > Math.Abs(dr)) goto L777;
       
  1196 				rr = di / dr;
       
  1197 				d = dr + di * rr;
       
  1198 				t1 = (tr + ti * rr) / d;
       
  1199 				t2 = (ti - tr * rr) / d;
       
  1200 
       
  1201 				switch (isw)
       
  1202 				{
       
  1203 					case 1: goto L787;
       
  1204 					case 2: goto L782;
       
  1205 				}
       
  1206 
       
  1207 			L777:
       
  1208 				rr = dr / di;
       
  1209 				d = dr * rr + di;
       
  1210 				t1 = (tr * rr + ti) / d;
       
  1211 				t2 = (ti * rr - tr) / d;
       
  1212 				switch (isw)
       
  1213 				{
       
  1214 					case 1: goto L787;
       
  1215 					case 2: goto L782;
       
  1216 				}
       
  1217 
       
  1218 			   // Complex 2-by-2 block
       
  1219 			L780:
       
  1220 				x = betm * a[i, i + 1] - almr * b[i, i + 1];
       
  1221 				x1 = -almi * b[i, i + 1];
       
  1222 				y = betm * a[i + 1, i];
       
  1223 				tr = y * ra - w * r + w1 * s;
       
  1224 				ti = y * sa - w * s - w1 * r;
       
  1225 				dr = w * zz - w1 * z1 - x * y;
       
  1226 				di = w * z1 + w1 * zz - x1 * y;
       
  1227 				if (dr == 0.0 && di == 0.0)
       
  1228 					dr = epsb;
       
  1229 				goto L775;
       
  1230 
       
  1231 			L782:
       
  1232 				b[i + 1, na] = t1;
       
  1233 				b[i + 1, en] = t2;
       
  1234 				isw = 1;
       
  1235 				if (Math.Abs(y) > Math.Abs(w) + Math.Abs(w1))
       
  1236 					goto L785;
       
  1237 				tr = -ra - x * b[(i + 1), na] + x1 * b[(i + 1), en];
       
  1238 				ti = -sa - x * b[(i + 1), en] - x1 * b[(i + 1), na];
       
  1239 				goto L773;
       
  1240 
       
  1241 			L785:
       
  1242 				t1 = (-r - zz * b[(i + 1), na] + z1 * b[(i + 1), en]) / y;
       
  1243 				t2 = (-s - zz * b[(i + 1), en] - z1 * b[(i + 1), na]) / y;
       
  1244 
       
  1245 			L787:
       
  1246 				b[i, na] = t1;
       
  1247 				b[i, en] = t2;
       
  1248 
       
  1249 			L790:
       
  1250 				;
       
  1251 			}
       
  1252 
       
  1253 			// End complex vector
       
  1254 		L795:
       
  1255 			isw = 3 - isw;
       
  1256 
       
  1257 		L800:
       
  1258 			;
       
  1259 		}
       
  1260 
       
  1261 		// End back substitution. Transform to original coordinate system.
       
  1262 		for (jj = 0; jj < n; ++jj)
       
  1263 		{
       
  1264 			j = n - jj - 1;
       
  1265 
       
  1266 			for (i = 0; i < n; ++i)
       
  1267 			{
       
  1268 				zz = 0.0;
       
  1269 				for (k = 0; k <= j; ++k)
       
  1270 					zz += z[i, k] * b[k, j];
       
  1271 				z[i, j] = zz;
       
  1272 			}
       
  1273 		}
       
  1274 
       
  1275 		// Normalize so that modulus of largest component of each vector is 1.
       
  1276 		// (isw is 1 initially from before)
       
  1277 		for (j = 0; j < n; ++j)
       
  1278 		{
       
  1279 			d = 0.0;
       
  1280 			if (isw == 2) goto L920;
       
  1281 			if (alfi[j] != 0.0) goto L945;
       
  1282 
       
  1283 			for (i = 0; i < n; ++i)
       
  1284 			{
       
  1285 				if ((Math.Abs(z[i, j])) > d)
       
  1286 					d = (Math.Abs(z[i, j]));
       
  1287 			}
       
  1288 
       
  1289 			for (i = 0; i < n; ++i)
       
  1290 				z[i, j] /= d;
       
  1291 
       
  1292 			goto L950;
       
  1293 
       
  1294 		L920:
       
  1295 			for (i = 0; i < n; ++i)
       
  1296 			{
       
  1297 				r = System.Math.Abs(z[i, j - 1]) + System.Math.Abs(z[i, j]);
       
  1298 				if (r != 0.0)
       
  1299 				{
       
  1300 					// Computing 2nd power
       
  1301 					double u1 = z[i, j - 1] / r;
       
  1302 					double u2 = z[i, j] / r;
       
  1303 					r *= Math.Sqrt(u1 * u1 + u2 * u2);
       
  1304 				}
       
  1305 				if (r > d)
       
  1306 					d = r;
       
  1307 			}
       
  1308 
       
  1309 			for (i = 0; i < n; ++i)
       
  1310 			{
       
  1311 				z[i, j - 1] /= d;
       
  1312 				z[i, j] /= d;
       
  1313 			}
       
  1314 
       
  1315 		L945:
       
  1316 			isw = 3 - isw;
       
  1317 
       
  1318 		L950:
       
  1319 			;
       
  1320 		}
       
  1321 
       
  1322 		return 0;
       
  1323 	}
       
  1324 
       
  1325 	#endregion
       
  1326 
       
  1327 
       
  1328 
       
  1329 	#region ICloneable Members
       
  1330 
       
  1331 	private GeneralizedEigenvalueDecomposition()
       
  1332 	{
       
  1333 	}
       
  1334 
       
  1335 	/// <summary>
       
  1336 	///   Creates a new object that is a copy of the current instance.
       
  1337 	/// </summary>
       
  1338 	/// <returns>
       
  1339 	///   A new object that is a copy of this instance.
       
  1340 	/// </returns>
       
  1341 	public object Clone()
       
  1342 	{
       
  1343 		var clone = new GeneralizedEigenvalueDecomposition();
       
  1344 		clone.ai = (double[])ai.Clone();
       
  1345 		clone.ar = (double[])ar.Clone();
       
  1346 		clone.beta = (double[])beta.Clone();
       
  1347 		clone.n = n;
       
  1348 		clone.Z = (double[,])Z.Clone();
       
  1349 		return clone;
       
  1350 	}
       
  1351 
       
  1352 	#endregion
       
  1353 
       
  1354 }
       
  1355