[comp.lang.fortran] CDC FORTRAN trivia questions

mike@quench.lbl.gov (Michael Helm) (10/29/88)

I'm trying to revive a dinosaur code that used to run on our CDC 6600/7600
years ago.  In so doing, I've come across some odd code fragments that
compilers on our newer machines don't like much.  Most of these I can
fix, but now I've come across one I'm not sure of, & my CDC-ish FORTRAN
manuals are long gone.  In particular, suppose one has this code:
   .
   .
   .
        LOGICAL IRON
   .
   .
   .
        IF(IRON)4,9
  4     A=B
   .
   .
  9     A=C
   .
   .
   .
        END

What logical state will IRON be in for #4 to be executed, & for #9
to be executed?  How were(are) logical values represented on old(current)
CDC hardware or in CDC FORTRAN programs?

Thanks for your help,

Michael Helm (Internet M_Helm@lbl.gov) 

ags@s.cc.purdue.edu (Dave Seaman) (10/31/88)

In article <1196@helios.ee.lbl.gov> mike@quench.lbl.gov (Michael Helm) writes:
	[Re:  Ancient CDC Fortran and the two-branch logical IF]

	[This is my corrected posting.  I have cancelled an incorrect
	earlier posting.  If you see another posting from me on this
	subject, ignore it.]

>        LOGICAL IRON
>   .
>   .
>   .
>        IF(IRON)4,9
>
>What logical state will IRON be in for #4 to be executed, & for #9
>to be executed?  

The Fortran 77 equivalent of this CDC-ism is:

	 IF (IRON) THEN
	   GO TO 4
	 ELSE
	   GO TO 9
	 ENDIF

CDC compilers also recognized a two-branch arithmetic IF of the form,

	IF (aexp) 10,20

where "aexp" is an arithmetic expression.  The Fortran 77 equivalent is:

	IF (aexp .NE. 0) THEN
	  GO TO 10
	ELSE
	  GO TO 20
	ENDIF

>How were(are) logical values represented on old(current)
>CDC hardware or in CDC FORTRAN programs?

The representation of logical values is a software concept, not a hardware
concept.  I can't imagine why you would need to know the representation
chosen by a particular Fortran compiler, but if I remember correctly, the
usual convention was to represent .TRUE. as -1 and .FALSE. as zero.  Some
of the very old CDC compilers used a different convention.
-- 
Dave Seaman	  					
ags@j.cc.purdue.edu

daniel@uxe.cso.uiuc.edu (11/01/88)

Re: IF(IRON)4,9

This is not a logical IF statement.  It is a variant on the
arithmetic IF.  It's meaning is as follows: Jump to the first
label if the value of the expression is non-zero and to the
second label if it is zero.

(Actually, it can be used as a two branch logical IF also:
Branch to the first label if the logical expression is true;
branch to the second label if it is false.)

These commands exist only in the CDC Fortran Version 4 compiler
which compiled the FORTRAN 66 language.

-- Daniel Pommert
   Computing Services Office
   University of Illinois
   1304 W. Springfield, Rm. 150
   Urbana, IL 61801-2987
   (217)333-8629
   daniel@uxh.cso.uiuc.edu (Internet)
   DANIEL@UIUCVMD          (Bitnet)

cccm001@ut-emx.UUCP (Tom Linsley) (11/01/88)

Some further trivia relating to the CDC two-branch IF and 6600 logic:

The values .TRUE. and .FALSE., when assigned to a variable, are represented
as a (60-bit) word with all bits set (-0) and all bits clear (+0), respectively.

Later CDC compilers (FTN, MNF) checked the sign bit (2**59), and .TRUE. was
high, .FALSE. low.

The venerable RUN compiler used a different convention, whereby a word with no
bits set (+0) was .FALSE., and _any_other_value_ was .TRUE.  This convention
made possible some peculiarly illogical logical behaviors, in that both "X" and
".NOT. X" could be true simultaneously, if "X" had been given some nonzero (or
"non-logical") value (i.e., neither +0 nor -0).  Remember that this compiler
dates from a time when "strong typing" meant pounding hard on the keypunch.

