[comp.lang.fortran] Fortran versus C for numerical anal

mcdonald@uxe.cso.uiuc.edu (09/01/88)

>The fact that C parenthesis don't force execution order is sufficient
>to exclude C from use in some instances.  

But in ANSI C parenthesis DO force execution order, in cases where
computational results could differ from the expected mathematical one.
Thus, if you compiler is ANSI, there is no problem.

Doug McDonald

davis@galaxy.ee.rochester.edu (Al Davis) (09/02/88)

The fact that Fortran does not support dynamic memory allocation makes it
unsuitable for nearly all numerical analysis applications.

The fact that Fortran does not have a convenient way of making a loop that
does not use a simple counter makes it really cumbersome for many numerical
applications (examples: FFT, any iterative method for solving nonlinear
equations, etc.)

The fact that C does not support conformant arrays is a trivial loss.  Most
who know what they are doing don't use static arrays anyway.

jlg@lanl.gov (Jim Giles) (09/07/88)

From article <1440@valhalla.ee.rochester.edu>, by davis@galaxy.ee.rochester.edu (Al Davis):
> 
> 
> The fact that Fortran does not support dynamic memory allocation makes it
> unsuitable for nearly all numerical analysis applications.

I've never had any trouble.  But then, I've never been saddled with a 
Fortran that couldn't do dynamic memory allocation either.  In any case,
aside from dynamic memory, there are _many_ things that Fortran does
_right_ and C doesn't.

J. Giles
Los Alamos

hirchert@uxe.cso.uiuc.edu (09/09/88)

Dominick Samperi(samperi@djs.UUCP) asks:
>I don't have a copy of the official FORTRAN standard handy, but there appears
>to be an inconsistency in the specifications. Specifically, most references on
>FORTRAN state that the primitive operators associate left to right, except
>for **, which associates right to left. This would imply that A+B+C will
>be evaluated as (A+B)+C.

>On the other hand, I have verified that the FORTRAN definition explicitly 
>allows any FORTRAN implementation to rearrange the order of evaluation of 
>an expression for optimization in any manner, provided that operator 
>precedence rules are obeyed, and parentheses are respected. Does this not 
>contradict the left-to-right/right-to-left rules mentioned above?

Left to right precedence means that A-B+C is interpreted mathematically as
(A-B)+C and not A-(B+C).  Freedom of evaluation order (in the absence of
explicit parentheses) means that mathematical (A-B)+C could be evaluated as
(A+C)-B or even A-(B-C).

>Dominick Samperi
>    samperi@acf8.nyu.edu             uunet!hombre!samperi
>    cmcl2!acf8!samperi               rutgers!acf8.nyu.edu!samperi
>      (^ ell)

Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications

wes@obie.UUCP (Barnacle Wes) (09/16/88)

In article <1440@valhalla.ee.rochester.edu>, davis@galaxy.ee.rochester.edu (Al Davis) writes:
> The fact that Fortran does not support dynamic memory allocation makes it
> unsuitable for nearly all numerical analysis applications.

An ex-colleague of mine :-) insisted for months that C was completely
unsuited for numerical analysis work, and that Fortran was the only
language with the requisite features.  Then he ran out of memory for the
program he was doing.  A friend and I re-wrote it in C in three hours,
using a linked list instead of the large array he was using, and the
size of problem he could handle went up by a factor of 10.  This
particular "programmer" had never heard of a sparse matrix.  And to
think, he was paid more that I was (then :-).
-- 
                     {hpda, uwmcsd1}!sp7040!obie!wes

         "How do you make the boat go when there's no wind?"
                                 -- Me --

mcdonald@uxe.cso.uiuc.edu (09/16/88)

From article <1511@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> 	(*twodarray)[10][5] = 'c';
> 
> Now you have.
Reply by J. Giles:
>Gee, that looks like and array of pointers to me.  If there's no pointers
>involved, what's that asterisk doing there?  This is certainly _not_
>an example of a 2-d array that is done without an array of pointers.

I tried to do this yesterday, but failed due to not getting the
parenthesis right. But Peter's example does indeed work, to wit
on my PC (microsoft 5.1):

main() {
char (*twodarray)[10][10];
int i;
        twodarray = malloc(sizeof(*twodarray));

       for(i = 0; i < 10; i++)
        (*twodarray)[i][3] = i;
}


_main   PROC NEAR
        push    bp
        mov     bp,sp
        mov     ax,4
        call    __chkstk
        push    si
;       twodarray = -4
;       i = -2
; Line 4
        mov     ax,100
        push    ax
        call    _malloc
        add     sp,2
        mov     WORD PTR [bp-4],ax      ;twodarray
; Line 6
        mov     WORD PTR [bp-2],0       ;i
$FC106:
; Line 7
        mov     si,WORD PTR [bp-2]      ;i
        mov     ax,si
        shl     si,1
        shl     si,1
        add     si,ax
        shl     si,1
        mov     bx,WORD PTR [bp-4]      ;twodarray
        mov     al,BYTE PTR [bp-2]      ;i
        mov     [bx+3][si],al
        inc     WORD PTR [bp-2] ;i
        cmp     WORD PTR [bp-2],10      ;i
        jl      $FC106
; Line 8
        pop     si
        mov     sp,bp
        pop     bp
        ret

_main   ENDP


Sure looks like array indexing calculations to me. Of course,
for this example pointer tricks could be faster. Now if those
two array sizes could be VARIABLES ........ Why not add this,
even at this late date?  Unnecessary but convenient.

Doug McDonald

jlg@lanl.gov (Jim Giles) (09/17/88)

From article <50500075@uxe.cso.uiuc.edu>, by mcdonald@uxe.cso.uiuc.edu:
>> 	(*twodarray)[10][5] = 'c';
> [... long example showing code generated ...]
> 
> Sure looks like array indexing calculations to me. [...]

