From: stevep@phoenix.ocf.llnl.gov (Steve J Patenaude)
Newsgroups: comp.lang.fortran
Subject: Re: Low level routines to do logical shifts
Keywords: lshft,rshft etc.
Date: 22 Aug 92 19:44:01 GMT
Organization: Lawrence Livermore National Laboratory


I read with interest your problem to convert from C to Fortran a
program that apparently generates random programs for an
imaginary computer.  My first inclination is to say "Don't, it's
better done in C".  However, since this comes from a university,
it is probably an assignment from a particularly diabolical
professor.  So, I'll try to give you some hints.

First, to do a <while> loop in Fortran 77, you must use the
dreaded -gasp- GOTO!

C FORTRAN FOR 'while (foo < finished) foo += incr;'
1     IF (FOO .GE. FINISHED) GOTO 2
      FOO = FOO + INCR
      GOTO 1
C END OF WHILE LOOP
2   ...

Now, for your program.  You are apparently generating random
programs for an imaginary computer with 64 bit word length using
a 32 bit word length computer.  Since there are no shift
instructions in FORTRAN 77, I would suggest that you address the
various p arts of the word using a type of CHARACTER*4, which
allows you to individually reference each byte of the 32 bit
word, or CHARACTER*8 which will pack 8 bytes into two 32-bit
words.  For example,

CHARACTER*4 WORD < WORD(1:1) = "X" > stores an 'X' character in
the 1st or uppermost byte position in the word.

You are generating 16 bit random instructions of the following
form:
    XXXXXIIIXXAABBCC
where X = unused bit
I = 3 bits of instr
A = 2 bits of mode1
B = 2 bits of mode2
C = 2 bits of mode3

by generating random numbers in this range and shifting and
or'ing them into the instruction part of the program.  The instr
part can be stored directly into the upper character position,
The modes will need to be defined as preshifted values.  Since
none of your values overlap and would cause a carry, you can add
rather than <or> the values together.  (The PARAMETER statement
is a good substitute for #define. ) To store the arguments with
mismatch types, you will probably need to equivalence 16-bit
intege rs and 16-bit character variables.  Therefore replace:

>#define MAXDATA 512
>#define ADD 0
>...
>#define BEQ 6
>    instr = RanInt(ADD,BEQ);
>    mode1 = RanInt(0,2);
>    mode2 = RanInt(0,2);
>    mode3 = RanInt(0,2);
>    arg1 = RanInt(0,MAXDATA);
>    arg2 = RanInt(0,MAXDATA);
>    arg3 = RanInt(0,MAXDATA);
>...
>    instr <<= 8;
>    instr |= mode1 << 4;
>    instr |= mode2 << 2;
>    instr |= mode3;

with:

      PARAMETER (MAXDATA=512)
      PARAMETER (ADD=0, ... BEQ=6)
      CHARACTER*8 WORD
      CHARACTER*1 VMODE1(3), VMODE2(3), VMODE3(3)
      INTEGER MODE1, MODE2, MODE3

      INTERGER*2 ARG1, ARG2, ARG3
      CHARACTER*2 CARG1, CARG2, CARG3
      EQUIVALENCE (CARG1, ARG1), (CARG2,ARG2), (CARG3,ARG3)
C  DEFINE PRESHIFTED VALUES FOR MODE1, MODE2, AND MODE3 WITH HEX VALUES
      VMODE1(1) = #H00
      VMODE1(2) = #H10
      VMODE1(3) = #H20
      VMODE2(1) = #H00
      VMODE2(2) = #H04
      VMODE2(3) = #H08
      VMODE3(1) = #H00
      VMODE3(2) = #H01
      VMODE3(3) = #H02
   ...
C GENERATE RANDOM INSTRUCTIONS
      WORD(1:1) = RANINT(ADD,BEQ)
      MODE1 = RANINT(0,2)+1
      MODE2 = RANINT(0,2)+1
      MODE3 = RANINT(0,2)+1
      WORD(2:2) = VMODE1(MODE1) + VMODE2(MODE2) + VMODE3(MODE3)

and store the arguments
      ARG1 = RANINT(0,MAXDATA)
      ARG2 = RANINT(0,MAXDATA)
      ARG3 = RANINT(0,MAXDATA)
      WORD(3:4) = CARG1(1:2)
      WORD(5:6) = CARG2(1:2)
      WORD(7:8) = CARG3(1:2)

You have no real need for pointers in this program, just
dimension the data.

>typedef int data_t;
>typedef struct prog {
>   int num_inst;
>   int num_data;
>   int Pd;
>   long instructions[2*MAXINSTRUCTIONS];
>   data_t data[MAXDATA];
>} prog_t;
>
>typedef struct prog_struct{
>   int num_progs;
>   prog_t program[MAXPROCESSORS];
>}prog_struct_t;
>...
> prog_struct_t programs;

>#define MAXPROCESSORS 1024
>#define MAXINSTRUCTIONS 10
>#define MAXDATA 512
>#define MAXPROGRAMS MAXPROCESSORS
>#define MAXDATAVAL 4096

      PARAMETER (MAXPROCESSORS=1024, MAXINSTRUCTIONS=10)
      PARAMETER (MAXDATA = 512, MAXPROGRAMS = MAXPROCESSORS)
      PARAMETER (MAXDATAVAL = 4096)

      INTEGER NUM_PROGS
      INTEGER NUM_INST(MAXPROCESSORS), NUM_DATA(MAXPROCESSORS)
      INTEGER PD(MAXPROCESSORS)
      CHARACTER*8 INSTRUCTIONS(2*MAXINSTRUCTIONS,MAXPROCESSORS)
      INTEGER DATA(MAXDATA,MAXPROCESSORS)

and reference it directly

>#define current programs.program[prog]
>...
> for (prog=0;  prog< MAXPROGRAMS; ++prog) {
> ...
>    for (inst=0;  inst  < MAXINSTRUCTIONS; ++inst) {
>...
>             current.instructions[2*inst] = (( instr & 0xffff) << 16 |
>                                                       (arg1 & 0xffff);
>             current.instructions[2*inst] = (( arg2 & oxffff) << 16 |
>                                                       (arg3 & 0xffff);
> ...

      DO 10 PROG=1,MAXPROGRAMS
          ...
          DO 20 INST=1,MAXINSTRUCTIONS
             ...
             INSTRUCTIONS( INST,  PROG) = WORD
             ...
10        CONTINUE
20    CONTINUE

I hope this, helps.  Of course your success with this technique
depends on which FORTRAN you are using.  Newer FORTRANs try to
help you with strong type casting, while older, friendlier
FORTRANS let you shoot yourself in the foot as well as any modern
C.

Cherie Jo Patenaude, email PATENAUDEC@LLNL.GOV