dlaexc function

void dlaexc(
  1. bool WANTQ,
  2. int N,
  3. Matrix<double> T_,
  4. int LDT,
  5. Matrix<double> Q_,
  6. int LDQ,
  7. int J1,
  8. int N1,
  9. int N2,
  10. Array<double> WORK_,
  11. Box<int> INFO,
)

Implementation

void dlaexc(
  final bool WANTQ,
  final int N,
  final Matrix<double> T_,
  final int LDT,
  final Matrix<double> Q_,
  final int LDQ,
  final int J1,
  final int N1,
  final int N2,
  final Array<double> WORK_,
  final Box<int> INFO,
) {
  final T = T_.having(ld: LDT);
  final Q = Q_.having(ld: LDQ);
  final WORK = WORK_.having();
  const ZERO = 0.0, ONE = 1.0;
  const TEN = 1.0e+1;
  const LDD = 4, LDX = 2;
  int J2, J3, J4, K, ND;
  double DNORM, EPS, SMLNUM, T11, T22, T33, THRESH;
  final D = Matrix<double>(LDD, 4), X = Matrix<double>(LDX, 2);
  final U = Array<double>(3), U1 = Array<double>(3), U2 = Array<double>(3);
  final CS = Box(0.0),
      SN = Box(0.0),
      SCALE = Box(0.0),
      XNORM = Box(0.0),
      TEMP = Box(0.0),
      TAU = Box(0.0),
      TAU1 = Box(0.0),
      TAU2 = Box(0.0),
      WI1 = Box(0.0),
      WI2 = Box(0.0),
      WR1 = Box(0.0),
      WR2 = Box(0.0);
  final IERR = Box(0);

  INFO.value = 0;

  // Quick return if possible

  if (N == 0 || N1 == 0 || N2 == 0) return;
  if (J1 + N1 > N) return;

  J2 = J1 + 1;
  J3 = J1 + 2;
  J4 = J1 + 3;

  if (N1 == 1 && N2 == 1) {
    // Swap two 1-by-1 blocks.

    T11 = T[J1][J1];
    T22 = T[J2][J2];

    // Determine the transformation to perform the interchange.

    dlartg(T[J1][J2], T22 - T11, CS, SN, TEMP);

    // Apply transformation to the matrix T.

    if (J3 <= N) {
      drot(N - J1 - 1, T(J1, J3).asArray(), LDT, T(J2, J3).asArray(), LDT,
          CS.value, SN.value);
    }
    drot(J1 - 1, T(1, J1).asArray(), 1, T(1, J2).asArray(), 1, CS.value,
        SN.value);

    T[J1][J1] = T22;
    T[J2][J2] = T11;

    if (WANTQ) {
      // Accumulate transformation in the matrix Q.

      drot(N, Q(1, J1).asArray(), 1, Q(1, J2).asArray(), 1, CS.value, SN.value);
    }
  } else {
    // Swapping involves at least one 2-by-2 block.

    // Copy the diagonal block of order N1+N2 to the local array D
    // and compute its norm.

    ND = N1 + N2;
    dlacpy('Full', ND, ND, T(J1, J1), LDT, D, LDD);
    DNORM = dlange('Max', ND, ND, D, LDD, WORK);

    // Compute machine-dependent threshold for test for accepting
    // swap.

    EPS = dlamch('P');
    SMLNUM = dlamch('S') / EPS;
    THRESH = max(TEN * EPS * DNORM, SMLNUM);

    // Solve T11*X - X*T22 = scale*T12 for X.

    dlasy2(false, false, -1, N1, N2, D, LDD, D(N1 + 1, N1 + 1), LDD,
        D(1, N1 + 1), LDD, SCALE, X, LDX, XNORM, IERR);

    // Swap the adjacent diagonal blocks.

    K = N1 + N1 + N2 - 3;
    //  GO TO ( 10, 20, 30 )K;
    switch (K) {
      case 1:

        // N1 = 1, N2 = 2: generate elementary reflector H so that:

        // ( scale, X11, X12 ) H = ( 0, 0, * )

        U[1] = SCALE.value;
        U[2] = X[1][1];
        U[3] = X[1][2];
        dlarfg(3, U.box(3), U, 1, TAU);
        U[3] = ONE;
        T11 = T[J1][J1];

        // Perform swap provisionally on diagonal block in D.

        dlarfx('L', 3, 3, U, TAU.value, D, LDD, WORK);
        dlarfx('R', 3, 3, U, TAU.value, D, LDD, WORK);

        // Test whether to reject swap.

        if (max(D[3][1].abs(), max(D[3][2].abs(), (D[3][3] - T11).abs())) >
            THRESH) {
          // Exit with INFO = 1 if swap was rejected.
          INFO.value = 1;
          return;
        }

        // Accept swap: apply transformation to the entire matrix T.

        dlarfx('L', 3, N - J1 + 1, U, TAU.value, T(J1, J1), LDT, WORK);
        dlarfx('R', J2, 3, U, TAU.value, T(1, J1), LDT, WORK);

        T[J3][J1] = ZERO;
        T[J3][J2] = ZERO;
        T[J3][J3] = T11;

        if (WANTQ) {
          // Accumulate transformation in the matrix Q.

          dlarfx('R', N, 3, U, TAU.value, Q(1, J1), LDQ, WORK);
        }
        break;

      case 2:

        // N1 = 2, N2 = 1: generate elementary reflector H so that:

        // H (  -X11 ) = ( * )
        // (  -X21 ) = ( 0 )
        // ( scale ) = ( 0 )

        U[1] = -X[1][1];
        U[2] = -X[2][1];
        U[3] = SCALE.value;
        dlarfg(3, U.box(1), U(2), 1, TAU);
        U[1] = ONE;
        T33 = T[J3][J3];

        // Perform swap provisionally on diagonal block in D.

        dlarfx('L', 3, 3, U, TAU.value, D, LDD, WORK);
        dlarfx('R', 3, 3, U, TAU.value, D, LDD, WORK);

        // Test whether to reject swap.

        if (max(D[2][1].abs(), max(D[3][1].abs(), (D[1][1] - T33).abs())) >
            THRESH) {
          // Exit with INFO = 1 if swap was rejected.
          INFO.value = 1;
          return;
        }

        // Accept swap: apply transformation to the entire matrix T.

        dlarfx('R', J3, 3, U, TAU.value, T(1, J1), LDT, WORK);
        dlarfx('L', 3, N - J1, U, TAU.value, T(J1, J2), LDT, WORK);

        T[J1][J1] = T33;
        T[J2][J1] = ZERO;
        T[J3][J1] = ZERO;

        if (WANTQ) {
          // Accumulate transformation in the matrix Q.

          dlarfx('R', N, 3, U, TAU.value, Q(1, J1), LDQ, WORK);
        }
        break;

      case 3:

        // N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so
        // that:
        //
        // H(2) H(1) (  -X11  -X12 ) = (  *  * )
        // (  -X21  -X22 )   (  0  * )
        // ( scale    0  )   (  0  0 )
        // (    0  scale )   (  0  0 )

        U1[1] = -X[1][1];
        U1[2] = -X[2][1];
        U1[3] = SCALE.value;
        dlarfg(3, U1.box(1), U1(2), 1, TAU1);
        U1[1] = ONE;

        TEMP.value = -TAU1.value * (X[1][2] + U1[2] * X[2][2]);
        U2[1] = -TEMP.value * U1[2] - X[2][2];
        U2[2] = -TEMP.value * U1[3];
        U2[3] = SCALE.value;
        dlarfg(3, U2.box(1), U2(2), 1, TAU2);
        U2[1] = ONE;

        // Perform swap provisionally on diagonal block in D.

        dlarfx('L', 3, 4, U1, TAU1.value, D, LDD, WORK);
        dlarfx('R', 4, 3, U1, TAU1.value, D, LDD, WORK);
        dlarfx('L', 3, 4, U2, TAU2.value, D(2, 1), LDD, WORK);
        dlarfx('R', 4, 3, U2, TAU2.value, D(1, 2), LDD, WORK);

        // Test whether to reject swap.

        if (max(
              max(D[3][1].abs(), D[3][2].abs()),
              max(D[4][1].abs(), D[4][2].abs()),
            ) >
            THRESH) {
          // Exit with INFO = 1 if swap was rejected.
          INFO.value = 1;
          return;
        }

        // Accept swap: apply transformation to the entire matrix T.

        dlarfx('L', 3, N - J1 + 1, U1, TAU1.value, T(J1, J1), LDT, WORK);
        dlarfx('R', J4, 3, U1, TAU1.value, T(1, J1), LDT, WORK);
        dlarfx('L', 3, N - J1 + 1, U2, TAU2.value, T(J2, J1), LDT, WORK);
        dlarfx('R', J4, 3, U2, TAU2.value, T(1, J2), LDT, WORK);

        T[J3][J1] = ZERO;
        T[J3][J2] = ZERO;
        T[J4][J1] = ZERO;
        T[J4][J2] = ZERO;

        if (WANTQ) {
          // Accumulate transformation in the matrix Q.

          dlarfx('R', N, 3, U1, TAU1.value, Q(1, J1), LDQ, WORK);
          dlarfx('R', N, 3, U2, TAU2.value, Q(1, J2), LDQ, WORK);
        }
        break;
    }

    if (N2 == 2) {
      // Standardize new 2-by-2 block T11

      dlanv2(T.box(J1, J1), T.box(J1, J2), T.box(J2, J1), T.box(J2, J2), WR1,
          WI1, WR2, WI2, CS, SN);
      drot(N - J1 - 1, T(J1, J1 + 2).asArray(), LDT, T(J2, J1 + 2).asArray(),
          LDT, CS.value, SN.value);
      drot(J1 - 1, T(1, J1).asArray(), 1, T(1, J2).asArray(), 1, CS.value,
          SN.value);
      if (WANTQ) {
        drot(N, Q(1, J1).asArray(), 1, Q(1, J2).asArray(), 1, CS.value,
            SN.value);
      }
    }

    if (N1 == 2) {
      // Standardize new 2-by-2 block T22

      J3 = J1 + N2;
      J4 = J3 + 1;
      dlanv2(T.box(J3, J3), T.box(J3, J4), T.box(J4, J3), T.box(J4, J4), WR1,
          WI1, WR2, WI2, CS, SN);
      if (J3 + 2 <= N) {
        drot(N - J3 - 1, T(J3, J3 + 2).asArray(), LDT, T(J4, J3 + 2).asArray(),
            LDT, CS.value, SN.value);
      }
      drot(J3 - 1, T(1, J3).asArray(), 1, T(1, J4).asArray(), 1, CS.value,
          SN.value);
      if (WANTQ) {
        drot(N, Q(1, J3).asArray(), 1, Q(1, J4).asArray(), 1, CS.value,
            SN.value);
      }
    }
  }
}