Rev 82211 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
!> \brief \b DLASSQ updates a sum of squares represented in scaled form.!! =========== DOCUMENTATION ===========!! Online html documentation available at! http://www.netlib.org/lapack/explore-html/!!> \htmlonly!> Download DLASSQ + dependencies!> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlassq.f90">!> [TGZ]</a>!> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlassq.f90">!> [ZIP]</a>!> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlassq.f90">!> [TXT]</a>!> \endhtmlonly!! Definition:! ===========!! SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ )!! .. Scalar Arguments ..! INTEGER INCX, N! DOUBLE PRECISION SCALE, SUMSQ! ..! .. Array Arguments ..! DOUBLE PRECISION X( * )! ..!!!> \par Purpose:! =============!>!> \verbatim!>!> DLASSQ returns the values scale_out and sumsq_out such that!>!> (scale_out**2)*sumsq_out = x( 1 )**2 +...+ x( n )**2 + (scale**2)*sumsq,!>!> where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is!> assumed to be non-negative.!>!> scale and sumsq must be supplied in SCALE and SUMSQ and!> scale_out and sumsq_out are overwritten on SCALE and SUMSQ respectively.!>!> \endverbatim!! Arguments:! ==========!!> \param[in] N!> \verbatim!> N is INTEGER!> The number of elements to be used from the vector x.!> \endverbatim!>!> \param[in] X!> \verbatim!> X is DOUBLE PRECISION array, dimension (1+(N-1)*abs(INCX))!> The vector for which a scaled sum of squares is computed.!> x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n.!> \endverbatim!>!> \param[in] INCX!> \verbatim!> INCX is INTEGER!> The increment between successive values of the vector x.!> If INCX > 0, X(1+(i-1)*INCX) = x(i) for 1 <= i <= n!> If INCX < 0, X(1-(n-i)*INCX) = x(i) for 1 <= i <= n!> If INCX = 0, x isn't a vector so there is no need to call!> this subroutine. If you call it anyway, it will count x(1)!> in the vector norm N times.!> \endverbatim!>!> \param[in,out] SCALE!> \verbatim!> SCALE is DOUBLE PRECISION!> On entry, the value scale in the equation above.!> On exit, SCALE is overwritten by scale_out, the scaling factor!> for the sum of squares.!> \endverbatim!>!> \param[in,out] SUMSQ!> \verbatim!> SUMSQ is DOUBLE PRECISION!> On entry, the value sumsq in the equation above.!> On exit, SUMSQ is overwritten by sumsq_out, the basic sum of!> squares from which scale_out has been factored out.!> \endverbatim!! Authors:! ========!!> \author Edward Anderson, Lockheed Martin!!> \par Contributors:! ==================!>!> Weslley Pereira, University of Colorado Denver, USA!> Nick Papior, Technical University of Denmark, DK!!> \par Further Details:! =====================!>!> \verbatim!>!> Anderson E. (2017)!> Algorithm 978: Safe Scaling in the Level 1 BLAS!> ACM Trans Math Softw 44:1--28!> https://doi.org/10.1145/3061665!>!> Blue, James L. (1978)!> A Portable Fortran Program to Find the Euclidean Norm of a Vector!> ACM Trans Math Softw 4:15--23!> https://doi.org/10.1145/355769.355771!>!> \endverbatim!!> \ingroup lassq!! =====================================================================subroutine DLASSQ( n, x, incx, scale, sumsq )use LA_CONSTANTS, &only: wp=>dp, zero=>dzero, one=>done, &sbig=>dsbig, ssml=>dssml, tbig=>dtbig, tsml=>dtsmluse LA_XISNAN!! -- LAPACK auxiliary routine --! -- LAPACK is a software package provided by Univ. of Tennessee, --! -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--!! .. Scalar Arguments ..integer :: incx, nreal(wp) :: scale, sumsq! ..! .. Array Arguments ..real(wp) :: x(*)! ..! .. Local Scalars ..integer :: i, ixlogical :: notbigreal(wp) :: abig, amed, asml, ax, ymax, ymin! ..!! Quick return if possible!if( LA_ISNAN(scale) .or. LA_ISNAN(sumsq) ) returnif( sumsq == zero ) scale = oneif( scale == zero ) thenscale = onesumsq = zeroend ifif (n <= 0) thenreturnend if!! Compute the sum of squares in 3 accumulators:! abig -- sums of squares scaled down to avoid overflow! asml -- sums of squares scaled up to avoid underflow! amed -- sums of squares that do not require scaling! The thresholds and multipliers are! tbig -- values bigger than this are scaled down by sbig! tsml -- values smaller than this are scaled up by ssml!notbig = .true.asml = zeroamed = zeroabig = zeroix = 1if( incx < 0 ) ix = 1 - (n-1)*incxdo i = 1, nax = abs(x(ix))if (ax > tbig) thenabig = abig + (ax*sbig)**2notbig = .false.else if (ax < tsml) thenif (notbig) asml = asml + (ax*ssml)**2elseamed = amed + ax**2end ifix = ix + incxend do!! Put the existing sum of squares into one of the accumulators!if( sumsq > zero ) thenax = scale*sqrt( sumsq )if (ax > tbig) thenif (scale > one) thenscale = scale * sbigabig = abig + scale * (scale * sumsq)else! sumsq > tbig^2 => (sbig * (sbig * sumsq)) is representableabig = abig + scale * (scale * (sbig * (sbig * sumsq)))end ifelse if (ax < tsml) thenif (notbig) thenif (scale < one) thenscale = scale * ssmlasml = asml + scale * (scale * sumsq)else! sumsq < tsml^2 => (ssml * (ssml * sumsq)) is representableasml = asml + scale * (scale * (ssml * (ssml * sumsq)))end ifend ifelseamed = amed + scale * (scale * sumsq)end ifend if!! Combine abig and amed or amed and asml if more than one! accumulator was used.!if (abig > zero) then!! Combine abig and amed if abig > 0.!if (amed > zero .or. LA_ISNAN(amed)) thenabig = abig + (amed*sbig)*sbigend ifscale = one / sbigsumsq = abigelse if (asml > zero) then!! Combine amed and asml if asml > 0.!if (amed > zero .or. LA_ISNAN(amed)) thenamed = sqrt(amed)asml = sqrt(asml) / ssmlif (asml > amed) thenymin = amedymax = asmlelseymin = asmlymax = amedend ifscale = onesumsq = ymax**2*( one + (ymin/ymax)**2 )elsescale = one / ssmlsumsq = asmlend ifelse!! Otherwise all values are mid-range or zero!scale = onesumsq = amedend ifreturnend subroutine