As an aside, negative zero was assigned to a variable read from a blank
field (rather than a field containing a zero), and the test for the blank
(often used for missing data) was

  IF ( .NOT. X ) T,F

where the "false" branch indicated a negative zero (arithmetic blank) value.

  IF ( X .AND. (X .EQ. 0) ) <blank field processing statement>

was also sometimes used for this check.

--
Tom Linsley
University of Texas Computation Center
cccm001@emx.cc.utexas.edu

dik@cwi.nl (Dik T. Winter) (11/01/88)

In article <3616@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
 > In article <1196@helios.ee.lbl.gov> mike@quench.lbl.gov (Michael Helm) writes:
 > 	[Re:  Ancient CDC Fortran and the two-branch logical IF]
 > 
 >                                          but if I remember correctly, the
 > usual convention was to represent .TRUE. as -1 and .FALSE. as zero.  Some
 > of the very old CDC compilers used a different convention.
 > -- 
Beware, .FALSE. is +0;  truth values returned by expressions could have any
arithmetic value with negative for .TRUE. and positive for .FALSE..
So -0 is .TRUE. (yes, it is a 1-s complement machine).
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

ags@s.cc.purdue.edu (Dave Seaman) (11/01/88)

In article <7523@ut-emx.UUCP> cccm001@ut-emx.UUCP (Tom Linsley) writes:
>
>Some further trivia relating to the CDC two-branch IF and 6600 logic:
>
>The values .TRUE. and .FALSE., when assigned to a variable, are represented
>as a (60-bit) word with all bits set (-0) and all bits clear (+0), respectively.
>
>Later CDC compilers (FTN, MNF) checked the sign bit (2**59), and .TRUE. was
>high, .FALSE. low.

I agree that there was more than one convention, but I believe most of the
later compilers used -1 (59 one bits out of 60 on a ones-complement
machine) for .TRUE. and zero for .FALSE.  I used to know exactly what each
of our dozen-or-so Fortran compilers did on the old CDC machines, but I
have forgotten most of the details.

>The venerable RUN compiler used a different convention, whereby a word with no
>bits set (+0) was .FALSE., and _any_other_value_ was .TRUE.  This convention
>made possible some peculiarly illogical logical behaviors, in that both "X" and
>".NOT. X" could be true simultaneously, if "X" had been given some nonzero (or
>"non-logical") value (i.e., neither +0 nor -0).  Remember that this compiler
>dates from a time when "strong typing" meant pounding hard on the keypunch.

I remember that there was some strangeness about logicals with the RUN
compiler, and this may have been it, but I think the later compilers used a
slightly different test:  zero for .FALSE. and nonzero for .TRUE.  The
ones-complement value -0 (all bits set) is considered "zero" as far as this
hardware test is concerned, so that the problem you described does not
arise.  This is also why .TRUE. was represented as not-quite-all-ones.

-- 
Dave Seaman	  					
ags@j.cc.purdue.edu

ags@s.cc.purdue.edu (Dave Seaman) (11/02/88)

In article <7691@boring.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:
>Beware, .FALSE. is +0;  truth values returned by expressions could have any
>arithmetic value with negative for .TRUE. and positive for .FALSE..
>So -0 is .TRUE. (yes, it is a 1-s complement machine).

I still have access to a CDC 6500.  Just a few minutes ago I ran the
following program:

	print 10, .true., .false.
     10 format(2(1x,o20))
	end

for which the output was:

 77777777777777777776 00000000000000000000

which shows that .true. is -1 and .false. is 0, just as I said.  The older
compilers (such as RUN) used a different convention, something like -0 for
.true. and +0 for .false.

-- 
Dave Seaman	  					
ags@j.cc.purdue.edu

cccm001@ut-emx.UUCP (Tom Linsley) (11/02/88)

