計算ルーチン: 4つの実部分行列に区分けされた直交行列の CS 分解

LAPACKサンプルソースコード : 使用ルーチン名:DORCSD

ホーム > LAPACKサンプルプログラム目次 > 計算ルーチン > 4つの実部分行列に区分けされた直交行列の CS 分解

概要

本サンプルはFortran言語によりLAPACKルーチンDORCSDを利用するサンプルプログラムです。

入力データ

(本ルーチンの詳細はDORCSD のマニュアルページを参照)

このデータをダウンロード
DORCSD Example Program Data
  5     3      2                         : m, p, q
 -0.7576  0.3697  0.3838  0.2126 -0.3112
 -0.4077 -0.1552 -0.1129  0.2676  0.8517
 -0.0488  0.7240 -0.6730 -0.1301  0.0602
 -0.2287  0.0088  0.2235 -0.9235  0.2120
  0.4530  0.5612  0.5806  0.1162  0.3595 : orthogonal matrix X

出力結果

(本ルーチンの詳細はDORCSD のマニュアルページを参照)

この出力例をダウンロード
 DORCSD Example Program Results

     Orthogonal matrix X
          1       2       3       4       5
 1  -0.7576  0.3697  0.3838  0.2126 -0.3112
 2  -0.4077 -0.1552 -0.1129  0.2676  0.8517
 3  -0.0488  0.7240 -0.6730 -0.1301  0.0602
 4  -0.2287  0.0088  0.2235 -0.9235  0.2120
 5   0.4530  0.5612  0.5806  0.1162  0.3595

 Components of CS factorization of X:

     Theta
          1
 1   0.1811
 2   0.8255

     U1
          1       2       3
 1   0.8249  0.3370 -0.4538
 2   0.2042  0.5710  0.7952
 3   0.5271 -0.7486  0.4022

     U2
          1       2
 1   0.9802  0.1982
 2   0.1982 -0.9802

     V1T
          1       2
 1  -0.7461  0.6658
 2  -0.6658 -0.7461

     V2T
          1       2       3
 1   0.3397 -0.8967  0.2837
 2  -0.7738 -0.4379 -0.4576
 3   0.5346 -0.0640 -0.8427

     Recombined matrix X = U * Sigma_p * V^T
          1       2       3       4       5
 1  -0.7576  0.3697  0.3838  0.2126 -0.3112
 2  -0.4077 -0.1551 -0.1129  0.2677  0.8517
 3  -0.0488  0.7240 -0.6730 -0.1300  0.0602
 4  -0.2287  0.0088  0.2235 -0.9234  0.2120
 5   0.4530  0.5612  0.5806  0.1162  0.3595

ソースコード

(本ルーチンの詳細はDORCSD のマニュアルページを参照)

※本サンプルソースコードのご利用手順は「サンプルのコンパイル及び実行方法」をご参照下さい。


このソースコードをダウンロード
    Program dorcsd_example

!     DORCSD Example Program Text

!     Copyright 2017, Numerical Algorithms Group Ltd. http://www.nag.com

!     .. Use Statements ..
      Use blas_interfaces, Only: dgemm
      Use lapack_example_aux, Only: nagf_file_print_matrix_real_gen
      Use lapack_interfaces, Only: dorcsd
      Use lapack_precision, Only: dp
!     .. Implicit None Statement ..
      Implicit None
!     .. Parameters ..
      Real (Kind=dp), Parameter :: one = 1.0_dp
      Real (Kind=dp), Parameter :: zero = 0.0_dp
      Integer, Parameter :: nin = 5, nout = 6, recombine = 1, reprint = 0
!     .. Local Scalars ..
      Integer :: i, ifail, info, info2, j, ldu, ldu1, ldu2, ldv, ldv1t, ldv2t, &
        ldx, ldx11, ldx12, ldx21, ldx22, lwork, m, n11, n12, n21, n22, p, q, r
!     .. Local Arrays ..
      Real (Kind=dp), Allocatable :: theta(:), u(:, :), u1(:, :), u2(:, :), &
        v(:, :), v1t(:, :), v2t(:, :), w(:, :), work(:), x(:, :), x11(:, :), &
        x12(:, :), x21(:, :), x22(:, :)
      Real (Kind=dp) :: wdum(1)
      Integer, Allocatable :: iwork(:)
