comp.lang.ada
 help / color / mirror / Atom feed
* Help with translation: Fortran77 => Ada95
@ 2001-07-04  9:19 N&J
  2001-07-04 17:04 ` Warren W. Gay VE3WWG
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: N&J @ 2001-07-04  9:19 UTC (permalink / raw)


Hi all,
Is anyone willing to help me translate a FORTRAN77 subroutine to Ada95? I
just can't understand one of those TERRIBLE and UNACCEPTABLE  Fortran "goto"

I attach the FORTRAN subroutine (It calculates the eigenvalues and the first
components of the eigenvectors of a symmetric tridiagonal matrix)

I can't cope with the loop starting at 105 and the "goto" to it before 240.

Thanks in advance,
John

-----SubRoutine gauss.f--------
c
c        Input:  n - - the number of points in the Gaussian quadrature
c                      formula; type integer
c                alpha,beta - - arrays of dimension  n  to be filled
c                      with the values of  alpha(k-1), beta(k-1), k=1,2,
c                      ...,n
c                eps - the relative accuracy desired in the nodes
c                      and weights
c
c        Output: zero- array of dimension  n  containing the Gaussian
c                      nodes (in increasing order)  zero(k)=x(k), k=1,2,
c                      ...,n
c                weight - array of dimension  n  containing the
c                      Gaussian weights  weight(k)=w(k), k=1,2,...,n
c                ierr- an error flag equal to  0  on normal return,
c                      equal to  i  if the QR algorithm does not
c                      converge within 30 iterations on evaluating the
c                      i-th eigenvalue, equal to  -1  if  n  is not in
c                      range, and equal to  -2  if one of the beta's is
c                      negative.
c
c The array  e  is needed for working space.
c
      dimension alpha(n),beta(n),zero(n),weight(n),e(n)
      if(n.lt.1) then
        ierr=-1
        return
      end if
      ierr=0
      zero(1)=alpha(1)
      if(beta(1).lt.0.) then
        ierr=-2
        return
      end if
      weight(1)=beta(1)
      if (n.eq.1) return
      weight(1)=1.
      e(n)=0.
      do 100 k=2,n
        zero(k)=alpha(k)
        if(beta(k).lt.0.) then
          ierr=-2
          return
        end if
        e(k-1)=sqrt(beta(k))
        weight(k)=0.
  100 continue
      do 240 l=1,n
        j=0
c
c Look for a small subdiagonal element.
c
  105   do 110 m=l,n
          if(m.eq.n) goto 120
          if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
  110   continue
  120   p=zero(l)
        if(m.eq.l) goto 240
        if(j.eq.30) goto 400
        j=j+1
c
c Form shift.
c
        g=(zero(l+1)-p)/(2.*e(l))
        r=sqrt(g*g+1.)
        g=zero(m)-p+e(l)/(g+sign(r,g))
        s=1.
        c=1.
        p=0.
        mml=m-l
c
c For i=m-1 step -1 until l do ...
c
        do 200 ii=1,mml
          i=m-ii
          f=s*e(i)
          b=c*e(i)
          if(abs(f).lt.abs(g)) goto 150
          c=g/f
          r=sqrt(c*c+1.)
          e(i+1)=f*r
          s=1./r
          c=c*s
          goto 160
  150     s=f/g
          r=sqrt(s*s+1.)
          e(i+1)=g*r
          c=1./r
          s=s*c
  160     g=zero(i+1)-p
          r=(zero(i)-g)*s +2.*c*b
          p=s*r
          zero(i+1)=g+p
          g=c*r-b
c
c Form first component of vector.
c
          f=weight(i+1)
          weight(i+1)=s*weight(i)+c*f
          weight(i)=c*weight(i)-s*f
  200   continue
        zero(l)=zero(l)-p
        e(l)=g
        e(m)=0.
        goto 105
  240 continue
c
c Order eigenvalues and eigenvectors.
c
      do 300 ii=2,n
        i=ii-1
        k=i
        p=zero(i)
        do 260 j=ii,n
          if(zero(j).ge.p) goto 260
          k=j
          p=zero(j)
  260   continue
        if(k.eq.i) goto 300
        zero(k)=zero(i)
        zero(i)=p
        p=weight(i)
        weight(i)=weight(k)
        weight(k)=p
  300 continue
      do 310 k=1,n
        weight(k)=beta(1)*weight(k)*weight(k)
  310 continue
      return
c
c Set error - no convergence to an eigenvalue after 30 iterations.
c
  400 ierr=l
      return
      end





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
@ 2001-07-04 17:04 ` Warren W. Gay VE3WWG
  2001-07-04 17:17 ` Colin Paul Gloster
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Warren W. Gay VE3WWG @ 2001-07-04 17:04 UTC (permalink / raw)


Gak... FORTRAN! Quick.. where is my wooden stake? ;-)

Warren.

N&J wrote:
> 
> Hi all,
> Is anyone willing to help me translate a FORTRAN77 subroutine to Ada95? I
> just can't understand one of those TERRIBLE and UNACCEPTABLE  Fortran "goto"
> 
> I attach the FORTRAN subroutine (It calculates the eigenvalues and the first
> components of the eigenvectors of a symmetric tridiagonal matrix)
> 
> I can't cope with the loop starting at 105 and the "goto" to it before 240.
> 
> Thanks in advance,
> John
> 
> -----SubRoutine gauss.f--------
> c
> c        Input:  n - - the number of points in the Gaussian quadrature
> c                      formula; type integer
> c                alpha,beta - - arrays of dimension  n  to be filled
> c                      with the values of  alpha(k-1), beta(k-1), k=1,2,
> c                      ...,n
> c                eps - the relative accuracy desired in the nodes
> c                      and weights
> c
> c        Output: zero- array of dimension  n  containing the Gaussian
> c                      nodes (in increasing order)  zero(k)=x(k), k=1,2,
> c                      ...,n
> c                weight - array of dimension  n  containing the
> c                      Gaussian weights  weight(k)=w(k), k=1,2,...,n
> c                ierr- an error flag equal to  0  on normal return,
> c                      equal to  i  if the QR algorithm does not
> c                      converge within 30 iterations on evaluating the
> c                      i-th eigenvalue, equal to  -1  if  n  is not in
> c                      range, and equal to  -2  if one of the beta's is
> c                      negative.
> c
> c The array  e  is needed for working space.
> c
>       dimension alpha(n),beta(n),zero(n),weight(n),e(n)
>       if(n.lt.1) then
>         ierr=-1
>         return
>       end if
>       ierr=0
>       zero(1)=alpha(1)
>       if(beta(1).lt.0.) then
>         ierr=-2
>         return
>       end if
>       weight(1)=beta(1)
>       if (n.eq.1) return
>       weight(1)=1.
>       e(n)=0.
>       do 100 k=2,n
>         zero(k)=alpha(k)
>         if(beta(k).lt.0.) then
>           ierr=-2
>           return
>         end if
>         e(k-1)=sqrt(beta(k))
>         weight(k)=0.
>   100 continue
>       do 240 l=1,n
>         j=0
> c
> c Look for a small subdiagonal element.
> c
>   105   do 110 m=l,n
>           if(m.eq.n) goto 120
>           if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
>   110   continue
>   120   p=zero(l)
>         if(m.eq.l) goto 240
>         if(j.eq.30) goto 400
>         j=j+1
> c
> c Form shift.
> c
>         g=(zero(l+1)-p)/(2.*e(l))
>         r=sqrt(g*g+1.)
>         g=zero(m)-p+e(l)/(g+sign(r,g))
>         s=1.
>         c=1.
>         p=0.
>         mml=m-l
> c
> c For i=m-1 step -1 until l do ...
> c
>         do 200 ii=1,mml
>           i=m-ii
>           f=s*e(i)
>           b=c*e(i)
>           if(abs(f).lt.abs(g)) goto 150
>           c=g/f
>           r=sqrt(c*c+1.)
>           e(i+1)=f*r
>           s=1./r
>           c=c*s
>           goto 160
>   150     s=f/g
>           r=sqrt(s*s+1.)
>           e(i+1)=g*r
>           c=1./r
>           s=s*c
>   160     g=zero(i+1)-p
>           r=(zero(i)-g)*s +2.*c*b
>           p=s*r
>           zero(i+1)=g+p
>           g=c*r-b
> c
> c Form first component of vector.
> c
>           f=weight(i+1)
>           weight(i+1)=s*weight(i)+c*f
>           weight(i)=c*weight(i)-s*f
>   200   continue
>         zero(l)=zero(l)-p
>         e(l)=g
>         e(m)=0.
>         goto 105
>   240 continue
> c
> c Order eigenvalues and eigenvectors.
> c
>       do 300 ii=2,n
>         i=ii-1
>         k=i
>         p=zero(i)
>         do 260 j=ii,n
>           if(zero(j).ge.p) goto 260
>           k=j
>           p=zero(j)
>   260   continue
>         if(k.eq.i) goto 300
>         zero(k)=zero(i)
>         zero(i)=p
>         p=weight(i)
>         weight(i)=weight(k)
>         weight(k)=p
>   300 continue
>       do 310 k=1,n
>         weight(k)=beta(1)*weight(k)*weight(k)
>   310 continue
>       return
> c
> c Set error - no convergence to an eigenvalue after 30 iterations.
> c
>   400 ierr=l
>       return
>       end

-- 
Warren W. Gay VE3WWG
http://members.home.net/ve3wwg



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
  2001-07-04 17:04 ` Warren W. Gay VE3WWG