By golly, Dave's right, the "logical truth" is even curiouser than I had
thought.  I ran a little "assign and print" program this afternoon using five
of the Fortran compilers on our Dual Cyber 170/750;  herewith the results:

 RUN         TRUE  77777777777777777777  (-0)
             FALSE 00000000000000000000  (+0)

 MNF 4.6     TRUE  77777777777777777776  (-1)
             FALSE 00000000000000000001  (+1)

 MNF 5.4     TRUE  77777777777777777776  (-1)
             FALSE 00000000000000000000  (+0)

 FTN 4.8     TRUE  77777777777777777776  (-1)
             FALSE 00000000000000000000  (+0)

 FTN 5.1     TRUE  77777777777777777776  (-1)
             FALSE 00000000000000000000  (+0)

 I sure hope none of Mike Helms' old CDC code relies on anything but just
 plain "true" or "false". - TL
--

Tom Linsley
University of Texas Computation Center
cccm001@emx.cc.utexas.edu

dik@cwi.nl (Dik T. Winter) (11/02/88)

In article <3622@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
 > I agree that there was more than one convention, but I believe most of the
 > later compilers used -1 (59 one bits out of 60 on a ones-complement
 > machine) for .TRUE. and zero for .FALSE.
Still true for FTN4 and FTN5.
 > 
In article <7523@ut-emx.UUCP> cccm001@ut-emx.UUCP (Tom Linsley) writes:
 >The venerable RUN compiler used a different convention, whereby a word with no
 >bits set (+0) was .FALSE., and _any_other_value_ was .TRUE.  This convention
 >made possible some peculiarly illogical logical behaviors, in that both "X" and
 >".NOT. X" could be true simultaneously, if "X" had been given some nonzero (or
 >"non-logical") value (i.e., neither +0 nor -0).  Remember that this compiler
 >dates from a time when "strong typing" meant pounding hard on the keypunch.
 > 
I doubt this.  On the Cybers it is very difficult to distinguish +0 from the
rest.  The hardware compare for zero gets both +0 and -0.  (Testing L you have
to write: OR(NOT(L)+0,L).GE.0 to distinguish +0).
So I do not think any compiler has used this scheme.  (Was RUN FORTRAN 2 or
FORTRAN 3?  I do not remember anymore.)  The illogical thing is of course
that you could have tests like (I.LT.0.AND.I.EQ.0) return .TRUE. or
(P.GE.Q.OR.Q.GE.P) return .FALSE..

In article <3622@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
 > I remember that there was some strangeness about logicals with the RUN
 > compiler, and this may have been it, but I think the later compilers used a
 > slightly different test:  zero for .FALSE. and nonzero for .TRUE.  The
 > ones-complement value -0 (all bits set) is considered "zero" as far as this
 > hardware test is concerned, so that the problem you described does not
 > arise.
No, both FTN4 and FTN5 use negative for TRUE and positive for FALSE.  The
following function:
	LOGICAL COMPARE(X, Y)
	COMPARE = X .LT. Y
	RETURN
	END
would compile to the equivalent of:
	return(x-y)
without postnormalisation step.  If X and Y are not both -0 the subtraction
does not return -0.  Of course the equivalent for integers fails due to
possible overflow, but well, so it is with any comparison on integers.
The best I have found for a fail proof integer compare (<) was:
	OR(AND(XOR(I,J),J),AND(EQV(I,J),I-J)).

There is a very slick method to translate L = A.NE.B:
L = OR(A-B,B-A).

To summarise, I like ones complement machines, and I liked the Cybers.
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

dik@cwi.nl (Dik T. Winter) (11/02/88)

In article <3624@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
 > In article <7691@boring.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:
 > >Beware, .FALSE. is +0;  truth values returned by expressions could have any
 > >arithmetic value with negative for .TRUE. and positive for .FALSE..
 > >So -0 is .TRUE. (yes, it is a 1-s complement machine).
 > 
 > 	print 10, .true., .false.
 >      10 format(2(1x,o20))
 > 	end
 > 
 > for which the output was:
 > 
 >  77777777777777777776 00000000000000000000