!     .. Intrinsic Procedures ..
      Intrinsic :: cos, min, nint, sin
!     .. Executable Statements ..
      Write (nout, *) 'DORCSD Example Program Results'
      Write (nout, *)
      Flush (nout)
!     Skip heading in data file
      Read (nin, *)
      Read (nin, *) m, p, q

      r = min(min(p,q), min(m-p,m-q))

      ldx = m
      ldx11 = p
      ldx12 = p
      ldx21 = m - p
      ldx22 = m - p
      ldu = m
      ldu1 = p
      ldu2 = m - p
      ldv = m
      ldv1t = q
      ldv2t = m - q
      Allocate (x(ldx,m), u(ldu,m), v(ldv,m), theta(r), iwork(m), w(ldx,m))
      Allocate (x11(ldx11,q), x12(ldx12,m-q), x21(ldx21,q), x22(ldx22,m-q))
      Allocate (u1(ldu1,p), u2(ldu2,m-p), v1t(ldv1t,q), v2t(ldv2t,m-q))

!     Read and print orthogonal X from data file
!     (as, say, generated by a generalized singular value decomposition).

      Read (nin, *)(x(i,1:m), i=1, m)

!     Print general matrix using simple matrix printing routine nagf_file_print_matrix_real_gen.
!     ifail: behaviour on error exit
!            =0 for hard exit, =1 for quiet-soft, =-1 for noisy-soft
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', m, m, x, ldx, &
        '    Orthogonal matrix X', ifail)
      Write (nout, *)

!     Compute the complete CS factorization of X:
!        X11 is stored in X(1:p,   1:q), X12 is stored in X(1:p,   q+1:m)
!        X21 is stored in X(p+1:m, 1:q), X22 is stored in X(p+1:m, q+1:m)
!        U1  is stored in U(1:p,   1:p), U2  is stored in U(p+1:m, p+1:m)
!        V1  is stored in V(1:q,   1:q), V2  is stored in V(q+1:m, q+1:m)
      x11(1:p, 1:q) = x(1:p, 1:q)
      x12(1:p, 1:m-q) = x(1:p, q+1:m)
      x21(1:m-p, 1:q) = x(p+1:m, 1:q)
      x22(1:m-p, 1:m-q) = x(p+1:m, q+1:m)

!     Workspace query first to get length of work array for complete CS
!     factorization routine dorcsd.
      lwork = -1
      Call dorcsd('Yes U1', 'Yes U2', 'Yes V1T', 'Yes V2T', 'Column', &
        'Default', m, p, q, x, ldx, x(1,q+1), ldx, x(p+1,1), ldx, x(p+1,q+1), &
        ldx, theta, u, ldu, u(p+1,p+1), ldu, v, ldv, v(q+1,q+1), ldv, wdum, &
        lwork, iwork, info)
      lwork = nint(wdum(1))
      Allocate (work(lwork))
!     Initialize all of  u, v to zero.
      u(1:m, 1:m) = zero
      v(1:m, 1:m) = zero

!     This is how you might pass partitions as sub-matrices
      Call dorcsd('Yes U1', 'Yes U2', 'Yes V1T', 'Yes V2T', 'Column', &
        'Default', m, p, q, x, ldx, x(1,q+1), ldx, x(p+1,1), ldx, x(p+1,q+1), &
        ldx, theta, u, ldu, u(p+1,p+1), ldu, v, ldv, v(q+1,q+1), ldv, work, &
        lwork, iwork, info)
      If (info/=0) Then
        Write (nout, 110) 'Failure in DORCSD. info =', info
        Go To 100
      End If
!     Print Theta, U1, U2, V1T, V2T using matrix printing routine nagf_file_print_matrix_real_gen.
      Write (nout, 120) 'Components of CS factorization of X:'
      Flush (nout)
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', r, 1, theta, r, &
        '    Theta', ifail)
      Write (nout, *)
      Flush (nout)
!     By changes of sign the first r elements of the first row of U1 can be
!     made positive.
      Do i = 1, r
        If (u(1,i)<0.0_dp) Then
          u(1:p, i) = -u(1:p, i)
          u(p+1:m, p+i) = -u(p+1:m, p+i)
          v(i, 1:q) = -v(i, 1:q)
          v(q+i, q+1:m) = -v(q+i, q+1:m)
        End If
      End Do
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', p, p, u, ldu, '    U1', &
        ifail)
      Write (nout, *)
      Flush (nout)
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', m-p, m-p, u(p+1,p+1), &
        ldu, '    U2', ifail)
      Write (nout, *)
      Flush (nout)
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', q, q, v, ldv, '    V1T', &
        ifail)
      Write (nout, *)
      Flush (nout)
      ifail = 0
      Call nagf_file_print_matrix_real_gen('G', 'N', m-q, m-q, v(q+1,q+1), &
        ldv, '    V2T', ifail)
      Write (nout, *)

!     And this is how you might pass partitions as separate matrices.
      Call dorcsd('Yes U1', 'Yes U2', 'Yes V1T', 'Yes V2T', 'Column', &
        'Default', m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, &
        theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, work, lwork, iwork, &
        info2)
      If (info2/=0) Then
        Write (nout, 110) 'Failure in DORCSD. info =', info
        Go To 100
      End If

!     Print Theta, U1, U2, V1T, V2T using matrix printing routine nagf_file_print_matrix_real_gen.
      If (reprint/=0) Then
!       By changes of sign the first r elements of the first row of U1 can be
!       made positive.
        Do i = 1, r
          If (u1(1,i)<0.0_dp) Then
            u1(1:p, i) = -u1(1:p, i)
            u2(1:m-p, i) = -u2(1:m-p, i)
            v1t(i, 1:q) = -v1t(i, 1:q)
            v2t(i, 1:m-q) = -v2t(i, 1:m-q)
          End If
        End Do
        Write (nout, 120) 'Components of CS factorization of X:'
        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', r, 1, theta, r, &
          '    Theta', ifail)
        Write (nout, *)
        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', p, p, u1, ldu1, &
          '    U1', ifail)
        Write (nout, *)
        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', m-p, m-p, u2, ldu2, &
          '    U2', ifail)
        Write (nout, *)
        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', q, q, v1t, ldv1t, &
          '    V1T', ifail)
        Write (nout, *)
        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', m-q, m-q, v2t, ldv2t, &
          '    V2T', ifail)
        Write (nout, *)
        Flush (nout)
      End If
      If (recombine/=0) Then
!       Recombining should return the original matrix
!       Assemble Sigma_p into X
        x(1:m, 1:m) = zero
        n11 = min(p, q) - r
        n12 = min(p, m-q) - r
        n21 = min(m-p, q) - r
        n22 = min(m-p, m-1) - r
!       Top Half
        Do j = 1, n11
          x(j, j) = one
        End Do
        Do j = 1, r
          x(j+n11, j+n11) = cos(theta(j))
          x(j+n11, j+n11+r+n21+n22) = -sin(theta(j))
        End Do
        Do j = 1, n12
          x(j+n11+r, j+n11+r+n21+n22+r) = -one
        End Do
!       Bottom half
        Do j = 1, n22
          x(p+j, q+j) = one
        End Do
        Do j = 1, r
          x(p+n22+j, j+n11) = sin(theta(j))
          x(p+n22+j, j+r+n21+n22) = cos(theta(j))
        End Do
        Do j = 1, n21
          x(p+n22+r+j, n11+r+j) = one
        End Do
!       multiply U * Sigma_p into w
        Call dgemm('n', 'n', m, m, m, one, u, ldu, x, ldx, zero, w, ldx)
!       form U * Sigma_p * V^T into u
        Call dgemm('n', 'n', m, m, m, one, w, ldx, v, ldv, zero, u, ldu)

        Flush (nout)
        ifail = 0
        Call nagf_file_print_matrix_real_gen('G', 'N', m, m, u, ldu, &
          '    Recombined matrix X = U * Sigma_p * V^T', ifail)
      End If

100   Continue

110   Format (1X, A, I4)
120   Format (1X, A, /)
    End Program


ご案内
関連情報
Privacy Policy  /  Trademarks