@ 2001-07-04 17:17 ` Colin Paul Gloster
  2001-07-04 17:55 ` Jeffrey Carter
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Colin Paul Gloster @ 2001-07-04 17:17 UTC (permalink / raw)


Sorry, I am tired and am not going to look through all of that now nor
really think of it in terms of the mathematical problem domain which could
produce a more elegant solution...especially the latter since it may just be
neater to forget about porting the FORTRAN and just write a function
which does as required.

However I have a suggestion, bearing in mind abhorrance of goto. Depending
on how mistaken I am, in F77 the continue keyword on line 110  is part of the
looping construct of do on line 105. I.e. m starts at one and each time it is
incremented it is incremented by the value of n (so m is not necessarily just
increased by one each time) and the loop is to be run one hundred and ten times
with continue signalling each next iteration.

-- more FORTRAN 77
-- Look for a small subdiagonal element.
--
  105   do 110 m=l,n
          if(m.eq.n) goto 120
          if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
  110   continue
  120   p=zero(l)
-- more FORTRAN 77

So in your Ada95 version you could try something like (tidy this up
in to proper compilable Ada when you have decided what you will go for)
-- more F77 to be ported
MAX_LOOP_ITERATIONS := 110;
loop_iterations_so_far := 1; -- or 0, you may change this in your translating
m := 1;
while loop_iterations_so_far <= MAX_LOOP_ITERATIONS  and  m /= n  and (
abs(e(m)) <= eps*(abs(zero(m))+abs(zero(m+1))) ) loop
               m := m + n;
end loop;
-- more F77 to be ported

Bye,
Colin Paul Gloster




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
  2001-07-04 17:04 ` Warren W. Gay VE3WWG
  2001-07-04 17:17 ` Colin Paul Gloster
@ 2001-07-04 17:55 ` Jeffrey Carter
  2001-07-05  1:33   ` Gary Scott
  2001-07-04 19:51 ` [SOLVED] " N&J
  2001-07-04 23:25 ` GianLuigi Piacentini
  4 siblings, 1 reply; 11+ messages in thread
From: Jeffrey Carter @ 2001-07-04 17:55 UTC (permalink / raw)


