C vs. FORTRAN

Richard A. O'Keefe ok at quintus.uucp
Thu Jun 30 08:49:55 AEST 1988


In article <20480 at beta.lanl.gov> jlg at beta.lanl.gov (Jim Giles) writes:
>In article <143 at quintus.UUCP>, ok at quintus.uucp (Richard A. O'Keefe) writes:
>> Not to knock either C or Fortran, but this may be a case where C is better
>> to use than Fortran.

>The exponentiation operator isn't bad just because some people use it badly.

I didn't say that it was bad.  What I do say is that it is _MISLEADING_.
In C, for example, most of the operations for which there is special
syntax correspond to machine operations of similar cost.

What with prototypes and all, an ANSI C compiler is fully entitled to treat
	#include <math.h>
	double x;
	...
	x = pow(x, 3);
	x = pow(x, 3.5);
just the same as Fortran 77 would treat
	DOUBLE PRECISION X
	...
	X = X**3
	X = X**3.5
It is already the case on the UNIX systems where I've tried it that
	pow(x, (double)3)
uses the iterative method used for X**3.  (I personally don't think that
is a good thing, but that's another story.)

>X**3 is more readable than X*X*X (particularly is X is an expression).
pow(x,3) isn't _that_ hard to read, either.
>X**3.5 is more readable than EXP(3.5*LOG(X)).
True, but again, pow(x,3.5) isn't terribly hard to read, and in any
case the two expressions X**3.5 and EXP(3.5*LOG(X)) don't mean exactly
the same thing (may have different over/underflow conditions, yield
different results, &c).

>If you always do pow(X,Y), the compiler has no choices to make.
Misleading and soon to be wrong.  Misleading, because the run-time library
_does_ have some choices to make, and current libraries make them.  Soon
to be wrong, because ANSI C compilers are allowed to detect the standard
library functions and do special things with them.

>If the potential for misuse doesn't even result in incorrect code
>(as in this case), then there is no reason not to include the feature.

Well, ANSI C _does_ include the feature.  My point was simply that the
notation "pow(x, y)" _looks_ as though it might be costly, while the
notation "x ** y" _looks_ as though it is cheap and simple, and that
the first perception is the correct one, so that ANSI C's notation may
be better.  In fact it is _not_ the case in this example that the
misuse did not result in incorrect code.  Consider the two fragments:

C	Assume that N.ge.2		/* Assume that N >= 2 */
C	Fragment 1			/* Fragment 1 */
	T = A(1)			t = a[0];
	DO 10 I = 2,N			for (i = 1; i < n; i++) {
	   T = T + A(I) * X**(I-1)	    t += a[i]*pow(x, (double)i);
10	CONTINUE			}
C	Fragment 2			/* Fragment 2 */
	T = A(N)			t = a[N-1];
	DO 20 I = N-1,1,-1		for (i = n-2; i >= 0l i--) {
	    T = T*X + A(I)		    t = t*x + a[i];
20	CONTINUE			}

The two fragments are *not* equivalent.  It is easy to come up with an
example where fragment 2 correctly yields 1.0 and fragment 1 overflows.
{I am not asserting that fragment 2 is always the right thing to use!}

A good numeric programmer will use X**N __very__ seldom for other than
constant arguments.

What C _does_ lack that a numeric programmer might miss is a single-
precision version of pow().  Given
	float x, y, u, v;
	x = pow(u,v)/y;
it is not in general safe to evaluate pow(u,v) in single precision.
How much faster is float**float than double**double?
Sun-3/50 (-fsoft)	1.2
Sun-3/160 (-f68881)	2.5
Sequent (80387)		1.4
If this is typical (and I have no reason to expect that it is), the
lack of single precision elementary functions in C comes into the
"nuisance" category rather than the "major problem" one.  Since UNIX
systems often come with Fortran these days, and Fortran has single
precision elementary functions, it seems a pity not to let ANSI C
share them.



More information about the Comp.lang.c mailing list