4444! > scale and sumsq must be supplied in SCALE and SUMSQ and
4545! > scale_out and sumsq_out are overwritten on SCALE and SUMSQ respectively.
4646! >
47- ! > If scale * sqrt( sumsq ) > tbig then
48- ! > we require: scale >= sqrt( TINY*EPS ) / sbig on entry,
49- ! > and if 0 < scale * sqrt( sumsq ) < tsml then
50- ! > we require: scale <= sqrt( HUGE ) / ssml on entry,
51- ! > where
52- ! > tbig -- upper threshold for values whose square is representable;
53- ! > sbig -- scaling constant for big numbers; \see la_constants.f90
54- ! > tsml -- lower threshold for values whose square is representable;
55- ! > ssml -- scaling constant for small numbers; \see la_constants.f90
56- ! > and
57- ! > TINY*EPS -- tiniest representable number;
58- ! > HUGE -- biggest representable number.
59- ! >
6047! > \endverbatim
6148!
6249! Arguments:
135122! =====================================================================
136123subroutine CLASSQ ( n , x , incx , scale , sumsq )
137124 use LA_CONSTANTS, &
138- only: wp= >sp, zero= >szero, one= >sone, &
125+ only: wp= >sp, zero= >szero, one= >sone, safmin = >ssafmin, &
139126 sbig= >ssbig, ssml= >sssml, tbig= >stbig, tsml= >stsml
140127 use LA_XISNAN
141128!
@@ -153,7 +140,11 @@ subroutine CLASSQ( n, x, incx, scale, sumsq )
153140! .. Local Scalars ..
154141 integer :: i, ix
155142 logical :: notbig
156- real (wp) :: abig, amed, asml, ax, ymax, ymin
143+ real (wp) :: abig, amed, asml, ax, ymax, ymin, sqrtmin, sqrtmax
144+ ! ..
145+ ! .. Set constants ..
146+ sqrtmin = sqrt (safmin)
147+ sqrtmax = one / sqrtmin
157148! ..
158149!
159150! Quick return if possible
@@ -209,13 +200,43 @@ subroutine CLASSQ( n, x, incx, scale, sumsq )
209200 if ( sumsq > zero ) then
210201 ax = scale* sqrt ( sumsq )
211202 if (ax > tbig) then
212- ! We assume scale >= sqrt( TINY*EPS ) / sbig
213- abig = abig + (scale* sbig)** 2 * sumsq
203+ if (scale > one) then
204+ scale = scale * sbig ! sbig < scale <= sbig * max
205+ if (scale > sqrtmin) then
206+ ! sqrtmin < scale < sqrtmax, so it is safe to square scale
207+ abig = abig + (scale * scale) * sumsq
208+ else
209+ ! Do not square scale, as it may underflow
210+ abig = abig + scale * (scale * sumsq)
211+ end if
212+ else
213+ ! sumsq > tbig^2 => (sbig * (sbig * sumsq)) is representable
214+ abig = abig + scale * (scale * (sbig * (sbig * sumsq)))
215+ end if
214216 else if (ax < tsml) then
215- ! We assume scale <= sqrt( HUGE ) / ssml
216- if (notbig) asml = asml + (scale* ssml)** 2 * sumsq
217+ if (notbig) then
218+ if (scale < one) then
219+ scale = scale * ssml ! ssml * min <= scale < ssml
220+ if (scale < sqrtmax) then
221+ ! sqrtmin < scale < sqrtmax, so it is safe to square scale
222+ asml = asml + (scale * scale) * sumsq
223+ else
224+ ! Do not square scale, as it may overflow
225+ asml = asml + scale * (scale * sumsq)
226+ end if
227+ else
228+ ! sumsq < tsml^2 => (ssml * (ssml * sumsq)) is representable
229+ asml = asml + scale * (scale * (ssml * (ssml * sumsq)))
230+ end if
231+ end if
217232 else
218- amed = amed + scale** 2 * sumsq
233+ if (scale > sqrtmin .and. scale < sqrtmax) then
234+ ! sqrtmin < scale < sqrtmax, so it is safe to square scale
235+ amed = amed + (scale * scale) * sumsq
236+ else
237+ ! Do not square scale, as it may overflow
238+ amed = amed + scale * (scale * sumsq)
239+ end if
219240 end if
220241 end if
221242!
0 commit comments