N&J wrote:
> 
> Hi all,
> Is anyone willing to help me translate a FORTRAN77 subroutine to Ada95? I
> just can't understand one of those TERRIBLE and UNACCEPTABLE  Fortran "goto"
> 
> I attach the FORTRAN subroutine (It calculates the eigenvalues and the first
> components of the eigenvectors of a symmetric tridiagonal matrix)
> 
> I can't cope with the loop starting at 105 and the "goto" to it before 240.
> 
> Thanks in advance,
> John
> 
> -----SubRoutine gauss.f--------
> c
> c        Input:  n - - the number of points in the Gaussian quadrature
> c                      formula; type integer
> c                alpha,beta - - arrays of dimension  n  to be filled
> c                      with the values of  alpha(k-1), beta(k-1), k=1,2,
> c                      ...,n
> c                eps - the relative accuracy desired in the nodes
> c                      and weights
> c
> c        Output: zero- array of dimension  n  containing the Gaussian
> c                      nodes (in increasing order)  zero(k)=x(k), k=1,2,
> c                      ...,n
> c                weight - array of dimension  n  containing the
> c                      Gaussian weights  weight(k)=w(k), k=1,2,...,n
> c                ierr- an error flag equal to  0  on normal return,
> c                      equal to  i  if the QR algorithm does not
> c                      converge within 30 iterations on evaluating the
> c                      i-th eigenvalue, equal to  -1  if  n  is not in
> c                      range, and equal to  -2  if one of the beta's is
> c                      negative.
> c
> c The array  e  is needed for working space.
> c
>       dimension alpha(n),beta(n),zero(n),weight(n),e(n)
>       if(n.lt.1) then
>         ierr=-1
>         return
>       end if
>       ierr=0
>       zero(1)=alpha(1)
>       if(beta(1).lt.0.) then
>         ierr=-2
>         return
>       end if
>       weight(1)=beta(1)
>       if (n.eq.1) return
>       weight(1)=1.
>       e(n)=0.
>       do 100 k=2,n
>         zero(k)=alpha(k)
>         if(beta(k).lt.0.) then
>           ierr=-2
>           return
>         end if
>         e(k-1)=sqrt(beta(k))
>         weight(k)=0.
>   100 continue
>       do 240 l=1,n
>         j=0
> c
> c Look for a small subdiagonal element.
> c
>   105   do 110 m=l,n
>           if(m.eq.n) goto 120
>           if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
>   110   continue
>   120   p=zero(l)
>         if(m.eq.l) goto 240
>         if(j.eq.30) goto 400
>         j=j+1
> c
> c Form shift.
> c
>         g=(zero(l+1)-p)/(2.*e(l))
>         r=sqrt(g*g+1.)
>         g=zero(m)-p+e(l)/(g+sign(r,g))
>         s=1.
>         c=1.
>         p=0.
>         mml=m-l
> c
> c For i=m-1 step -1 until l do ...
> c
>         do 200 ii=1,mml
>           i=m-ii
>           f=s*e(i)
>           b=c*e(i)
>           if(abs(f).lt.abs(g)) goto 150
>           c=g/f
>           r=sqrt(c*c+1.)
>           e(i+1)=f*r
>           s=1./r
>           c=c*s
>           goto 160
>   150     s=f/g
>           r=sqrt(s*s+1.)
>           e(i+1)=g*r
>           c=1./r
>           s=s*c
>   160     g=zero(i+1)-p
>           r=(zero(i)-g)*s +2.*c*b
>           p=s*r
>           zero(i+1)=g+p
>           g=c*r-b
> c
> c Form first component of vector.
> c
>           f=weight(i+1)
>           weight(i+1)=s*weight(i)+c*f
>           weight(i)=c*weight(i)-s*f
>   200   continue
>         zero(l)=zero(l)-p
>         e(l)=g
>         e(m)=0.
>         goto 105
>   240 continue
> c
> c Order eigenvalues and eigenvectors.
> c
>       do 300 ii=2,n
>         i=ii-1
>         k=i
>         p=zero(i)
>         do 260 j=ii,n
>           if(zero(j).ge.p) goto 260
>           k=j
>           p=zero(j)
>   260   continue
>         if(k.eq.i) goto 300
>         zero(k)=zero(i)
>         zero(i)=p
>         p=weight(i)
>         weight(i)=weight(k)
>         weight(k)=p
>   300 continue
>       do 310 k=1,n
>         weight(k)=beta(1)*weight(k)*weight(k)
>   310 continue
>       return
> c
> c Set error - no convergence to an eigenvalue after 30 iterations.
> c
>   400 ierr=l
>       return
>       end

This at least compiles and has no Goto's (watch for wrapped lines):

with Ada.Numerics.Generic_Elementary_Functions;
procedure Make_It_Compile is
   type Real is digits 12; 
   type Vector is array (Positive range <>) of Real; 

   package Math_Stuff is new Ada.Numerics.Generic_Elementary_Functions
(Real);
   use Math_Stuff;

   Too_Short        : exception;
   Length_Mismatch  : exception;
   Negative_Beta    : exception;
   Did_Not_Converge : exception;

   procedure Gauss (Alpha  : in     Vector;
                    Beta   : in     Vector;
                    Eps    : in     Real;
                    Zero   :    out Vector;
                    Weight :    out Vector)
   is
      -- Translated from Fortran:
      --c
      --c        Input:  n - - the number of points in the Gaussian
quadrature
      --c                      formula; type integer
      --c                alpha,beta - - arrays of dimension  n  to be
filled
      --c                      with the values of  alpha(k-1),
beta(k-1), k=1,2,
      --c                      ...,n
      --c                eps - the relative accuracy desired in the
nodes
      --c                      and weights
      --c
      --c        Output: zero- array of dimension  n  containing the
Gaussian
      --c                      nodes (in increasing order) 
zero(k)=x(k), k=1,2,
      --c                      ...,n
      --c                weight - array of dimension  n  containing the
      --c                      Gaussian weights  weight(k)=w(k),
k=1,2,...,n
      --c                ierr- an error flag equal to  0  on normal
return,
      --c                      equal to  i  if the QR algorithm does not
      --c                      converge within 30 iterations on
evaluating the
      --c                      i-th eigenvalue, equal to  -1  if  n  is
not in
      --c                      range, and equal to  -2  if one of the
