1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
     132
     133
     134
     135
     136
     137
     138
     139
     140
     141
     142
     143
     144
     145
     146
     147
     148
     149
     150
     151
     152
     153
     154
     155
     156
     157
     158
     159
     160
     161
     162
     163
     164
     165
     166
      SUBROUTINE DORT01ROWCOLMNULDUWORKLWORKRESID )
*
*  -- LAPACK test routine (version 3.1) --
*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
*     November 2006
*
*     .. Scalar Arguments ..
      CHARACTER          ROWCOL
      INTEGER            LDULWORKMN
      DOUBLE PRECISION   RESID
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION   ULDU* ), WORK* )
*     ..
*
*  Purpose
*  =======
*
*  DORT01 checks that the matrix U is orthogonal by computing the ratio
*
*     RESID = norm( I - U*U' ) / ( n * EPS ), if ROWCOL = 'R',
*  or
*     RESID = norm( I - U'*U ) / ( m * EPS ), if ROWCOL = 'C'.
*
*  Alternatively, if there isn't sufficient workspace to form
*  I - U*U' or I - U'*U, the ratio is computed as
*
*     RESID = abs( I - U*U' ) / ( n * EPS ), if ROWCOL = 'R',
*  or
*     RESID = abs( I - U'*U ) / ( m * EPS ), if ROWCOL = 'C'.
*
*  where EPS is the machine precision.  ROWCOL is used only if m = n;
*  if m > n, ROWCOL is assumed to be 'C', and if m < n, ROWCOL is
*  assumed to be 'R'.
*
*  Arguments
*  =========
*
*  ROWCOL  (input) CHARACTER
*          Specifies whether the rows or columns of U should be checked
*          for orthogonality.  Used only if M = N.
*          = 'R':  Check for orthogonal rows of U
*          = 'C':  Check for orthogonal columns of U
*
*  M       (input) INTEGER
*          The number of rows of the matrix U.
*
*  N       (input) INTEGER
*          The number of columns of the matrix U.
*
*  U       (input) DOUBLE PRECISION array, dimension (LDU,N)
*          The orthogonal matrix U.  U is checked for orthogonal columns
*          if m > n or if m = n and ROWCOL = 'C'.  U is checked for
*          orthogonal rows if m < n or if m = n and ROWCOL = 'R'.
*
*  LDU     (input) INTEGER
*          The leading dimension of the array U.  LDU >= max(1,M).
*
*  WORK    (workspace) DOUBLE PRECISION array, dimension (LWORK)
*
*  LWORK   (input) INTEGER
*          The length of the array WORK.  For best performance, LWORK
*          should be at least N*(N+1) if ROWCOL = 'C' or M*(M+1) if
*          ROWCOL = 'R', but the test will be done even if LWORK is 0.
*
*  RESID   (output) DOUBLE PRECISION
*          RESID = norm( I - U * U' ) / ( n * EPS ), if ROWCOL = 'R', or
*          RESID = norm( I - U' * U ) / ( m * EPS ), if ROWCOL = 'C'.
*
*  =====================================================================
*
*     .. Parameters ..
      DOUBLE PRECISION   ZEROONE
      PARAMETER          ( ZERO = 0.0D+0ONE = 1.0D+0 )
*     ..
*     .. Local Scalars ..
      CHARACTER          TRANSU
      INTEGER            IJKLDWORKMNMIN
      DOUBLE PRECISION   EPSTMP
*     ..
*     .. External Functions ..
      LOGICAL            LSAME
      DOUBLE PRECISION   DDOTDLAMCHDLANSY
      EXTERNAL           LSAMEDDOTDLAMCHDLANSY
*     ..
*     .. External Subroutines ..
      EXTERNAL           DLASETDSYRK
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC          ABSDBLEMAXMIN
*     ..
*     .. Executable Statements ..
*
      RESID = ZERO
*
*     Quick return if possible
*
      IFM.LE.0 .OR. N.LE.0 )
     $   RETURN
*
      EPS = DLAMCH'Precision' )
      IFM.LT.N .OR. ( M.EQ.N .AND. LSAMEROWCOL'R' ) ) ) THEN
         TRANSU = 'N'
         K = N
      ELSE
         TRANSU = 'T'
         K = M
      END IF
      MNMIN = MINMN )
*
      IF( ( MNMIN+1 )*MNMIN.LE.LWORK ) THEN
         LDWORK = MNMIN
      ELSE
         LDWORK = 0
      END IF
      IFLDWORK.GT.0 ) THEN
*
*        Compute I - U*U' or I - U'*U.
*
         CALL DLASET'Upper'MNMINMNMINZEROONEWORKLDWORK )
         CALL DSYRK'Upper'TRANSUMNMINK-ONEULDUONEWORK,
     $               LDWORK )
*
*        Compute norm( I - U*U' ) / ( K * EPS ) .
*
         RESID = DLANSY'1''Upper'MNMINWORKLDWORK,
     $           WORKLDWORK*MNMIN+1 ) )
         RESID = ( RESID / DBLEK ) ) / EPS
      ELSE IFTRANSU.EQ.'T' ) THEN
*
*        Find the maximum element in abs( I - U'*U ) / ( m * EPS )
*
         DO 20 J = 1N
            DO 10 I = 1J
               IFI.NE.J ) THEN
                  TMP = ZERO
               ELSE
                  TMP = ONE
               END IF
               TMP = TMP - DDOTMU1I ), 1U1J ), 1 )
               RESID = MAXRESIDABSTMP ) )
   10       CONTINUE
   20    CONTINUE
         RESID = ( RESID / DBLEM ) ) / EPS
      ELSE
*
*        Find the maximum element in abs( I - U*U' ) / ( n * EPS )
*
         DO 40 J = 1M
            DO 30 I = 1J
               IFI.NE.J ) THEN
                  TMP = ZERO
               ELSE
                  TMP = ONE
               END IF
               TMP = TMP - DDOTNUJ1 ), LDUUI1 ), LDU )
               RESID = MAXRESIDABSTMP ) )
   30       CONTINUE
   40    CONTINUE
         RESID = ( RESID / DBLEN ) ) / EPS
      END IF
      RETURN
*
*     End of DORT01
*
      END