Skip to content

Commit e961d4d

Browse files
authored
Merge pull request #2864 from martin-frbg/lapack445
FIx underflow/rounding errors in LAPACK (S,D)LANV2
2 parents 7b16937 + 7ed25e9 commit e961d4d

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

lapack-netlib/SRC/dlanv2.f

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,16 @@ SUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
140140
*
141141
* .. Parameters ..
142142
DOUBLE PRECISION ZERO, HALF, ONE
143-
PARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 )
143+
PARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0,
144+
$ TWO = 2.0D0 )
144145
DOUBLE PRECISION MULTPL
145146
PARAMETER ( MULTPL = 4.0D+0 )
146147
* ..
147148
* .. Local Scalars ..
148149
DOUBLE PRECISION AA, BB, BCMAX, BCMIS, CC, CS1, DD, EPS, P, SAB,
149-
$ SAC, SCALE, SIGMA, SN1, TAU, TEMP, Z
150+
$ SAC, SCALE, SIGMA, SN1, TAU, TEMP, Z, SAFMIN,
151+
$ SAFMN2, SAFMX2
152+
INTEGER COUNT
150153
* ..
151154
* .. External Functions ..
152155
DOUBLE PRECISION DLAMCH, DLAPY2
@@ -157,7 +160,11 @@ SUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
157160
* ..
158161
* .. Executable Statements ..
159162
*
163+
SAFMIN = DLAMCH( 'S' )
160164
EPS = DLAMCH( 'P' )
165+
SAFMN2 = DLAMCH( 'B' )**INT( LOG( SAFMIN / EPS ) /
166+
$ LOG( DLAMCH( 'B' ) ) / TWO )
167+
SAFMX2 = ONE / SAFMN2
161168
IF( C.EQ.ZERO ) THEN
162169
CS = ONE
163170
SN = ZERO
@@ -212,7 +219,24 @@ SUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
212219
* Complex eigenvalues, or real (almost) equal eigenvalues.
213220
* Make diagonal elements equal.
214221
*
222+
COUNT = 0
215223
SIGMA = B + C
224+
10 CONTINUE
225+
COUNT = COUNT + 1
226+
SCALE = MAX( ABS(TEMP), ABS(SIGMA) )
227+
IF( SCALE.GE.SAFMX2 ) THEN
228+
SIGMA = SIGMA * SAFMN2
229+
TEMP = TEMP * SAFMN2
230+
IF (COUNT .LE. 20)
231+
$ GOTO 10
232+
END IF
233+
IF( SCALE.LE.SAFMN2 ) THEN
234+
SIGMA = SIGMA * SAFMX2
235+
TEMP = TEMP * SAFMX2
236+
IF (COUNT .LE. 20)
237+
$ GOTO 10
238+
END IF
239+
P = HALF*TEMP
216240
TAU = DLAPY2( SIGMA, TEMP )
217241
CS = SQRT( HALF*( ONE+ABS( SIGMA ) / TAU ) )
218242
SN = -( P / ( TAU*CS ) )*SIGN( ONE, SIGMA )

lapack-netlib/SRC/slanv2.f

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,16 @@ SUBROUTINE SLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
140140
*
141141
* .. Parameters ..
142142
REAL ZERO, HALF, ONE
143-
PARAMETER ( ZERO = 0.0E+0, HALF = 0.5E+0, ONE = 1.0E+0 )
143+
PARAMETER ( ZERO = 0.0E+0, HALF = 0.5E+0, ONE = 1.0E+0,
144+
$ TWO = 2.0E+0 )
144145
REAL MULTPL
145146
PARAMETER ( MULTPL = 4.0E+0 )
146147
* ..
147148
* .. Local Scalars ..
148149
REAL AA, BB, BCMAX, BCMIS, CC, CS1, DD, EPS, P, SAB,
149-
$ SAC, SCALE, SIGMA, SN1, TAU, TEMP, Z
150+
$ SAC, SCALE, SIGMA, SN1, TAU, TEMP, Z, SAFMIN,
151+
$ SAFMN2, SAFMX2
152+
INTEGER COUNT
150153
* ..
151154
* .. External Functions ..
152155
REAL SLAMCH, SLAPY2
@@ -157,7 +160,11 @@ SUBROUTINE SLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
157160
* ..
158161
* .. Executable Statements ..
159162
*
163+
SAFMIN = SLAMCH( 'S' )
160164
EPS = SLAMCH( 'P' )
165+
SAFMN2 = SLAMCH( 'B' )**INT( LOG( SAFMIN / EPS ) /
166+
$ LOG( SLAMCH( 'B' ) ) / TWO )
167+
SAFMX2 = ONE / SAFMN2
161168
IF( C.EQ.ZERO ) THEN
162169
CS = ONE
163170
SN = ZERO
@@ -212,7 +219,24 @@ SUBROUTINE SLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )
212219
* Complex eigenvalues, or real (almost) equal eigenvalues.
213220
* Make diagonal elements equal.
214221
*
222+
COUNT = 0
215223
SIGMA = B + C
224+
10 CONTINUE
225+
COUNT = COUNT + 1
226+
SCALE = MAX( ABS(TEMP), ABS(SIGMA) )
227+
IF( SCALE.GE.SAFMX2 ) THEN
228+
SIGMA = SIGMA * SAFMN2
229+
TEMP = TEMP * SAFMN2
230+
IF (COUNT .LE. 20)
231+
$ GOTO 10
232+
END IF
233+
IF( SCALE.LE.SAFMN2 ) THEN
234+
SIGMA = SIGMA * SAFMX2
235+
TEMP = TEMP * SAFMX2
236+
IF (COUNT .LE. 20)
237+
$ GOTO 10
238+
END IF
239+
P = HALF*TEMP
216240
TAU = SLAPY2( SIGMA, TEMP )
217241
CS = SQRT( HALF*( ONE+ABS( SIGMA ) / TAU ) )
218242
SN = -( P / ( TAU*CS ) )*SIGN( ONE, SIGMA )

0 commit comments

Comments
 (0)