Annotation of rpl/lapack/blas/dnrm2.f90, revision 1.1

1.1     ! bertrand    1: !> \brief \b DNRM2
        !             2: !
        !             3: !  =========== DOCUMENTATION ===========
        !             4: !
        !             5: ! Online html documentation available at
        !             6: !            http://www.netlib.org/lapack/explore-html/
        !             7: !
        !             8: !  Definition:
        !             9: !  ===========
        !            10: !
        !            11: !       DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX)
        !            12: !
        !            13: !       .. Scalar Arguments ..
        !            14: !       INTEGER INCX,N
        !            15: !       ..
        !            16: !       .. Array Arguments ..
        !            17: !       DOUBLE PRECISION X(*)
        !            18: !       ..
        !            19: !
        !            20: !
        !            21: !> \par Purpose:
        !            22: !  =============
        !            23: !>
        !            24: !> \verbatim
        !            25: !>
        !            26: !> DNRM2 returns the euclidean norm of a vector via the function
        !            27: !> name, so that
        !            28: !>
        !            29: !>    DNRM2 := sqrt( x'*x )
        !            30: !> \endverbatim
        !            31: !
        !            32: !  Arguments:
        !            33: !  ==========
        !            34: !
        !            35: !> \param[in] N
        !            36: !> \verbatim
        !            37: !>          N is INTEGER
        !            38: !>         number of elements in input vector(s)
        !            39: !> \endverbatim
        !            40: !>
        !            41: !> \param[in] X
        !            42: !> \verbatim
        !            43: !>          X is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
        !            44: !> \endverbatim
        !            45: !>
        !            46: !> \param[in] INCX
        !            47: !> \verbatim
        !            48: !>          INCX is INTEGER, storage spacing between elements of X
        !            49: !>          If INCX > 0, X(1+(i-1)*INCX) = x(i) for 1 <= i <= n
        !            50: !>          If INCX < 0, X(1-(n-i)*INCX) = x(i) for 1 <= i <= n
        !            51: !>          If INCX = 0, x isn't a vector so there is no need to call
        !            52: !>          this subroutine.  If you call it anyway, it will count x(1)
        !            53: !>          in the vector norm N times.
        !            54: !> \endverbatim
        !            55: !
        !            56: !  Authors:
        !            57: !  ========
        !            58: !
        !            59: !> \author Edward Anderson, Lockheed Martin
        !            60: !
        !            61: !> \date August 2016
        !            62: !
        !            63: !> \ingroup single_blas_level1
        !            64: !
        !            65: !> \par Contributors:
        !            66: !  ==================
        !            67: !>
        !            68: !> Weslley Pereira, University of Colorado Denver, USA
        !            69: !
        !            70: !> \par Further Details:
        !            71: !  =====================
        !            72: !>
        !            73: !> \verbatim
        !            74: !>
        !            75: !>  Anderson E. (2017)
        !            76: !>  Algorithm 978: Safe Scaling in the Level 1 BLAS
        !            77: !>  ACM Trans Math Softw 44:1--28
        !            78: !>  https://doi.org/10.1145/3061665
        !            79: !>
        !            80: !>  Blue, James L. (1978)
        !            81: !>  A Portable Fortran Program to Find the Euclidean Norm of a Vector
        !            82: !>  ACM Trans Math Softw 4:15--23
        !            83: !>  https://doi.org/10.1145/355769.355771
        !            84: !>
        !            85: !> \endverbatim
        !            86: !>
        !            87: !  =====================================================================
        !            88: function DNRM2( n, x, incx ) 
        !            89:    integer, parameter :: wp = kind(1.d0)
        !            90:    real(wp) :: DNRM2
        !            91: !
        !            92: !  -- Reference BLAS level1 routine (version 3.9.1) --
        !            93: !  -- Reference BLAS is a software package provided by Univ. of Tennessee,    --
        !            94: !  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
        !            95: !     March 2021
        !            96: !
        !            97: !  .. Constants ..
        !            98:    real(wp), parameter :: zero = 0.0_wp
        !            99:    real(wp), parameter :: one  = 1.0_wp
        !           100:    real(wp), parameter :: maxN = huge(0.0_wp)
        !           101: !  ..
        !           102: !  .. Blue's scaling constants ..
        !           103:    real(wp), parameter :: tsml = real(radix(0._wp), wp)**ceiling( &
        !           104:        (minexponent(0._wp) - 1) * 0.5_wp)
        !           105:    real(wp), parameter :: tbig = real(radix(0._wp), wp)**floor( &
        !           106:        (maxexponent(0._wp) - digits(0._wp) + 1) * 0.5_wp)
        !           107:    real(wp), parameter :: ssml = real(radix(0._wp), wp)**( - floor( &
        !           108:        (minexponent(0._wp) - digits(0._wp)) * 0.5_wp))
        !           109:    real(wp), parameter :: sbig = real(radix(0._wp), wp)**( - ceiling( &
        !           110:        (maxexponent(0._wp) + digits(0._wp) - 1) * 0.5_wp))
        !           111: !  ..
        !           112: !  .. Scalar Arguments ..
        !           113:    integer :: incx, n
        !           114: !  ..
        !           115: !  .. Array Arguments ..
        !           116:    real(wp) :: x(*)
        !           117: !  ..
        !           118: !  .. Local Scalars ..
        !           119:    integer :: i, ix
        !           120:    logical :: notbig
        !           121:    real(wp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin
        !           122: !
        !           123: !  Quick return if possible
        !           124: !
        !           125:    DNRM2 = zero
        !           126:    if( n <= 0 ) return
        !           127: !
        !           128:    scl = one
        !           129:    sumsq = zero
        !           130: !
        !           131: !  Compute the sum of squares in 3 accumulators:
        !           132: !     abig -- sums of squares scaled down to avoid overflow
        !           133: !     asml -- sums of squares scaled up to avoid underflow
        !           134: !     amed -- sums of squares that do not require scaling
        !           135: !  The thresholds and multipliers are
        !           136: !     tbig -- values bigger than this are scaled down by sbig
        !           137: !     tsml -- values smaller than this are scaled up by ssml
        !           138: !
        !           139:    notbig = .true.
        !           140:    asml = zero
        !           141:    amed = zero
        !           142:    abig = zero
        !           143:    ix = 1
        !           144:    if( incx < 0 ) ix = 1 - (n-1)*incx
        !           145:    do i = 1, n
        !           146:       ax = abs(x(ix))
        !           147:       if (ax > tbig) then
        !           148:          abig = abig + (ax*sbig)**2
        !           149:          notbig = .false.
        !           150:       else if (ax < tsml) then
        !           151:          if (notbig) asml = asml + (ax*ssml)**2
        !           152:       else
        !           153:          amed = amed + ax**2
        !           154:       end if
        !           155:       ix = ix + incx
        !           156:    end do
        !           157: !
        !           158: !  Combine abig and amed or amed and asml if more than one
        !           159: !  accumulator was used.
        !           160: !
        !           161:    if (abig > zero) then
        !           162: !
        !           163: !     Combine abig and amed if abig > 0.
        !           164: !
        !           165:       if ( (amed > zero) .or. (amed > maxN) .or. (amed /= amed) ) then
        !           166:          abig = abig + (amed*sbig)*sbig
        !           167:       end if
        !           168:       scl = one / sbig
        !           169:       sumsq = abig
        !           170:    else if (asml > zero) then
        !           171: !
        !           172: !     Combine amed and asml if asml > 0.
        !           173: !
        !           174:       if ( (amed > zero) .or. (amed > maxN) .or. (amed /= amed) ) then
        !           175:          amed = sqrt(amed)
        !           176:          asml = sqrt(asml) / ssml
        !           177:          if (asml > amed) then
        !           178:             ymin = amed
        !           179:             ymax = asml
        !           180:          else
        !           181:             ymin = asml
        !           182:             ymax = amed
        !           183:          end if
        !           184:          scl = one
        !           185:          sumsq = ymax**2*( one + (ymin/ymax)**2 )
        !           186:       else
        !           187:          scl = one / ssml
        !           188:          sumsq = asml
        !           189:       end if
        !           190:    else
        !           191: !
        !           192: !     Otherwise all values are mid-range
        !           193: !
        !           194:       scl = one
        !           195:       sumsq = amed
        !           196:    end if
        !           197:    DNRM2 = scl*sqrt( sumsq )
        !           198:    return
        !           199: end function

CVSweb interface <joel.bertrand@systella.fr>