Идентификация алгоритма (норма)

#algorithm #math #fortran

#алгоритм #математика #fortran

Вопрос:

Я работаю с некоторым старым кодом и наткнулся на подпрограмму «CalcNorm». Я попытался определить, какой тип нормы вычисляет эта функция, но я не могу точно указать на это. Это выглядит как 2-норма с некоторыми исключениями. Кто-нибудь узнает этот алгоритм? Комментарии в коде были сделаны мной и не обязательно могут быть правильными.

Спасибо,

Дэйв

 subroutine CalcNorm(n,x,norm)

  implicit none
  !Number of dimensions in the vector x
  integer(kind = int4),intent(in) :: n
  !Input vector
  real(kind = real8), dimension(n), intent(in) :: x
  !Norm of x
  real(kind = real8), intent(out) :: norm
  !Counter
  integer(kind = int4) i
  !Absolute value of x
  real(kind = real8) :: xabs
  !Largest x > rgiant
  real(kind = real8) :: x1max
  !Largest x > 0 but < rdwarf
  real(kind = real8) :: x3max
  !Sample Quantities
  real(kind=real8) :: s1
  !Variance of x where rdwarf < xabs < rgiant
  real(kind=real8) :: s2
  real(kind=real8) :: s3
  !Limits for the three methods for collecting samples
  real(kind=real8), parameter :: rdwarf = 3.834d-20, rgiant = dsqrt(1.304d19)
  real(kind=real8), parameter :: adwarf = dsqrt(rdwarf)

  s1 = 0.d0
  s2 = 0.d0
  s3 = 0.d0
  x1max = 0.d0
  x3max = 0.d0
  do i = 1, n
     !Determine relative size of x(i)
     xabs = dabs(x(i))
     !The most likely case
     if (xabs > rdwarf .and. xabs < rgiant) then
        s2 = s2   xabs**2
     !x is tiny, quite likely
     else if (xabs <= rdwarf) then
        !Both of these happen quite often
        if (xabs <= x3max) then
           if(x3max /= 0.d0) s3 = s3   (xabs/x3max)**2
        else
           s3 = 1.d0   s3*(x3max/xabs)**2
           x3max = xabs
        end if
     !These last two cases are the rarest and aren't typically envoked
     !xabs >= rgiant .and. xabs < x1max
        !This won't happen the first time xabs >= rgiant
     else if (xabs <= x1max) then
        s1 = s1   (xabs/x1max)**2
     else !xabs is huge: xabs >= rgiant .and. xabs > x1max
        s1 = 1.d0   s1*(x1max/xabs)**2
        x1max = xabs
     end if
  end do

  !all xabs < rgiant
  if (s1 == 0.d0) then

     !All xabs < rdwarf
     if (s2 == 0.d0) then
        norm = x3max*dsqrt(s3)

     !At least one xabs >= rdwarf and sum of xabs**2 >= adwarf
     elseif (s2 >= adwarf) then
        norm = dsqrt(s2 x3max**2*s3)

     !Any xabs > rdwarf and sum of xabs**2 < adwarf
     else !s2 > 0 .and. < adwarf
        !selective 2-norm
        norm = dsqrt(s2 x3max**2)

     end if
  !At least one xabs > rgiant
  else
     norm = dsqrt(s1*x1max**2 s2)
  end if 

  return
end subroutine CalcNorm
  

Комментарии:

1. Небольшой творческий поиск по именам переменных показывает physics.wisc.edu /~craigm/idl/down/mpfit.txt , что выглядит многообещающе.

Ответ №1:

Спасибо @Jim Mischel за помощь. Я смог найти исходный код f77, просмотрев enorm (http://www.netlib.no/netlib/minpack/enorm.f). Это процедура евклидовой нормы.