stdlib_dnrm2 Function

public pure function stdlib_dnrm2(n, x, incx)

DNRM2 returns the euclidean norm of a vector via the function name, so that DNRM2 := sqrt( x'*x )

Arguments

Type IntentOptional Attributes Name
integer(kind=ilp), intent(in) :: n
real(kind=dp), intent(in) :: x(*)
integer(kind=ilp), intent(in) :: incx

Return Value real(kind=dp)


Source Code

     pure function stdlib_dnrm2( n, x, incx )
     !! DNRM2 returns the euclidean norm of a vector via the function
     !! name, so that
     !! DNRM2 := sqrt( x'*x )
        real(dp) :: stdlib_dnrm2
        ! -- reference blas level1 routine (version 3.9.1_dp) --
        ! -- reference blas is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           ! march 2021
        ! Constants 
        real(dp), parameter :: maxn = huge(0.0_dp)
        ! .. blue's scaling constants ..
        ! Scalar Arguments 
     integer(ilp), intent(in) :: incx, n
        ! Array Arguments 
        real(dp), intent(in) :: x(*)
        ! Local Scalars 
     integer(ilp) :: i, ix
     logical(lk) :: notbig
        real(dp) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin
        ! quick return if possible
        stdlib_dnrm2 = zero
        if( n <= 0 ) return
        scl = one
        sumsq = zero
        ! 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 = zero
        amed = zero
        abig = zero
        ix = 1
        if( incx < 0 ) ix = 1 - (n-1)*incx
        do i = 1, n
           ax = abs(x(ix))
           if (ax > tbig) then
              abig = abig + (ax*sbig)**2
              notbig = .false.
           else if (ax < tsml) then
              if (notbig) asml = asml + (ax*ssml)**2
           else
              amed = amed + ax**2
           end if
           ix = ix + incx
        end do
        ! 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. (amed > maxn) .or. (amed /= amed) ) then
              abig = abig + (amed*sbig)*sbig
           end if
           scl = one / sbig
           sumsq = abig
        else if (asml > zero) then
           ! combine amed and asml if asml > 0.
           if ( (amed > zero) .or. (amed > maxn) .or. (amed /= amed) ) then
              amed = sqrt(amed)
              asml = sqrt(asml) / ssml
              if (asml > amed) then
                 ymin = amed
                 ymax = asml
              else
                 ymin = asml
                 ymax = amed
              end if
              scl = one
              sumsq = ymax**2*( one + (ymin/ymax)**2 )
           else
              scl = one / ssml
              sumsq = asml
           end if
        else
           ! otherwise all values are mid-range
           scl = one
           sumsq = amed
        end if
        stdlib_dnrm2 = scl*sqrt( sumsq )
        return
     end function stdlib_dnrm2