Xref: utzoo comp.lang.c:11016 comp.lang.fortran:846 Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!hc!lanl!beta!jlg From: jlg@beta.lanl.gov (Jim Giles) Newsgroups: comp.lang.c,comp.lang.fortran Subject: Re: C vs. FORTRAN Keywords: C FORTRAN exponentiation Message-ID: <20506@beta.lanl.gov> Date: 30 Jun 88 16:14:26 GMT References: <3136@phoenix.Princeton.EDU> <19633@watmath.waterloo.edu> <147@quintus.UUCP> Organization: Los Alamos National Laboratory Lines: 118 In article <147@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes: > [...] > 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. It's not misleading. It means what it says - exponentiation. It looks as expensive as an exponentiation operator - no more or less. If the syntactical appearance is what you mean by 'special syntax', why does pow() look any more expensive than abs()? Divide doesn't look all that much more expensive than multiply either, but it is. > > What with prototypes and all, an ANSI C compiler is fully entitled to treat > [example ...] > just the same as Fortran 77 would treat > [other example ...] Possibly true. Also irrelevant. You are making basically a syntactical point. So the fact that the future versions of C will fix something (that IT shouldn't have broke to begin with) is not relevant. > [...] > >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 LISP isn't terribly hard to read either, but it's not what I want to code numerical expressions in. The syntax that mathematics uses is really well suited to the task. The programming language syntax for the same purposes should look as similar as possible to the original math. There is no reason that I can see to adopt any other rule of choice in language design. > 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 X is in range, then LOG(X) is in range. If X**3.5 is in range, then certainly 3.5*LOG(X) is. The expression given overflows (or underflows) ONLY if the original numbers are out of range or if the final answer is out of range. > > >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 The choice I'm talking about is whether to cause a function call (the most expensive of all the 'simple' operations). Doesn't matter what the subroutine library does, you've already made the expensive call. > to be wrong, because ANSI C compilers are allowed to detect the standard > library functions and do special things with them. Fine, C is fixing something that shouldn't have been broken to begin with. Now, if it would just add the operator ... > [...] > 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!} An interesting example. But it makes my point, not yours. The first fragment (in either language) looks expensive. The C fragment also looks harder to write and maintain - but no more expensive than the Fortran fragment (this, of course, IS misleading, the C fragment is probably slower). Fragment 2 looks clearly preferable in either language. The existence of the exponentiation operator doesn't alter my perceptions about these code fragments AT ALL. > > A good numeric programmer will use X**N __very__ seldom for other than > constant arguments. Finally! Something we agree upon. But what does this have to do with the value of placing the operator into the syntax? Just because it's seldom used for large or non-constant arguments, doesn't mean it needs to be arcane or cryptic when it IS used. > > What C _does_ lack that a numeric programmer might miss is a single- > precision version of pow(). Given > [...] > 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 > [...] For just multiplies, X*Y, the ratio on the Crays is about 60 (actually that's an underestimate, since the single precision multiply can be pipelined). The ratio for exponentiation must be enormous! Of course, this would never be acceptable. So the Cray C compiler uses SINGLE instead of DOUBLE for all arithmetic. I don't know if it even HAS a way of doing real double. (Cray single has ~14 decimal digits of precision.) My point is that if you're suggesting that languages should be designed to protect a small number of naive users from making simple efficiency errors - you're wrong. Programming languages should be designed to allow _good_ programmers to write and maintain their codes as productively as possible. After all, this is why C, with its terse (and sometimes cryptic) syntax is so popular. If you really want to protect naive users, you should lobby for removal of expressions with side-effects from C. J. Giles Los Alamos