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

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (08/30/88)

I am looking for opinions of experienced
numerical/scientific/engineering programmers along the lines of why
Fortran is a better language than C for numerical analysis.

Actually, I'll take any opinions at all as a starting point.

I'm particularly interested in hearing from people who have actually
attempted significant (your definition) implementations in C and gone
back to Fortran, and from people who are just simply unwilling to use
C at all.

Reply to me, and I'll sumarize if there is enough interest:

fouts@lemming.nas.nasa.gov

..!ames!orville!fouts
+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

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

From article <893@amelia.nas.nasa.gov>, by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):
> I am looking for opinions of experienced
> numerical/scientific/engineering programmers along the lines of why
> Fortran is a better language than C for numerical analysis.

The fact that C parenthesis don't force execution order is sufficient
to exclude C from use in some instances.  The suggestion has been made 
to force execution order by introducing more temporary variables, but
this costs time (to store the variables), space (for the variables),
and/or additional compiler complexity (to recognize that the variables
are temporaries).  A really 'smart' compiler might even optimize out
temporary variables and then reorder the execution.  

At any rate, the ability to force a particular order of expression
evaluation is sometimes VERY important.  It is often important in a 
time-critical part of the code (so extra temporaries are 'out').
The lack of SOME mechanism to do this is a deficiency in C.  (Note:
I don't maintain that significant parenthesis is the ONLY or even the
BEST way, but to have NO WAY is certainly bad.)

J. Giles
Los Alamos

samperi@djs.UUCP (Dominick Samperi) (09/01/88)

In article <3064@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
|The fact that C parenthesis don't force execution order is sufficient
|to exclude C from use [for numerical analysis] in some instances.
|J. Giles
|Los Alamos

This is no longer true for the draft-proposed ANSI C standard (which 
should be adopted shortly). The following is taken from the second 
edition of Kernighan and Ritchie's text on C (Page 260):

o A compiler's license to treat mathematically associative operators
  as computationally associative is revoked [in the new standard]. 

Other features of the new standard that may be of interest are:

o All floating point values are no longer automatically converted to
  double in expressions; instead, values are promoted, if necessary,
  to the smallest capacious-enough type.

o The notion of a "function prototype" is introduced. It permits the
  programmer to declare the data type of function formal parameters 
  in a way that enables the compiler to check the actual parameters
  in each invocation of the function for type consistency.

o The Standard places explicit minima on the ranges of the arithmetic
  types, and mandates headers (<limits.h> and <float.h>) giving the
  characteristics of each particular implementation.

o The minimum significance of all internal identifiers is increased to
  31 characters (but the smallest mandated significance of external
  identifiers - names of FORTRAN subroutines, for example - remains at 6
  monocase letters).
-- 
Dominick Samperi
    samperi@acf8.nyu.edu             uunet!hombre!samperi
    cmcl2!acf8!samperi               rutgers!acf8.nyu.edu!samperi
      (^ ell)

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

In article <3064@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>The fact that C parentheses don't force execution order is sufficient
>to exclude C from use in some instances.

Fortran's kludge of using () to control evaluation order (which means that
it has no way of expressing plain grouping *without* forcing evaluation
order) has been adopted in the draft ANSI C standard, so this should cease
to be a problem.

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

From article <338@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> Fortran's kludge of using () to control evaluation order (which means that
> it has no way of expressing plain grouping *without* forcing evaluation
> order) has been adopted in the draft ANSI C standard, so this should cease
> to be a problem.

It was proposed in a previous draft.  Significant parenthesis has more
recently been excluded again.  (If it has been included yet again, I 
haven't heard yet - the committee seems about evenly split on this.)

J. Giles
Los Alamos

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

From article <177@djs.UUCP>, by samperi@djs.UUCP (Dominick Samperi):
> o A compiler's license to treat mathematically associative operators
>   as computationally associative is revoked [in the new standard]. 

This is MORE restrictive than the significant parenthesis of Fortran.
The main complaint against Fortran was that it restricted optimization
too much.  I haven't seen this in any of the ANSI draft standards yet.
I hope I won't.

J. Giles
Los Alamos

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

In article <338@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>In article <3064@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>>The fact that C parentheses don't force execution order is sufficient
>>to exclude C from use in some instances.
>
>Fortran's kludge of using () to control evaluation order (which means that
>it has no way of expressing plain grouping *without* forcing evaluation
>order) has been adopted in the draft ANSI C standard, so this should cease
>to be a problem.

On the contrary, Fortran's parentheses control only grouping and have
nothing to do with evaluation order.  Consider the statement

	Y = A(X) + (B(X) + C(X))

where A, B and C are external functions.  There are 3! = 6 possible orders
of evaluation for the three functions.  All six of them are legal in
Fortran.  For example, a perfectly legal code sequence would be the
following:

	1. Evaluate C(X) and place the result in a temporary, t1.
	2. Evaluate A(X) and place the result in a temporary, t2.
	3. Evaluate B(X) and place the result in a temporary, t3.
	4. Add t3 to t2 and place the result in t3.
	5. Add t3 to t1 and store the result in Y.


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

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

In article <3118@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>From article <177@djs.UUCP>, by samperi@djs.UUCP (Dominick Samperi):
>> o A compiler's license to treat mathematically associative operators
>>   as computationally associative is revoked [in the new standard]. 

>This is MORE restrictive than the significant parenthesis of Fortran.
>The main complaint against Fortran was that it restricted optimization
>too much.  I haven't seen this in any of the ANSI draft standards yet.
>I hope I won't.

I am puzzles by this.  After close reading of the standard, I don't see
how it is possible.  Can you give an example of a Fortran expression that
illustrates your claim that Fortran can treat mathematically associative
operators as computationally associative?

While you are at it, can you name a language that does less to inhibit
optimization than Fortran?  Fortran is the only language I know that
prohibits modifying aliased subroutine arguments, as in

	REAL A(10)
	CALL SUB(A,A,10)
	 . . .
	SUBROUTINE SUB(X,Y,N)
	REAL X(N), Y(N)
	DO 10 I=1,N
	  T = ...something or other...
	  Y(I) = T**2
	  X(I) = T
     10 CONTINUE
	END

Without this prohibition, optimization would be very difficult, as has been
discussed in this group before.

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

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

In article <3534@s.cc.purdue.edu> ags@s.cc.purdue.edu.UUCP (Dave Seaman) writes:
>In article <338@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>[I said it badly, so I shan't quote it]
>On the contrary, Fortran's parentheses control only grouping and have
>nothing to do with evaluation order.

Oops, sorry, expressed myself badly.  When writing "evaluator order"
I had in mind evaluate of _operators_, not of _operands_.

What I meant was that there is no method of saying "this grouping is
just syntactic so that I can read the expression, mathematical laws may
be applied".  The point is that some expressions can't be written
without using parens, and there is no way of distinguishing those parens
from ones that you *want* to have the special effect.  For example,
unless I am mistaken, (1.0+X)*2.0 must be evaluated that way rather than
as 2.0+2.0*X. Sometimes you care, but sometimes you don't. In this
particular example, unless you want to do part of the calculation
yourself, you have to put the parens in to get around the operator
priorities.  If, however, I write 2*I+2, the compiler *is* free to
rearrange this as 2*(I+1).  Isn't it?

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

From article <3534@s.cc.purdue.edu>, by ags@s.cc.purdue.edu (Dave Seaman):
> 
> On the contrary, Fortran's parentheses control only grouping and have
> nothing to do with evaluation order.  Consider the statement
> 
> 	Y = A(X) + (B(X) + C(X))
> 
> where A, B and C are external functions.  There are 3! = 6 possible orders
> of evaluation for the three functions.  All six of them are legal in
> Fortran.  For example, a perfectly legal code sequence would be the
> following:
> 
> 	1. Evaluate C(X) and place the result in a temporary, t1.
> 	2. Evaluate A(X) and place the result in a temporary, t2.
> 	3. Evaluate B(X) and place the result in a temporary, t3.
> 	4. Add t3 to t2 and place the result in t3.
> 	5. Add t3 to t1 and store the result in Y.

This is simply _not_ true.  Read the standard before claiming things
like this.  ANSI X3.9-1978 FORTRAN 77, page 6-18, line 30:
   
    In addition to the parenthesis required to establish the
    desired interpretation, parenthesis may be included to
    restrict the alternative form that may be used by the
    processor in the actual evaluation of the expression. This
    is useful for controlling the magnitude and accuracy of
    intermediate values developed during the evaluation of an
    expression.  For example, in the expression

              A+(B-C)

    the term (B-C) must be evaluated and then added to A. [...]

This seems pretty clear.  To be sure, the three function calls in your
example can be evaluated in any order.  But, the result of functions
B and C _must_ be added first, then added to the result of function A.

J. Giles
Los Alamos

fpst@hubcap.UUCP (Steve Stevenson) (09/03/88)

From article <344@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> 
> What I meant was that there is no method of saying "this grouping is
> just syntactic so that I can read the expression, mathematical laws may
> be applied".


I'm afraid that "mathematical laws" are not numerical laws.
You are not free to premute and mess with expressions because the
programmer is taking great pains to keep numerical error right where
he or she wants it.  Minimal coding and slick optimization which
produces a wrong answer for the physicist (or some )*_*&*() SDI type)
won't do you any good.
-- 
Steve Stevenson                            fpst@hubcap.clemson.edu
(aka D. E. Stevenson),                     fpst@prism.clemson.csnet
Department of Computer Science,            comp.parallel
Clemson University, Clemson, SC 29634-1906 (803)656-5880.mabell

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

From article <3535@s.cc.purdue.edu>, by ags@s.cc.purdue.edu (Dave Seaman):
>>This is MORE restrictive than the significant parenthesis of Fortran.
>>The main complaint against Fortran was that it restricted optimization
>>too much.  I haven't seen this in any of the ANSI draft standards yet.
>>I hope I won't.
> 
> I am puzzles by this.  After close reading of the standard, I don't see
> how it is possible.  Can you give an example of a Fortran expression that
> illustrates your claim that Fortran can treat mathematically associative
> operators as computationally associative?

You almost gave one yourself.  The expression A+B+C may be evaluated 
as (A+B)+C, A+(B+C), or (A+C)+B.  Fortran is free to do the calculation
in any of those orders.  But, if the original expression had been
parenthesised, the order would have been required.  The only associative
optimization that is explicitly prohibited by the standard is violating
parenthesis integrity (ANSI X3.9-1978, section 6.6.3).  The processor
is therefore free to do other optimizations (ANSI X3.9-1978, section 1.4).

J. Giles
Los Alamos

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

In article <3534@s.cc.purdue.edu> I write:
>	1. Evaluate C(X) and place the result in a temporary, t1.
>	2. Evaluate A(X) and place the result in a temporary, t2.
>	3. Evaluate B(X) and place the result in a temporary, t3.
>	4. Add t3 to t2 and place the result in t3.
>	5. Add t3 to t1 and store the result in Y.

I misspoke myself in steps 4 and 5.  I didn't mean to imply that Fortran
was free to ignore the parentheses entirely, only that the terms could be
evaluated in any order.  Because of the parentheses in the original
expression, steps 4 and 5 need to be changed to:

	4. Add t1 and t3 and place the result in t3.
	5. Add t3 and t2 and store the result in Y.


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

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

From article <344@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> What I meant was that there is no method of saying "this grouping is
> just syntactic so that I can read the expression, mathematical laws may
> be applied".  The point is that some expressions can't be written
> without using parens, and there is no way of distinguishing those parens
> from ones that you *want* to have the special effect.  For example,
> unless I am mistaken, (1.0+X)*2.0 must be evaluated that way rather than
> as 2.0+2.0*X. Sometimes you care, but sometimes you don't.

This is what I meant when I said that parenthesis aren't necessarily
the _best_ way of doing this.  But _some_ method is needed.  In this
respect, Fortran beats C.

> [...]                                                       In This
> particular example, unless you want to do part of the calculation
> yourself, you have to put the parens in to get around the operator
> priorities.  If, however, I write 2*I+2, the compiler *is* free to
> rearrange this as 2*(I+1).  Isn't it?

YES!  Fortran _can_ optimize using the distributive rule in reverse.
Maybe what's needed is a new syntax which specifies meaning without
forcing order.  How about {A+B}*C, which the compiler would be allowed 
to implement as A*C+B*C.

J. Giles
Los Alamos

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

In article <2932@hubcap.UUCP> fpst@hubcap.UUCP (Steve Stevenson) writes:
>From article <344@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
>> What I meant was that there is no method of saying "this grouping is
>> just syntactic so that I can read the expression, mathematical laws may
>> be applied".
>
>I'm afraid that "mathematical laws" are not numerical laws.
>You are not free to permute and mess with expressions because the
>programmer is taking great pains to keep numerical error right where
>he or she wants it.

I know perfectly well that computer arithmetic doesn't follow the usual
laws of algebra.  *IF* I have taken great pains to control numerical
error, then yes indeed I want it done the way I wrote it.  But in that
case, it is quite likely that I have given the individual parts of the
expression names so that I could say things about their error bounds in
my proof that this was the right way to compute the expression...

But it is not the case that all Fortran code is written by, or with the
aid of, numerical analysts.  I haven't seen a great deal of Fortran
code, but apart from statistical packages, most of the Fortran programs
I've seen were written by physicists.  Their Fortran expressions were
derived from mathematical expressions which *DID* obey the standard
algebraic laws.  They had enough trouble translating their formulas
into a weirdly limited character set, so the better ones coded their
formulas with desk-checking in mind, _not_ numerical analysis.  Now, if
your floating point instructions signal overflow *and* underflow (and
inexact if you've got it), and if you have well-written library packages,
it's ok for the compiler to rearrange the expressions to its convenience
because the programmer didn't have a particular arrangement in mind.

I am not alleging that the programmer *never* has a particular arrangement
in mind, only that *some* expressions are carefully ordered and *some* are
not, and "(A+B)+C -because-it-must-be-done-that-way-for-numerical-reasons"
and "(A+B)+C -because-that's-the-way-Thingy's-paper-wrote-the-original-
formula" are different things that deserve different notation.

Ideally, of course, we would have a language where the compiler could be
given information about the range of variables and the criterion it would
optimise in compiler-has-a-free-hand expressions would be numerical
accuracy.  Alternatively, some sort of preprocessor which points out
possible numerical problems and suggests improvements?  It seems to me
that even something fairly simpleminded might at least provide a useful
place to start.

samperi@djs.UUCP (Dominick Samperi) (09/03/88)

In article <3183@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
|The expression A+B+C may be evaluated as (A+B)+C, A+(B+C), or (A+C)+B.
|Fortran is free to do the calculation in any of those orders.  
|J. Giles
|Los Alamos

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?

I also checked into the aliasing example that was mentioned recently in
this group, and the compilers I used could not detect that I was modifying
the same array by two different aliases. Since rules like "functions may not
have side effects that affect the result of expression evaluation" usually
cannot be enforced by the compiler, they might more properly be called
programming guidelines.
-- 
Dominick Samperi
    samperi@acf8.nyu.edu             uunet!hombre!samperi
    cmcl2!acf8!samperi               rutgers!acf8.nyu.edu!samperi
      (^ ell)

ags@s.cc.purdue.edu (Dave Seaman) (09/04/88)

In article <3183@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
 [I asked for an example of Fortran using associativity legally]
>You almost gave one yourself.  The expression A+B+C may be evaluated 
>as (A+B)+C, A+(B+C), or (A+C)+B.  Fortran is free to do the calculation
>in any of those orders.  

Well, ok, that's technically an application of associativity, but it's not
exactly what I had in mind.  The only reason you are allowed to write
A+B+C in the first place, rather than (A+B)+C or A+(B+C), is that you are
assuming associativity and therefore you are telling the compiler that it
doesn't matter.

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

fpst@hubcap.UUCP (Steve Stevenson) (09/05/88)

From article <349@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> In article <2932@hubcap.UUCP> fpst@hubcap.UUCP (Steve Stevenson) writes:
>>From article <344@quintus.UUCP>, by ok@quintus.uucp (Richard A. O'Keefe):
> But it is not the case that all Fortran code is written by, or with the
> aid of, numerical analysts.  ...

Richard:

	As usual, you and I are not communicating.  The question at
hand is whether or not Fortran should be the way it is for (see Subject)
numerical analysis.  I agree that much fortran is written by not
NAs.  I also believe, given your background, you will agree that there
are two problems: getting physicists to write proper numerical code and
not impeding NAs from writing proper code.  Why doesn't Quintus take
that up --- should be a straight forward problem if PRESS ever is released
:-).  I certainly respect your opinion.

	It seems a poor choice of action to perpetuate the use of
Fortran for the business folks and for comp. sci. majors who do not
have the background to translate from their very limited understanding
of the axiomatic reals into the real world of floating point.  The
myth that anybody can code was debunk quite a while ago.



-- 
Steve Stevenson                            fpst@hubcap.clemson.edu
(aka D. E. Stevenson),                     fpst@prism.clemson.csnet
Department of Computer Science,            comp.parallel
Clemson University, Clemson, SC 29634-1906 (803)656-5880.mabell

shenkin@cubsun.BIO.COLUMBIA.EDU (Peter Shenkin) (09/06/88)

+ In article <3064@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
+ 
+ >From article <893@amelia.nas.nasa.gov>, 
+ >  by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):
+ >> I am looking for opinions of experienced
+ >> numerical/scientific/engineering programmers along the lines of why
+ >> Fortran is a better language than C for numerical analysis.
+ 
+ >The fact that C parenthesis don't force execution order is sufficient
+ >to exclude C from use in some instances.....

I believe that under the new C standard, parentheses will force order of
evaluation.  This replaces a previous provision that used unary + for the
same purpose.
-- 
*******************************************************************************
Peter S. Shenkin, Department of Chemistry, Barnard College, Columbia University
New York, NY   10027         Tel: (212) 280-5517 (work);  (212) 829-5363 (home)
shenkin@cubsun.bio.columbia.edu    shenkin%cubsun.bio.columbia.edu@cuvmb.BITNET

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

The compiler is free to perform any optimisation it wants, so long as
it doesn't change the result. So (1.0+x)*2.0 can be evaluated as 2+2*x
if that's more efficient. Multiplying by 2 is an exact operation in
binary floating point.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

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

From article <1421@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> The compiler is free to perform any optimisation it wants, so long as
> it doesn't change the result. So (1.0+x)*2.0 can be evaluated as 2+2*x
> if that's more efficient. Multiplying by 2 is an exact operation in
> binary floating point.

This was just a badly chosen example.  Suppose the expression had been:
(1.2345+x)*6.7890?  Applying the distributive law to this doesn't
produce the same computational result.  The question is: should the
optimization be allowed anyway?  The rules of Fortran don't allow it,
the rules of C (there are rules in C?) do.  The problem with C is that
it provides _no_ way to force a given order of expression evaluation
(ANSI doesn't count - expression ordering of one kind or another has
been proposed and removed so many times that there is no way of telling
whether the final standard will have the feature or not).

J. Giles
Los Alamos

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/09/88)

In article <3349@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>The problem with C is that
>it provides _no_ way to force a given order of expression evaluation

I can't let you get away with this.  _no_ way is very strong.  C
allows you to break the expression up into subexpressions, calculate
the subexpressions into temporary variables and then combine the temps
into the final expression.  If you don't run the optimizer on this
code, you are going to get exactly what you express.  (;-)

Marty


+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

fpst@hubcap.UUCP (Steve Stevenson) (09/09/88)

From article <976@amelia.nas.nasa.gov>, by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):

> C allows you to break the expression up into subexpressions, calculate
> the subexpressions into temporary variables and then combine the temps
> into the final expression.  

Back in the Jurassic age, Knuth (I think) wrote an article which pointed
out that most expressions are very short when occuring  in assignment
statements.  I could believe the above was the reason.

But the point is --- Why in the name of science do I have to hack.  I
thought we were trying to get away from that.  What's wrong with
C recogizing that floating point arithmetic is not real arithmetic and
observing the rules.  EXAMPLE:  the easiest rip-off scheme in DP
is to pick up the fuzz from interest calculations and put it in your account.
I certainly would never try to convince the business types that that
occurs.  I rather let them figure it out.  Star Wars --- that's a
different issue.-- 
Steve Stevenson                            fpst@hubcap.clemson.edu
(aka D. E. Stevenson),                     fpst@prism.clemson.csnet
Department of Computer Science,            comp.parallel
Clemson University, Clemson, SC 29634-1906 (803)656-5880.mabell

samperi@marob.MASA.COM (Dominick Samperi) (09/09/88)

In article <3349@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>the rules of C (there are rules in C?) do.  The problem with C is that
>it provides _no_ way to force a given order of expression evaluation

But you criticized C (ANSI C) for forcing a left-to-right evaluation order
in expressions like a+b+c+d in a previous posting. The beauty of C stems
from the mathematical consistency of its rules; the new (strict)
associativity rules for mathematical expressions is a natural extension
of the associativity rules for the non-mathematical C operators, which
enable the programmer to predict exactly how an expression will be
evaluated.

True, ANSI C is not yet an "official" standard, but neither is the current C,
yet the current language has undergone very few changes in 10+ years of use.
I maintain that the reason for this remarkable stability is the mathematical
consistency of the language, together with its fine data structuring
capabilities, and its low-level features (which facilitate the design of
portable code).

ANSI conformant C compilers are already in existence, and I suspect that
most C compilers will conform to this standard in the near future, even
if the standard is never published! (Well, one might say that it has
already been published, in the Second Edition of K&R's text, which has been
the definitive working standard for the last 10 years.)

I'm sure that the new FORTRAN standard will address many of the shortcommings
of the language: no support for data abstraction (no data structuring tools),
no support for information hiding (all function identifiers are globally
accessible), no recursion, identifiers limited to 6 characters, automatic
variable typing via the "first letter rule," ambiguous or inconsistent
specs. (the simple operators associate left-to-right, except for **, which
associates right-to-left, but forget this because the compiler can do
what it pleases for optimization...), programming guidelines made part
of the language spec., etc. 

Unfortunately, last I heard was that this new FORTRAN standard is not likely to
appear for a long time, due to the inability of the committee to
agree on anything.
-- 
Dominick Samperi, NYC
    samperi@acf8.NYU.EDU	samperi@marob.MASA.COM
    cmcl2!phri!marob        	uunet!hombre!samperi
      (^ ell)

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

Hi Jim... you should meet Mr. Rubin over in comp.lang.c.

In article <3349@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1421@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > ...(1.0+x)*2.0 can be evaluated as 2+2*x...

> This was just a badly chosen example.  Suppose the expression had been:
> (1.2345+x)*6.7890?  Applying the distributive law to this doesn't
> produce the same computational result.

No.

> The question is: should the optimization be allowed anyway?

No.

> The rules of Fortran don't allow it, the rules of C (there are rules in C?)
> do. 

The rules of ANSI X3J11 do require that this optimisation not be taken.

> The problem with C is that
> it provides _no_ way to force a given order of expression evaluation

Yes, this is a shortcoming addressed by ANSI X3J11. Other shortcomings
addressed by this standard (and shared, by the way, by Fortran) include
such things as the lack of function prototyping and a guaranteed method
for handling I/O devices and other asynchronous processing (volatile).

> (ANSI doesn't count - expression ordering of one kind or another has
> been proposed and removed so many times that there is no way of telling
> whether the final standard will have the feature or not).

Given the fact that it's now in the final stages, and only editorial
changes are allowed (as in, this or that wording is unclear...), it's
highly unlikely that it will be removed.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

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

