File:  [local] / rpl / lapack / blas / dznrm2.f90
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:55:29 2023 UTC (8 months, 3 weeks ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Ajout de fichiers de lapack 3.11

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

CVSweb interface <joel.bertrand@systella.fr>