zcposv function

void zcposv(
  1. String UPLO,
  2. int N,
  3. int NRHS,
  4. Matrix<Complex> A_,
  5. int LDA,
  6. Matrix<Complex> B_,
  7. int LDB,
  8. Matrix<Complex> X_,
  9. int LDX,
  10. Matrix<Complex> WORK_,
  11. Array<Complex> SWORK_,
  12. Array<double> RWORK_,
  13. Box<int> ITER,
  14. Box<int> INFO,
)

Implementation

void zcposv(
  final String UPLO,
  final int N,
  final int NRHS,
  final Matrix<Complex> A_,
  final int LDA,
  final Matrix<Complex> B_,
  final int LDB,
  final Matrix<Complex> X_,
  final int LDX,
  final Matrix<Complex> WORK_,
  final Array<Complex> SWORK_,
  final Array<double> RWORK_,
  final Box<int> ITER,
  final Box<int> INFO,
) {
  final A = A_.having(ld: LDA);
  final B = B_.having(ld: LDB);
  final X = X_.having(ld: LDX);
  final WORK = WORK_.having(ld: N);
  final SWORK = SWORK_.having();
  final RWORK = RWORK_.having();
  const DOITREF = false;
  const ITERMAX = 30;
  const BWDMAX = 1.0e+00;
  const NEGONE = Complex(-1.0e+00, 0.0e+00);
  int I, IITER, PTSA, PTSX;
  double ANRM, CTE, EPS, RNRM, XNRM;

  INFO.value = 0;
  ITER.value = 0;

  // Test the input parameters.

  if (!lsame(UPLO, 'U') && !lsame(UPLO, 'L')) {
    INFO.value = -1;
  } else if (N < 0) {
    INFO.value = -2;
  } else if (NRHS < 0) {
    INFO.value = -3;
  } else if (LDA < max(1, N)) {
    INFO.value = -5;
  } else if (LDB < max(1, N)) {
    INFO.value = -7;
  } else if (LDX < max(1, N)) {
    INFO.value = -9;
  }
  if (INFO.value != 0) {
    xerbla('ZCPOSV', -INFO.value);
    return;
  }

  // Quick return if (N == 0).

  if (N == 0) return;

  skipSinglePrecision:
  while (true) {
    // Skip single precision iterative refinement if a priori slower
    // than double precision factorization.
    if (!DOITREF) {
      ITER.value = -1;
      break skipSinglePrecision;
    }

    // Compute some constants.

    // ignore: dead_code
    ANRM = zlanhe('I', UPLO, N, A, LDA, RWORK);
    EPS = dlamch('Epsilon');
    CTE = ANRM * EPS * sqrt(N) * BWDMAX;

    // Set the indices PTSA, PTSX for referencing SA and SX in SWORK.

    PTSA = 1;
    PTSX = PTSA + N * N;

    // Convert B from double precision to single precision and store the
    // result in SX.

    zlag2c(N, NRHS, B, LDB, SWORK(PTSX).asMatrix(N), N, INFO);

    if (INFO.value != 0) {
      ITER.value = -2;
      break skipSinglePrecision;
    }

    // Convert A from double precision to single precision and store the
    // result in SA.

    zlat2c(UPLO, N, A, LDA, SWORK(PTSA).asMatrix(N), N, INFO);

    if (INFO.value != 0) {
      ITER.value = -2;
      break skipSinglePrecision;
    }

    // Compute the Cholesky factorization of SA.

    cpotrf(UPLO, N, SWORK(PTSA).asMatrix(N), N, INFO);

    if (INFO.value != 0) {
      ITER.value = -3;
      break skipSinglePrecision;
    }

    // Solve the system SA*SX = SB.

    cpotrs(UPLO, N, NRHS, SWORK(PTSA).asMatrix(N), N, SWORK(PTSX).asMatrix(N),
        N, INFO);

    // Convert SX back to Complex

    clag2z(N, NRHS, SWORK(PTSX).asMatrix(N), N, X, LDX, INFO);

    // Compute R = B - AX (R is WORK).

    zlacpy('All', N, NRHS, B, LDB, WORK, N);

    zhemm('Left', UPLO, N, NRHS, NEGONE, A, LDA, X, LDX, Complex.one, WORK, N);

    // Check whether the NRHS normwise backward errors satisfy the
    // stopping criterion. If yes, set ITER=0 and return.

    var satisfy = true;
    for (I = 1; I <= NRHS; I++) {
      XNRM = X[izamax(N, X(1, I).asArray(), 1)][I].cabs1();
      RNRM = WORK[izamax(N, WORK(1, I).asArray(), 1)][I].cabs1();
      if (RNRM > XNRM * CTE) {
        satisfy = false;
        break;
      }
    }

    if (satisfy) {
      // If we are here, the NRHS normwise backward errors satisfy the
      // stopping criterion. We are good to exit.

      ITER.value = 0;
      return;
    }

    for (IITER = 1; IITER <= ITERMAX; IITER++) {
      // Convert R (in WORK) from double precision to single precision
      // and store the result in SX.

      zlag2c(N, NRHS, WORK, N, SWORK(PTSX).asMatrix(N), N, INFO);

      if (INFO.value != 0) {
        ITER.value = -2;
        break skipSinglePrecision;
      }

      // Solve the system SA*SX = SR.

      cpotrs(UPLO, N, NRHS, SWORK(PTSA).asMatrix(N), N, SWORK(PTSX).asMatrix(N),
          N, INFO);

      // Convert SX back to double precision and update the current
      // iterate.

      clag2z(N, NRHS, SWORK(PTSX).asMatrix(N), N, WORK, N, INFO);

      for (I = 1; I <= NRHS; I++) {
        zaxpy(N, Complex.one, WORK(1, I).asArray(), 1, X(1, I).asArray(), 1);
      }

      // Compute R = B - AX (R is WORK).

      zlacpy('All', N, NRHS, B, LDB, WORK, N);

      zhemm('L', UPLO, N, NRHS, NEGONE, A, LDA, X, LDX, Complex.one, WORK, N);

      // Check whether the NRHS normwise backward errors satisfy the
      // stopping criterion. If yes, set ITER=IITER>0 and return.

      var satisfy = true;
      for (I = 1; I <= NRHS; I++) {
        XNRM = X[izamax(N, X(1, I).asArray(), 1)][I].cabs1();
        RNRM = WORK[izamax(N, WORK(1, I).asArray(), 1)][I].cabs1();
        if (RNRM > XNRM * CTE) {
          satisfy = false;
          break;
        }
      }

      if (satisfy) {
        // If we are here, the NRHS normwise backward errors satisfy the
        // stopping criterion, we are good to exit.

        ITER.value = IITER;

        return;
      }
    }

    // If we are at this place of the code, this is because we have
    // performed ITER=ITERMAX iterations and never satisfied the
    // stopping criterion, set up the ITER flag accordingly and follow
    // up on double precision routine.

    ITER.value = -ITERMAX - 1;

    break;
  }

  // Single-precision iterative refinement failed to converge to a
  // satisfactory solution, so we resort to double precision.

  zpotrf(UPLO, N, A, LDA, INFO);

  if (INFO.value != 0) return;

  zlacpy('All', N, NRHS, B, LDB, X, LDX);
  zpotrs(UPLO, N, NRHS, A, LDA, X, LDX, INFO);
}