[net.lang.f77] Problem with EQUIVALENCE

sundman@ttds.UUCP (Bo Sundman) (01/22/85)

C The following piece of code is extracted from a numerical routine for which
C I am not guilty. However, I am expected to make it work on f77 under
C UNIX and I do not understand why it does not work. 
C The code works perfectly on a number of machines, including Fortran
C on VAX/VMS, but f77 does not give the correct value on the same VAX.
C
C The intention of the code is, I believe, to store integer indices for matrix
C elements in the only available workspace, a real array. I guess the reason
C for the equivalence is to avoid conversion from real to integer and back
C either to increase speed or to avoid rounding off errors.
C
	IMPLICIT DOUBLE PRECISION (A-H,O-Z)
	DIMENSION W(10),NW(2)
	EQUIVALENCE (WW,NW(1)),(NQ,NW(2))
C MEMORY MAP OF WW, NW AND NQ
C WORD:		1	2
C WW	 (..............)
C NW     (...1..)(...2..)
C NQ		 (......)
C
C Storing an integer value into NQ is thus equivalent to storing the same
C bit pattern into the least significant word of WW.
C
	WRITE(*,*)'Test 1'
	NQ=10
	WRITE(*,*)'Values should be     0  10:',NW
	W(5)=WW
	NQ=100
	WRITE(*,*)'Values should be     0 100:',NW
	WW=1.
	WRITE(*,*)'Values should be 16512   0:',NW
	WW=W(5)
	WRITE(*,*)'Values should be     0  10:',NW,' <<< wrong'
	WRITE(*,*)'Test 2, WW=1.'
	WW=1.
	NQ=10
	WRITE(*,*)'Values should be 16512  10:',NW
	W(5)=WW
	NQ=100
	WRITE(*,*)'Values should be 16512 100:',NW
	WW=1.
	WRITE(*,*)'Values should be 16512   0:',NW
	WW=W(5)
	WRITE(*,*)'Values should be 16512  10:',NW
	END
C
C Output:
C
  Test 1
  Values should be     0  10:  0  10
  Values should be     0 100:  0  100
  Values should be 16512   0:  16512  0
  Values should be     0  10:  0  0        <<< THIS IS WRONG
  Test 2, WW=1.
  Values should be 16512  10:  16512  10
  Values should be 16512 100:  16512  100
  Values should be 16512   0:  16512  0
  Values should be 16512  10:  16512  10

My conclusion is that the run time system is "smart" and when it
shall make the assignment
	WW=W(5)
it discovers that the exponent of W(5) is zero, which normally means
that W(5) IS zero, and it assigns zero to WW rather than copying the
value of W(5) to WW. It may save some nanoseconds of execution time but
is nontrivial in a case like this.
-- 
	Bo Sundman                      (..mcvax!enea!ttds!sundman)
        Thermo-Calc group, Division of Physical Metallurgy
	The Royal Institute of Technology
	Stockholm, Sweden

donn@utah-gr.UUCP (Donn Seeley) (01/27/85)

Bo Sundman (sundman@ttds.UUCP) and Steve Correll (sjc@angband.UUCP)
write about a problem with equivalences.  Steve Correll is correct in
pointing out that the basic problem is that the VAX has floating point
move instructions which normalize data; these instructions also may
cause reserved operand faults for malformed data.  The 4.2 BSD compiler
generates floating point move instructions for floating point
assignments when optimization is not enabled.  In the examples, the
'wrong' result is achieved by taking a variable last defined as an
INTEGER, treating it as a DOUBLE PRECISION value and assigning it to a
DOUBLE PRECISION variable, then treating the result as an INTEGER.

Jerry Berkman at Berkeley has a change, implemented in recent versions
of the compiler, which causes integer move instructions to be
substituted for floating point move instructions in all situations, not
just when optimizing.  The change is fairly complicated and is one of
many that I haven't posted since I began using code from post-4.2 BSD
versions of the C compiler...  At any rate, both Sundman's and
Correll's examples work 'correctly' with the local version of f77
because an integer move is a straightforward copy with no normalization
or checks for well-formedness.

Of course the behavior of the examples under the 4.2 compiler is
technically in accord with the standard.  Section 17.3 of ANSI
X3.9-1978, subsection 2, states:  'When an entity of a given type
becomes defined, all totally associated entities of different type
become undefined.' You are strongly advised not to write code that
assumes that undefined values are predictable.  But (sigh) there are
lots of old programs written by people who 'knew' there would never be
a problem, so the next release of the compiler will support them.

Before Jerry's fix, I used to arrange for 'make' to run 'sed' on the
assembler output of the compiler when not optimizing so that all 'movf'
and 'movd' instructions were changed to 'movl' and 'movq'
instructions.  It's something to think about...  If you're really
desperate, write me for a copy of the new compiler.  FTP is
encouraged, tapes are tolerated but have a long turnaround...

Donn Seeley    University of Utah CS Dept    donn@utah-cs.arpa
40 46' 6"N 111 50' 34"W    (801) 581-5668    decvax!utah-cs!donn