FORTRAN IV was a major change from FORTRAN II. Not only did it introduce several new features, but there were several incompatibilities between FORTRAN IV and FORTRAN II.
Function names no longer ended in F, and a function returned an integer value (by default) if it began with a letter from I through N, rather than the letter X, following the same rules as variables.
Variables could be explicitly given a type by a type declaration statement. Arrays could also be dimensioned in these statements, so that a separate DIMENSION statement would not be required, and variables could be initialized in those statements, so that a separate DATA statement, also a new statement for FORTRAN IV, would not be required.
Character strings in FORMAT statements could be enclosed in single quotes, rather than it being necessary to count the characters in them for the former syntax of a Hollerith format specification.
Explicitly declaring the type of variables allowed variables to be declared as DOUBLE PRECISION, LOGICAL, or COMPLEX.
The LOGICAL data type could only have two values, .TRUE. or .FALSE., and corresponded to the type of a relational expression in a logical IF statement. Thus, instead of writing
IF (X-Y) 10,20,10 10 CONTINUE
it was now possible to write
IF (X .NE. Y) GO TO 20
The form of input-output statements was changed in FORTRAN IV as well. Instead of special purpose statements such as READ, PRINT, PUNCH, READ INPUT TAPE, and WRITE OUTPUT TAPE, there was simply READ (device, format) and WRITE (device, format). However, the BACKSPACE and REWIND statements continued to be available.
Also, the NAMELIST statement was provided, allowing list-directed input/output; on input, the variables to be changed could be indicated by name.
Functions and subroutines replaced the special statements that dealt with the sense switches and sense lights, as well as those that provided trapping of overflow and related conditions.
One important additional feature of FORTRAN IV was the ability to pass a function or subroutine to another function or subroutine as an argument. This meant, for example, that one could write a subroutine that did numerical integration, and pass to it the function to be integrated. This feature worked like this:
EXTERNAL FUN X=ANUMIN(FUN,0.0,1.0) PRINT(6,11) X STOP END REAL FUNCTION FUN(X) FUN=X+TAN(X) RETURN END REAL FUNCTION ANUMINT(FN,ALOW,AHIGH) EXTERNAL FN AINC=(AHIGH-ALOW)*0.001 SUM=0.0005*(FN(ALOW)+FN(AHIGH)) DO 7 I=1,999 7 SUM=SUM+FN(ALOW+FLOAT(I)*AINC) RETURN END
The versions of FORTRAN IV provided by IBM for the IBM System/360 included some extensions. REAL and DOUBLE PRECISION could be referred to as REAL*4 and REAL*8. COMPLEX*16, allowing complex numbers the real and imaginary parts of which were both double precision, was also one of these extensions.
As well, one could declare a variable to be of CHARACTER*n type, to reserve space for n characters. These variables would usually have to be filled with trailing blanks if they contained a short string, and no explicit character manipulation functions were included in the language, but the A format code, present even in the original FORTRAN language, permitted the input and output of these variables.
The IMPLICIT statement, allowing the first letter rule to be changed, was another extension to FORTRAN IV included on the System/360.
The first FORTRAN IV compiler, the one for the STRETCH, still included the FREQUENCY statement from the original FORTRAN compiler.
Here is an example of a FORTRAN IV program. It includes constants for converting from degrees to radians, and radians to degrees, expressed in internal binary form, which is machine dependent. Also note that it makes use of the assigned GO TO statement, because it repeatedly uses the same one of several alternatives in an inner loop: it is a program to draw a map of the world in one of several projections.
Aside from System/360 machine dependencies, this also calls routines to use an on-line plotter on I/O unit 9 that are peculiar to the particular MTS installation on which it was used: it also tested if it was being run from punched cards or from a terminal, to determine how it would ask for input, again using a routine peculiar to the operating system.
The version of FORTRAN used (or a local addition to its library) allowed free-format I/O, but the compiler did not allow putting an asterisk directly in the I/O statement, although a variable containing an asterisk was what indicated free-format I/O. So, as $ is the shift of * on a keypunch, and this version of FORTRAN allowed $ in variable names even as the first letter, a variable containing only an asterisk was given $ as its name.
Also, it is meant to work with either a CALCOMP plotter whose plotting area is 33 inches wide, or to be used from a Tektronix 4010 display, which is the reason for some of the less obvious portions of the code. It should be immediately obvious that CALL PLOT(X,Y,3) means to plot to point X, Y without drawing (with the pen up) and CALL PLOT(X,Y,2) means to draw to point X, Y from a perusal of the code.
A few comments have been added to the code as it stood originally; otherwise, it is not changed. In addition to an assigned GO TO being used to switch the program to the correct routine to calculate a point for the projection in use, another is used to allow the program to switch from plotting the map to the graticule, and another deals with various possible cases of whether or not a line should be drawn to the current point from the previous point.
This code does not illustrate particularly good programming style, and could thus be categorized as a youthful folly of mine, but it still does illustrate that even in the FORTRAN IV era, the assigned GO TO still can be put to good use shaving cycles from a program.
C THIS IS A PROGRAM TO DRAW MAPS OF THE WORLD REAL BUF(60),DTR/Z3F477D1B/,RTD/Z42394BB8/ INTEGER FILE(20) REAL ASPA(12)/-1.,1.,1.5,2.,2.,1.,2.,1.8,0.,0.,0.,0./ INTEGER IBF(58)/58*0/ LOGICAL*1 LIB(232) INTEGER ITERC/0/ LOGICAL*1 FIAR(44),ICAR(4) LOGICAL*1 $(1)/1H*/ INTEGER*2 HX,HY LOGICAL*1 REPL EQUIVALENCE (LIB,IBF) EQUIVALENCE (ICAR,ITERC) ASSIGN 4406 TO IFIRS CALL PLOTS CALL GDINF('9 ',FIAR) ICAR(4)=FIAR(14) C ITERC IS 2 FOR TERMINAL, 3 FOR FILE GO TO (90801,90801,90802),ITERC 90801 ASSIGN 272 TO ITCL ASSIGN 4404 TO ITC2 GO TO 90803 90802 ASSIGN 373 TO ITCL ASSIGN 4401 TO ITC2 90803 CONTINUE CALL CREPLY(&875) REPL=.TRUE. ASSIGN 575 TO IQIZ 676 WRITE(6,991) WRITE(6,992) READ(5,$,END=909)AMR,AAR,AMS WRITE(6,981) READ(5,$)PLEN WRITE(6,971) WRITE(6,972) WRITE(6,973) READ(5,$)IPROJ WRITE(6,961) READ(5,$)ILAI,ILOI WRITE(6,951) WRITE(6,952) WRITE(6,953) READ(5,$)IGTO GO TO 287 875 ASSIGN 878 TO IQIZ REPL=.FALSE. GO TO 878 575 WRITE(6,1901) 878 READ(5,$,END=909)AMR,AAR,AMS,PLEN,IPROJ,ILAI,ILOI,IGTO 287 YCT=.5*PLEN ASPE=ASPA(IPROJ) IF (ASPE .GT. 0.0) GO TO 553 IF(REPL)WRITE(6,941) READ(5,$)ASPE 553 IF(PLEN-33.0)53,53,9999 53 XCT=YCT*ASPE PWID=XCT+XCT SCALE=PWID*2.638889E-3 GO TO ITC2,(4401,4404) 4401 GO TO IFIRS,(4400,4406) 4400 IF(IGTO)4404,4404,4402 4402 YCM=YCUM+PLEN IF(YCM .GT. 33.0) GO TO 4403 CALL PLOT(0.0,PLPR,-3) XMAX=AMAX1(XMAX,PWID) YCUM=YCN GO TO 4404 4406 ASSIGN 4400 TO IFIRS GO TO 4405 4403 CALL PLOT(XMAX,PLPR-YCUM,-3) 4405 YCUM=PLEN XMAX=PWID 4404 IGTO=IABS(IGTO) IF(IGTO-10)4408,4407,4407 4407 IGTO=IGTO-10 IF(REPL)WRITE(6,931) READ(5,31)FILE CALL SETLIO('2 ',FILE) 4408 PLPR=PLEN C INITIALIZATION FOR THE CHOSEN PROJECTION, INCLUDING DRAWING THE C BORDER OF THE MAP GO TO (600,601,602,603,604,605,606,607,608,609,610,611),IPROJ C MERCATOR 600 QTR=DTR*.5 AMX=PLEN*.48 AMH=181.894*ASPE XXB=180.*SCALE XXC=XXB+XCT AXA=AMX+YCT CALL PLOT(XXC,AXA,3) XXD=XCT-XXB CALL PLOT(XXD,AXA,2) AXB=YCT-AMX CALL PLOT(XXD,AXB,2) CALL PLOT(XXC,AXB,2) CALL PLOT(XXC,AXA,2) ASSIGN 401 TO IPR GO TO 167 C AZIMUTHAL EQUIDISTANT 601 RAD=SCALE*180. CALL PLOT(XCT,YCT+RAD,3) DO 27 ID=1,360 ANGLE=DTR*FLOAT(ID) Y=YCT+RAD*COS(ANGLE) X=XCT+RAD*SIN(ANGLE) 27 CALL PLOT(X,Y,2) ASSIGN 402 TO IPR GO TO 167 C SAVARD EGG 602 RAD=SCALE*180. SRAD=SCALE*120. CALL PLOT(XCT,YCT+SRAD,3) DO 57 ID=1,360 ANGLE=DTR*FLOAT(ID) X=XCT+RAD*SIN(ANGLE) Y=YCT+SRAD*COS(ANGLE) 57 CALL PLOT(X,Y,2) ASSIGN 403 TO IPR GO TO 167 C SINUSOIDAL 603 XMA=180.*SCALE CALL PLOT(YCT-90.*SCALE,16.5,3) DO 7631 ID=1,180 ANGLE=FLOAT(ID-90) 7631 CALL PLOT(XCT-XMA*COS(ANGLE*DTR),SCALE*ANGLE+YCT,2) DO 7632 ID=1,180 ANGLE=FLOAT(90-ID) 7632 CALL PLOT(XCT+XMA*COS(ANGLE*DTR),SCALE*ANGLE+YCT,2) ASSIGN 404 TO IPR GO TO 167 C ORTHOGRAPHIC 604 XMH=90.*SCALE CALL PLOT(XCT,YCT,3) DO 7641 ID=2,360,2 ANGLE=DTR*FLOAT(ID) 7641 CALL PLOT(XCT+XMH-XMH*COS(ANGLE),XMH*SIN(ANGLE)+YCT,2) DO 7642 ID=2,360,2 ANGLE=DTR*FLOAT(ID) 7642 CALL PLOT(XCT+XMH*COS(ANGLE)-XMH,XMH*SIN(ANGLE)+YCT,2) ASSIGN 405 TO IPR GO TO 167 C LAMBERT AZIMUTHAL EQUAL-AREA 605 RAD=SCALE*180. SS=.5*DTR ASSIGN 406 TO IPR GO TO 167 C HAMMER-AITOFF 606 XSH=SCALE*90. XMH=XSH+XSH SS=.5*DTR XS=127.2792 SF=2.0 CALL PLOT(XCT,XSH+YCT,3) DO 7661 ID=1,360 ANGLE=DTR*FLOAT(ID) 7661 CALL PLOT(XMH*SIN(ANGLE)+XCT,XSH*COS(ANGLE)+YCT,2) ASSIGN 407 TO IPR GO TO 167 C AITOFF EQUAL-AREA 607 SF=1.8 XS=141.4214 C MULTIPLIES BY ROOT 2, TAKING FIXED +/- 90 OF PROJ TO 1/SF FOR VERT SS=.5*DTR RAD=SCALE*180. SRAD=SCALE*100. DO 7682 IE=1,2 CALL PLOT(XCT+RAD*.4358899,YCT+SRAD*.9,3) DO 7681 ID=1,100 ANGLE=FLOAT(ID-50)*2.39539E-2 C ARC SINE .9 EQUALS 64.158 DEGREES OR 1.19769515 RADIANS C ARC SINE .75 EQUALS 48 DEGREES, 35 MINUTES OR .84806208 RAD 7681 CALL PLOT(XCT+RAD*COS(ANGLE),YCT-SRAD*SIN(ANGLE),2) 7682 RAD=-RAD ALATH=1.197695 7684 ILON=-180 IC=3 ASSIGN 65 TO IQIC 7683 ALON=FLOAT(ILON) ALAT=ALATH GO TO 1478 2678 ILON=ILON+1 IF(ILON.LT.180)GO TO 7683 ALATH=-ALATH IF (ALATH .LT. 0.) GO TO 7684 ASSIGN 408 TO IPR GO TO 167 C CARDS TO ENSURE LABELS ARE DEFINED FOR FUTURE EXPANSION 608 ASSIGN 409 TO IPR 609 ASSIGN 410 TO IPR 610 ASSIGN 411 TO IPR 611 ASSIGN 412 TO IPR 167 CONTINUE ASSIGN 82 TO ILAC IF(ABS(AAR) .LT. .009) GO TO 276 C ROTATIONS UNDER .01 DEG, NOT ALLOWED: IF NO ROTATION OF C COORDINATES, INITIALIZATION AND DIFFICULT PART OF ROTATION SKIPPED. AAR=AAR*DTR CA=COS(AAR) SA=SIN(AAR) ASSIGN 86 TO ILAC 276 IF (IGTO-2) 376,99,376 376 ASSIGN 205 TO IPPR REWIND 2 C THIS STATEMENT READS A RECORD THE FIRST FIVE CHARACTERS OF WHICH GIVE C THE NUMBER OF POINTS IN A STRETCH OF COASTLINE 476 READ(2,11,END=9099)ICO IC=3 ASSIGN 85 TO IQIC C THESE POINTS WILL BE GIVEN ON SUBSEQUENT RECORDS, THIRTY POINTS TO A C RECORD C THESE RECORDS HAVE THE FOLLOWING FORMAT: C SIX SPACES C THE LATITUDE OF THE FIRST POINT, AS A 16-BIT INTEGER IN TENTHS OF A C DEGREE, IN A2 FORMAT C ONE SPACE C THE LONGITUDE OF THE FIRST POINT, AS A 16-BIT INTEGER IN TENTHS OF A C DEGREE, IN A2 FORMAT C ONE SPACE C DELTA LAT AND DELTA LON, IN TENTHS OF A DEGREE FOR THE REMAINING C 29 POINTS, IN EXCESS-128 FORM 4 IK=MIN0(ICO,30) IP=IK+IK-2 IIP=IP*4 IF(IP)476,48,44 C IF ONLY ONE POINT REMAINS TO BE READ, OMIT THE IMPLIED DO 48 READ(2,21)HX,HY IHX=HX IHY=HY BUF(1)=FLOAT(IHX)/10. BUF(2)=FLOAT(IHY)/10. GO TO 500 44 READ(2,21)HX,HY,(LIB(I),I=4,IIP,4) IHX=HX IHY=HY BUF(1)=FLOAT(IHX)/10. BUF(2)=FLOAT(IHY)/10. DO 7 J=1,IP 7 BUF(J+2)=BUF(J)+FLOAT(IBF(J)-128)/10. 500 IO=IK+IK-1 J=1 17 CONTINUE ALAT=BUF(J) ALON=BUF(J+1) C PROCEED TO PROGRAM TO PLOT POINTS GO TO 222 205 CONTINUE IF(J.LE.10)GO TO 17 ICO=ICO-30 GO TO 4 9899 IF(IGTO-1)373,373,99 99 ASSIGN 215 TO IPPR IMLL=MIN0(-80,-90+ILAI) IXLL=0-IMLL ILON=ILOI-180 ALONH=ALON IC=3 ASSIGN 65 TO IQIC ILAT=IMLL 420 ALAT=FLOAT(ILAT) ALON=ALONH GO TO 222 215 CONTINUE ILAT=ILAT+1 IF (ILAT.LE.IXLL) GO TO 420 ILON=ILON+ILOI IF (ILON.LE.180) GO TO 4410 ASSIGN 225 TO IPPR ILAM=90-ILAI ILAT=ILAI-90 510 ALAT=FLOAT(ILAT) ASSIGN 65 TO IQIC IC=3 ILON=-180 520 ALON=FLOAT(ILON) ALAT=ALATH GO TO 222 225 CONTINUE ILON=ILON+1 IF(ILON.LE.180)GOTO 520 ILAT=ILAT+ILAI IF(ILAT .LE. ILAM) GO TO 510 GO TO ITCL,(272,373) 272 CALL PLOT(0.0,0.0,-3) 373 GO TO IQIZ(878,676,575) 909 CALL PLOT(0.0,0.0,999) STOP 9999 WRITE(6.9961) STOP 222 CONTINUE C CARDS TO ACTUALLY PLOT POINT FOLLOW. C ****************************************** 1 C ROTATION OF AXES ALON=ALON-AMR C ASSIGNED GO TO USED TO SPEED PROGRAM GO TO ILAC,(86,82) 86 ALON=ALON*DTR ALAT=ALAT*DTR Z=SIN(ALAT) X=COS(ALAT) Y=X*SIN(ALON) X=X*COS(ALON) ZN=Z*CA-X*SA XN=X*CA+Z*SA ALAT=ARSIN(ZN)*RTD IF(ABS(XN)+ABS(Y)-.002)350,360,360 350 ALON=0. GO TO 65 360 ALON=ATAN2(Y,XN)*RTD 82 ALON=ALON+AMS C ANGLES HAVE NOW BEEN ROTATED, AND ARE IN DEGREES. C THEIR SIGN IS CORRECT, AND USING ATAN2 TO GET ALON C PREVENTS BLOWUP NEAR 0 OR 90 DEG. ALON=AMOD(ALON+900.,360.)-180. C IF AMS IS WITHIN +/- 180. THIS WILL GIVE ANGLE PROPER RANGE. GO TO IQIC,(65,75,85,95) C IF DECIDED IN ADVANCE NOT TO PLOT POINT, SKIP BOUNDARY CHECK, C OR IF FIRST POINT OF RUN, TO BE ALWAYS PLOTTED TO WITH PEN UP. 95 IF (ALON*AFIR.LE.0.) IC=3 75 IF(ABS(ALON-AFIR).GT.100.) IC=3 65 CONTINUE C ACTUAL PROCEDURE TO PERFORM PROJECTION NOW BEGINS. GO TO IPR,(401,402,403,404,405,406,407,408,409,410,411,412) C MERCATOR 401 X=ALON Y=RTD*ALOG(TAN(QTR*(ALAT+90.))) IF (ABS(Y)-AMH)660,660,949 C AZIMUTHAL EQUIDISTANT 402 R=90.-ALAT IF(R.GT.179.8) GO TO 949 ALON=ALON*DTR Y=R*SIN(ALON) X=R*COS(ALON) GO TO 665 C SAVARD EGG 403 ALATA=ABS(ALAT) ALONA=ABS(ALON) YZR=ALATA+ALATA*ALATA*ALATA/24300. X=ALONA*SQRT(8100.-ALATA*ALATA)*1.111111E-2 DELT=1.333333*ALATA-YZR IF (ALATA .LE. .1) GO TO 1476 RAD=.5*DELT+2.*(8100.-ALATA*ALATA)/DELT Y-YZR+RAD-SQRT(RAD*RAD-X*X) 6601 X=SIGN(X,ALON) Y=SIGN(Y,ALAT) GO TO 660 C CLOSE TO THE EQUATOR, PARABOLAE APPROXIMATE ARCS TO AVOID NUMERICAL PROBLEMS 1476 Y=YZR+DELT*ALONA*ALONA/32400. GO TO 6601 C SINUSOIDAL 404 Y=ALAT X=ALON*COS(ALAT*DTR) GO TO 660 C ORTHOGRAPHIC 405 ALAT=ALAT*DTR Y=90*SIN(ALAT) X=SIGN(90.,ALON)+COS(ALAT)*SIN((ABS(ALON)-90.)*DTR)*SIGN(90.*ALON) ASSIGN 90 TO IQIC GO TO 665 C LAMBERT AZIMUTHAL EQUAL AREA 406 R=90.-ALAT IF (R.GT.179.8) GO TO 949 R=180.*SIN(SS*R) ALON=ALON*DTR X=R*COS(ALON) Y=Y*SIN(ALON) GO TO 665 C HAMMER-AITOFF 407 ALAT=ALAT*DTR 1470 ALONHA=SS*ALON Z=SIN(ALAT) X=COS(ALAT) Y=X*SIN(ALONHA) X=X*COS(ALONHA) ALAT=ARSIN(X)*RTD IF(ABS(Z)+ABS(Y)-.002)881,882,882 881 ALON=0. GO TO 883 882 ALON=ATAN2(Z,Y) 883 R=XS*SIN(SS*(90.-ALAT)) Y=R*SIN(ALON) X=SF*R*COS(ALON) GO TO 660 408 ALAT=ARSIN(.9*SIN(DTR*ALAT)) GO TO 1476 409 CONTINUE 410 CONTINUE 411 CONTINUE 412 CONTINUE C |||||||||||||||||||||||||||||||||||||||||| 2 C RETURN TO CONVERSION SEGMENT TO PLOT POINT. 949 IC=3 GO TO 999 660 ASSIGN 75 TO IQIC 665 YYO=Y*SCALE+YCT XXO=X*SCALE+XCT CALL PLOT(XXO,YYO,IC) C ****************************************** 1 C RETURN TO POINT CO-ORDINATING EXTERNAL PROGRAM. IC=2 999 CONTINUE GO TO IPPR,(205,215,225,2670) 9961 FORMAT(' PLOT TOO LARGE: TALLER THAN 33 IN.') 931 FORMAT(' ENTER NEW MAP FILE NAME, FOLLOWED BY AT LEAST ONE BLANK') 941 FORMAT(' ENTER ASPECT RATIO (WIDTH/HEIGHT) OF PLOT DESIRED.') 951 FORMAT(' ENTER GRATICULE OPTION: 1-MAP ONLY, 2-GRATICULE ONLY,') 952 FORMAT(' 3-MAP AND GRATICULE: MAKE NEGATIVE IF PREVIOUS MAP') 953 FORMAT(' IS TO BE OVERDRAWN,+10 TO RESPECIFY MAP FILE') 961 FORMAT(' ENTER LAT. AND LONG. INCREMENTS FOR GRATICULE') 971 FORMAT(' ENTER PROJECTION NUMBER: 1-MERCATOR, 2-AZIM. EQUIDIST.') 972 FORMAT(' 3-SAVARD EGG,4-SINUSOIDAL,5-ORTHOGRAPHIC') 973 FORMAT(' 6-LAMBERT AZIMUTHAL EQUAL-AREA,7-HAMMER-AITOFF,') 981 FORMAT(' ENTER HEIGHT OF DESIRED MAP') 991 FORMAT(' ENTER MERIDIAN OF ROTATION, AMOUNT OF ROTATION,') 992 FORMAT(' MERIDIAN TO WHICH IT IS ASSIGNED AFTERWARDS,') 1901 FORMAT(' MR/AR/MA:PLEN:PROJ:LATI/LONI:GRATOPS') 11 FORMAT(I5) 21 FORMAT(6X,A2,1X,A2,1X,58A1) 31 FORMAT(20A4) END
The FORTRAN 66 standard codified FORTRAN IV in an official standard; since FORTRAN IV had been in existence since 1963, however, except in contexts where standards conformance was specified, FORTRAN 66 never really caught on as the name of this form of the language.
Copyright (c) 2007 John J. G. Savard