Still doesn't look like array indexing to me.  Now _if_ the parenthesis
and asterisk could be removed - then you'd have something.  The fact is,
the semantics _and_ the syntax should be the same for dynamic and static 
arrays - the only difference should be a 'dynamic' flag on the declaration
and an allocation call.  All you've shown me here is an example of the 
weakness that I've objected to all along - the same semantics but two 
incompatible syntaxes.  This goes along with other dynamic array mechanisms 
which allow the same syntax but have different semantics.  I hope that when
Fortran includes a dynamic array capability it will fit more elegantly
into the language than C's capability does.

Consider the Fortran 8x proposal for allocatable arrays:

      REAL, ALLOCATABLE :: twodarray (:,:)

      ...

      ALLOCATE (twodarray(5,10))

      ...

      twodarray(5,10) = 5.0

      ...

Note that a _use_ of the 2-d array looks just like the use of any other
2-d array - static or dynamic.  The semantics are also identical except
that the address of 'twodarray' doesn't become defined until run-time
(neither does the size).  Any optimization that Fortran could apply
to a statically allocated array with unknown extent (like an argument to
a function, for example) can be applied to this one in _exactly_ the 
same way.

J. Giles
Los Alamos

peter@ficc.uu.net (Peter da Silva) (09/19/88)

In article <3708@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <50500075@uxe.cso.uiuc.edu>, by mcdonald@uxe.cso.uiuc.edu:
> >> 	(*twodarray)[9][5] = 'c';
> > [... long example showing code generated ...]

> > Sure looks like array indexing calculations to me. [...]

> Still doesn't look like array indexing to me.

char (*twodarray)[10];

	twodarray = malloc(10*sizeof(*twodarray));

	...

	twodarray[9][5] = 'c';

Exactly the same example, with one vector indeterminate. Now you not
only have two-d arrays, you have dynamically sizable ones... and it's
syntactically and semantically identical to using:

char twodarray[10][10];

Satisfied?
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

dorn@fabscal.UUCP (Alan Dorn Hetzel) (09/19/88)

Both linked lists and sparse arrays are fairly trivial to implement in
FORTRAN.  Many implementations also support dynamic memory.  Without the
dynamic memory, one can allocate a working array and build structures
within it.  Pointers are array base relative, i.e. indexes, instead of
absolute memory pointers.  This also has the advantage of guaranteeing 
that the "pointer" is an integer.  If the data types within the nodes
are integer, one can store them within the same array, if not, one can
allocate a second array of the appropriate type and point to them there
with a node data pointer (whose base is the data array).

Dorn
gatech.edu!fabscal!dorn

lamaster@ames.arc.nasa.gov (Hugh LaMaster) (09/20/88)

In article <1530@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>char (*twodarray)[10];
:
>	twodarray = malloc(10*sizeof(*twodarray));
:
>	twodarray[9][5] = 'c';
:
>Satisfied?

I think the point of dynamically sized arrays has been lost here.  The
capability which C does not have is that of writing a subroutine which
does not contain any information on what the size of the array being
passed in is at compile time, while using the same syntax as statically
sized arrays.  

-- 
  Hugh LaMaster, m/s 233-9,  UUCP ames!lamaster
  NASA Ames Research Center  ARPA lamaster@ames.arc.nasa.gov
  Moffett Field, CA 94035     
  Phone:  (415)694-6117       

lfm@fpssun.fps.com (Larry Meadows) (09/20/88)

In article <182@obie.UUCP>, wes@obie.UUCP (Barnacle Wes) writes:
:
: An ex-colleague of mine :-) insisted for months that C was completely
: unsuited for numerical analysis work, and that Fortran was the only
: language with the requisite features.  Then he ran out of memory for the
: program he was doing.  A friend and I re-wrote it in C in three hours,
: using a linked list instead of the large array he was using, and the
: size of problem he could handle went up by a factor of 10.  This
: particular "programmer" had never heard of a sparse matrix.  And to
: think, he was paid more that I was (then :-).

Of course, we have been writing programs using sparse matrices in
Fortran for years & years (e.g., Spice).  Linked lists are not
specific to C, and it is likely that one would want to use an
'array of indices' implementation rather than an 'absolute pointer'
implementation regardless of the language used.  As the header to
the Lawrence Livermore benchmark states:

	There is not now and there never will be a language in
	which it is the least difficult to write bad programs.
-- 
Larry Meadows @ FPS			...!tektronix!fpssun!lfm
					...!nosun!fpssun!lfm

jlg@lanl.gov (Jim Giles) (09/20/88)

From article <1530@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> char (*twodarray)[10];
> 	twodarray = malloc(10*sizeof(*twodarray));
> 	twodarray[9][5] = 'c';
> Satisfied?

No, I still like the Fortran 8x stuff better:

      ALLOCATABLE, CHARACTER::TWODARRAY(:,:)
      ...
      ALLOCATE (TWODARRAY(10,10))
      ...
      TWODARRAY(5,9) = 'c'

You are a died-in-the-wool C type and I suppose I could never convince
you that arrays and pointers are two separate and distinct concepts that
should each be used only when appropriate.  _Most_ uses of arrays (even
dynamically allocated ones) don't need explicit user-visable pointers
to function correctly.  Your declaration syntax above still contains a
lot of pointer related _junk_ that has nothing to do which what I want
to declare.

J. Giles
Los Alamos

link@stew.ssl.berkeley.edu (Richard Link) (09/20/88)

In article <3746@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>You are a died-in-the-wool C type 

I am NOT taking a position here regarding C vs FORTRAN in
numerical applications. One Friday night, after probably
too much beer, one of our systems programmers working on a
very complex satellite mission (he also has an MS in physics)
and I had a relatively incoherent discussion on the relative
merits of C and FORTRAN. We both remained unconvinced.

From experience, I suspect that comparing computer languages
is rather like comparing religions. One is either a true
believer or an infidel.

Having taught numerical analysis to senior physics students, let me
say that the choice of language is not all that important. I even
taught Algol for 2 years. However, the arguments against FORTRAN
ignore both its historical and contemporary importance.