From article <408@marob.MASA.COM>, by samperi@marob.MASA.COM (Dominick Samperi):
> In article <3349@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>>the rules of C (there are rules in C?) do.  The problem with C is that
>>it provides _no_ way to force a given order of expression evaluation
> 
> But you criticized C (ANSI C) for forcing a left-to-right evaluation order
> in expressions like a+b+c+d in a previous posting. The beauty of C stems
> [...
I have never criticized C (either ANSI or K&R) for forcing strict left
to right ordering.  Neither makes that requirement.  I the most recent
version of the ANSI standard _does_ make that constraint, I'm opposed!
Allowing _no_ optimization is as bad as not constraining optimization.
There should be a middle ground which allows the compiler to optimize
in most cases but allows the user to enforce a particular order in those
cases where it's important to do so.

> from the mathematical consistency of its rules; the new (strict)

What consistency?  There are deliberately ambiguous features in C.  Not
just in expression ordering, but in assignment ordering.  For example:
what is the value of i after the expression i=f(i++)?  Both ANSI and K&R
say this is undefined but _not_ illegal.  And this is the language you
claim is consistent?

> I'm sure that the new FORTRAN standard will address many of the shortcommings
> [...]
> specs. (the simple operators associate left-to-right, except for **, which
> associates right-to-left, but forget this because the compiler can do
> what it pleases for optimization...), programming guidelines made part
> of the language spec., etc. 

Exponentiation is _not_ associative so I don't know what you're telling
me about the 'compiler can do what it pleases'.  Operators which _are_
associative may be optimized using this fact as long as the integrity
of parenthesis is observed.  This has been around (and _well_ understood)
for much longer than C has even existed.  It's only C programmers who
complain about this rule, many even claim not to understand it.  Most
other programming languages follow the same rule as Fortran.  It is a
good rule.  C has no such rule.  By the way, just out of curiosity,
what 'programming guidelines' are part of the Fortran language spec?
I've got the standard right here and I can't find any.

> Unfortunately, last I heard was that this new FORTRAN standard is not likely to
> appear for a long time, due to the inability of the committee to
> agree on anything.

The same might be said of the C committee.  C is out for its _third_
public review (Fortran has only had one so far).  And so far the C
committee hasn't addressed many of the shortcommings of the K&R version
(like deliberate ambiguities in the semantics, conflicting operator
precidence rules (the worst are the unary prefix and postfix operators
some of which have high precidence and some of which have lower precidence),
arcane declaration syntax, etc.).  None of this even mentions the unreadable
terse syntax, the lack of even the _concept_ of an array (the array syntax
is instantly turned into pointers - there is no semantic concept of arrays),
and no floating-point arithmetic (ANSI will supposedly introduce it, but
C has previously been _all_ double precision), the lack of complex data
type (macros are inherently slower and less optimizable, other patches
for complex are even less attractive), etc..

J. Giles
Los Alamos

samperi@marob.MASA.COM (Dominick Samperi) (09/12/88)

In article <3417@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>> from the mathematical consistency of its rules; the new (strict)
>What consistency?  There are deliberately ambiguous features in C.  Not
>just in expression ordering, but in assignment ordering.  For example:
>what is the value of i after the expression i=f(i++)?  Both ANSI and K&R
>say this is undefined but _not_ illegal.  And this is the language you
>claim is consistent?

This ambiguity is easily avoided by following the rule: "a
variable that is auto-incremented/decremented should never appear on
both sides of the '=' operator." 

One might compare this rule to the FORTRAN: "do not modify the same array
by two different aliases," since both rules have in common the fact that
the compiler will not make sure you obey them (though FORTRAN compilers
are supposed to catch this error, I haven't seen any that do). This is
the programming guideline that I was referrring to in my previous posting.

>terse syntax, the lack of even the _concept_ of an array (the array syntax
>is instantly turned into pointers - there is no semantic concept of arrays),

C and FORTRAN handle arrays similarly, though you are permitted to do more
with an array in C than you can in FORTRAN (like manipulate its address
explicitly). And of course, the rows/columns are stored differently in the
two languages, but I wouldn't conclude from this that C does not support
the array concept. An array can be used in C just like it would be in
FORTRAN (with the rows/columns reversed); there is no need to use the lower-
level capabilities of C. And when arrays are passed to functions, a
pointer is passed in both languages.

I am not arguing that C is necessarily a good language to use for
numerical analysis (which was the question that started this discussion),
but I do feel that FORTRAN needs some work: should be able to hide
the names of internal package function names, some data structuring
facility is needed, the 6-letter restriction should be removed, the
compiler should require that all variable names be explicitly declared
(or at least support the VMS IMPLICIT NONE feature), more flexible
comment syntax would be nice, and a standardized macro facility would
help to patch up other blemishes.

-- 
Dominick Samperi, NYC
    samperi@acf8.NYU.EDU	samperi@marob.MASA.COM
    cmcl2!phri!marob        	uunet!hombre!samperi
      (^ ell)

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

From article <410@marob.MASA.COM>, by samperi@marob.MASA.COM (Dominick Samperi):
> This ambiguity is easily avoided by following the rule: "a
> variable that is auto-incremented/decremented should never appear on
> both sides of the '=' operator." 

Who's putting programming guidlines into a language _now_?
Why can't C make the above rule part of the standard and have done with it?
That way the compiler could check for this error (and, it really is an
error in every use I've ever seen).  The alias rule in Fortran is indeed
comparable (as you pointed out), and Fortran correctly rules this to be
illegal (even though aliased arrays are more difficult to check).  C doesn't
outlaw aliased arrays either (thgat's why dynamically allocated multi-
dimensional arrays don't optimize well in C - they are implemented as
an array of pointers which _can_ point to aliased areas of memory).
This is, by the way, what I mean when I say that C doesn't have the
concept of array (that is, a one or more dimensional collection of
data of identical type, no part of which is aliased to any other part).
Fortran extensions to allow dynamic memory all implement multidimensional
dynamic arrays the same as statically allocated arrays - the optimizer
doesn't have to assume that aliasing is possible so it does better than
C does.  (Note: the Fortran 8x proposal for allocatable arrays follows
this rule as well.)

J. Giles

cik@l.cc.purdue.edu (Herman Rubin) (09/13/88)

One deficiency in FORTRAN which is corrected in C is the ability to use
a variable pointer.  If this is wanted, it can be a major headache in
FORTRAN to find a way around it.

-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)

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

In article <3417@lanl.gov> jlg@lanl.gov (Jim Giles) writes......:

>(comments on consistency, expressions like i=f(i++), etc.
To catch all possiblilites is impossible.  To restrict this kind of thing
would unnecesarily cripple the language, and make it harder to read.  It is
up to the coder to code clearly.

>(in response to comment that Fortran commitee can't agree on anything)
>The same might be said of the C committee.  C is out for its _third_
>public review (Fortran has only had one so far).
Only one because they can't......  at least the C committee publishes

>(comments on the unary syntax, C is cryptic, etc.)
Any language is cryptic if you don't know it.  I like the C terse syntax.
I find it interesting that Fortran users who complain loudest about often
are mathematicians who use lots of terse, cryptic math notation in their
writings.  The reason is clear: terse is easier to read, if you know the
language.  It is unfortunate that much of the code written is of poor
quality, but that is not an indication that the language is poor.  It seems
all languages have their share.

>the lack of even the _concept_ of an array (the array syntax
>is instantly turned into pointers - there is no semantic concept of arrays),
Fortran and C handle arrays in almost the same way, if you insist.  C
programmers rarely do it that way, because the pointer and dynamic
allocation approach is much more flexible.  If you understand C's dynamic
allocation, Fortran's conformant arrays look painfully error prone and
primitive.

If you want to look at it this way, Fortran has no semantic concept of a
CONSTANT.  oops.

>(no single precision, no complex, etc.)
C does have some faults.  I wish ANSI would fix it.  C++ fixes it, and more.
The no single precision (actually there is single precision, but the type
conversions often eliminate the speed advantages, and ANSI did fix this.  I
never use single precision anyway, it is not accurate enough.) is a
consequence of two bad moves: portability at the expense of function, and
taking K&R too literally.

>J. Giles
>Los Alamos

I am curious why Ratfor isn't used more.  I think I know the real reason,
and it isn't portability.

Albert Davis
University of Rochester

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

In article <3445@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> Why can't C make the above rule part of the standard and have done with it?

Because putting it in doesn't enhance the utility of the language? You
can't possibly outlaw every peice of bad progframming practice. That
way lies ADA.

> C doesn't
> outlaw aliased arrays either (thgat's why dynamically allocated multi-
> dimensional arrays don't optimize well in C - they are implemented as
> an array of pointers which _can_ point to aliased areas of memory).

You mean dynamically sized arrays. Dynamically allocated but statically
sized arrays are implemented like any other array.

> This is, by the way, what I mean when I say that C doesn't have the
> concept of array (that is, a one or more dimensional collection of
> data of identical type, no part of which is aliased to any other part).

Sure it does. You just can't size it dynamically.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

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

Consider the following cases:

      I = (5 / 4) * 5		(I gets 5)

      I = 5 / (4 * 5)		(I gets 0)

      I = 5 / 4 * 5		(I gets 5 in F77, I gets something in C)

Personally, I wouldn't use case 3; I would always enforce an evaluation order
by using parentheses.  If this could be ambiguous in C, I wouldn't use it for
numerical work.  The same problem occurs when using mixed-mode arithmetic.
Evaluation order is important, and parentheses are the most obvious way of
expressing it.  Temporary variables are a hack.

	Hubert Matthews

samperi@djs.UUCP (Dominick Samperi) (09/13/88)

In article <3445@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
|that's why dynamically allocated multi-
|dimensional arrays don't optimize well in C - they are implemented as
|an array of pointers which _can_ point to aliased areas of memory).

The emphasis on _can_ is important here, for C permits many freedoms
that you need not use for routine numerical applications. Arrays can be
declared or created at runtime that are no different from FORTRAN arrays
(except that the rows/columns are swapped); there is no need to use any
tricks that result in obscure aliasing. It is true though that because of
the freedoms, the compiler may not be able to optimize the way it does
for FORTRAN arrays (how does it do this, by the way?). The use of the
autoincrement/decrement operators might be classified along with these
aliasing tricks and other lower-level C constructs as "advanced" features
of the language, and avoided entirely in numerical applications. Then
obscure code like

	while(*dest++ = *source++) ;

could be written like this instead:

	i = 0 ;
	while(source[i] != 0)
	{
		dest[i] = source[i] ;
		i = i + 1 ;
	}
	dest[i] = 0 ;

	This would also rule out those tricky expressions of the form
b[i] = a[i++], for example.

	On the other hand, using some of the low-level features might be
useful at times. For example, a lower-triangular matrix a[i][j], j <= i,
can be created, where memory is not allocated for the zero elements above
the diagonal. A more exotic example might be one where it is possible
to arrange for the various rows of a matrix to be allocated in different
memory modules/banks. This functionality could easily be added to FORTRAN
by simply providing a standardized macro facility.
-- 
Dominick Samperi
    samperi@acf8.nyu.edu             uunet!hombre!samperi
    cmcl2!acf8!samperi               rutgers!acf8.nyu.edu!samperi
      (^ ell)

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

From article <1454@valhalla.ee.rochester.edu>, by davis@galaxy.ee.rochester.edu (Al Davis):
> Any language is cryptic if you don't know it.  I like the C terse syntax.
> I find it interesting that Fortran users who complain loudest about often
> are mathematicians who use lots of terse, cryptic math notation in their
> writings.  [...]

This is a discussion about programming for numerical analysis.  I would
argue that if any terse syntax is used at all, it should be the one that
mathematicians and physicists use - not a new one invented from the strange
mind of an AT&T type.  If you can't do the terse syntax that is really
used by mathemeticians, you shouldn't have a terse syntax at all.  

But that wasn't my complaint about C.  The C syntax is not desireable
because the operator precidence doesn't follow any sensible rules.  For
example, left-to-right would imply that prefix operators should have
higher precidence than postfix - that's not how it was done though.

> never use single precision anyway, it is not accurate enough.) [...]

Single precision on the Cray carries 48 bits of precision and 15 bits of
exponent.  That's more than accurate enough for any work presently being
done on those toy VAXen.

J. Giles
Los Alamos

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

In article <410@marob.MASA.COM>, samperi@marob.MASA.COM (Dominick Samperi) writes:

>  [...]                             FORTRAN: "do not modify the same array
> by two different aliases," since both rules have in common the fact that
> the compiler will not make sure you obey them (though FORTRAN compilers
> are supposed to catch this error, I haven't seen any that do).

I know we have beaten this dead horse to death, but I just can't
resist.  The FORTRAN ANSI-77 standard says that the behavior in this
case is undefined.  It does not, repeat not, ..., repeat not state,
imply, or suggest that a compiler is required to detect this error, any
more than it is required to detect assignment to a constant passed as
an actual parameter, different length common blocks with the same name,
ad nauseum.  What it means is that a standard-conforming compiler can
assume that these rules are not violated and perhaps optimize the code
better as a result.  Of course, some of these rules are violated so
often that compiler writers, to satisfy their users, must treat the
violations as de facto extensions to the standard.
-- 
Larry Meadows @ FPS			...!tektronix!fpssun!lfm
					...!nosun!fpssun!lfm

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

From article <1484@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> You mean dynamically sized arrays. Dynamically allocated but statically
> sized arrays are implemented like any other array.

No, I've never seen a C dynamically allocated multidimensional array
that wasn't implemented as an array of pointers.  For a two dimensional
array, each pointer in the array of pointers points to a row of the array.
Higher dimensions are implementes as pointers_to_pointers_to_....
the number of indirect levels is one less than the number of dimensions.

- This is _NOT_ 'like any other array'.

J. Giles
Los Alamos

chris@mimsy.UUCP (Chris Torek) (09/14/88)

>In article <1484@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>>You mean dynamically sized arrays. Dynamically allocated but statically
>>sized arrays are implemented like any other array.

In article <3502@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
>No, I've never seen a C dynamically allocated multidimensional array
>that wasn't implemented as an array of pointers.  For a two dimensional
>array, each pointer in the array of pointers points to a row of the array.
>Higher dimensions are implementes as pointers_to_pointers_to_....
>the number of indirect levels is one less than the number of dimensions.
>
>- This is _NOT_ 'like any other array'.

You seem to have conveniently forgotten the material I posted here not
long ago.  Here is a dynamic (fixed size) array that is not an array of
pointers:

	extern char *malloc();

	f()
	{
		double (*arr)[64];
		int n_rows = 16, i, j;

		arr = (double (*)[64])malloc(n_rows * sizeof(*arr));
		if (arr == NULL) ... do something

		for (i = 0; i < n_rows; i++)
			for (j = 0; j < 64; j++)
				/* work on arr[i][j] */;
	}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

In article <3502@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>From article <1484@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
>> You mean dynamically sized arrays. Dynamically allocated but statically
>> sized arrays are implemented like any other array.
>
>No, I've never seen a C dynamically allocated multidimensional array
>that wasn't implemented as an array of pointers.

Well, what is wrong with an array of pointers?  Having worked with both, I
believe the array of pointers is the superior method.  It eliminates the
conformant array fudge.  It is usually faster.  It is more general.  It
works for strangely shaped sparse matrices.  Etc.

All the world is not a Cray.  Some of us have to work with finite resources.

Al Davis

chris@mimsy.UUCP (Chris Torek) (09/14/88)

In article <183@djs.UUCP> samperi@djs.UUCP (Dominick Samperi) writes:
>The emphasis on _can_ is important here ....

Indeed.

>[some features] might be classified ... as "advanced" features
>of the language, and avoided entirely in numerical applications.

Alas, unless there were some way to signal to the compiler that this
were the case, or unless it were obvious, it would not help the
compiler generate better code.  (Fortunately, what is `obvious' is
growing by leaps and bounds in compiler technology.  Cross-module
optimisation is no longer considered `too hard'.  I predict that decent
alias detection will soon not be considered `too hard' either.  [Never
mind that it is in some sense impossible: so is loop optimisation, in
the presense of irreducible flow graphs, yet compilers do that today.])

>	while(*dest++ = *source++) ;
>
>could be written like this instead:
>
>	i = 0 ;
>	while(source[i] != 0)
>	{
>		dest[i] = source[i] ;
>		i = i + 1 ;
>	}
>	dest[i] = 0 ;

Any half-decent optimiser should have no trouble converting the former
to the latter (with `source += i, dest += i' added).  (This assumes
that the latter is more efficient.  Typically optimisers have had to
convert the latter to the former.)

I do suggest, though, that no one use `i = i + 1' to increment.  If you
dislike `++', use `i += 1'.  When you mean `add one to i', why not *say*
it?
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

From article <13547@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
> I do suggest, though, that no one use `i = i + 1' to increment.  If you
> dislike `++', use `i += 1'.  When you mean `add one to i', why not *say*
> it?

'i = i + 1' _does_ say it!!!  Any compiler which generates different code
for 'i = i + 1', 'i += 1', and 'i++' is a certifiably _stupid_ compiler.
Those three examples are semantically _identical_, their syntactic difference
is a textual convenience - at best.

J. Giles
Los Alamos

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

From article <1457@valhalla.ee.rochester.edu>, by davis@galaxy.ee.rochester.edu (Al Davis):
> Well, what is wrong with an array of pointers?  Having worked with both, I
> believe the array of pointers is the superior method.  It eliminates the
                                       ^^^^^^^^^^^^^^^
> conformant array fudge.  It is usually faster.  It is more general.  It
                           ^^^^^^^^^^^^^^^^^^^^
> works for strangely shaped sparse matrices.  Etc.

I agree with everything above except the marked portions.  If I want an
array of pointers to pointers to ..., I should do something different from
just declaring a two dimensional array - arrays of pointers aren't the 
same!  For one thing, they are almost always slower - they can _never_
be faster because a conformant array _can_ be implemented that way if
necessary.  An array of pointer to pointer to ... _can't_ be treated
as a conformant array though - some of the pointers might be aliased!
The fact that they usually aren't doesn't help, the optimizer must assume
that it's possible.  Someone claimed that interprocedural alias detection
will soon be simple - I haven't seen it yet.  In any case, even inter-
procedural analysis doesn't help if the array isn't constructed until
run-time - the compiler can only do things like unrolling loops if
it knows _at_compile_time_ that there are no aliased arrays involved.

In short, any optimization possible for arrays of pointer to... is
also possible for conformant arrays.  The reverse is _not_ true.
Admittedly, the pointers are more powerful and more general, but if
your application doesn't need the power or generality of pointers,
you probably would prefer the more optimal conformant arrays.  Indeed,
it's possible to extend Fortran to include pointers (the Fortran I use
has them), it's very difficult to get conformant arrays in C - even
when that's what you really want!

J. Giles
Los Alamos

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/15/88)

In article <3502@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>
>No, I've never seen a C dynamically allocated multidimensional array
>that wasn't implemented as an array of pointers.  For a two dimensional
>array, each pointer in the array of pointers points to a row of the array.
>Higher dimensions are implementes as pointers_to_pointers_to_....
>the number of indirect levels is one less than the number of dimensions.
>
>- This is _NOT_ 'like any other array'.

Jim,  here's one:

main()
{
  float x[10][10];
  fprintf(stdout,"Hi Jim!\n");
  exit(0);
}

Most C compilers will generate the same kind of 2d array code for this
as any other language with adjacently spaced arrays.  The array
qualifies as dynamic, since it is local/automatic and gets allocated
on the stack when the procedure is run. (;-)

I think various people are quibbling over poor definitions at this
point.  Fortran doesn't support dynamic arrays -- in the sense of
space allocated at runtime -- at all. (Well, it didn't before the
"SAVE" statement introduced the possiblility of recursion.  Now it
does.)   C supports two different kinds of dynamic arrays:  Call stack
allocated and memory allocator returned.  Fortran doesn't support
memory allocator returned. (No pointers) The above is an example of
call stack allocated.  memory allocator returned is slightly
different.  Fortran does support conformant arrays (sort of) in
subroutine references This

      SUBROUTINE A(X,N,M)
      DIMENSION X(N,M)

is legal, but this

      SUBROUTINE A(X,N,M)
      DIMENSION X(N,M), Y(N,M)

is not.  This has been the cause of considerable grief to Fortran
programers over the years. C only sort of has conformant arrays.  The
C declaration 

suba(x)
 real x[][N];

is a sort of conformant C array.  C lets you get away with one
dimension being unspecified, but requires you specify the others.
Conformant local arrays are also quite illegal in C.

It is true that C compilers can't generate efficent code in
the general case of memory allocated dynamic arrays, but Fortran
compilers can't generate any code at all.  (;-) Further, C compilers
can, and some do, generate good code when they detect explicit dope
vectors.  In order to avoid the math of index calculation, many
compilers generate offset index vectors.  There is a C idiom (See
Numerical Recipes in C's appendices for an example) which looks
exactly like a dope vector.  At least one compiler I am aware of can
sometimes detect and always be told that a dynamic array is of this
form, allowing the compiler to generate exactly the code you would
expect for a contiguously allocated array.

Neither language has all of the features that I could use for arrays
in numerical work.  A partial list (off the top of my head) includes:

  o Range specification, ala Pascal's [n..m] format.
  o The ability to query an array for its shape.  By shape, I mean
    the number of indices and the ranges of each index.
  o not having to specify the shape of an array when it is passed
    as an argument.
  o True dynamic (all senses) multiple dimensioned arrays in
    subroutines.
  o good checking for uninitialized reference errors
    and index out of bound errors which I can selectively enable
    at runtime.
  o reduction operators (;-)

With respect to array semantics, Fortran is very good in the presences
of vector machines and naive compiler technology.  C is very good for
dynamically varying requirements in memory tight environments.  I can
easily make C behave like Fortran for many applications; I have a
great deal of trouble going the other way.

Marty






+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

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

In article <1484@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>You mean dynamically sized arrays. Dynamically allocated but statically
>sized arrays are implemented like any other array.

>> This is, by the way, what I mean when I say that C doesn't have the
>> concept of array (that is, a one or more dimensional collection of

>Sure it does. You just can't size it dynamically.

I still consider the lack of dynamically SIZED arrays to be a major stumbling
block for the acceptance of C for numerical analysis.  I do not accept that
applications programmers should have to deal constantly with arrays of
pointers just to get this capability.  But then, I believe that pointers
should be used as a LAST RESORT in APPLICATIONS code, unlike REAL
programmers who eat arrays of pointers to functions for breakfast :-)


-- 
  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       

chris@mimsy.UUCP (Chris Torek) (09/15/88)

>In article <1457@valhalla.ee.rochester.edu> davis@galaxy.ee.rochester.edu
>(Al Davis) writes:
>>Well, what is wrong with an array of pointers?  Having worked with both, I
>>believe the array of pointers is the superior method.  It eliminates the
>                                      ^^^^^^^^^^^^^^^
>>conformant array fudge.  It is usually faster.  It is more general.  It
>                          ^^^^^^^^^^^^^^^^^^^^
>>works for strangely shaped sparse matrices.  Etc.

In article <3570@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>I agree with everything above except the marked portions.

Good so far.

>If I want an array of pointers to pointers to ..., I should do something
>different from just declaring a two dimensional array - arrays of pointers
>aren't the same!

You have just described C declarations.

>For one thing, they are almost always slower - they can _never_
			 ^^^^^^^^^^^^^^^^^^^^
>be faster because a conformant array _can_ be implemented that way if
>necessary.  An array of pointer to pointer to ... _can't_ be treated
>as a conformant array though - some of the pointers might be aliased!

It is true that they can never be faster.  Saying that they are `almost
always slower', however, shows just as much bias as Al Davis's claim.

>The fact that they usually aren't doesn't help, the optimizer must assume
>that it's possible.  Someone claimed that interprocedural alias detection
>will soon be simple - I haven't seen it yet.

Of course not.  When I said `soon' I meant `on the order of 10 years'.
(This is certainly not `soon enough' for those doing this sort of work now.)

>...  Indeed,
>it's possible to extend Fortran to include pointers (the Fortran I use
>has them), it's very difficult to get conformant arrays in C - even
>when that's what you really want!

Indeed, it is possible to extend C to include conformant arrays (the C
I use has them%); it is very difficult to get pointers in Fortran---even
when that is what you really want!

-----
% Well, actually, I do not use it.  It is GCC, available for free from
prep.ai.mit.edu and other places on the Internet.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chris@mimsy.UUCP (Chris Torek) (09/15/88)

In article <820@cernvax.UUCP> hjm@cernvax.UUCP (Hubert Matthews) writes:
>Consider the following cases:
>
>      I = (5 / 4) * 5		(I gets 5)
>
>      I = 5 / (4 * 5)		(I gets 0)
>
>      I = 5 / 4 * 5		(I gets 5 in F77, I gets something in C)

I gets 5 in C (even in K&R 1st ed. C).  The arithmetic operators group
left-to-right, and while

    The order of evaluation is not specified for associative and
    commutative operators like * and +

(K&R 1st ed., p. 37), the divide operator is hardly commutative!

>Evaluation order is important, and parentheses are the most obvious way of
>expressing it.  Temporary variables are a hack.

Sometimes (many people will break up ten-line expressions for the sake
of clarity).  Nonetheless, there are two problems being solved:
overriding the default groupings, and specifying order of operation.
Any time you use a single solution for two (or more) orthogonal
problems, you have missed out on some potential orthogonality.
(Whether it would in fact be *useful* is a different argument entirely.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

In article <820@cernvax.UUCP> hjm@cernvax.UUCP (Hubert Matthews) writes:
>      I = 5 / 4 * 5		(I gets 5 in F77, I gets something in C)
>
>Personally, I wouldn't use [this]; I would always enforce an evaluation order
>by using parentheses.  If this could be ambiguous in C, I wouldn't use it for
>numerical work.

This is not ambiguous in C, and never has been.
	% echo "I = 5 / 4 * 5;" | cparen
	I = ((5 / 4) * 5);

In fact, this is one of the reasons why some C programmers resent the
Fortran people telling them what to do with parentheses:  C programmers
are used to adding parentheses to expressions to clarify the grouping
*without* changing the semantics.  The point at issue is whether
	I = N * P * Q;
and	I = (N * P) * Q;
have the same meaning.  In pre-ANSI C, they did; a compiler could
rearrange both.  In the current draft, the two expressions are different,
exactly as in Fortran.

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

In article <14897@ames.arc.nasa.gov> lamaster@ames.arc.nasa.gov.UUCP (Hugh LaMaster) writes:
>I still consider the lack of dynamically SIZED arrays to be a major stumbling
>block for the acceptance of C for numerical analysis.

"Algol 60 is an improvement on its successors".  Still true.
But if the lack of dynamically sized arrays didn't stop Fortran,
why complain about C?

Array parameters are another matter.  Fortran has such ``real'' arrays
that
	DIMENSION A(10)
	CALL KLUDGE(A(5), 6)
	END
	SUBROUTINE KLUDGE(B, N)
	DIMENSION B(N)
	B(1) = 0.0
	B(N) = 0.0
	RETURN
	END
is a legal program.  Is A(5) a scalar or an array?  Well, yes, sort of.

I hope *some* of the things that were going to be in Fortran 8X make it
into a standard fairly soon.  I was looking forward to having decent arrays.
[Why should we an exception library be "language-independent", when we
haven't even got a "language-independent" notion of arrays?]

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

In article <3502@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1484@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > You mean dynamically sized arrays. Dynamically allocated but statically
> > sized arrays are implemented like any other array.

> No, I've never seen a C dynamically allocated multidimensional array
> that wasn't implemented as an array of pointers.

char (*twodarray)[10][10];

	twodarray = malloc(sizeof(*twodarray));

	(*twodarray)[10][5] = 'c';

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

ags@h.cc.purdue.edu (Dave Seaman) (09/15/88)

In article <406@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
 [ explaining that a particular expression is not ambiguous in C ]
>In fact, this is one of the reasons why some C programmers resent the
>Fortran people telling them what to do with parentheses:  C programmers
>are used to adding parentheses to expressions to clarify the grouping
>*without* changing the semantics.  The point at issue is whether
>	I = N * P * Q;
>and	I = (N * P) * Q;
>have the same meaning.  In pre-ANSI C, they did; a compiler could
>rearrange both.  In the current draft, the two expressions are different,
>exactly as in Fortran.

What are you afraid of?  What problem does it cause if the compiler decides
to respect the extra parentheses that you put in for no reason?  After all,
even in C under the K&R standard, there is no guarantee that the compiler
will NOT treat the expression differently because of the parentheses.

If all you are interested in is emphasizing grouping for the benefit of the
human reader, you can do that quite effectively by the proper use of white
space.  You don't need parentheses.  In fact, white space works BETTER than
parentheses for this purpose.  Compare:

	t = a*cos(x) + b*cos(y)   +   c*f(x-y) + d*f(x+y)
with
	t=((a*cos(x))+(b*cos(y)))+((c*f(x-y))+(d*f(x+y)))

-- which would you rather read?

In the expression "(A*B)*C", suppose A and C are large enough that
the product causes overflow, while B is small enough that the expression
can be evaluated sensibly, provided the compiler does not rearrange it to
"(A*C)*B".  I think the programmer has good reason to complain if his
parentheses are not respected in this situation.

In short, respecting parentheses has no bad effects, and not respecting
them can be downright harmful.

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

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/15/88)

In article <3570@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>In short, any optimization possible for arrays of pointer to... is
>also possible for conformant arrays.  The reverse is _not_ true.

'taint so.  Perhaps any *time* optimization, but certainly not any
*space* optimization.  I don't have to allocate space for unused array
of pointer references.  Consider sparse address spaces, such as sparse
matrices. . .

Marty
+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

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

From article <13567@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
> 
> You have just described C declarations.

No, I didn't.  I said that the declaration for an array should look 
(and mean) something different than the declaration of a pointer.
In C, there are indeed two different syntaxes - they just both mean
the _same_ thing.  I can't declare an array in C without getting
one or more pointers declared into the bargain.  I want a language
that gives _me_ the choice.  C doesn't do it!  Most of the pointer
proposals for Fortran do!  C _can't_ do it without making changes which
aren't backward compatible.  _All_ the Fortran pointer proposals
I've seen _are_ backward compatible.  (The Cray Fortran compiler has
had pointers for years.  Everything you can do with C pointers you can
do with Fortran pointers.  Arrays can be dynamically allocated - but
the declaration and use of the arrays are identical with statically
allocated arrays except for the additional POINTER statement.  In C,
the declaration of a dynamically allocated (multi-D) array is completely
different from the declaration for a statically allocated one - the use
is different too if you follow most implementation proposals.)

J. Giles
Los Alamos

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

From article <13570@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
> Sometimes (many people will break up ten-line expressions for the sake
> of clarity).  Nonetheless, there are two problems being solved:
> overriding the default groupings, and specifying order of operation.
> Any time you use a single solution for two (or more) orthogonal
> problems, you have missed out on some potential orthogonality.

This is true.  But if you omit a functionality completely simply because
you don't want to overload some part of the syntax - you haven't done
the users any favors either.  In fact, the parenthesis rule in Fortran
is quite useful and is well understood by most programmers (because
almost all languages except C have the same rule).  Inserting parenthesis
for clarity does indeed impeed optimization somewhat - but not as much
as you might think.  The only real case is when common sub-expressions
are parenthesized differently so that they can't be folded together.
The lack of grouping for precision control would pose a _much_ more
serious problem.

J. Giles
Los Alamos

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

From article <1511@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> 	(*twodarray)[10][5] = 'c';
> 
> Now you have.

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.

J. Giles
Los Alamos

shenkin@cubsun.BIO.COLUMBIA.EDU (Peter Shenkin) (09/16/88)

In article <3630@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>                          ... I can't declare an array in C without getting
>one or more pointers declared into the bargain.

Sorry, but
	int a[10];
declares space for 10 ints and no pointers.  If you want a pointer, too,
you have to say, in addition,
	int *pa = &*a[0];
or some such.  Of course, if you call a function with
	x = func( a );
what is passed to the function is the address of a[0], as in FORTRAN, but
no extra storage has been declared.

>                               ...(The Cray Fortran compiler has
>had pointers for years.  Everything you can do with C pointers you can
>do with Fortran pointers.  Arrays can be dynamically allocated....

A nice feature.  And the common availability of this feature in many Fortrans
is testimony to its usefulness.  The fact that Fortran 8x, if it ever
makes it, has a good chance of including it is further testimony.  But 
standard (f77) Fortran doesn't have it, and most of us don't work on Crays, 
and many of us work on multiple machines.

>                                                                ... In C,
>the declaration of a dynamically allocated (multi-D) array is completely
>different from the declaration for a statically allocated one...

An unfortunate aspect of C.  But at least we can do the allocation and
use the array within the original definition of the C, assuming only the
run-time library functions that are supplied with virtually all 
implementations of C that the numerical analyst, in any case, is likely to see.

This is not true of Fortran.  The proposed 8x standard indicates that
those who find the feature useful wish to have it standardized;  the mere
fact that it is available one way or another in most good implementations
is not enough for such users, despite the fact that, as Giles points out,
some programmers use various preprocessors.

At least C does provide a standard and source-code portable way of doing this,
although I admit that C makes you stand on your head to create and use true 
(contiguous) dynamic multidimensional arrays whose shape (size and/or 
dimensionality) is not known until run-time.  I agree with Giles that this
is unfortunate.  But I fail to see why he doesn't agree that the virtually
universal availability of dynamic allocation in C, using the same syntactical
convention, doesn't count in favor of C (over Fortran) in his eyes.
-- 
*******************************************************************************
Peter S. Shenkin, Department of Chemistry, Barnard College, Columbia University
New York, NY   10027         Tel: (212) 280-5517 (work);  (212) 829-5363 (home)
shenkin@cubsun.bio.columbia.edu    shenkin%cubsun.bio.columbia.edu@cuvmb.BITNET

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

In article <3974@h.cc.purdue.edu> ags@h.cc.purdue.edu.UUCP (Dave Seaman) writes:
>In article <406@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
> [ explaining that a particular expression is not ambiguous in C ]

>What are you afraid of?  What problem does it cause if the compiler decides
>to respect the extra parentheses that you put in for no reason?  After all,
>even in C under the K&R standard, there is no guarantee that the compiler
>will NOT treat the expression differently because of the parentheses.

Quite true.  But if I stick extra parens into a C expression, whatever code
the compiler comes up with, it was entitled to generate _anyway_.  Because
C has a lot more operator precedence levels than Fortran, and because it is
not immediately obvious that, say, *a[i] means *(a[i]) -- hence the utility
of the tool called "cparen" -- and because of macros, C programmers tend to
write a lot of parentheses "just to be safe".  For example, a Fortran
programmer might write a statement function
	MIDPT(X, Y) = (X + Y)/2
but a C programmer would write
	#define MIDPT(X,Y) (((X) + (Y))/2.0)
-- the parens around X and Y are needed in case their principal operators bind
   more weakly than "+", e.g. MIDPT(a < b, a < c)
-- the parens around the whole are needed in case it is used within the scope
   of an operator binding more tightly than "/".
Note that a compiler was formerly licenced to optimise MIDPT(a+b,c+d)/4.0 just
like (a+b+c+d)/8.0, but is now required to do {({a+b} + {c+d})/2.0}/4.0.

It is a bit worrying to suddenly be told that the parentheses you were
putting in just to play safe now carry semantic import, just because people
who were used to Fortran didn't like the idea of having an explicit
"don't do this any other way" mark.

>If all you are interested in is emphasizing grouping for the benefit of the
>human reader, you can do that quite effectively by the proper use of white
>space.  You don't need parentheses.  In fact, white space works BETTER than
>parentheses for this purpose.  Compare:
>
>	t = a*cos(x) + b*cos(y)   +   c*f(x-y) + d*f(x+y)
>with
>	t=((a*cos(x))+(b*cos(y)))+((c*f(x-y))+(d*f(x+y)))
>
>-- which would you rather read?

No, in fact what I'm concerned about is the human *writer*.
Since I read code with the aid of a text editor, I would rather have the
second form:  I can be *sure* of the grouping.  With the white-space
version, I *still* have to read every character unaided, because the
spacing might be wrong.  Consider

	t = a-cos(x) / b-cos(y)   /   c-f(x-y) / d-f(x+y)

[example of why "strong" parens are useful]
It is conceded that *some* way of saying "do this *exactly* as I wrote it"
is a Good Idea.  The point is that that is a _different_ thing to say from
"I am confused about the operator precedence and want to make sure", and the
two deserve different notation.  Fortran having historically (ab)used
parentheses for the strong form, I wouldn't dream of suggesting that that
should be changed.  C having historically used parentheses for purely
syntactic effect, I think it is at best bad manners to change _that_; a
new notation should have been used.  +(...) seemed ok to me.

I seriously doubt that many Fortran programmers Out There understand enough
about numerical analysis to work out where strong brackets are needed.  It
would be a big help in reading Fortran programs (especially when trying to
convert them to another language) if one only knew which parentheses were
present for numerical reasons and which were not.  Comments would be enough.

Here are a couple of examples from "Numerical Recipes":
	WT = 1./(SIG(I) ** 2)
Why has this been written like that instead of as
	WT = SIG(I) ** (-2)
is there something deep I am missing here, or was it just a matter of taste?

	SXOSS = SX/SS
	...
	SIGA = SQRT((1. + SX*SX/(SS*ST2))/SS)
Is it really important that this should be computed as (SX*SX)/(SS*ST2)
or perhaps SX/(SS*ST2)*SX rather than (SX/ST2)*SXOSS, or was it just
what the authors thought clearest?  {In context, I'd be more worried
about overflow/underflow than about roundoff, so I'd have thought
(SX/ST2)*SXOSS would be preferred on numeric grounds.}

I hope these examples make my point clear:  I do not regard *either* the
Fortran or the pre-ANSI C positions on parentheses as satisfactory.
There are *two* constructs, and both languages should have *both*.
It is precisely because I _agree_ that control over evaluation is
important that I want to know which parentheses are which!

chris@mimsy.UUCP (Chris Torek) (09/16/88)

>In article <13570@mimsy.UUCP> I wrote
>>Any time you use a single solution for two (or more) orthogonal
>>problems, you have missed out on some potential orthogonality.
[and I add back the line:]
Whether this orthogonality is in fact *useful* is another argument entirely.

In article <3631@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>This is true.  But if you omit a functionality completely simply because
>you don't want to overload some part of the syntax - you haven't done
>the users any favors either.  In fact, the parenthesis rule in Fortran
>is quite useful and is well understood by most programmers ....
>The lack of grouping for precision control would pose a _much_ more
>serious problem.

I agree.  Introducing temporary variables to force evaluation order
(required in `old C') is significantly inelegant.  This was a real
problem with `old C'.  I am just not sure I like the solution used
in the dpANS (and in FORTRAN and all those other languages).  Ah well,
time will tell how well it works.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

In article <3645@lanl.gov>, jlg@lanl.gov (Jim Giles) writes:
> From article <1511@ficc.uu.net>, by peter@ficc.uu.net (Peter da Silva):
> > 	(*twodarray)[10][5] = 'c';

> > Now you have.

> Gee, that looks like and array of pointers to me.

Nope, it's a pointer to an array. There's a difference. A big difference.

> This is certainly _not_
> an example of a 2-d array that is done without an array of pointers.

It certainly is.

If you can't read that much 'C' correctly, then why are you even trying
to carry on this debate? I refuse to carry on a battle of wits with an
unarmed man.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

PLS@cup.portal.com (09/17/88)

hjm@cernvax.UUCP (Hubert Matthews) writes

>Consider the following cases:
>
>      I = (5 / 4) * 5		(I gets 5)
>
>      I = 5 / (4 * 5)		(I gets 0)
>
>      I = 5 / 4 * 5		(I gets 5 in F77, I gets something in C)

Now just a minute. Surely you don't mean to say that the first two are both
equivalent to the third except for a choice in order of operations? The
second is a completely different formula. The two correct choices are

       I = (5 / 4) * 5           = 5
  
       I = (5 * 5) / 4           = 6

I suspect there are very few compilers that do this kind of reordering. 

  ++PLS
 onsider the following cases:

      I = (5 / 4) * 5		(I gets 5)

      I = 5 / (4 * 5)		(I gets 0)

      I = 5 / 4 * 5		(I gets 5 in F77, I gets something in C)

Personally, I wouldn't use case 3; I would always enforce an evaluation order
by using parentheses.  If this could be ambiguous in C, I wouldn't use it for
numerical work.  The same problem occurs when using mixed-mode arithmetic.
Ev