Mata course: Translating from FORTRAN

FORTRAN code

See for complete code, with comments.

Code is one of the routines from the old EISPACK, a precurser of the LAPACK.

Here is balbak.f with comments removed:

subroutine balbak(nm,n,low,igh,scale,m,z)
c
integer i,j,k,m,n,ii,nm,igh,low
double precision scale(n),z(nm,m)
double precision s
c
c ------------------------------------------------------------------
c
if (m .eq. 0) go to 200
if (igh .eq. low) go to 120
c
do 110 i = low, igh
s = scale(i)
c .......... left hand eigenvectors are back transformed
c if the foregoing statement is replaced by
c s=1.0d0/scale(i). ..........
do 100 j = 1, m
100 z(i,j) = z(i,j) * s
c
110 continue
c ......... for i=low-1 step -1 until 1,
c igh+1 step 1 until n do -- ..........
120 do 140 ii = 1, n
i = ii
if (i .ge. low .and. i .le. igh) go to 140
if (i .lt. low) i = low - ii
k = scale(i)
if (k .eq. i) go to 140
c
do 130 j = 1, m
s = z(i,j)
z(i,j) = z(k,j)
z(k,j) = s
130 continue
c
140 continue
c
200 return
end

Line-by-line translation

subroutine balbak(nm,n,low,igh,scale,m,z)
c
integer i,j,k,m,n,ii,nm,igh,low
double precision scale(n),z(nm,m)
double precision s

becomes

void balbak(real scalar nm, real scalar n,
real scalar low, real scalar igh,
real vector scale,
real scalar m,
real matrix z)
{
real scalar i, j, k, ii
real scalar s

FORTRAN code

if (m .eq. 0) go to 200
if (igh .eq. low) go to 120

becomes

if (m==0) goto L200
if (igh==low) goto L120

FORTRAN CODE

do 110 i = low, igh
s = scale(i)
do 100 j = 1, m
100 z(i,j) = z(i,j) * s
c
110 continue

becomes

for (i=low; i<=igh; i++) {
s = scale[i]
for (j=1; j<=m; j++) z[i,j] = z[i,j] * s
}

FORTRAN code

120 do 140 ii = 1, n
i = ii
if (i .ge. low .and. i .le. igh) go to 140
if (i .lt. low) i = low - ii
k = scale(i)
if (k .eq. i) go to 140
c
do 130 j = 1, m
s = z(i,j)
z(i,j) = z(k,j)
z(k,j) = s
130 continue
c
140 continue

becomes

L120:
for(ii=1, ii<=n; ii++) {
i = ii
if (i>=low & i<=igh) goto L140
if (i<low) i = low-ii
k = scale[i]
if (k==i) goto L140
for (j=1;l j<=m; j++) {
s = z[i,j]
z[i,j] = z[k,j]
z[i,j] = s
}
L140:	}

FORTRAN code

200 return
end

becomes

L200:	return
}

Put the whole thing together, and we have

void balbak(real scalar nm, real scalar n,
real scalar low, real scalar igh,
real vector scale,
real scalar m,
real matrix z)
{
real scalar i, j, k, ii
real scalar s

if (m==0) goto L200
if (igh==low) goto L120

for (i=low; i<=igh; i++) {
s = trunc(scale[i])
for (j=1; j<=m; j++) z[i,j] = z[i,j] * s
}

L120:
for(ii=1, ii<=n; ii++) {
i = ii
if (i>=low & i<=igh) goto L140
if (i<low) i = low-ii
k = scale[i]
if (k==i) goto L140
for (j=1;l j<=m; j++) {
s = z[i,j]
z[i,j] = z[k,j]
z[i,j] = s
}
L140:	}
L200:	return
}

It works!

During development of Mata, and as a check that

1. Our LAPACK routines were working

2. That our Mata compiler was working

I translated the majority of the EISPACK to Mata. That took me a day or two.

In certification,
we use the Mata-compiled EISPACK routines as a check
against Mata-builtin LAPACK results.

By the way, performance (execution time) is excellent.

Translated EISPACK routines:

Top