zhsein function

void zhsein(
  1. String SIDE,
  2. String EIGSRC,
  3. String INITV,
  4. Array<bool> SELECT_,
  5. int N,
  6. Matrix<Complex> H_,
  7. int LDH,
  8. Array<Complex> W_,
  9. Matrix<Complex> VL_,
  10. int LDVL,
  11. Matrix<Complex> VR_,
  12. int LDVR,
  13. int MM,
  14. Box<int> M,
  15. Array<Complex> WORK_,
  16. Array<double> RWORK_,
  17. Array<int> IFAILL_,
  18. Array<int> IFAILR_,
  19. Box<int> INFO,
)

Implementation

void zhsein(
  final String SIDE,
  final String EIGSRC,
  final String INITV,
  final Array<bool> SELECT_,
  final int N,
  final Matrix<Complex> H_,
  final int LDH,
  final Array<Complex> W_,
  final Matrix<Complex> VL_,
  final int LDVL,
  final Matrix<Complex> VR_,
  final int LDVR,
  final int MM,
  final Box<int> M,
  final Array<Complex> WORK_,
  final Array<double> RWORK_,
  final Array<int> IFAILL_,
  final Array<int> IFAILR_,
  final Box<int> INFO,
) {
  final SELECT = SELECT_.having();
  final W = W_.having();
  final H = H_.having(ld: LDH);
  final VL = VL_.having(ld: LDVL);
  final VR = VR_.having(ld: LDVR);
  final WORK = WORK_.having();
  final RWORK = RWORK_.having();
  final IFAILL = IFAILL_.having();
  final IFAILR = IFAILR_.having();
  const RZERO = 0.0;
  bool BOTHV, FROMQR, LEFTV, NOINIT, RIGHTV;
  int I, K, KL, KLN, KR, KS, LDWORK;
  double EPS3 = 0, HNORM, SMLNUM, ULP, UNFL;
  Complex WK = Complex.zero;
  final IINFO = Box(0);

  // Decode and test the input parameters.

  BOTHV = lsame(SIDE, 'B');
  RIGHTV = lsame(SIDE, 'R') || BOTHV;
  LEFTV = lsame(SIDE, 'L') || BOTHV;

  FROMQR = lsame(EIGSRC, 'Q');

  NOINIT = lsame(INITV, 'N');

  // Set M to the number of columns required to store the selected
  // eigenvectors.

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

  INFO.value = 0;
  if (!RIGHTV && !LEFTV) {
    INFO.value = -1;
  } else if (!FROMQR && !lsame(EIGSRC, 'N')) {
    INFO.value = -2;
  } else if (!NOINIT && !lsame(INITV, 'U')) {
    INFO.value = -3;
  } else if (N < 0) {
    INFO.value = -5;
  } else if (LDH < max(1, N)) {
    INFO.value = -7;
  } else if (LDVL < 1 || (LEFTV && LDVL < N)) {
    INFO.value = -10;
  } else if (LDVR < 1 || (RIGHTV && LDVR < N)) {
    INFO.value = -12;
  } else if (MM < M.value) {
    INFO.value = -13;
  }
  if (INFO.value != 0) {
    xerbla('ZHSEIN', -INFO.value);
    return;
  }

  // Quick return if possible.

  if (N == 0) return;

  // Set machine-dependent constants.

  UNFL = dlamch('Safe minimum');
  ULP = dlamch('Precision');
  SMLNUM = UNFL * (N / ULP);

  LDWORK = N;

  KL = 1;
  KLN = 0;
  if (FROMQR) {
    KR = 0;
  } else {
    KR = N;
  }
  KS = 1;

  for (K = 1; K <= N; K++) {
    if (SELECT[K]) {
      // Compute eigenvector(s) corresponding to W(K).

      if (FROMQR) {
        // If affiliation of eigenvalues is known, check whether
        // the matrix splits.

        // Determine KL and KR such that 1 <= KL <= K <= KR <= N
        // and H(KL,KL-1) and H(KR+1,KR) are zero (or KL = 1 or
        // KR = N).

        // Then inverse iteration can be performed with the
        // submatrix H(KL:N,KL:N) for a left eigenvector, and with
        // the submatrix H(1:KR,1:KR) for a right eigenvector.

        for (I = K; I >= KL + 1; I--) {
          if (H[I][I - 1] == Complex.zero) break;
        }
        KL = I;
        if (K > KR) {
          for (I = K; I <= N - 1; I++) {
            if (H[I + 1][I] == Complex.zero) break;
          }
          KR = I;
        }
      }

      if (KL != KLN) {
        KLN = KL;

        // Compute infinity-norm of submatrix H(KL:KR,KL:KR) if it
        // has not ben computed before.

        HNORM = zlanhs('I', KR - KL + 1, H(KL, KL), LDH, RWORK);
        if (disnan(HNORM)) {
          INFO.value = -6;
          return;
        } else if (HNORM > RZERO) {
          EPS3 = HNORM * ULP;
        } else {
          EPS3 = SMLNUM;
        }
      }

      // Perturb eigenvalue if it is close to any previous
      // selected eigenvalues affiliated to the submatrix
      // H(KL:KR,KL:KR). Close roots are modified by EPS3.

      WK = W[K];
      repeat:
      while (true) {
        for (I = K - 1; I >= KL; I--) {
          if (SELECT[I] && (W[I] - WK).cabs1() < EPS3) {
            WK += EPS3.toComplex();
            continue repeat;
          }
        }
        break;
      }
      W[K] = WK;

      if (LEFTV) {
        // Compute left eigenvector.

        zlaein(
            false,
            NOINIT,
            N - KL + 1,
            H(KL, KL),
            LDH,
            WK,
            VL(KL, KS).asArray(),
            WORK.asMatrix(),
            LDWORK,
            RWORK,
            EPS3,
            SMLNUM,
            IINFO);
        if (IINFO.value > 0) {
          INFO.value++;
          IFAILL[KS] = K;
        } else {
          IFAILL[KS] = 0;
        }
        for (I = 1; I <= KL - 1; I++) {
          VL[I][KS] = Complex.zero;
        }
      }
      if (RIGHTV) {
        // Compute right eigenvector.

        zlaein(true, NOINIT, KR, H, LDH, WK, VR(1, KS).asArray(),
            WORK.asMatrix(), LDWORK, RWORK, EPS3, SMLNUM, IINFO);
        if (IINFO.value > 0) {
          INFO.value++;
          IFAILR[KS] = K;
        } else {
          IFAILR[KS] = 0;
        }
        for (I = KR + 1; I <= N; I++) {
          VR[I][KS] = Complex.zero;
        }
      }
      KS++;
    }
  }
}