You missed something: I wrote: the constant .TRUE. is -1 indeed, but a logical
expression could very well return -0 for .TRUE..
Try:
	logical function equal(i,j)
	equal = i.eq.j
	return
	end
	print 10, equal(1,1)
	10 format(1x,o20)
	end
the output is:
	77777777777777777777
(yes, -0).  (It might depend on the level of optimisation.)
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

ags@s.cc.purdue.edu (Dave Seaman) (11/03/88)

>In article <7523@ut-emx.UUCP> cccm001@ut-emx.UUCP (Tom Linsley) writes:
>>The venerable RUN compiler used a different convention, whereby a word with no
>>bits set (+0) was .FALSE., and _any_other_value_ was .TRUE.  

In article <7693@boring.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:
>I doubt this.  On the Cybers it is very difficult to distinguish +0 from the
>rest.  The hardware compare for zero gets both +0 and -0.  

The RUN compiler did indeed use this scheme.  It is true that the hardware
compare for zero gets both +0 and -0, but all this proves is that the RUN
compiler did not use the hardware compare for zero when testing logicals.

>(Testing L you have
>to write: OR(NOT(L)+0,L).GE.0 to distinguish +0).
>So I do not think any compiler has used this scheme.  

No, you just write .NOT. L, assuming L is typed LOGICAL.  The compiler does
the rest.

>The illogical thing is of course
>that you could have tests like (I.LT.0.AND.I.EQ.0) return .TRUE. or
>(P.GE.Q.OR.Q.GE.P) return .FALSE..

I don't see how.  I tried evaluating your first expression with I equal to
minus zero, and it still gave me .FALSE.  I tried the second expression
with P and Q both equal to minus zero, and it gave me .TRUE.  Did you have
some other values in mind?  It seems to me you are making unwarranted
assumptions about how compilers generate code.

 [Concerning my claim that the later compilers use nonzero for TRUE and
 zero for FALSE]:
>No, both FTN4 and FTN5 use negative for TRUE and positive for FALSE.  

You're right.  I got the compilers confused on this point.  It was the RUN
compiler that behaved as I described. 

-- 
Dave Seaman	  					
ags@j.cc.purdue.edu

forags@violet.berkeley.edu (11/03/88)

In article <3627@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
>
>The RUN compiler did indeed use this scheme.  It is true that the hardware
>compare for zero gets both +0 and -0, but all this proves is that the RUN
>compiler did not use the hardware compare for zero when testing logicals.
>
Right!  The RUN compiler used a CXi Xk instruction (count all one-bits in Xi
and store the result in Xk, so anything but 60 zero bits was true). (On a 
6000-series machine this took an obscene number of minor cycles (68 on a
6400), which made logical variables rather slow to evaluate...)


Al Stangenberger                    Dept. of Forestry & Resource Mgt.
forags@violet.berkeley.edu          145 Mulford Hall - Univ. of Calif.
uucp:  ucbvax!ucbviolet!forags      Berkeley, CA  94720
BITNET: FORAGS AT UCBVIOLE          (415) 642-4424                      

rchrd@well.UUCP (Richard Friedman) (11/04/88)

I believe the old RUN compiler would generate code to test
the number of 1 bits in a register.  If this was 60, the result
was true.  (The 6600 hardware had a CXi Xj  instruction to count
the number of 1 bits in Xj and leave that number in Xi).
-- 
...Richard Friedman [rchrd]                         
uucp:  {ucbvax,lll-lcc,ptsfa,hplabs}!well!rchrd
- or -   rchrd@well.uucp

kurtk@tekcae.CAX.TEK.COM (Kurt Krueger) (11/04/88)

Something that may be confusing the issue is that CDC in the FTN and FTN5
compilers always inserted code to make sure that -0 would 'disappear'.
In logical statements, this would at times amount to adding a +0 to the
logical expression so SOME mathematics would always get done BEFORE a sign
test was done.  The hardware is such that -0 can NEVER get calculated
but is a perfectly legitimate operand.

-- I too like the Cybers.  Even the new NOS/VE ones - a REAL computer.

khb%chiba@Sun.COM (Keith Bierman - Sun Tactical Engineering) (11/05/88)

In article <2183@tekcae.CAX.TEK.COM> kurtk@tekcae.CAX.TEK.COM (Kurt Krueger) writes:
>Something that may be confusing the issue is that CDC in the FTN and FTN5
>compilers always inserted code to make sure that -0 would 'disappear'.
>In logical statements, this would at times amount to adding a +0 to the
>logical expression so SOME mathematics would always get done BEFORE a sign
>test was done.  The hardware is such that -0 can NEVER get calculated
>but is a perfectly legitimate operand.

-0 DID get computed. This proved to be a problem during my student
days on a Cyber 17x with using the ETH Pascal compiler in conjuction
with one of the fortran compilers (I forget which) Pascal couldn't
cope with -0's which were being generated by the fortran compiler.






Keith H. Bierman
It's Not My Fault ---- I Voted for Bill & Opus

dik@cwi.nl (Dik T. Winter) (11/06/88)

In article <16427@agate.BERKELEY.EDU> forags@violet.berkeley.edu writes:
 > Right!  The RUN compiler used a CXi Xk instruction (count all one-bits in Xi
 > and store the result in Xk, so anything but 60 zero bits was true). (On a 
 > 6000-series machine this took an obscene number of minor cycles (68 on a
 > 6400), which made logical variables rather slow to evaluate...)
 > 
This explains it.  I would never have thought that a compiler writer would use
that instruction for logicals.  Interestingly, on many Cybers the sequence I
gave (OR(NOT(L)+0,L).GE.0) is faster than CXi Xk followed by a PL, and does
the same!  And if you follow comp.arch you know why this instruction was there.
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

rchrd@well.UUCP (Richard Friedman) (11/08/88)

The comment was made that CDC hardware prevented -0 from being
generated.  This was/is true, but there were times the FTN4 and
FTN5 math library routines would (for specific arguments) return -0.
This was a hard error to find, but eventually it got corrected.

-- 
...Richard Friedman [rchrd]                         
uucp:  {ucbvax,lll-lcc,ptsfa,hplabs}!well!rchrd
- or -   rchrd@well.uucp

dik@cwi.nl (Dik T. Winter) (11/09/88)

In article <7588@well.UUCP> rchrd@well.UUCP (Richard Friedman) writes:
 > The comment was made that CDC hardware prevented -0 from being
 > generated.  This was/is true, but there were times the FTN4 and
 > FTN5 math library routines would (for specific arguments) return -0.
 > This was a hard error to find, but eventually it got corrected.
 > 
Not exactly true; floating-point and integer arithmetic do not generate -0,
if the input operands do not contain -0.  But otherwise they can be generated.
E.g. truncating a negative floating point value to integer (if between -1.0
and 0.0).  Also overflowing integer multiply (which is really a special case
of floating-point multiply) can return -0.  Most compilers compensate
for this by adding +0 to the result, which turns -0 to +0.
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

rchrd@well.UUCP (Richard Friedman) (11/11/88)

In article <7709@boring.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:
>                  floating-point and integer arithmetic do not generate -0,
>if the input operands do not contain -0.  But otherwise they can be generated.
>E.g. truncating a negative floating point value to integer (if between -1.0
>and 0.0).  Also overflowing integer multiply (which is really a special case
>of floating-point multiply) can return -0.  Most compilers compensate
>for this by adding +0 to the result, which turns -0 to +0.
>-- 
>dik t. winter, cwi, amsterdam, nederland

Yes, but the math library was written in COMPASS and early versions
were not very careful about propagating -0 thru sign extension under
special cases, usually resulting from scaling exponents.
In general the code compiled by FTN did a good job avoiding -0
but the library could not be trusted.


-- 
 ...Richard Friedman [rchrd]  Berkeley, CA.                         
    rchrd@well.uucp        -or-
   {ucbvax,lll-lcc,pacbell,hplabs}!well!rchrd