@@ -101,17 +101,16 @@ SUBROUTINE CRSCL( N, A, X, INCX )
101101 PARAMETER ( ZERO = 0.0E+0 , ONE = 1.0E+0 )
102102* ..
103103* .. Local Scalars ..
104- REAL BIGNUM, SMLNUM, HUGE , AR, AI, ABSR, ABSI, UR
104+ REAL SAFMAX, SAFMIN, OV , AR, AI, ABSR, ABSI, UR
105105 % , UI
106- COMPLEX INVA
107106* ..
108107* .. External Functions ..
109108 REAL SLAMCH
110109 COMPLEX CLADIV
111110 EXTERNAL SLAMCH, CLADIV
112111* ..
113112* .. External Subroutines ..
114- EXTERNAL CSCAL, CSSCAL
113+ EXTERNAL CSCAL, CSSCAL, CSRSCL
115114* ..
116115* .. Intrinsic Functions ..
117116 INTRINSIC ABS
@@ -125,9 +124,9 @@ SUBROUTINE CRSCL( N, A, X, INCX )
125124*
126125* Get machine parameters
127126*
128- SMLNUM = SLAMCH( ' S' )
129- BIGNUM = ONE / SMLNUM
130- HUGE = SLAMCH( ' O' )
127+ SAFMIN = SLAMCH( ' S' )
128+ SAFMAX = ONE / SAFMIN
129+ OV = SLAMCH( ' O' )
131130*
132131* Initialize constants related to A.
133132*
@@ -136,68 +135,63 @@ SUBROUTINE CRSCL( N, A, X, INCX )
136135 ABSR = ABS ( AR )
137136 ABSI = ABS ( AI )
138137*
139- IF ( ABSI .EQ. ZERO ) THEN
138+ IF ( AI .EQ. ZERO ) THEN
140139* If alpha is real, then we can use csrscl
141140 CALL CSRSCL( N, AR, X, INCX )
142141*
143- ELSE IF ( ABSR .EQ. ZERO ) THEN
142+ ELSE IF ( AR .EQ. ZERO ) THEN
144143* If alpha has a zero real part, then we follow the same rules as if
145144* alpha were real.
146- IF ( ABSI.GT. BIGNUM ) THEN
147- INVA = CMPLX ( ZERO, - BIGNUM / AI )
148- CALL CSSCAL( N, SMLNUM, X, INCX )
149- CALL CSCAL( N, INVA, X, INCX )
150- ELSE IF ( ABSI.LT. SMLNUM ) THEN
151- INVA = CMPLX ( ZERO, - SMLNUM / AI )
152- CALL CSCAL( N, INVA, X, INCX )
153- CALL CSSCAL( N, BIGNUM, X, INCX )
145+ IF ( ABSI.GT. SAFMAX ) THEN
146+ CALL CSSCAL( N, SAFMIN, X, INCX )
147+ CALL CSCAL( N, CMPLX ( ZERO, - SAFMAX / AI ), X, INCX )
148+ ELSE IF ( ABSI.LT. SAFMIN ) THEN
149+ CALL CSCAL( N, CMPLX ( ZERO, - SAFMIN / AI ), X, INCX )
150+ CALL CSSCAL( N, SAFMAX, X, INCX )
154151 ELSE
155- INVA = CMPLX ( ZERO, - ONE / AI )
156- CALL CSCAL( N, INVA, X, INCX )
152+ CALL CSCAL( N, CMPLX ( ZERO, - ONE / AI ), X, INCX )
157153 END IF
158- *
159- ELSE IF ( (ABSR.GE. BIGNUM).OR. (ABSI.GE. BIGNUM) ) THEN
160- * Either real or imaginary part is too large.
161- INVA = CLADIV( CMPLX ( BIGNUM, ZERO ), A )
162- CALL CSSCAL( N, SMLNUM, X, INCX )
163- CALL CSCAL( N, INVA, X, INCX )
164154*
165155 ELSE
166- * The following numbers can be computed without NaNs and zeros.
167- * They do not overflow simultaneously.
156+ * The following numbers can be computed.
168157* They are the inverse of the real and imaginary parts of 1/alpha.
158+ * Note that a and b are always different from zero.
159+ * NaNs are only possible if either:
160+ * 1. alphaR or alphaI is NaN.
161+ * 2. alphaR and alphaI are both infinite, in which case it makes sense
162+ * to propagate a NaN.
169163 UR = AR + AI * ( AI / AR )
170164 UI = AI + AR * ( AR / AI )
171165*
172- IF ( (ABS ( UR ).LT. SMLNUM).OR. (ABS ( UI ).LT. SMLNUM) ) THEN
173- INVA = CMPLX ( SMLNUM / UR, - SMLNUM / UI )
174- CALL CSCAL( N, INVA, X, INCX )
175- CALL CSSCAL( N, BIGNUM, X, INCX )
176- ELSE IF ( ABS ( UR ).GT. HUGE ) THEN
177- IF ( ABSR.GE. ABSI ) THEN
178- UR = (SMLNUM * AR) + AI * (SMLNUM * (AI / AR))
179- ELSE
180- UR = (SMLNUM * AR) + AI * ((SMLNUM * AI) / AR)
181- END IF
182- INVA = CMPLX ( ONE / UR, - BIGNUM / UI )
183- CALL CSSCAL( N, SMLNUM, X, INCX )
184- CALL CSCAL( N, INVA, X, INCX )
185- ELSE IF ( ABS ( UI ).GT. HUGE ) THEN
186- IF ( ABSI.GE. ABSR ) THEN
187- UI = (SMLNUM * AI) + AR * (SMLNUM * (AR / AI))
166+ IF ( (ABS ( UR ).LT. SAFMIN).OR. (ABS ( UI ).LT. SAFMIN) ) THEN
167+ * This means that both alphaR and alphaI are very small.
168+ CALL CSCAL( N, CMPLX ( SAFMIN / UR, - SAFMIN / UI ), X, INCX )
169+ CALL CSSCAL( N, SAFMAX, X, INCX )
170+ ELSE IF ( (ABS ( UR ).GT. SAFMAX).OR. (ABS ( UI ).GT. SAFMAX) ) THEN
171+ IF ( (ABSR.GT. OV).OR. (ABSI.GT. OV) ) THEN
172+ * This means that a and b are both Inf. No need for scaling.
173+ CALL CSCAL( N, CMPLX ( ONE / UR, - ONE / UI ), X, INCX )
188174 ELSE
189- UI = (SMLNUM * AI) + AR * ((SMLNUM * AR) / AI)
175+ CALL CSSCAL( N, SAFMIN, X, INCX )
176+ IF ( (ABS ( UR ).GT. OV).OR. (ABS ( UI ).GT. OV) ) THEN
177+ * Infs were generated. We do proper scaling to avoid them.
178+ IF ( ABSR.GE. ABSI ) THEN
179+ * ABS( UR ) <= ABS( UI )
180+ UR = (SAFMIN * AR) + SAFMIN * (AI * ( AI / AR ))
181+ UI = (SAFMIN * AI) + AR * ( (SAFMIN * AR) / AI )
182+ ELSE
183+ * ABS( UR ) > ABS( UI )
184+ UR = (SAFMIN * AR) + AI * ( (SAFMIN * AI) / AR )
185+ UI = (SAFMIN * AI) + SAFMIN * (AR * ( AR / AI ))
186+ END IF
187+ CALL CSCAL( N, CMPLX ( ONE / UR, - ONE / UI ), X, INCX )
188+ ELSE
189+ CALL CSCAL( N, CMPLX ( SAFMAX / UR, - SAFMAX / UI ),
190+ $ X, INCX )
191+ END IF
190192 END IF
191- INVA = CMPLX ( BIGNUM / UR, - ONE / UI )
192- CALL CSSCAL( N, SMLNUM, X, INCX )
193- CALL CSCAL( N, INVA, X, INCX )
194- ELSE IF ( (ABS ( UR ).GT. BIGNUM).OR. (ABS ( UI ).GT. BIGNUM) ) THEN
195- INVA = CMPLX ( BIGNUM / UR, - BIGNUM / UI )
196- CALL CSSCAL( N, SMLNUM, X, INCX )
197- CALL CSCAL( N, INVA, X, INCX )
198193 ELSE
199- INVA = CMPLX ( ONE / UR, - ONE / UI )
200- CALL CSCAL( N, INVA, X, INCX )
194+ CALL CSCAL( N, CMPLX ( ONE / UR, - ONE / UI ), X, INCX )
201195 END IF
202196 END IF
203197*
0 commit comments