dgglse function

void dgglse(
  1. int M,
  2. int N,
  3. int P,
  4. Matrix<double> A_,
  5. int LDA,
  6. Matrix<double> B_,
  7. int LDB,
  8. Array<double> C_,
  9. Array<double> D_,
  10. Array<double> X_,
  11. Array<double> WORK_,
  12. int LWORK,
  13. Box<int> INFO,
)

Implementation

void dgglse(
  final int M,
  final int N,
  final int P,
  final Matrix<double> A_,
  final int LDA,
  final Matrix<double> B_,
  final int LDB,
  final Array<double> C_,
  final Array<double> D_,
  final Array<double> X_,
  final Array<double> WORK_,
  final int LWORK,
  final Box<int> INFO,
) {
  final A = A_.having(ld: LDA);
  final B = B_.having(ld: LDB);
  final C = C_.having();
  final D = D_.having();
  final X = X_.having();
  final WORK = WORK_.having();
  const ONE = 1.0;
  bool LQUERY;
  int LOPT, LWKMIN, LWKOPT, MN, NB, NB1, NB2, NB3, NB4, NR;

  // Test the input parameters

  INFO.value = 0;
  MN = min(M, N);
  LQUERY = (LWORK == -1);
  if (M < 0) {
    INFO.value = -1;
  } else if (N < 0) {
    INFO.value = -2;
  } else if (P < 0 || P > N || P < N - M) {
    INFO.value = -3;
  } else if (LDA < max(1, M)) {
    INFO.value = -5;
  } else if (LDB < max(1, P)) {
    INFO.value = -7;
  }

  // Calculate workspace

  if (INFO.value == 0) {
    if (N == 0) {
      LWKMIN = 1;
      LWKOPT = 1;
    } else {
      NB1 = ilaenv(1, 'DGEQRF', ' ', M, N, -1, -1);
      NB2 = ilaenv(1, 'DGERQF', ' ', M, N, -1, -1);
      NB3 = ilaenv(1, 'DORMQR', ' ', M, N, P, -1);
      NB4 = ilaenv(1, 'DORMRQ', ' ', M, N, P, -1);
      NB = max(max(NB1, NB2), max(NB3, NB4));
      LWKMIN = M + N + P;
      LWKOPT = P + MN + max(M, N) * NB;
    }
    WORK[1] = LWKOPT.toDouble();

    if (LWORK < LWKMIN && !LQUERY) {
      INFO.value = -12;
    }
  }

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

  // Quick return if possible

  if (N == 0) return;

  // Compute the GRQ factorization of matrices B and A:

  // B*Q**T = (  0  T12 ) P   Z**T*A*Q**T = ( R11 R12 ) N-P
  //             N-P  P                     (  0  R22 ) M+P-N
  //                                           N-P  P

  // where T12 and R11 are upper triangular, and Q and Z are
  // orthogonal.

  dggrqf(P, M, N, B, LDB, WORK, A, LDA, WORK(P + 1), WORK(P + MN + 1),
      LWORK - P - MN, INFO);
  LOPT = WORK[P + MN + 1].toInt();

  // Update c = Z**T *c = ( c1 ) N-P
  //                      ( c2 ) M+P-N

  dormqr('Left', 'Transpose', M, 1, MN, A, LDA, WORK(P + 1),
      C.asMatrix(max(1, M)), max(1, M), WORK(P + MN + 1), LWORK - P - MN, INFO);
  LOPT = max(LOPT, WORK[P + MN + 1].toInt());

  // Solve T12*x2 = d for x2

  if (P > 0) {
    dtrtrs('Upper', 'No transpose', 'Non-unit', P, 1, B(1, N - P + 1), LDB,
        D.asMatrix(P), P, INFO);

    if (INFO.value > 0) {
      INFO.value = 1;
      return;
    }

    // Put the solution in X

    dcopy(P, D, 1, X(N - P + 1), 1);

    // Update c1

    dgemv(
        'No transpose', N - P, P, -ONE, A(1, N - P + 1), LDA, D, 1, ONE, C, 1);
  }

  // Solve R11*x1 = c1 for x1

  if (N > P) {
    dtrtrs('Upper', 'No transpose', 'Non-unit', N - P, 1, A, LDA,
        C.asMatrix(N - P), N - P, INFO);

    if (INFO.value > 0) {
      INFO.value = 2;
      return;
    }

    // Put the solutions in X

    dcopy(N - P, C, 1, X, 1);
  }

  // Compute the residual vector:

  if (M < N) {
    NR = M + P - N;
    if (NR > 0) {
      dgemv('No transpose', NR, N - M, -ONE, A(N - P + 1, M + 1), LDA,
          D(NR + 1), 1, ONE, C(N - P + 1), 1);
    }
  } else {
    NR = P;
  }
  if (NR > 0) {
    dtrmv('Upper', 'No transpose', 'Non unit', NR, A(N - P + 1, N - P + 1), LDA,
        D, 1);
    daxpy(NR, -ONE, D, 1, C(N - P + 1), 1);
  }

  // Backward transformation x = Q**T*x

  dormrq('Left', 'Transpose', N, 1, P, B, LDB, WORK(1), X.asMatrix(N), N,
      WORK(P + MN + 1), LWORK - P - MN, INFO);
  WORK[1] = P + MN + max(LOPT, WORK[P + MN + 1].toInt()).toDouble();
}