beta's is
      --c                      negative.
      --c
      --c The array  e  is needed for working space.
      --c

      -- Assume all arrays have lower bound of 1 (generalize later).
      
      -- Placeholder for Sign function
      function Sign (A : Real; B : Real) return Real is
         -- null;
      begin -- Sign
         return 1.0;
      end Sign;

      E   : Vector (Alpha'range);
      J   : Natural;
      M   : Positive;
      P   : Real;
      G   : Real;
      R   : Real;
      S   : Real;
      C   : Real;
      Mml : Positive;
      F   : Real;
      B   : Real;
      I   : Positive;
      K   : Positive;
   begin -- Gauss
      --      if(n.lt.1) then
      --        ierr=-1
      --        return
      --      end if
      if Alpha'Length < 1 then
         raise Too_Short;
      end if;

      if Alpha'Length /= Beta'Length or else
         Alpha'Length /= Zero'Length or else
         Alpha'Length /= Weight'Length
      then
         raise Length_Mismatch;
      end if;

      --      ierr=0

      Zero(1):=Alpha(1);

      --      if(beta(1).lt.0.) then
      --        ierr=-2
      --        return
      --      end if
      if Beta (1) < 0.0 then
         raise Negative_Beta;
      end if;

      Weight(1):=Beta(1);
      --      if (n.eq.1) return
      if Alpha'Length = 1 then
         return;
      end if;

      Weight(1):=1.0;
      E(E'Last):=0.0;
      --      do 100 k=2,n
      Do_100 : for K in 2 .. Alpha'Last loop
         Zero(K):=Alpha(K);
         --        if(beta(k).lt.0.) then
         --          ierr=-2
         --          return
         --        end if
         if Beta (K) < 0.0 then
            raise Negative_Beta;
         end if;

         E(K-1):=Sqrt(Beta(K));
         Weight(K):=0.0;
         --  100 continue
      end loop Do_100;

      --      do 240 l=1,n
      Do_240 : for L in Alpha'range loop
         J:=0;
         --c
         --c Look for a small subdiagonal element.
         --c
         Goto_105 : loop
            --  105   do 110 m=l,n
            Do_110 : for Mm in L .. Alpha'Last loop -- Determine M
               M := Mm;

               --          if(m.eq.n) goto 120
               exit Do_110 when M = Alpha'Last;

               --         
if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
               exit Do_110 when abs E (M) <= Eps * (abs Zero (M) + abs
Zero (M + 1) );
               --  110   continue
            end loop Do_110;

            --  120   p=zero(l)
            P := Zero (L);

            --        if(m.eq.l) goto 240
            exit Goto_105 when M = L;

            --        if(j.eq.30) goto 400
            if J = 30 then
               raise Did_Not_Converge;
            end if;

            J:=J+1;
            --c
            --c Form shift.
            --c
            G:=(Zero(L+1)-P)/(2.0*E(L));
            R:=Sqrt(G*G+1.0);
            G:=Zero(M)-P+E(L)/(G+Sign(R,G));
            S:=1.0;
            C:=1.0;
            P:=0.0;
            Mml:=M-L;
            --c
            --c For i=m-1 step -1 until l do ...
            --c

            --        do 200 ii=1,mml
            Do_200 : for I in reverse L .. M - 1 loop -- This hides
outer I
               --          i=m-ii
               F:=S*E(I);
               B:=C*E(I);
               --          if(abs(f).lt.abs(g)) goto 150
               if abs F >= abs G then
                  C:=G/F;
                  R:=Sqrt(C*C+1.0);
                  E(I+1):=F*R;
                  S:=1.0/R;
                  C:=C*S;
                  --          goto 160
               else
                  --  150     s:=f/g
                  S := F / G;
                  R:=Sqrt(S*S+1.0);
                  E(I+1):=G*R;
                  C:=1.0/R;
                  S:=S*C;
               end if;

               --  160     g:=zero(i+1)-p
               G := Zero (I + 1) - P;
               R:=(Zero(I)-G)*S +2.0*C*B;
               P:=S*R;
               Zero(I+1):=G+P;
               G:=C*R-B;
               --c
               --c Form first component of vector.
               --c
               F:=Weight(I+1);
               Weight(I+1):=S*Weight(I)+C*F;
               Weight(I):=C*Weight(I)-S*F;
               --  200   continue
            end loop Do_200;

            Zero(L):=Zero(L)-P;
            E(L):=G;
            E(M):=0.0;

            --        goto 105
         end loop Goto_105;
         --  240 continue
      end loop Do_240;
      --c
      --c Order eigenvalues and eigenvectors.
      --c
      --      do 300 ii=2,n
      Do_300 : for Ii in 2 .. Alpha'Last loop
         I:=Ii-1;
         K:=I;
         P:=Zero(I);

         --        do 260 j=ii,n
         Do_260 : for J in Ii .. Alpha'Last loop -- This hides outer J
            --          if(zero(j).ge.p) goto 260
            if Zero (J) < P then
               K:=J;
               P:=Zero(J);
            end if;
            --  260   continue
         end loop Do_260;

         --        if(k.eq.i) goto 300
         if K /= I then
            Zero(K):=Zero(I);
            Zero(I):=P;
            P:=Weight(I);
            Weight(I):=Weight(K);
            Weight(K):=P;
         end if;
         --  300 continue
      end loop Do_300;

      --      do 310 k=1,n
      Do_310 : for K in Weight'range loop -- This hides outer K
         Weight(K):=Beta(1)*Weight(K)*Weight(K);
         --  310 continue
      end loop Do_310;
      --      return
      --c
      --c Set error - no convergence to an eigenvalue after 30
iterations.
      --c
      --  400 ierr=l
      --      return
      --      end
   end Gauss;
begin -- Make_It_Compile;
   null;
end Make_It_Compile;

-- 
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [SOLVED] Help with translation: Fortran77 => Ada95
  2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
                   ` (2 preceding siblings ...)
  2001-07-04 17:55 ` Jeffrey Carter
@ 2001-07-04 19:51 ` N&J
  2001-07-04 23:25 ` GianLuigi Piacentini
  4 siblings, 0 replies; 11+ messages in thread
From: N&J @ 2001-07-04 19:51 UTC (permalink / raw)


Hi all,
I have been working on this translation for more than a day. Thanks to your
help, and from some personal e-mails I got and from a similar C ("goto"
free) program I found, I finally managed to translate it to Ada95 (I at
least think so!). Some minor modifications and testing remains. If anyone is
interested in the result please send me an e-mail and I will gladly send
him/her the code.

Thanks again,
John.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
                   ` (3 preceding siblings ...)
  2001-07-04 19:51 ` [SOLVED] " N&J
@ 2001-07-04 23:25 ` GianLuigi Piacentini
  4 siblings, 0 replies; 11+ messages in thread
From: GianLuigi Piacentini @ 2001-07-04 23:25 UTC (permalink / raw)


    do label iteration_variable= starting value, ending value
[,                                                             
increment]
      statements to be looped
label last statement to be looped (usually continue)

so   do 100 k=2, n
     ...
100  continue

means loop statements in the ... place the number of times needed to k
to go from 2 to n (with increment 1)
each time k (the loop variable) is used in the loop, it takes its
current value (2, 3, .., n)

goto 120 is a way to jump out of the loop, control resuming at the
statement labelled 120.

goto's after an if seems quite clear, and in old code is used as a quick
and dirt way to skip some instructions (like old BASIC).

goto to the end of a loop is a way to jump to the end of a loop (usually
a continue) skipping some loop statement but remaining inside the loop.

Hoping this helps

G.L. Piacentini



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-04 17:55 ` Jeffrey Carter
@ 2001-07-05  1:33   ` Gary Scott
  2001-07-05  6:03     ` tmoran
  2001-07-05 17:36     ` Jeffrey Carter
  0 siblings, 2 replies; 11+ messages in thread
From: Gary Scott @ 2001-07-05  1:33 UTC (permalink / raw)


Interesting that it's almost exactly twice as long as the Fortran.  Why
not just update the Fortran to Fortran 95 and make it a lot more clear
and a lot more comprehensible.


Jeffrey Carter wrote:
> 
> N&J wrote:
> >
> > Hi all,
> > Is anyone willing to help me translate a FORTRAN77 subroutine to Ada95? I
> > just can't understand one of those TERRIBLE and UNACCEPTABLE  Fortran "goto"
> >
> > I attach the FORTRAN subroutine (It calculates the eigenvalues and the first
> > components of the eigenvectors of a symmetric tridiagonal matrix)
> >
> > I can't cope with the loop starting at 105 and the "goto" to it before 240.
> >
> > Thanks in advance,
> > John
> >
> > -----SubRoutine gauss.f--------
> > c
> > c        Input:  n - - the number of points in the Gaussian quadrature
> > c                      formula; type integer
> > c                alpha,beta - - arrays of dimension  n  to be filled
> > c                      with the values of  alpha(k-1), beta(k-1), k=1,2,
> > c                      ...,n
> > c                eps - the relative accuracy desired in the nodes
> > c                      and weights
> > c
> > c        Output: zero- array of dimension  n  containing the Gaussian
> > c                      nodes (in increasing order)  zero(k)=x(k), k=1,2,
> > c                      ...,n
> > c                weight - array of dimension  n  containing the
> > c                      Gaussian weights  weight(k)=w(k), k=1,2,...,n
> > c                ierr- an error flag equal to  0  on normal return,
> > c                      equal to  i  if the QR algorithm does not
> > c                      converge within 30 iterations on evaluating the
> > c                      i-th eigenvalue, equal to  -1  if  n  is not in
> > c                      range, and equal to  -2  if one of the beta's is
> > c                      negative.
> > c
> > c The array  e  is needed for working space.
> > c
> >       dimension alpha(n),beta(n),zero(n),weight(n),e(n)
> >       if(n.lt.1) then
> >         ierr=-1
> >         return
> >       end if
> >       ierr=0
> >       zero(1)=alpha(1)
> >       if(beta(1).lt.0.) then
> >         ierr=-2
> >         return
> >       end if
> >       weight(1)=beta(1)
> >       if (n.eq.1) return
> >       weight(1)=1.
> >       e(n)=0.
> >       do 100 k=2,n
> >         zero(k)=alpha(k)
> >         if(beta(k).lt.0.) then
> >           ierr=-2
> >           return
> >         end if
> >         e(k-1)=sqrt(beta(k))
> >         weight(k)=0.
> >   100 continue
> >       do 240 l=1,n
> >         j=0
> > c
> > c Look for a small subdiagonal element.
> > c
> >   105   do 110 m=l,n
> >           if(m.eq.n) goto 120
> >           if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
> >   110   continue
> >   120   p=zero(l)
> >         if(m.eq.l) goto 240
> >         if(j.eq.30) goto 400
> >         j=j+1
> > c
> > c Form shift.
> > c
> >         g=(zero(l+1)-p)/(2.*e(l))
> >         r=sqrt(g*g+1.)
> >         g=zero(m)-p+e(l)/(g+sign(r,g))
> >         s=1.
> >         c=1.
> >         p=0.
> >         mml=m-l
> > c
> > c For i=m-1 step -1 until l do ...
> > c
> >         do 200 ii=1,mml
> >           i=m-ii
> >           f=s*e(i)
> >           b=c*e(i)
> >           if(abs(f).lt.abs(g)) goto 150
> >           c=g/f
> >           r=sqrt(c*c+1.)
> >           e(i+1)=f*r
> >           s=1./r
> >           c=c*s
> >           goto 160
> >   150     s=f/g
> >           r=sqrt(s*s+1.)
> >           e(i+1)=g*r
> >           c=1./r
> >           s=s*c
> >   160     g=zero(i+1)-p
> >           r=(zero(i)-g)*s +2.*c*b
> >           p=s*r
> >           zero(i+1)=g+p
> >           g=c*r-b
> > c
> > c Form first component of vector.
> > c
> >           f=weight(i+1)
> >           weight(i+1)=s*weight(i)+c*f
> >           weight(i)=c*weight(i)-s*f
> >   200   continue
> >         zero(l)=zero(l)-p
> >         e(l)=g
> >         e(m)=0.
> >         goto 105
> >   240 continue
> > c
> > c Order eigenvalues and eigenvectors.
> > c
> >       do 300 ii=2,n
> >         i=ii-1
> >         k=i
> >         p=zero(i)
> >         do 260 j=ii,n
> >           if(zero(j).ge.p) goto 260
> >           k=j
> >           p=zero(j)
> >   260   continue
> >         if(k.eq.i) goto 300
> >         zero(k)=zero(i)
> >         zero(i)=p
> >         p=weight(i)
> >         weight(i)=weight(k)
> >         weight(k)=p
> >   300 continue
> >       do 310 k=1,n
> >         weight(k)=beta(1)*weight(k)*weight(k)
> >   310 continue
> >       return
> > c
> > c Set error - no convergence to an eigenvalue after 30 iterations.
> > c
> >   400 ierr=l
> >       return
> >       end
> 
> This at least compiles and has no Goto's (watch for wrapped lines):
> 
> with Ada.Numerics.Generic_Elementary_Functions;
> procedure Make_It_Compile is
>    type Real is digits 12;
>    type Vector is array (Positive range <>) of Real;
> 
>    package Math_Stuff is new Ada.Numerics.Generic_Elementary_Functions
> (Real);
>    use Math_Stuff;
> 
>    Too_Short        : exception;
>    Length_Mismatch  : exception;
>    Negative_Beta    : exception;
>    Did_Not_Converge : exception;
> 
>    procedure Gauss (Alpha  : in     Vector;
>                     Beta   : in     Vector;
>                     Eps    : in     Real;
>                     Zero   :    out Vector;
>                     Weight :    out Vector)
>    is
>       -- Translated from Fortran:
>       --c
>       --c        Input:  n - - the number of points in the Gaussian
> quadrature
>       --c                      formula; type integer
>       --c                alpha,beta - - arrays of dimension  n  to be
> filled
>       --c                      with the values of  alpha(k-1),
> beta(k-1), k=1,2,
>       --c                      ...,n
>       --c                eps - the relative accuracy desired in the
> nodes
>       --c                      and weights
>       --c
>       --c        Output: zero- array of dimension  n  containing the
> Gaussian
>       --c                      nodes (in increasing order)
> zero(k)=x(k), k=1,2,
>       --c                      ...,n
>       --c                weight - array of dimension  n  containing the
>       --c                      Gaussian weights  weight(k)=w(k),
> k=1,2,...,n
>       --c                ierr- an error flag equal to  0  on normal
> return,
>       --c                      equal to  i  if the QR algorithm does not
>       --c                      converge within 30 iterations on
> evaluating the
>       --c                      i-th eigenvalue, equal to  -1  if  n  is
> not in
>       --c                      range, and equal to  -2  if one of the
> beta's is
>       --c                      negative.
>       --c
>       --c The array  e  is needed for working space.
>       --c
> 
>       -- Assume all arrays have lower bound of 1 (generalize later).
> 
>       -- Placeholder for Sign function
>       function Sign (A : Real; B : Real) return Real is
>          -- null;
>       begin -- Sign
>          return 1.0;
>       end Sign;
> 
>       E   : Vector (Alpha'range);
>       J   : Natural;
>       M   : Positive;
>       P   : Real;
>       G   : Real;
>       R   : Real;
>       S   : Real;
>       C   : Real;
>       Mml : Positive;
>       F   : Real;
>       B   : Real;
>       I   : Positive;
>       K   : Positive;
>    begin -- Gauss
>       --      if(n.lt.1) then
>       --        ierr=-1
>       --        return
>       --      end if
>       if Alpha'Length < 1 then
>          raise Too_Short;
>       end if;
> 
>       if Alpha'Length /= Beta'Length or else
>          Alpha'Length /= Zero'Length or else
>          Alpha'Length /= Weight'Length
>       then
>          raise Length_Mismatch;
>       end if;
> 
>       --      ierr=0
> 
>       Zero(1):=Alpha(1);
> 
>       --      if(beta(1).lt.0.) then
>       --        ierr=-2
>       --        return
>       --      end if
>       if Beta (1) < 0.0 then
>          raise Negative_Beta;
>       end if;
> 
>       Weight(1):=Beta(1);
>       --      if (n.eq.1) return
>       if Alpha'Length = 1 then
>          return;
>       end if;
> 
>       Weight(1):=1.0;
>       E(E'Last):=0.0;
>       --      do 100 k=2,n
>       Do_100 : for K in 2 .. Alpha'Last loop
>          Zero(K):=Alpha(K);
>          --        if(beta(k).lt.0.) then
>          --          ierr=-2
>          --          return
>          --        end if
>          if Beta (K) < 0.0 then
>             raise Negative_Beta;
>          end if;
> 
>          E(K-1):=Sqrt(Beta(K));
>          Weight(K):=0.0;
>          --  100 continue
>       end loop Do_100;
> 
>       --      do 240 l=1,n
>       Do_240 : for L in Alpha'range loop
>          J:=0;
>          --c
>          --c Look for a small subdiagonal element.
>          --c
>          Goto_105 : loop
>             --  105   do 110 m=l,n
>             Do_110 : for Mm in L .. Alpha'Last loop -- Determine M
>                M := Mm;
> 
>                --          if(m.eq.n) goto 120
>                exit Do_110 when M = Alpha'Last;
> 
>                --
> if(abs(e(m)).le.eps*(abs(zero(m))+abs(zero(m+1)))) goto 120
>                exit Do_110 when abs E (M) <= Eps * (abs Zero (M) + abs
> Zero (M + 1) );
>                --  110   continue
>             end loop Do_110;
> 
>             --  120   p=zero(l)
>             P := Zero (L);
> 
>             --        if(m.eq.l) goto 240
>             exit Goto_105 when M = L;
> 
>             --        if(j.eq.30) goto 400
>             if J = 30 then
>                raise Did_Not_Converge;
>             end if;
> 
>             J:=J+1;
>             --c
>             --c Form shift.
>             --c
>             G:=(Zero(L+1)-P)/(2.0*E(L));
>             R:=Sqrt(G*G+1.0);
>             G:=Zero(M)-P+E(L)/(G+Sign(R,G));
>             S:=1.0;
>             C:=1.0;
>             P:=0.0;
>             Mml:=M-L;
>             --c
>             --c For i=m-1 step -1 until l do ...
>             --c
> 
>             --        do 200 ii=1,mml
>             Do_200 : for I in reverse L .. M - 1 loop -- This hides
> outer I
>                --          i=m-ii
>                F:=S*E(I);
>                B:=C*E(I);
>                --          if(abs(f).lt.abs(g)) goto 150
>                if abs F >= abs G then
>                   C:=G/F;
>                   R:=Sqrt(C*C+1.0);
>                   E(I+1):=F*R;
>                   S:=1.0/R;
>                   C:=C*S;
>                   --          goto 160
>                else
>                   --  150     s:=f/g
>                   S := F / G;
>                   R:=Sqrt(S*S+1.0);
>                   E(I+1):=G*R;
>                   C:=1.0/R;
>                   S:=S*C;
>                end if;
> 
>                --  160     g:=zero(i+1)-p
>                G := Zero (I + 1) - P;
>                R:=(Zero(I)-G)*S +2.0*C*B;
>                P:=S*R;
>                Zero(I+1):=G+P;
>                G:=C*R-B;
>                --c
>                --c Form first component of vector.
>                --c
>                F:=Weight(I+1);
>                Weight(I+1):=S*Weight(I)+C*F;
>                Weight(I):=C*Weight(I)-S*F;
>                --  200   continue
>             end loop Do_200;
> 
>             Zero(L):=Zero(L)-P;
>             E(L):=G;
>             E(M):=0.0;
> 
>             --        goto 105
>          end loop Goto_105;
>          --  240 continue
>       end loop Do_240;
>       --c
>       --c Order eigenvalues and eigenvectors.
>       --c
>       --      do 300 ii=2,n
>       Do_300 : for Ii in 2 .. Alpha'Last loop
>          I:=Ii-1;
>          K:=I;
>          P:=Zero(I);
> 
>          --        do 260 j=ii,n
>          Do_260 : for J in Ii .. Alpha'Last loop -- This hides outer J
>             --          if(zero(j).ge.p) goto 260
>             if Zero (J) < P then
>                K:=J;
>                P:=Zero(J);
>             end if;
>             --  260   continue
>          end loop Do_260;
> 
>          --        if(k.eq.i) goto 300
>          if K /= I then
>             Zero(K):=Zero(I);
>             Zero(I):=P;
>             P:=Weight(I);
>             Weight(I):=Weight(K);
>             Weight(K):=P;
>          end if;
>          --  300 continue
>       end loop Do_300;
> 
>       --      do 310 k=1,n
>       Do_310 : for K in Weight'range loop -- This hides outer K
>          Weight(K):=Beta(1)*Weight(K)*Weight(K);
>          --  310 continue
>       end loop Do_310;
>       --      return
>       --c
>       --c Set error - no convergence to an eigenvalue after 30
> iterations.
>       --c
>       --  400 ierr=l
>       --      return
>       --      end
>    end Gauss;
> begin -- Make_It_Compile;
>    null;
> end Make_It_Compile;
> 
> --
> Jeff Carter
> "You cheesy lot of second-hand electric donkey-bottom biters."
> Monty Python & the Holy Grail


-- 

Gary Scott
mailto:scottg@flash.net

mailto:webmaster@fortranlib.com
http://www.fortranlib.com

Support the GNU Fortran G95 Project:  http://g95.sourceforge.net



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-05  1:33   ` Gary Scott
@ 2001-07-05  6:03     ` tmoran
  2001-07-06  1:35       ` Gary Scott
  2001-07-05 17:36     ` Jeffrey Carter
  1 sibling, 1 reply; 11+ messages in thread
From: tmoran @ 2001-07-05  6:03 UTC (permalink / raw)


>Interesting that it's almost exactly twice as long as the Fortran.
  Would you prefer this version, shorter than the Fortran one?  I dropped
the comments that just showed the original Fortran code, tightened up
things that fit nicely on one line and didn't really need multiple lines,
pretty printed, and did a few other "personal preference" changes.

  Negative_Beta: exception;

  procedure Gauss(Alpha, Beta   : in     Vector;
                  Eps           : in     Real;
                  Zero, Weight  :    out Vector;
                  Ierr          :    out Integer) is
  --
  --         Input:  n - - the number of points in the Gaussian quadrature
  --                       formula; type integer
  --         Input:  alpha,beta - - arrays (of the same dimension) to be filled
  --                       with the values of  alpha(k-1), beta(k-1), k=1,2,
  --                       ...,n
  --                 eps - the relative accuracy desired in the nodes
  --                       and weights
  --
  --         Output: zero- array containing the Gaussian nodes (in increasing
  --                       order) zero(k)=x(k), k=1,2,...,n
  --                 weight - array containing the
  --                       Gaussian weights  weight(k)=w(k), k=1,2,...,n
  --                 ierr- an error flag equal to  0  on normal return,
  --                       equal to  i  if the QR algorithm does not
  --                       converge within 30 iterations on evaluating the
  --                       i-th eigenvalue.
  --         Exceptions:
  --                 Negative_Beta if one of the beta's is negative.
  --                 Constraint_Error if the input vectors don't match in
  --                        length, or have zero length.
  --
  --
    E : Vector(Alpha'range);   --  working space.
    J : Natural;
    I, K, M, Mml : Positive;
    P, G, R, S, C, F, B : Real;
  begin
    Ierr := 0;  -- hope for the best
    Zero(1) := Alpha(1);
    if Beta(1) < 0.0 then
      raise Negative_Beta;
    end if;
    Weight(1) := Beta(1);
    if Alpha'Length = 1 then
      return;
    end if;
    Weight(1) := 1.0;
    E(E'Last) := 0.0;
    for K in 2 .. Alpha'Last loop
      Zero(K) := Alpha(K);
      if Beta(K) < 0.0 then
        raise Negative_Beta;
      end if;
      E(K - 1) := Sqrt(Beta(K));
      Weight(K) := 0.0;
    end loop;
    for L in Alpha'range loop
      J := 0;
      -- Look for a small subdiagonal element.
      loop
          for Mm in L .. Alpha'Last loop
            M := Mm;
            exit when abs(E(M)) <= Eps * (abs(Zero(M)) + abs(Zero(M + 1)));
          end loop;
          P := Zero(L);
          exit when M = L;
          if J = 30 then
            Ierr := L;
            return;
          end if;
          J := J + 1;
          -- Form shift.
          G := (Zero(L + 1) - P) / (2.0 * E(L));
          R := Sqrt(G * G + 1.0);
          G := Zero(M) - P + E(L) / (G + Sign(R, G));
          S := 1.0;
          C := 1.0;
          P := 0.0;
          Mml := M - L;
          for I in reverse L .. M - 1 loop -- This hides outer I
            F := S * E(I);
            B := C * E(I);
            if abs(F) >= abs(G) then
              C := G / F;
              R := Sqrt(C * C + 1.0);
              E(I + 1) := F * R;
              S := 1.0 / R;
              C := C * S;
            else
              S := F / G;
              R := Sqrt(S * S + 1.0);
              E(I + 1) := G * R;
              C := 1.0 / R;
              S := S * C;
            end if;
            G := Zero(I + 1) - P;
            R := (Zero(I) - G) * S + 2.0 * C * B;
            P := S * R;
            Zero(I + 1) := G + P;
            G := C * R - B;
            -- Form first component of vector.
            F := Weight(I + 1);
            Weight(I + 1) := S * Weight(I) + C * F;
            Weight(I) := C * Weight(I) - S * F;
          end loop;
          Zero(L) := Zero(L) - P;
          E(L) := G;
          E(M) := 0.0;
      end loop;
    end loop;
    -- Order eigenvalues and eigenvectors.
    for Ii in 2 .. Alpha'Last loop
      I := Ii - 1;
      K := I;
      P := Zero(I);
      for J in Ii .. Alpha'Last loop -- This hides outer J
        if Zero(J) < P then
          K := J;
          P := Zero(J);
        end if;
      end loop;
      if K /= I then
        Zero(K) := Zero(I);
        Zero(I) := P;
        P := Weight(I);
        Weight(I) := Weight(K);
        Weight(K) := P;
      end if;
    end loop;
    for K in Weight'range loop -- This hides outer K
      Weight(K) := Beta(1) * Weight(K) * Weight(K);
    end loop;
  end Gauss;



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-05  1:33   ` Gary Scott
  2001-07-05  6:03     ` tmoran
@ 2001-07-05 17:36     ` Jeffrey Carter
  2001-07-06  1:14       ` Gary Scott
  1 sibling, 1 reply; 11+ messages in thread
From: Jeffrey Carter @ 2001-07-05 17:36 UTC (permalink / raw)


Gary Scott wrote:
> 
> Interesting that it's almost exactly twice as long as the Fortran.

Interesting that it compiles and the FORTRAN doesn't. Interesting that,
if you leave off all the stuff needed to make it compile, and all the
comments showing the original FORTRAN, and all the extra white space not
found in the FORTRAN, it's certainly no longer than the FORTRAN.

Try comparing kumquats to quinces next time.

-- 
Jeffrey Carter



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-05 17:36     ` Jeffrey Carter
@ 2001-07-06  1:14       ` Gary Scott
  0 siblings, 0 replies; 11+ messages in thread
From: Gary Scott @ 2001-07-06  1:14 UTC (permalink / raw)


Hi,

Jeffrey Carter wrote:
> 
> Gary Scott wrote:
> >
> > Interesting that it's almost exactly twice as long as the Fortran.
> 
> Interesting that it compiles and the FORTRAN doesn't. Interesting that,
> if you leave off all the stuff needed to make it compile, and all the
> comments showing the original FORTRAN, and all the extra white space not
> found in the FORTRAN, it's certainly no longer than the FORTRAN.
> 
> Try comparing kumquats to quinces next time.

Apparently, you took my comments as a personal attack.  I never make
personal attacks, I merely intended to note the difference in style and
a slight tendency to being verbose of the posted update as compared to
the original.  I realized that the original source was poorly designed,
was incomplete, and had several flat-out errors.  The original was not
poorly designed because of the language used, necessarily, and could be
dramatically improved using the same language or a newer variant. 
Perhaps, this was not a point worth making in this particular news
group, but it is just a news group...

> 
> --
> Jeffrey Carter


-- 

Gary Scott
mailto:scottg@flash.net



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Help with translation: Fortran77 => Ada95
  2001-07-05  6:03     ` tmoran
@ 2001-07-06  1:35       ` Gary Scott
  0 siblings, 0 replies; 11+ messages in thread
From: Gary Scott @ 2001-07-06  1:35 UTC (permalink / raw)


Hi,

I guess I wasn't intending to start a competition to see how few
statements this could be written in.  I simply noted that the non-blank,
non-comment portion of the posted example was about twice as long as the
original, no big deal.  I also noted that significant improvements could
be made to the original.  Here's a minimalist update which only
eliminates the GOTOs.  At least it's more readable to me, if no one else
(not 100% guaranteed, certainly there's still lots of room for
improvement, a few opportunities for  whole or partial array
operations):

!
!        Input:  n - - the number of points in the Gaussian quadrature
!                      formula; type integer
!                alpha,beta - - arrays of dimension  n  to be filled
!                      with the values of  alpha(k-1), beta(k-1), k=1,2,
!                      ...,n
!                eps - the relative accuracy desired in the nodes
!                      and weights
!
!        Output: zero- array of dimension  n  containing the Gaussian
!                      nodes (in increasing order)  zero(k)=x(k), k=1,2,
!                      ...,n
!                weight - array of dimension  n  containing the
!                      Gaussian weights  weight(k)=w(k), k=1,2,...,n
!                ierr- an error flag equal to  0  on normal return,
!                      equal to  i  if the QR algorithm does not
!                      converge within 30 iterations on evaluating the
!                      i-th eigenvalue, equal to  -1  if  n  is not in
!                      range, and equal to  -2  if one of the beta's is
!                      negative.
!
! The array  e  is needed for working space.
!
subroutine gauss(n, alpha, beta, eps, zero, weight, ierr)

   implicit none

   integer, intent(in)    :: n                    !Automatic extent
   integer, intent(out)   :: ierr                 !Return code
   integer                :: ii, i, j, k, l, m    !Loop counters

   real, intent(in)       :: alpha(n), beta(n), eps
   real, intent(out)      :: zero(n), weight(n)
   real                   :: e(n), b, c, f, g, p, r, s, mml 
!Intermediates and workspaces

   if (n < 1) then  !Invalid extent
      ierr = -1
      return
   end if

   ierr = 0; zero = 0.0; weight = 0.0; e = 0.0 !Initialize

   zero(1) = alpha(1)

   if (beta(1) < 0.0) then
      ierr = -2
      return
   end if

   weight(1) = beta(1)

   if (n == 1) return

   weight(1) = 1.0

   do k = 2, n
      zero(k) = alpha(k)

      if (beta(k) < 0.0) then
        ierr = -2
        return
      end if

      e(k - 1) = sqrt( beta(k) )
      weight(k) = 0.0
   end do

   j = 0

   do l = 1, n

      do m = l, n           ! Look for a small subdiagonal element
         if (m == n) exit
         if (abs( e(m) ) <= eps * (abs( zero(m) ) + abs( zero(m + 1) )))
exit
      end do

      p = zero(l)

      if (m == l) then
         j = 0
         cycle
      end if

      if (j == 30) then !No convergence after 30 interations
         ierr = 1
         return
      end if

      j = j + 1
!
! Form shift
!
      g = (zero(l + 1) - p) / (2.0 * e(l))

      r = sqrt(g * g + 1.0)
      g = zero(m) - p + e(l) / (g + sign(r,g))

      s = 1.0
      c = 1.0
      p = 0.0

      mml = m - l
!
! For i=m-1 step -1 until l do ...
!
      do ii = 1, mml

         i = m - ii
         f = s * e(i)
         b = c * e(i)

         if (abs(f) < abs(g)) then
            s = f / g
            r = sqrt(s * s + 1.0)
            e(i + 1) = g * r
            c = 1.0 / r
            s = s * c
         else
            c = g / f
            r = sqrt(c * c + 1.0)
            e(i + 1) = f * r
            s = 1.0 / r
            c = c * s
         end if

         g = zero(i + 1) - p
         r = (zero(i) - g) * s + 2.0 * c * b
         p = s * r
         zero(i + 1) = g + p
         g = c * r - b
!
! Form first component of vector.
!
         f = weight(i + 1)
         weight(i + 1) = s * weight(i) + c * f
         weight(i) = c * weight(i) - s * f
      end do

      zero(l) = zero(l) - p
      e(l) = g
      e(m) = 0.0

   end do
!
! Order eigenvalues and eigenvectors.
!
   do ii = 2, n
      i = ii - 1
      k = i
      p = zero(i)

      do j = ii, n
         if (zero(j) >= p) cycle
         k = j
         p = zero(j)
      end do

      if (k >= i) cycle

      zero(k) = zero(i)
      zero(i) = p
      p = weight(i)
      weight(i) = weight(k)
      weight(k) = p
   end do

   do k = 1, n
      weight(k) = beta(1) * weight(k) * weight(k)
   end do

   return

end subroutine




tmoran@acm.org wrote:
> 
> >Interesting that it's almost exactly twice as long as the Fortran.
>   Would you prefer this version, shorter than the Fortran one?  I dropped
> the comments that just showed the original Fortran code, tightened up
> things that fit nicely on one line and didn't really need multiple lines,
> pretty printed, and did a few other "personal preference" changes.
> 

<snip>



-- 

Gary Scott
mailto:scottg@flash.net

mailto:webmaster@fortranlib.com
http://www.fortranlib.com

Support the GNU Fortran G95 Project:  http://g95.sourceforge.net



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2001-07-06  1:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-04  9:19 Help with translation: Fortran77 => Ada95 N&J
2001-07-04 17:04 ` Warren W. Gay VE3WWG
2001-07-04 17:17 ` Colin Paul Gloster
2001-07-04 17:55 ` Jeffrey Carter
2001-07-05  1:33   ` Gary Scott
2001-07-05  6:03     ` tmoran
2001-07-06  1:35       ` Gary Scott
2001-07-05 17:36     ` Jeffrey Carter
2001-07-06  1:14       ` Gary Scott
2001-07-04 19:51 ` [SOLVED] " N&J
2001-07-04 23:25 ` GianLuigi Piacentini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox