ztrsen function

void ztrsen(
  1. String JOB,
  2. String COMPQ,
  3. Array<bool> SELECT_,
  4. int N,
  5. Matrix<Complex> T_,
  6. int LDT,
  7. Matrix<Complex> Q_,
  8. int LDQ,
  9. Array<Complex> W_,
  10. Box<int> M,
  11. Box<double> S,
  12. Box<double> SEP,
  13. Array<Complex> WORK_,
  14. int LWORK,
  15. Box<int> INFO,
)

Implementation

void ztrsen(
  final String JOB,
  final String COMPQ,
  final Array<bool> SELECT_,
  final int N,
  final Matrix<Complex> T_,
  final int LDT,
  final Matrix<Complex> Q_,
  final int LDQ,
  final Array<Complex> W_,
  final Box<int> M,
  final Box<double> S,
  final Box<double> SEP,
  final Array<Complex> WORK_,
  final int LWORK,
  final Box<int> INFO,
) {
  final SELECT = SELECT_.having();
  final T = T_.having(ld: LDT);
  final Q = Q_.having(ld: LDQ);
  final W = W_.having();
  final WORK = WORK_.having();
  const ZERO = 0.0, ONE = 1.0;
  bool LQUERY, WANTBH, WANTQ, WANTS, WANTSP;
  int K, KS, LWMIN = 0, N1, N2, NN;
  double RNORM;
  final ISAVE = Array<int>(3);
  final RWORK = Array<double>(1);
  final IERR = Box(0), KASE = Box(0);
  final SCALE = Box(0.0), EST = Box(0.0);

  // Decode and test the input parameters.

  WANTBH = lsame(JOB, 'B');
  WANTS = lsame(JOB, 'E') || WANTBH;
  WANTSP = lsame(JOB, 'V') || WANTBH;
  WANTQ = lsame(COMPQ, 'V');

  // Set M to the number of selected eigenvalues.

  M.value = 0;
  for (K = 1; K <= N; K++) {
    if (SELECT[K]) M.value++;
  }

  N1 = M.value;
  N2 = N - M.value;
  NN = N1 * N2;

  INFO.value = 0;
  LQUERY = (LWORK == -1);

  if (WANTSP) {
    LWMIN = max(1, 2 * NN);
  } else if (lsame(JOB, 'N')) {
    LWMIN = 1;
  } else if (lsame(JOB, 'E')) {
    LWMIN = max(1, NN);
  }

  if (!lsame(JOB, 'N') && !WANTS && !WANTSP) {
    INFO.value = -1;
  } else if (!lsame(COMPQ, 'N') && !WANTQ) {
    INFO.value = -2;
  } else if (N < 0) {
    INFO.value = -4;
  } else if (LDT < max(1, N)) {
    INFO.value = -6;
  } else if (LDQ < 1 || (WANTQ && LDQ < N)) {
    INFO.value = -8;
  } else if (LWORK < LWMIN && !LQUERY) {
    INFO.value = -14;
  }

  if (INFO.value == 0) {
    WORK[1] = LWMIN.toComplex();
  }

  if (INFO.value != 0) {
    xerbla('ZTRSEN', -INFO.value);
    return;
  } else if (LQUERY) {
    return;
  }

  // Quick return if possible

  if (M.value == N || M.value == 0) {
    if (WANTS) S.value = ONE;
    if (WANTSP) SEP.value = zlange('1', N, N, T, LDT, RWORK);
  } else {
    // Collect the selected eigenvalues at the top left corner of T.

    KS = 0;
    for (K = 1; K <= N; K++) {
      if (SELECT[K]) {
        KS++;

        // Swap the K-th eigenvalue to position KS.

        if (K != KS) ztrexc(COMPQ, N, T, LDT, Q, LDQ, K, KS, IERR);
      }
    }

    if (WANTS) {
      // Solve the Sylvester equation for R:

      // T11*R - R*T22 = scale*T12

      zlacpy('F', N1, N2, T(1, N1 + 1), LDT, WORK.asMatrix(N1), N1);
      ztrsyl('N', 'N', -1, N1, N2, T, LDT, T(N1 + 1, N1 + 1), LDT,
          WORK.asMatrix(N1), N1, SCALE, IERR);

      // Estimate the reciprocal of the condition number of the cluster
      // of eigenvalues.

      RNORM = zlange('F', N1, N2, WORK.asMatrix(N1), N1, RWORK);
      if (RNORM == ZERO) {
        S.value = ONE;
      } else {
        S.value = SCALE.value /
            (sqrt(SCALE.value * SCALE.value / RNORM + RNORM) * sqrt(RNORM));
      }
    }

    if (WANTSP) {
      // Estimate sep(T11,T22).

      EST.value = ZERO;
      KASE.value = 0;
      while (true) {
        zlacn2(NN, WORK(NN + 1), WORK, EST, KASE, ISAVE);
        if (KASE.value == 0) break;
        if (KASE.value == 1) {
          // Solve T11*R - R*T22 = scale*X.
          ztrsyl('N', 'N', -1, N1, N2, T, LDT, T(N1 + 1, N1 + 1), LDT,
              WORK.asMatrix(N1), N1, SCALE, IERR);
        } else {
          // Solve T11**H*R - R*T22**H = scale*X.
          ztrsyl('C', 'C', -1, N1, N2, T, LDT, T(N1 + 1, N1 + 1), LDT,
              WORK.asMatrix(N1), N1, SCALE, IERR);
        }
      }

      SEP.value = SCALE.value / EST.value;
    }
  }

  // Copy reordered eigenvalues to W.
  for (K = 1; K <= N; K++) {
    W[K] = T[K][K];
  }

  WORK[1] = LWMIN.toComplex();
}