dorgtsqr function

void dorgtsqr(
  1. int M,
  2. int N,
  3. int MB,
  4. int NB,
  5. Matrix<double> A_,
  6. int LDA,
  7. Matrix<double> T_,
  8. int LDT,
  9. Array<double> WORK_,
  10. int LWORK,
  11. Box<int> INFO,
)

Implementation

void dorgtsqr(
  final int M,
  final int N,
  final int MB,
  final int NB,
  final Matrix<double> A_,
  final int LDA,
  final Matrix<double> T_,
  final int LDT,
  final Array<double> WORK_,
  final int LWORK,
  final Box<int> INFO,
) {
  final A = A_.having(ld: LDA);
  final T = T_.having(ld: LDT);
  final WORK = WORK_.having();
  const ONE = 1.0, ZERO = 0.0;
  bool LQUERY;
  int LDC = 0, LWORKOPT = 0, LC = 0, LW = 0, NBLOCAL = 0, J;
  final IINFO = Box(0);

  // Test the input parameters

  LQUERY = LWORK == -1;
  INFO.value = 0;
  if (M < 0) {
    INFO.value = -1;
  } else if (N < 0 || M < N) {
    INFO.value = -2;
  } else if (MB <= N) {
    INFO.value = -3;
  } else if (NB < 1) {
    INFO.value = -4;
  } else if (LDA < max(1, M)) {
    INFO.value = -6;
  } else if (LDT < max(1, min(NB, N))) {
    INFO.value = -8;
  } else {
    // Test the input LWORK for the dimension of the array WORK.
    // This workspace is used to store array C(LDC, N) and WORK(LWORK)
    // in the call to DLAMTSQR. See the documentation for DLAMTSQR.

    if (LWORK < 2 && !LQUERY) {
      INFO.value = -10;
    } else {
      // Set block size for column blocks

      NBLOCAL = min(NB, N);

      // LWORK = -1, then set the size for the array C(LDC,N)
      // in DLAMTSQR call and set the optimal size of the work array
      // WORK(LWORK) in DLAMTSQR call.

      LDC = M;
      LC = LDC * N;
      LW = N * NBLOCAL;

      LWORKOPT = LC + LW;

      if ((LWORK < max(1, LWORKOPT)) && !LQUERY) {
        INFO.value = -10;
      }
    }
  }

  // Handle error in the input parameters and return workspace query.

  if (INFO.value != 0) {
    xerbla('DORGTSQR', -INFO.value);
    return;
  } else if (LQUERY) {
    WORK[1] = LWORKOPT.toDouble();
    return;
  }

  // Quick return if possible

  if (min(M, N) == 0) {
    WORK[1] = LWORKOPT.toDouble();
    return;
  }

  // (1) Form explicitly the tall-skinny M-by-N left submatrix Q1_in
  // of M-by-M orthogonal matrix Q_in, which is implicitly stored in
  // the subdiagonal part of input array A and in the input array T.
  // Perform by the following operation using the routine DLAMTSQR.

  // Q1_in = Q_in * ( I ), where I is a N-by-N identity matrix,
  //                ( 0 )        0 is a (M-N)-by-N zero matrix.

  // (1a) Form M-by-N matrix in the array WORK(1:LDC*N) with ones
  // on the diagonal and zeros elsewhere.

  dlaset('F', M, N, ZERO, ONE, WORK.asMatrix(LDC), LDC);

  // (1b)  On input, WORK(1:LDC*N) stores ( I );
  //                                      ( 0 )

  // On output, WORK(1:LDC*N) stores Q1_in.

  dlamtsqr('L', 'N', M, N, N, MB, NBLOCAL, A, LDA, T, LDT, WORK.asMatrix(LDC),
      LDC, WORK(LC + 1), LW, IINFO);

  // (2) Copy the result from the part of the work array (1:M,1:N)
  // with the leading dimension LDC that starts at WORK(1) into
  // the output array A(1:M,1:N) column-by-column.

  for (J = 1; J <= N; J++) {
    dcopy(M, WORK((J - 1) * LDC + 1), 1, A(1, J).asArray(), 1);
  }

  WORK[1] = LWORKOPT.toDouble();
}