[comp.std.c] power operator as an extension

karl@haddock.ISC.COM (Karl Heuer) (07/28/88)

As expected, the X3J11 committee has decided not to add an exponentation
operator to ANSI C.  Given the charter of the committee, this was an
appropriate decision: there is no prior art.  Yet I (and others, including
many fortran converts) would find such an operator useful.

I suggest that individual implementors add this feature to their ANSI C
compilers as an experimental extension.  If people need this operator, they'll
prefer to buy compilers that support it.  If many compilers support it, it'll
have a chance at being blessed in the second standardization (1999?).

In particular, I wonder if this would be interesting to the maintainers of GNU
cc, which I believe already supports at least one fortranish extension.  I'm
cross-posting this to gnu.gcc, but followups not related to GNU should
probably go to comp.std.c only.

I suggest "*^" for the symbol, as it doesn't conflict with existing syntax,
and is somewhat mnemonic.  ("^^" would also fit the bill, but this looks as if
it should mean logical-xor.)  The grammar should be revised thus:

power-expression:
	cast-expression
	cast-expression *^ power-expression

multiplicative-expression:
	power-expression
	multiplicative-expression * power-expression
	multiplicative-expression / power-expression
	multiplicative-expression % power-expression

(Also, "*^=" should be added to the list of assignment operators.)

In the expression x *^ y, x can be any integral or floating expression;
its type is the type of the result.  The exponent y must be an integral
expression; if x has integral type, then y must be nonnegative.  If y==0,
then the value is 1 (even if x==0 also).

Here are my prebuttals to some anticipated objections.

] We don't need to raise numbers to a power.

Some of us do.  Having to use a temporary just to square an expression is a
real pain.

] Negative exponents should be allowed even if the base is an int.

I don't care whether 3*^-1 returns 0 or -1431655765 or dies with a core dump.
All three answers can be justified, so it's probably best to leave this as an
undefined situation, just like a negative shift.  (Of course, if there is a
consensus on the "right" answer in 1999, it may get blessed anyway.)

] The precedence is wrong; -x*^2 should mean (-x)*^2, not -(x*^2).

The compiler (or lint) should produce a warning for that construct, then.  The
alternatives are to put *^ between postfix unary and prefix unary (which would
screw up expressions like *p++ *^ 2), or to split off unary minus into its own
precedence level (I don't think it's worth it).

Besides, the proposed precedence agrees with that of bc.

] It should allow floating-point exponents, too.

Less necessary, since the pow() function already handles this, and is probably
just as efficient.  But you could add it if you like.  (Cf. extending "%" to
floating-point operands.)

] None of this is necessary, because pow() exists.  In fact, pow() can be
] implemented as a builtin which optimizes integral exponents.

There is no guarantee that pow() will produce the right answer.  On my
machine, (int)pow(2.0, 3.0) produces 7 instead of 8.  Unless X3J11 is willing
to guarantee the accuracy of the result (even for those implementations that
choose not to inline it), this is not a solution.

] An operator for a non-simple function runs counter to the Spirit of C.

It has been reported that nearly all (95%?) uses of exponentiation in actual
programs used a small, constant, integral exponent.  This *is* a simple
operation.  The general case may require more work, but this is also true of
the shift operators on some architectures.

] 0*^0 is mathematically indeterminate; it should be undefined, not 1.

It has to be 1, e.g. for a polynomial: sum a[i]*x*^i.  This is consistent
with mathematical usage; 0*^0 is only indeterminate when the exponent is a
continuous variable.  (And even then, the result is "almost always" 1.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint