Skip to content
Open
Changes from 1 commit
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
fd5e74e
Add GSVD solver based on QR, CS decompositions
christoph-conrads Sep 26, 2016
63ce490
Make DGGQRCS compile
christoph-conrads Sep 26, 2016
96dccdf
Fix DGGQRCS
christoph-conrads Sep 27, 2016
1e815ee
Fix many DGGQRCS bugs
christoph-conrads Sep 28, 2016
ace0611
Fix matrix computation in DGGQRCS
christoph-conrads Sep 28, 2016
4bb8054
Avoid DGGQRCS workspace query memory overflows
christoph-conrads Sep 28, 2016
32622a6
DGGQRCS: ensure #columns <= #rows with DORCSD2BY1
christoph-conrads Sep 28, 2016
1750e47
Fix completely broken DGGQRCS matrix scaling
christoph-conrads Sep 28, 2016
fbf90a0
Fix DGGQRCS bugs
christoph-conrads Sep 28, 2016
fd8c487
Use 1-based indexing in DGGQRCS
christoph-conrads Sep 29, 2016
7c89211
DGGQRCS: always return optimal workspace
christoph-conrads Sep 29, 2016
d58326f
DGGQRCS: fix indentation in a multiline statement
christoph-conrads Sep 29, 2016
b35fd6c
DGGQRCS: compute V^T R1( 1:RANK, : ) correctly
christoph-conrads Sep 29, 2016
2d8da3a
DGGQRCS: change location of matrix R
christoph-conrads Sep 29, 2016
2c83b37
DGGQRCS: overwrite unused memory with NaNs
christoph-conrads Sep 29, 2016
436931e
DGGQRCS: fix argument to DLACPY
christoph-conrads Sep 29, 2016
094c302
DGGQRCS: use correct leading dimension
christoph-conrads Sep 29, 2016
a25860a
DGGQRCS: fix triangular matrices copies again
christoph-conrads Sep 30, 2016
1e7e677
DGGQRCS: more accurate comments
christoph-conrads Sep 30, 2016
81a282b
Add single-precision GSVD via QR+CSD
christoph-conrads Oct 20, 2019
957e217
DGGQRCS: fix typos
christoph-conrads Oct 20, 2019
f683c79
CGGQRCS: draft complex (2x32bit) GSVD via QR, CSD
christoph-conrads Oct 20, 2019
8e30cd1
Fix harmless out-of-bounds accesses for ASAN
christoph-conrads Dec 15, 2019
fffae5f
SGGQRCS: fix branch condition causing NaNs
christoph-conrads Dec 15, 2019
4f0080a
CGGQRCS: fix an EXTERNAL statement
christoph-conrads Apr 10, 2020
706d952
CGGQRCS: fix argument type
christoph-conrads Apr 10, 2020
5110d92
SGGQRCS: improve comments
christoph-conrads Apr 11, 2020
9944790
CGGQRCS: multiple fixes
christoph-conrads Apr 11, 2020
7caf824
xGGQRCS: replace a loop with scalar assignment
christoph-conrads Apr 15, 2020
fe9ee05
xGGQRCS: remove integer variable `R`
christoph-conrads Apr 15, 2020
c9e5167
CGGQRCS: fix LRWORK computation
christoph-conrads Apr 15, 2020
2a55ab9
DGGQRCS: set all THETA entries to NaN
christoph-conrads Apr 19, 2020
3bb2c51
xGGQRCS: disallow zero dimensions
christoph-conrads Apr 19, 2020
087875f
CGGQRCS: fix LRWORK computation
christoph-conrads Apr 19, 2020
5f307f6
CGGQRCS: fix documentation
christoph-conrads Apr 19, 2020
5121631
Add ZGGQRCS, COMPLEX*16 GSVD via QR, CSD
christoph-conrads Apr 22, 2020
846a97a
xGGQRCS: complete list of external subroutines
christoph-conrads Apr 22, 2020
bf66250
SGGQRCS: fix generalized singular values
christoph-conrads Apr 28, 2020
366de5e
Revert "SGGQRCS: fix generalized singular values"
christoph-conrads Apr 28, 2020
0f06a18
Add SLASRTI sorting indices based on numbers
christoph-conrads Apr 28, 2020
29d3e3b
SLASRTI: update documentation
christoph-conrads Apr 28, 2020
1e512db
Add DLASRTI
christoph-conrads Apr 28, 2020
a238a65
Add SLASRTR, a function sorting rows by max norm
christoph-conrads Apr 29, 2020
7cc4495
xGGQRCS: fix typos
christoph-conrads Apr 29, 2020
3bd430d
xLASRTI: fix typos
christoph-conrads Apr 29, 2020
ae68646
SLASRTR: list missing external subroutines
christoph-conrads Apr 29, 2020
eb7f37e
Add DLASRTR
christoph-conrads Apr 29, 2020
aaaf98c
Add CLASRTR
christoph-conrads Apr 29, 2020
bb2c0b9
Add ZLASRTR
christoph-conrads Apr 29, 2020
b954151
xLASRTI: fix indexing error
christoph-conrads May 1, 2020
eefd3a7
SGGQRCS: do not factor right-hand side GSVD matrix
christoph-conrads May 1, 2020
22735c9
SGGQRCS: fix typo
christoph-conrads May 1, 2020
3a6b92b
SGGQRCS: remove unused subroutines
christoph-conrads May 1, 2020
d7e01db
SGGQRCS: replace matrix scaling with row sorting
christoph-conrads May 1, 2020
84cb49d
Revert "SGGQRCS: replace matrix scaling with row sorting"
christoph-conrads May 3, 2020
2678b0f
SGGQRCS: revert effects of matrix scaling
christoph-conrads May 3, 2020
19a1e0b
SGGQRCS: add row sorting again, keep matrix scaling
christoph-conrads May 3, 2020
b17648c
SGGQRCS: fix error codes after recent API changes
christoph-conrads May 3, 2020
32ebe2b
SGGQRCS: avoid unnecessary operations
christoph-conrads May 4, 2020
357a5b9
SGGQRCS: fix incorrect branch condition
christoph-conrads May 4, 2020
69e0e6b
SGGQRCS: handle A=0 properly
christoph-conrads May 4, 2020
f3e4a2d
SGGQRCS: fix row scaling with singular value zero
christoph-conrads May 4, 2020
20c578d
SGGQRCS: fix documentation typo
christoph-conrads May 5, 2020
060d77c
SGGQRCS: improve documentation
christoph-conrads May 5, 2020
dc2f5e0
SGGQRCS: remove row sorting
christoph-conrads May 5, 2020
676f894
SGGQRCS: ensure matrix scaling factors always >1
christoph-conrads May 6, 2020
b5eb358
SGGQRCS: return sine, cosine values
christoph-conrads May 7, 2020
4202857
SGGQRCS: avoid needless matrix norm recomputation
christoph-conrads May 7, 2020
6e5c3a6
SGGQRCS: update documentation
christoph-conrads May 7, 2020
29eff1b
DGGQRCS: update implementation
christoph-conrads May 7, 2020
ea6b975
DGGQRCS: fix typo
christoph-conrads May 7, 2020
dbae805
CGGQRCS: update implementation
christoph-conrads May 7, 2020
02cc14d
ZGGQRCS: update implementation
christoph-conrads May 7, 2020
3b0f2ac
{s,d}GGQRCS: fix a formula in documentation
christoph-conrads May 7, 2020
762ef54
SGGQRCS: try speeding up matrix multiplication
christoph-conrads May 10, 2020
1593ed7
Revert "SGGQRCS: try speeding up matrix multiplication"
christoph-conrads May 11, 2020
baf0f41
xGGQRCS: fix out-of-bounds access
christoph-conrads May 11, 2020
b9ca9b6
xLASRTI: improve documentation wording
christoph-conrads Jan 16, 2021
0a61fa4
xGGQRCS: fix external functions return value type
christoph-conrads Jan 30, 2021
58f2a5b
CGGQRCS: fix accidental memory allocation
christoph-conrads Jan 30, 2021
dda1d0f
CGGQRCS: fix off-by-one bug
christoph-conrads Jan 30, 2021
702991a
ZGGQRCS: fix accidental memory allocation
christoph-conrads Feb 12, 2021
4a6a0f8
SGGQRCS: fix documentation typos
christoph-conrads Feb 12, 2021
332b4e6
xGGQRCS: fix accidental memory allocation
christoph-conrads Feb 12, 2021
2652e1f
xGGQRCS: remove dead assignments to LWKOPT
christoph-conrads Feb 12, 2021
42f9910
xGGQRCS: fix incorrect info values on error
christoph-conrads Feb 12, 2021
f1358ca
xGGQRCS: check for sufficiently large workspace
christoph-conrads Feb 12, 2021
bd80228
ZGGQRCS: fix documentation typos
christoph-conrads Feb 12, 2021
24fc861
xGGQRCS: update version number, release date
christoph-conrads Feb 13, 2021
3f267f1
xLASRTI: update version number, release date
christoph-conrads Feb 13, 2021
305afaf
xLASRTR: update version number, release date
christoph-conrads Feb 13, 2021
224c527
xGGQRCS: add Fortran files to Makefile
christoph-conrads Feb 13, 2021
0298da0
xGGRCS: documentation improvements
christoph-conrads Feb 13, 2021
3cb8736
xGGQRCS: remove debugging code
christoph-conrads Feb 13, 2021
5b48881
xGGQRCS: remove version and date information
christoph-conrads Apr 20, 2021
9f23fbd
xLASRTR: remove version and date information
christoph-conrads Apr 20, 2021
2a8c4dd
xLASRTI: remove version and date information
christoph-conrads Apr 20, 2021
48d8488
xERRGG: test xGGQRCS input handling
christoph-conrads Apr 20, 2021
6cb9a5f
xGGQRCS: allow matrix input with dimension zero
christoph-conrads Apr 20, 2021
e805767
{c,z}GGQRCS: check if LRWORK is valid
christoph-conrads Apr 21, 2021
8a0bef1
xGGQRCS: ensure leading dimension is at least one
christoph-conrads Apr 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
SGGQRCS: ensure matrix scaling factors always >1
The singular values must be corrected for matrix scaling. Let w be a
power of two such that norm(wA) equals approximately norm(B). Then the
radians representation of the singular values must corrected with

x' = arctan(w * tan(x)),

where x is the computed radians value with matrix scaling and x' is the
computed radians value without matrix scaling. If w is less than one
and if x is large (close to pi/2), then roughly speaking

* tan(x) has a large derivative (i.e. it is badly conditioned),
* w * tan(x) will be smaller than tan(x),
* arctan(w * tan(x)) has derivative near one, because its argument
  is closer to zero.

This commit modifies the GSVD computation such that w >= 1 by choosing
to compute the GSVD of (A, B) or (B, A) depending on the relative norms.
Then

* tan(x) has a small derivative if x is sufficiently small,
* arctan(w * tan(x)) has derivative near zero, and
* if x is large (near pi/2), then x' will be near pi/2 as well.

This commit fixes the large relative forward errors detected by
xGGQRCS_test_singular_values<float>' when the singular values of the
matrix pair (A,B) where drawn from [0, pi/2000).
  • Loading branch information
christoph-conrads committed Apr 21, 2021
commit 676f894932f9fc5a5b2cccf0c3a280568577c82d
140 changes: 76 additions & 64 deletions SRC/sggqrcs.f
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* Definition:
* ===========
*
* SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
* SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L, W,
* A, LDA, B, LDB,
* THETA, U1, LDU1, U2, LDU2
* WORK, LWORK, IWORK, INFO )
Expand Down Expand Up @@ -155,6 +155,14 @@
*> (A**T, B**T)**T.
*> \endverbatim
*>
*> \param[out] W
*> \verbatim
*> W is REAL
*> On exit, W is a radix power chosen such that the Frobenius
*> norm of A and W*B are with SQRT(RADIX) and 1/SQRT(RADIX) of
*> each other.
*> \endverbatim
*>
*> \param[in,out] A
*> \verbatim
*> A is REAL array, dimension (LDA,N)
Expand Down Expand Up @@ -288,7 +296,7 @@
*> stability.
*>
* =====================================================================
SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
RECURSIVE SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L, W,
$ A, LDA, B, LDB,
$ THETA, U1, LDU1, U2, LDU2,
$ WORK, LWORK, IWORK, INFO )
Expand All @@ -302,6 +310,7 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
* .. Scalar Arguments ..
CHARACTER JOBU1, JOBU2, JOBX
INTEGER INFO, LDA, LDB, LDU1, LDU2, L, M, N, P, LWORK
REAL W
* ..
* .. Array Arguments ..
INTEGER IWORK( * )
Expand All @@ -314,9 +323,9 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
*
* .. Local Scalars ..
LOGICAL WANTU1, WANTU2, WANTX, LQUERY
INTEGER I, J, K, K2, LMAX, Z, LDG, LDX, LDVT, LWKOPT
INTEGER I, J, K, K1, LMAX, Z, LDG, LDX, LDVT, LWKOPT
REAL BASE, NAN, NORMA, NORMB, NORMG, TOL, ULP, UNFL,
$ T, W
$ T
* .. Local Arrays ..
REAL G( M + P, N ), VT( N, N )
* ..
Expand All @@ -330,7 +339,7 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
$ SLASET, SORGQR, SORCSD2BY1, XERBLA
* ..
* .. Intrinsic Functions ..
INTRINSIC MAX, MIN
INTRINSIC MAX, MIN, SQRT
* ..
* .. Executable Statements ..
*
Expand All @@ -342,27 +351,6 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
LQUERY = ( LWORK.EQ.-1 )
LWKOPT = 1
*
* Initialize variables
*
L = 0
LMAX = MIN( M + P, N )
Z = ( M + P ) * N
IF ( LQUERY ) THEN
G = 0
ELSE
G = WORK( 1 )
END IF
IF( WANTX .AND. .NOT.LQUERY ) THEN
VT = WORK( Z + 1 )
ELSE
VT = 0
END IF
LDVT = N
LDG = M + P
* Computing 0.0 / 0.0 directly causes compiler errors
NAN = 1.0E0
NAN = 0.0 / (NAN - 1.0E0)
*
* Test the input arguments
*
INFO = 0
Expand All @@ -379,22 +367,53 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
ELSE IF( P.LT.1 ) THEN
INFO = -6
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -9
INFO = -10
ELSE IF( LDB.LT.MAX( 1, P ) ) THEN
INFO = -11
INFO = -12
ELSE IF( LDU1.LT.1 .OR. ( WANTU1 .AND. LDU1.LT.M ) ) THEN
INFO = -14
INFO = -15
ELSE IF( LDU2.LT.1 .OR. ( WANTU2 .AND. LDU2.LT.P ) ) THEN
INFO = -16
INFO = -17
ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN
INFO = -18
INFO = -19
END IF
*
* Make sure A is the matrix smaller in norm
*
IF( INFO.EQ.0 ) THEN
NORMA = SLANGE( 'F', M, N, A, LDA, WORK )
NORMB = SLANGE( 'F', P, N, B, LDB, WORK )
*
IF( NORMA.GT.SQRT( 2.0E0 ) * NORMB ) THEN
CALL SGGQRCS( JOBU2, JOBU1, JOBX, P, N, M, L, W,
$ B, LDB, A, LDA,
$ THETA,
$ U2, LDU2, U1, LDU1,
$ WORK, LWORK, IWORK, INFO )
W = -W
RETURN
ENDIF
END IF
*
* Initialize variables
*
* Computing 0.0 / 0.0 directly causes compiler errors
NAN = 1.0E0
NAN = 0.0 / (NAN - 1.0E0)
*
L = 0
LMAX = MIN( M + P, N )
Z = ( M + P ) * N
G = WORK( 1 )
LDG = M + P
VT = 0
LDVT = N
W = NAN
*
* Compute workspace
*
IF( INFO.EQ.0 ) THEN
* SLASRTR workspace
LWKOPT = M + P
LWKOPT = 0

CALL SGEQP3( M+P, N, G, LDG, IWORK, THETA, WORK, -1, INFO )
LWKOPT = MAX( LWKOPT, INT( WORK( 1 ) ) )
Expand All @@ -403,12 +422,12 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
CALL SORGQR( M + P, LMAX, LMAX, G, LDG, THETA, WORK, -1, INFO )
LWKOPT = MAX( LWKOPT, INT( WORK( 1 ) ) )

CALL SORCSD2BY1( JOBU2, JOBU1, JOBX, M + P, P, LMAX,
CALL SORCSD2BY1( JOBU2, JOBU1, JOBX, M + P, M, LMAX,
$ G, LDG, G, LDG,
$ THETA, U2, LDU2, U1, LDU1, VT, LDVT,
$ THETA, U1, LDU1, U2, LDU2, VT, LDVT,
$ WORK, -1, IWORK, INFO )
LWKOPT = MAX( LWKOPT, INT( WORK( 1 ) ) )
* The matrix (A, B) must be stored sequentially for SORCSD2BY1
* The matrix (A, B) must be stored sequentially for SORGQR
LWKOPT = LWKOPT + Z
* 2-by-1 CSD matrix V1 must be stored
IF( WANTX ) THEN
Expand All @@ -425,28 +444,29 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
IF( LQUERY ) THEN
RETURN
ENDIF
* Finish initialization
IF( WANTX ) THEN
VT = WORK( Z + 1 )
END IF
*
* Scale matrix B such that norm(A) \approx norm(B)
*
NORMA = SLANGE( 'F', M, N, A, LDA, WORK )
NORMB = SLANGE( 'F', P, N, B, LDB, WORK )
* Scale matrix A such that norm(A) \approx norm(B)
*
IF( NORMB.EQ.0 .OR. NORMA.EQ.0 ) THEN
IF( NORMA.EQ.0.0E0 ) THEN
W = 1.0E0
ELSE
BASE = SLAMCH( 'B' )
W = BASE ** INT( LOG( NORMA / NORMB ) / LOG( BASE ) )
W = BASE ** INT( LOG( NORMB / NORMA ) / LOG( BASE ) )
*
CALL SLASCL( 'G', -1, -1, 1.0E0, W, P, N, B, LDB, INFO )
CALL SLASCL( 'G', -1, -1, 1.0E0, W, M, N, A, LDA, INFO )
IF ( INFO.NE.0 ) THEN
RETURN
END IF
END IF
*
* Copy matrices A, B into the (M+P) x N matrix G
*
CALL SLACPY( 'A', M, N, A, LDA, G( P + 1, 1 ), LDG )
CALL SLACPY( 'A', P, N, B, LDB, G( 1, 1 ), LDG )
CALL SLACPY( 'A', M, N, A, LDA, G( 1, 1 ), LDG )
CALL SLACPY( 'A', P, N, B, LDB, G( M + 1, 1 ), LDG )
*
* DEBUG
*
Expand Down Expand Up @@ -480,12 +500,12 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
*
* Determine the rank of G
*
DO 20 I = 1, MIN( M + P, N )
DO I = 1, MIN( M + P, N )
IF( ABS( G( I, I ) ).LE.TOL ) THEN
EXIT
END IF
L = L + 1
20 CONTINUE
END DO
*
* Handle rank=0 case
*
Expand Down Expand Up @@ -530,19 +550,11 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
*
* Compute the CS decomposition of Q1( :, 1:L )
*
IF( WANTX ) THEN
CALL SORCSD2BY1( JOBU2, JOBU1, JOBX, M + P, P, L,
$ G( 1, 1 ), LDG, G( P + 1, 1 ), LDG, THETA,
$ U2, LDU2, U1, LDU1, VT, LDVT,
$ WORK( Z + LDVT*N + 1 ), LWORK - Z - LDVT*N,
$ IWORK( N + 1 ), INFO )
ELSE
CALL SORCSD2BY1( JOBU2, JOBU1, JOBX, M + P, P, L,
$ G( 1, 1 ), LDG, G( P + 1, 1 ), LDG, THETA,
$ U2, LDU2, U1, LDU1, VT, LDVT,
$ WORK( Z + 1 ), LWORK - Z,
$ IWORK, INFO )
END IF
CALL SORCSD2BY1( JOBU1, JOBU2, JOBX, M + P, M, L,
$ G( 1, 1 ), LDG, G( M + 1, 1 ), LDG, THETA,
$ U1, LDU1, U2, LDU2, VT, LDVT,
$ WORK( Z + LDVT*N + 1 ), LWORK - Z - LDVT*N,
$ IWORK( N + 1 ), INFO )
IF( INFO.NE.0 ) THEN
RETURN
END IF
Expand Down Expand Up @@ -573,7 +585,7 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
* Prepare row scaling of X
IF( .NOT. W.EQ.1.0E0 ) THEN
K = MIN( M, P, L, M + P - L )
K2 = MAX( L - M, 0 )
K1 = MAX( L - P, 0 )
DO I = 1, K
T = THETA( I )
* Do not adjust singular value if THETA(I) is greater
Expand All @@ -593,12 +605,12 @@ SUBROUTINE SGGQRCS( JOBU1, JOBU2, JOBX, M, N, P, L,
END DO
* Adjust rows of X for matrix scaling
DO J = 0, N-1
DO I = 1, K2
DO I = 1, K1
WORK( LDX*J + I + 1 ) = WORK( LDX*J + I + 1 ) / W
END DO
DO I = 1, K
WORK( LDX*J + I + K2 + 1 ) =
$ WORK( LDX*J + I + K2 + 1 ) * WORK( Z + I + 1 )
WORK( LDX*J + I + K1 + 1 ) =
$ WORK( LDX*J + I + K1 + 1 ) * WORK( Z + I + 1 )
END DO
END DO
END IF
Expand Down