Numerical analysis, for better or worse, is virtually synonymous with
FORTRAN. Very few IMPORTANT mathematical packages have been written
in other languages and then ported to FORTRAN; the opposite is the
rule - serious scientific programming is done in FORTRAN. Period.

The latter statement is not an opinion; it is a fact. Check the
available scientific libraries and compare the lines of code available
in C and FORTRAN.

I have yet to discover a single compelling reason to switch from FORTRAN
to C, other than "it's a more modern language". I am grateful for the fact
that I did not endeavour to learn PL/I or Pascal on this specious basis.
Both (!) are still taught at educational institutions I attended.

FORTRAN is a good number-crunching tool; it is not intended to be a good
systems development language such as C. But then C was not designed to
be a number cruncher.

Why don't we all save the bull on the net and try to use the most
appropriate tool for the problem at hand?

Dr. Richard Link
Space Sciences Laboratory
University of California, Berkeley
link@ssl.berkeley.edu

ok@quintus.uucp (Richard A. O'Keefe) (09/20/88)

In article <3746@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>No, I still like the Fortran 8x stuff better:
>      ALLOCATABLE, CHARACTER::TWODARRAY(:,:)
>      ...
>      ALLOCATE (TWODARRAY(10,10))
>      ...
>      TWODARRAY(5,9) = 'c'
>You are a died-in-the-wool C type and I suppose I could never convince
>you that arrays and pointers are two separate and distinct concepts that
>should each be used only when appropriate.

There is something here I don't understand.  I am not a DYED-in-the-wool
C type, so it is easy to convince me that arrays and pointers are two
separate and distinct concepts.  What I don't understand is why Giles
affirms this in one breath, and then in the next applauds a notation
which confuses the two.  If I declare a local array, I get an array,
there and then.  But that rather appalling declaration (this is _Fortran_?)
gives me a name which _looks_ like an array, but doesn't act like one:
if I try to use it before executing the allocate statement I'll end up
with an undefined reference (and that's a property of _pointers_), and
the allocate statement is _only_ applicable to pointers, not to ordinary
arrays.  The name TWODARRAY is used in *some* contexts to refer to the
pointer variable (allocate and free) and in *other* contexts to refer to
the thing pointed to.  "separate and distinct"?

peter@ficc.uu.net (Peter da Silva) (09/20/88)

In article <15145@ames.arc.nasa.gov>, lamaster@ames.arc.nasa.gov (Hugh LaMaster) writes:
> In article <1530@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
> >char (*twodarray)[10];

> >	twodarray = malloc(10*sizeof(*twodarray));

> >	twodarray[9][5] = 'c';

> >Satisfied?

> I think the point of dynamically sized arrays has been lost here.

Nah, it wasn't ever there. Jim's assertion was that he has never seen
dynamically allocated arrays in 'C' that matched the syntax and semantics
of statically allocated ones. Yes, conformant arrays are very nice. No,
'C' doesn't have them. However, the assertion that you can't allocate
an array without defining a bunch of pointers is demonstrably bunk.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

peter@ficc.uu.net (Peter da Silva) (09/20/88)

In article <3746@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1530@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > char (*twodarray)[10];
> > 	twodarray = malloc(10*sizeof(*twodarray));
> > 	twodarray[9][5] = 'c';
> > Satisfied?

> No, I still like the Fortran 8x stuff better:
  [ description and assertions that I'm a 'C' fanatic removed ]

Actually I don't much care for 'C's pointer syntax... a postfix syntax
like Pascal's is much cleaner and would get rid of all the nasty aspects
of 'C' declaration syntax. However, no matter how you want to hide it
when you allocate memory dynamically you're dealling with a pointer.

I don't much like the 'C' code I listed above. I much prefer:

> > char (*twodarray)[10][10];
> > 	twodarray = malloc(sizeof(*twodarray));
> > 	(*twodarray)[9][5] = 'c';

because there is a pointer. It is a pointer to a two dimentional array,
but it's a real live pointer. It doesn't matter whether you hide it in the
Fortran syntax or not, there is a cell somewhere that contains the address
of that array and every reference to that cell involves that indirection.

In my ideal syntax, it'd look like this:

> > char twodarray^[10][10];
> > 	twodarray = malloc(sizeof(twodarray^));
> > 	twodarray^[9][5] = 'c';

You can use anything you want for XOR. There are still a couple of spare
characters in 'C'.

> Your declaration syntax above still contains a
> lot of pointer related _junk_ that has nothing to do which what I want
> to declare.

But it has everything to do with what you're doing.

If you have a pointer, call it a pointer. If it's a pointer to an array,
hiding that in the declaration (as in your Fortran example, and as ADA
and PL/I do in their own way) just causes confusion somewhere down the
line.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

jlg@lanl.gov (Jim Giles) (09/21/88)

From article <447@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> In article <3746@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>>No, I still like the Fortran 8x stuff better:
>>      ALLOCATABLE, CHARACTER::TWODARRAY(:,:)
>>      ...
>>      ALLOCATE (TWODARRAY(10,10))
>>      ...
>>      TWODARRAY(5,9) = 'c'
> ...
> if I try to use it before executing the allocate statement I'll end up
> with an undefined reference (and that's a property of _pointers_), and
> the allocate statement is _only_ applicable to pointers, not to ordinary
> arrays.  The name TWODARRAY is used in *some* contexts to refer to the
> pointer variable (allocate and free) and in *other* contexts to refer to
> the thing pointed to.  "separate and distinct"?

This is the proposed syntax in Fortran 8x. Fortran 8x _HAD_NO_POINTERS_!!
So, rather obviously, the allocate statement is _NOT_ applicable to
pointers at all.  Further, TWODARRAY is an identifier.  Like _all_ 
identifiers, it has certain attributes (data type, dimensionality, 
SAVE/automatic, EXTERNAL/local/COMMON, etc.).  In the above example,
I gave a local array identifier two more attributes: allocatable and
uninitialized.  The allocate statement changed the second attribute
to initialized and added explicit sizes to the array attributes.  In
any case, TWODARRAY _always_ refers to an array.

The above doesn't confuse arrays and pointers - doesn't even mention
pointers.  It introduces a _new_ type of array - one that can be allocated
dynamically.  'Undefined reference' may be _a_ property of pointers, not not
a property exclusive to pointers!  Other things can be undefined at 
various times during the execution of a program.  Being represented as
a binary number is also a property of pointers - and everything else in
most machines.

Note: arrays and pointers _do_ have one thing in common - they can each
be implemented using the other.  I did dynamic memory in the early '70s
using an array (called MEM) located at the end of my memory image.  The
system had a call which allowed me to change field length (rather like
brk()).  I wrote routines which allocated and freed blocks of memory
within the MEM array and returned 'pointers' to me in the form of array
indices (rather like malloc() and free()).  To reference a dynamically
allocated array area I wrote 'MEM(A+I)' - if you think of 'MEM' as a '*',
'A' as a pointer and 'I' as an index, this is the exact same syntax as
C arrays/pointers.  I was dissatisfied with this 15 years ago, and I'm
not pleased with it in C now.  (By the way, this was the most common way
of doing dynamic memory in Fortran until about 8 years ago when most
large scientific programming installations managed to get pointers
installed in their Fortran compilers.)

J. Giles
Los Alamos

davis@galaxy.ee.rochester.edu (Al Davis) (09/21/88)

In article <14494@agate.BERKELEY.EDU> link@stew.ssl.berkeley.edu (Richard
Link) writes:
>Having taught numerical analysis to senior physics students, let me
>say that the choice of language is not all that important.

>Numerical analysis, for better or worse, is virtually synonymous with
>FORTRAN. Very few IMPORTANT mathematical packages have been written
>in other languages and then ported to FORTRAN; the opposite is the
>rule - serious scientific programming is done in FORTRAN. Period.
 
True, but why?  Numerical analysis is mostly done in FORTRAN for historical
reasons.  Once the research is done, the new methods are put to use.  While
FORTRAN may be adequate for the pure numerical problem, it is often not for
the complete problem to be solved using the new method.  A complete
application is more like system programming.  Even in programs that seem to
be mostly numerical, most of the code deals with user interface, i/o
processing, etc.  The same program must run on a minimal system, (example:
256k memory) and without recompiling support a loaded system (example:
megabytes of memory).  The same source must, without changes, work on an IBM
PC and a Cray.

>I have yet to discover a single compelling reason to switch from FORTRAN
>to C, other than "it's a more modern language". I am grateful for the fact
>that I did not endeavour to learn PL/I or Pascal on this specious basis.

If you don't know any other languages, how can you judge, never mind.

>Why don't we all save the bull on the net and try to use the most
>appropriate tool for the problem at hand?

Mixing languages is not portable.  C is a fair choice for many classes of
problems.  Fortran vs C for numerical analysis may be a religious argument
(if you consider the merits of structured programming a religious argument)
but when you cross the boundary, the choice is clear.

Here is a challenge: write a portable program that does LU decomposition of
a matrix of arbitrary size, in Fortran.  I believe it can't be done, in a
straightforward way.  (Read the input, do it, write the result)
Someone please prove me wrong.

Al Davis

jlg@lanl.gov (Jim Giles) (09/21/88)

From article <1553@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> In my ideal syntax, it'd look like this:
> 
>> > char twodarray^[10][10];
>> > 	twodarray = malloc(sizeof(twodarray^));
>> > 	twodarray^[9][5] = 'c';

Now, let's add an array syntax to this proposed language, shall we?

      char static_array [10][10]    // my declaration to compare with your
                                    // dynamic array.  (// is C++ for comment)

      char twodarray^[10][10];
         twodarray = malloc(sizeof(twodarray^)); // your array now exists.

Now let's use the array assignment:

      static_array = 'c';            // all 100 elements set to 'c'
      twodarray = 'c';               // whoops, just set the pointer instead!
//    I really meant
      twodarray^ = 'c';              // set 100 elements to 'c' at location 'c'

But now I have to know which type of allocation I am planning _before_
I write the body of the code!  Suppose I write the code with all static
arrays and then decide that I need to switch to dynamic arrays - your
syntax requires me to alter the whole program!  The proposed Fortran 8x
syntax only requires that I change the declarations and add the allocation
call.

Furthermore, suppose the _use_ of the array is not local to the declaration:

      set_array (array)
      char array []                // what syntax for passed in array?
      {  
         array = 'c'
      }

I could call set_array with either static_array or twodarray as an argument.
The compiler can't know which was which!

Your argument about there 'being a pointer there anyway' is wrong.  There
is a pointer for the statically declared array as well - it's just optimized
out during constant folding in the compile.  I only need the declaration
which explicitly includes a pointer if I plan to change the pointer in
ways other than through the ALLOCATE/DEALLOCATE sequence - something
I _rarely_ need to do and which I would prefer a different syntax entirely
just to remind me that pointers are dangerous like GOTO's are.

J. Giles
Los Alamos

ok@quintus.uucp (Richard A. O'Keefe) (09/21/88)

In article <3826@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>From article <447@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
>> In article <3746@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>>>No, I still like the Fortran 8x stuff better:
>>>      ALLOCATABLE, CHARACTER::TWODARRAY(:,:)
>>>      ...
>>>      ALLOCATE (TWODARRAY(10,10))
>>>      ...
>>>      TWODARRAY(5,9) = 'c'
>> ...
>> the allocate statement is _only_ applicable to pointers, not to ordinary
>> arrays.  The name TWODARRAY is used in *some* contexts to refer to the
>> pointer variable (allocate and free) and in *other* contexts to refer to
>> the thing pointed to.  "separate and distinct"?
>
>This is the proposed syntax in Fortran 8x. Fortran 8x _HAD_NO_POINTERS_!!
>So, rather obviously, the allocate statement is _NOT_ applicable to
>pointers at all.  Further, TWODARRAY is an identifier.

When I said "this is _Fortran_?" it was an exclamation of disgust at the
syntax.  I knew perfectly well that it was 8X, but 8X declarations are so
awful that they make PL/I look good.

Fortran 8X had pointers all right, it just didn't let you NAME them
unambiguously.  ``TWODARRAY'' is an identifier all right, but at compile
time it is associated with a pointer variable by the declaration, and at
run time that pointer variable is associated with an array by the allocate
statement.  To claim that TWODARRAY stands for an array simpliciter is to
accept the confusion between a pointer and an array.  Throughout the life-time
of an instance of TWODARRAY, several quite distinct arrays with distinguishable
properties (such as dimensions) may become associated with it, and at times
there may be no array at all.

Now the PL/I designers weren't stupid enough to REQUIRE this confusion, but
they were "generous" enough to ALLOW it.  In PL/I you can say
	DECLARE (TD_ONE, TD_TWO) FIXED;
	DECLARE TWODARRAY(1:TD_ONE,1:TD_TWO) CHARACTER CONTROLLED;

	TD_ONE, TD_TWO = 10;		/* define size of array */
	ALLOCATE(TWODARRAY);		/* allocate it */
	TWODARRAY(5,9) = 'c';		/* use it */
	FREE(TWODARRAY);		/* deallocate it*/
I should have thought that experience with PL/I would have convinced people
that concealing the pointer is a Bad Idea.

I'm reminded of one of Lincoln's jokes:
	Question: If you call a tail a leg, how many legs has a dog got?
	Answer:   Five.
	Riposte:  Wrong, _calling_ a tail a leg doesn't _make_ it one!

peter@ficc.uu.net (Peter da Silva) (09/21/88)

In article <3904@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1553@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > In my ideal syntax, it'd look like this:

> > char twodarray^[10][10];
> > 	twodarray = malloc(sizeof(twodarray^));
> > 	twodarray^[9][5] = 'c';

> Now, let's add an array syntax to this proposed language, shall we?

The proposed variant of 'C', at any rate.

>       char static_array [10][10]    // my declaration to compare with your
>                                     // dynamic array.  (// is C++ for comment)

>       char twodarray^[10][10];
>          twodarray = malloc(sizeof(twodarray^)); // your array now exists.

> Now let's use the array assignment:

>       static_array = 'c';            // all 100 elements set to 'c'
>       twodarray = 'c';               // whoops, just set the pointer instead!

Error 10 on line 357: Character/pointer conversion.

I don't care for your array assignment... if you want a loop, make it a loop.
One of the primary design goals of 'C' was to use operations that were close
to the fundamental machine operations. Thus no exponentiation, and no array
assignment.

> //    I really meant
>       twodarray^ = 'c';              // set 100 elements to 'c' at location 'c'

> Suppose I write the code with all static
> arrays and then decide that I need to switch to dynamic arrays - your
> syntax requires me to alter the whole program!

To quote you, just use a text editor. Or use the syntax I used earlier:

char twodarray^[10] = malloc(10*sizeof(twodarray^));

	twodarray[5][5];

> Furthermore, suppose the _use_ of the array is not local to the declaration:

>       set_array (array)
>       char array []                // what syntax for passed in array?

Depends on what you're passing. That syntax is fine.

>       {  
>          array = 'c'
>       }

> I could call set_array with either static_array or twodarray as an argument.
> The compiler can't know which was which!

Why should it care? You're passing a pointer to it anyway.

Have you ever played with VIRTUAL arrays in Fortran, and passed one to a
routine that's not expecting one?

> Your argument about there 'being a pointer there anyway' is wrong.  There
> is a pointer for the statically declared array as well - it's just optimized
> out during constant folding in the compile.

Nonesense. There is no cell containing the address of that array. It's just
the 'C' equivalent of an assembly language label.

'C' is lower level than Fortran. If that's a problem for you, by all means
don't use it. Nobody's forcing you to. All I'm saying is look at the
language on its own merits instead of asking why it isn't more like Fortran.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

lamaster@ames.arc.nasa.gov (Hugh LaMaster) (09/21/88)

In article <1552@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>In article <15145@ames.arc.nasa.gov>, lamaster@ames.arc.nasa.gov (Hugh LaMaster) writes:
>> I think the point of dynamically sized arrays has been lost here.
>
>Nah, it wasn't ever there. Jim's assertion was that he has never seen

>of statically allocated ones. Yes, conformant arrays are very nice. No,

I guess I lost the thread of the argument in all the postings!  Sorry about 
that.

While we are on the subject though, I find that lack of conformant arrays is
probably the only real stumbling block to using C for numerical analysis.
But, it is a MAJOR stumbling block.  Fortran is the language of numerical
analysis today.  Since it is so similar to C, it might be nice to use a
single language for most things.  But right now, there is no way to write
precompiled libraries which handle multi-dimensional arrays in a 
CONSISTENT way (some have suggested that the "standard" has now been set
by "Numerical Recipes" - maybe so...  ) defined in the language itself.

And, in any case, using an array of pointers when you just mean a
multi-dimensional array is introducing a lot of error-prone machinery
for such a simple idea; most numerical analysts balk at such unnecessary
complication.

Another possible stumbling block is optimization.  I believe that, once
C gets dynamically sized arrays, and people start using it for numerical
analysis, vendors will start putting "go ahead and ignore possible
aliasing problems" switches on compilers, thus opening up another whole
can of worms.  On fast vector machines, the payoff CAN be a factor 30 for
a code that vectorizes well.


-- 
  Hugh LaMaster, m/s 233-9,  UUCP ames!lamaster
  NASA Ames Research Center  ARPA lamaster@ames.arc.nasa.gov
  Moffett Field, CA 94035     
  Phone:  (415)694-6117       

mike@arizona.edu (Mike Coffin) (09/22/88)

From article <3746@lanl.gov>, by jlg@lanl.gov (Jim Giles):
> No, I still like the Fortran 8x stuff better:
> 
>       ALLOCATABLE, CHARACTER::TWODARRAY(:,:)
>       ...
>       ALLOCATE (TWODARRAY(10,10))
>       ...
>       TWODARRAY(5,9) = 'c'
> 

This seems ugly to me, for several reasons.

(1) If FORTRAN ever gets pointers, there will presumably be two
    entirely separate ways of allocating arrays --- ALLOCATE and
    new/release, or alloc/dealloc, or whatever they're called.
    They will both do essentially the same thing; only the syntax will
    be different.
(2) Although the above manages (barely) to avoid introducing pointers,
    it suffers from almost all the problems that pointers have.  You
    cannot easily tell if TWODARRAY is "attached" (oops; I almost
    slipped and said "points to") to a real array, and if so what the
    dimensions are.  Moreover, the dimensions can potentially be
    specified in many places; thus you have to trace the execution
    path to determine what the current bounds are.
(3) Since the array associated with TWODARRAY does not follow the
    normal scope rules, ALLOCATE must use a very general allocation
    scheme --- something along the lines of C's malloc().
    For instance, the array cannot be allocated on the stack,
    since the current stack frame may disappear before the array is
    deallocated. 
(4) There is a much cleaner way to do this.  Allow declarations
    wherever there are statements, and allow arrays to be declared with
    general expressions as bounds.  E.g., in SR we can say

	var a, b: int
	read(a,b)
	var twodarray[1:a, 1:b]: char

    The declaration remains in effect until the end of the block where
    it is declared.  Twodarray *is* an array anywhere it is visible.
    The bounds can be determined by looking at the declaration.  On
    most machines, it can be allocated by adjusting the stack pointer,
    since the array disappears when the current block does.  (Of
    course, if the bounds are constant, it is allocated statically.)

    And finally, if you really need to declare arrays that don't
    follow normal scope rules, you use pointers and new/release.
    Thus there is one way to get objects that follow normal scope
    rules (declarations)  and one way to get objects with
    indefinite life-times (new/release).  The need for arrays that
    don't follow normal scope rules is rare, and the explicit pointers
    remind you of the possible problems.  
-- 
Mike Coffin				mike@arizona.edu
Univ. of Ariz. Dept. of Comp. Sci.	{allegra,cmcl2,ihnp4}!arizona!mike
Tucson, AZ  85721			(602)621-2858

jlg@lanl.gov (Jim Giles) (09/22/88)

From article <1475@valhalla.ee.rochester.edu>, by davis@galaxy.ee.rochester.edu (Al Davis):
> Here is a challenge: write a portable program that does LU decomposition of
> a matrix of arbitrary size, in Fortran.  I believe it can't be done, in a
> straightforward way.  (Read the input, do it, write the result)
> Someone please prove me wrong.

We have a Monte-Carlo particle code that uses dynamic memory.  It is entirely
written in standard Fortran except for the two routines that actually
allocate and free the dynamic memory.  The code has been ported to IBM,
DEC, CDC, and Cray mainframes as well as several other machines.  The
portability problems are limited to differences in file naming conventions
on the various systems and to numerical differences in the hardware.  These
problems would effect porting a code written in _any_ language.

Please note that the C dynamic memory routines _also_ can't be written 
entirely in C.  At some point a call to the system to change the program's
field length (or other memory mapping strategy) must be used.  On any
given system, brk() is usually written in assembly or at least has some
in-line assembly code.

J. Giles
Los Alamos

davis@galaxy.ee.rochester.edu (Al Davis) (09/22/88)

I said...
>> Here is a challenge: write a portable program that does LU decomposition of
>> a matrix of arbitrary size, in Fortran.  I believe it can't be done, in a
>> straightforward way.  (Read the input, do it, write the result)
>> Someone please prove me wrong.

In article <3963@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>We have a Monte-Carlo particle code that uses dynamic memory.  It is entirely
>written in standard Fortran except for the two routines that actually
>allocate and free the dynamic memory.

Well, then it is not portable.

>portability problems are limited to differences in file naming conventions
>on the various systems and to numerical differences in the hardware.  These
>problems would effect porting a code written in _any_ language.

They could, but they don't have to.  In my example, use stdin and stdout.
It is bad practice to hard code file names in any system.  I didn't say
anything about precision.  The machine default is fine, so numerical
differences are not an issue for such a simple problem.

>Please note that the C dynamic memory routines _also_ can't be written 
>entirely in C.

I don't care.  malloc exists as a part of the library supplied with every C
compiler, except for a few joke versions.  Portable Fortran has no
counterpart.  You are allowed to use the standard library.

Do you accept the challenge?  I still don't think you can do it.

Al Davis

jlg@lanl.gov (Jim Giles) (09/23/88)

From article <1565@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
>> Your argument about there 'being a pointer there anyway' is wrong.  There
>> is a pointer for the statically declared array as well - it's just optimized
>> out during constant folding in the compile.
> 
> Nonesense. There is no cell containing the address of that array. It's just
> the 'C' equivalent of an assembly language label.

YES, there _IS_ a cell containing the address of the array.  It is an
immediate constant imbedded in the instructions of the code.  All data
objects have an address.  If, as you claim, we need explicit names
for the addresses of _some_ data objects, then we should have such
names for the addresses of _all_ data objects - there's such a thing
as orthogonality.

You still haven't addressed the _central_ point - _NOBODY_CARES_ where 
the array is located once it has been allocated!  For the _vast_ majority 
of the code an array is an array is an array is an....  User's have no 
more need for an explicit handle on the address of a dynamic array than 
they do for a static one.  The _only_ difference is (and should be) 
the declaration.

J. Giles
Los Alamos

jlg@lanl.gov (Jim Giles) (09/23/88)

From article <1483@valhalla.ee.rochester.edu>, by davis@galaxy.ee.rochester.edu (Al Davis):
> Well, then it is not portable.

It's portable enough.  It has never failed to be implemented on a
machine to which the port has been attempted.  If IBM, Cray, CDC, DEC,
SUN, Apollo, etc.... aren't portable enough for you, well just forget it.

Also, you comment that malloc is a standard part of the C library is
nonsense.  C has _no_ standard library yet.  Besides, _sombody_ has to
port the library to each machine.  If dynamic memory _can_ be ported to 
a machine, then it can be made Fortran callable.  If it can't, C can't
ported either.  Both languages are equivalent to universal Turing 
machines (without the infinite tape).

Here's a challange for you.  Port all the C utilities in UNIX system V
to some machine which is not-at-all similar to a VAX.  I know people
who have just done this.  Their Fortran code ported without a hitch, the
C code had all sorts of problems.  Fortran programmers seldom make
assumptions about wordsize, addressability, etc..  C programmers nearly
always make such assumptions.  (I hear that YACC has a reference to 
x[-1] in it somewhere - illegal, but oft used.)

J. Giles
Los Alamos

hjm@cernvax.UUCP (Hubert Matthews) (09/23/88)

In article <1475@valhalla.ee.rochester.edu> davis@ee.rochester.edu (Al Davis) writes:
>
>In article <14494@agate.BERKELEY.EDU> link@stew.ssl.berkeley.edu (Richard
>Here is a challenge: write a portable program that does LU decomposition of
>a matrix of arbitrary size, in Fortran.  I believe it can't be done, in a
>straightforward way.  (Read the input, do it, write the result)
>Someone please prove me wrong.
>
>Al Davis

If you wish to be really precise, then you can't do anything in C portably
as there is no I/O in the language, never mind memory allocation.  You have
to call a library function called malloc() to get memory, just like any
F77 programmer has to do.  You also have to call library functions to do
I/O; printf was designed to imitate FORTRANs formatted I/O.  You have to
call library functions to do most things in C.  Therein lies a portability
problem.  If it's in the language, then it will be there.  If it's not, then
you just have to hope.  If it's printf or malloc, you'll probably be lucky.

OK, so to make the contest into a contest (without libraries you lose) we'll
allow standard libraries.  You take <stdio.h> and I'll take the NAG library.
<stdio.h> is available on almost all machines with a C compiler.  NAG is
available on almost all machines with a FORTRAN compiler for people interested
in numerical work, so that's obviously fair.  You can't use it, as mixed
language programming is very non-portable, just as I can't use <stdio.h> or
malloc.  So, here's an outline of my program:

      PROGRAM MINE
      CALL GETSIZ(M,N)
C  non-portable, system specific memory allocator
      CALL GETMEM(M*N,IPTR)
      CALL RDMTRX(IPTR)
C  enormous cheat.  Call the NAG library routine to do LU decomposition
      CALL F01LBF(IPTR,M,N,some_other_parameters......)
      CALL PRNTLU(IPTR)
      STOP '5 minutes work'
      END

"But, you can't cheat like that", I hear you say.  You allowed standard
libraries, and the NAG library has been available on every machine I've
ever used for numerical work, so I'm going to use the tools available.
You take away my NAG, and I'll take away your stdio, malloc, read, printf,
and anything else that K&R didn't declare as part of C itself.

Let's see how much code you have to write to do an LU decomposition.  Let's
see how long it takes you to get it right.  (Your rules, not mine.)

	Hubert Matthews
-- 

	Hubert Matthews

peter@ficc.uu.net (Peter da Silva) (09/23/88)

In article <4028@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1565@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > Nonesense. There is no cell containing the address of that array. It's just
> > the 'C' equivalent of an assembly language label.
> 
> YES, there _IS_ a cell containing the address of the array.  It is an
> immediate constant imbedded in the instructions of the code.

A constant that's in lots of different places, maybe in different formats,
maybe only part of a cell, not something that you can get a handle on
(say, for example, if you need to expand the array by copying it to a
larger version without disturbing the code).

> If, as you claim, we need explicit names
> for the addresses of _some_ data objects, then we should have such
> names for the addresses of _all_ data objects - there's such a thing
> as orthogonality.

Well it would be nice. BCPL tried this. I think you would find that
the overhead would be unreasonably high... there are a lot of optimisations
that you would no longer be able to do. You can't do these optimisations
on a dynamically allocated object without self-modifying code, so it makes
sense to have a pointer.

The pointer gives you all sorts of convenient features, and doesn't cost
anything. Why not make it explicit?

I thought, originally, that you were opposed to the idea of the dope vector
in 'C'. Now you seem to have expanded this to all pointers. What, if you
will pardon the pun, is the point in all this?
> 
> You still haven't addressed the _central_ point - _NOBODY_CARES_ where 
> the array is located once it has been allocated!  For the _vast_ majority 
> of the code an array is an array is an array is an....  User's have no 
> more need for an explicit handle on the address of a dynamic array than 
> they do for a static one.  The _only_ difference is (and should be) 
> the declaration.
> 
> J. Giles
> Los Alamos


-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

warner@hydrovax.nmt.edu (M. Warner Losh) (09/24/88)

In article <4031@lanl.gov>, jlg@lanl.gov (Jim Giles) writes...
>(I hear that YACC has a reference to 
>x[-1] in it somewhere - illegal, but oft used.)

YACC does have this reference, sort of.  As I recall from the generated code,
it is used in two places.  Once is an initialization (a lot of stuff is
pre increment).  This usage is dubious at best.  The other place is where 
it addresses the previous thing in some array, which is cool by anyone's
definition of C.  eg

	x = &y[10];
	x[-1] = 3;

(or some such garbage).

So what Jim is saying is correct, but people generally don't try to port 
the C code generated by YACC.  They just run the .y file through YACC on 
the target machine (which we surely can assume will work).

>J. Giles
>Los Alamos
--
Warner Losh
warner@hydrovax.nmt.edu		...!unmvax!nmtsun!warner%hydrovax
Insert quote here.  A nice cure little quote.
My spelling and views are my own.  Only the letters have been changed...

jlg@lanl.gov (Jim Giles) (09/25/88)

From article <1584@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> The pointer gives you all sorts of convenient features, and doesn't cost
> anything. Why not make it explicit?

It may not cost YOU anything, but I can think of at least 2 things it
_can_ cost me (I could probably think of more, but it's Saturday and
who wants to do too much of this stuff on a Saturday?):

1) It rasies the spectre of aliasing in contexts where it doesn't exist
   if the pointer isn't user accessible.  For this reason, things that
   would otherwise vectorize or unroll for pipelining must be done by
   the compiler as if the possible aliasing has actually occurred.

2) It clutters up it's scope with the name of something I don't need
   explicit access to.  This increases the possibility of another
   variable, whose name is misspelled, going undetected.  This is always
   possible, but the more names there are in the local scope, the more
   likely it becomes.  Why introduce a name you have no need for?

If I don't need any of those 'convenient features' you mentioned, why
should I make the pointer explicit?  My position has always been that
n explicit pointer should only be introduced if there's no other way
for your language to provide some needed 'convenient feature'.  For
future design of Fortran (and even C) I would recommend that explicit
ways of providing these 'convenient features' be included which _don't_
use pointers.

J. Giles
Los Alamos

ok@quintus.uucp (Richard A. O'Keefe) (09/25/88)

In article <834@cernvax.UUCP> hjm@cernvax.UUCP (Hubert Matthews) writes:
>OK, so to make the contest into a contest (without libraries you lose) we'll
>allow standard libraries.  You take <stdio.h> and I'll take the NAG library.
><stdio.h> is available on almost all machines with a C compiler.  NAG is
>available on almost all machines with a FORTRAN compiler for people interested
>in numerical work, so that's obviously fair.

This is _not_ a fair comparison.  malloc(), printf(), and other things are
part of the draft ANSI C standard, and have been four the last four years to
my own knowledge and probably longer.  A "hosted" version of C which does
not provide printf() will _not_ be standard, and people have known this for
years.  malloc() is no more a "library" function in C than SIN() is a
"library" function in Fortran.    If you buy a Fortran compiler, you do not
normally get a copy of the NAG library; you have to go to a different
company and pay them more money.  Furthermore, there are competing numerical
libraries:  some people might use NAG, some might use IMSL, some might use
PORT, some might pick things up from netlib, ...   There are no well-known
libraries competing with the stdio interface.

--
I may not understand what you say,
but I will defend to the death my right to deny it	- Walt Kelly

peter@ficc.uu.net (Peter da Silva) (09/26/88)

In article <4151@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> 1) It rasies the spectre of aliasing in contexts where it doesn't exist
>    if the pointer isn't user accessible.  For this reason, things that
>    would otherwise vectorize or unroll for pipelining must be done by
>    the compiler as if the possible aliasing has actually occurred.

You use Fortran and you complain about aliasing? What about common blocks,
call-by-reference to constants, equivalence, and all the other horrible
places that Fortran can bite you on aliasing. Even *without* worrying
about optimisation.

> 2) It clutters up it's scope with the name of something I don't need
>    explicit access to.  This increases the possibility of another
>    variable, whose name is misspelled, going undetected.

You use Fortran and you complain about misspellings going undetected? This
language has more of a problem with typos than any other just because of
implicit typing of variables. I think that this 'feature' of Fortran by itself,
counts far more against it than *anything* you can call up against C.

I said before I wasn't going to have a battle of wits with an unarmed man. I'm
afraid I lied.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

hirchert@uxe.cso.uiuc.edu (09/28/88)

Peter da Silva (peter@ficc.uu.net) writes:
>In article <4151@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
>> 1) It rasies the spectre of aliasing in contexts where it doesn't exist
>>    if the pointer isn't user accessible.  For this reason, things that
>>    would otherwise vectorize or unroll for pipelining must be done by
>>    the compiler as if the possible aliasing has actually occurred.

>You use Fortran and you complain about aliasing? What about common blocks,
>call-by-reference to constants, equivalence, and all the other horrible
>places that Fortran can bite you on aliasing. Even *without* worrying
>about optimisation.

FORTRAN doesn't mandate call-by-reference to constants and other expressions,
but even when this implementation technique is used, it does not cause problems
for correct programs, and it is not a barrier to optimization.  (I also have
never before seen the term "aliasing" used to describe this situation.)  Using
common blocks can create multiple names for the same object, but since these
different names are in different scopes that are typically compiled separately,
this is not normally a performance problem (or referred to as "aliasing").  If
you happen to have a compiler that does cross-procedural analysis (just
beginning to become popular in the FORTRAN world), then the compiler might
"see" both names at one time, in which case the effect is essentially the same
as equivalence.  Equivalence does create multiple names for an object, but since
this effect is static, it can be analyzed by the compiler so that no more
performance degradation takes place that would have occurred if a single name
had been used at each reference.  (Although this is aliasing in the English
language sense, this is not what is usually meant by "aliasing" when discussing
compilation problems.)  In the context of performance and compilation
discussions I have encountered, "aliasing" means dynamic aliasing, i.e.
run-time behavior that causes two or more names to identify the same object.
In order to insure correct behavior, a compiler may have to forgo optimizing
transformations because of the _possibility_ that two names might identify
the same object.  To the extent that this possibility is not realized, this
is an unnecessary loss in performance and considered a problem.  One of the
reasons FORTRAN so frequently outperforms C and other "modern" languages on
computationally intensive benchmarks is that FORTRAN is largely free of
"aliasing" in this sense and thus suffers fewer unnecessary performance losses.

>> 2) It clutters up it's scope with the name of something I don't need
>>    explicit access to.  This increases the possibility of another
>>    variable, whose name is misspelled, going undetected.

>You use Fortran and you complain about misspellings going undetected? This
>language has more of a problem with typos than any other just because of
>implicit typing of variables. I think that this 'feature' of Fortran by itself,
>counts far more against it than *anything* you can call up against C.

Other things being equal, variable "clutter" increases the chances of undetected
typos.  Implicit typing increases this possibility far more, but most FORTRAN
programmers who care about this that I know of either use IMPLICIT NONE (on
machines where it is available) or simulate the effects of IMPLICIT NONE with
either IMPLICIT LOGICAL(A-Z) or IMPLICIT COMPLEX(A-Z)  (or better still, by
alternating between these two on successive compilations).

>Peter da Silva  `-_-'  Ferranti International Controls Corporation.

Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications