dlarrk function

void dlarrk(
  1. int N,
  2. int IW,
  3. double GL,
  4. double GU,
  5. Array<double> D_,
  6. Array<double> E2_,
  7. double PIVMIN,
  8. double RELTOL,
  9. Box<double> W,
  10. Box<double> WERR,
  11. Box<int> INFO,
)

Implementation

void dlarrk(
  final int N,
  final int IW,
  final double GL,
  final double GU,
  final Array<double> D_,
  final Array<double> E2_,
  final double PIVMIN,
  final double RELTOL,
  final Box<double> W,
  final Box<double> WERR,
  final Box<int> INFO,
) {
  final D = D_.having();
  final E2 = E2_.having();
  const HALF = 0.5, TWO = 2.0, FUDGE = TWO, ZERO = 0.0;
  int I, IT, ITMAX, NEGCNT;
  double ATOLI, EPS, LEFT, MID, RIGHT, RTOLI, TMP1, TMP2, TNORM;

  // Quick return if possible

  if (N <= 0) {
    INFO.value = 0;
    return;
  }

  // Get machine constants
  EPS = dlamch('P');

  TNORM = max(GL.abs(), GU.abs());
  RTOLI = RELTOL;
  ATOLI = FUDGE * TWO * PIVMIN;
  ITMAX = (log(TNORM + PIVMIN) - log(PIVMIN)) ~/ log(TWO) + 2;

  INFO.value = -1;

  LEFT = GL - FUDGE * TNORM * EPS * N - FUDGE * TWO * PIVMIN;
  RIGHT = GU + FUDGE * TNORM * EPS * N + FUDGE * TWO * PIVMIN;
  IT = 0;

  while (true) {
    // Check if interval converged or maximum number of iterations reached

    TMP1 = (RIGHT - LEFT).abs();
    TMP2 = max(RIGHT.abs(), LEFT.abs());
    if (TMP1 < max(ATOLI, max(PIVMIN, RTOLI * TMP2))) {
      INFO.value = 0;
      break;
    }
    if (IT > ITMAX) break;

    // Count number of negative pivots for mid-point

    IT++;
    MID = HALF * (LEFT + RIGHT);
    NEGCNT = 0;
    TMP1 = D[1] - MID;
    if (TMP1.abs() < PIVMIN) TMP1 = -PIVMIN;
    if (TMP1 <= ZERO) NEGCNT++;

    for (I = 2; I <= N; I++) {
      TMP1 = D[I] - E2[I - 1] / TMP1 - MID;
      if (TMP1.abs() < PIVMIN) TMP1 = -PIVMIN;
      if (TMP1 <= ZERO) NEGCNT++;
    }

    if (NEGCNT >= IW) {
      RIGHT = MID;
    } else {
      LEFT = MID;
    }
  }

  // Converged or maximum number of iterations reached

  W.value = HALF * (LEFT + RIGHT);
  WERR.value = HALF * (RIGHT - LEFT).abs();
}