exponentiation operator (lack of)

K

Keith Thompson

Jordan Abel said:
it'd probably be **, but

If we were going to add an exponentiation operator to C, we couldn't
use "**" without breaking existing code. x**y already means x * *y.

It wouldn't have been entirely unreasonable to have a built-in
exponentiation operator in C. If it had been there from the
beginning, x**y wouldn't have been a problem; if you wanted x * *y,
you'd have to insert a space. It would provide some opportunities for
optimization that a function doesn't; for example, x**2 can be
translated to a simple multiplication, and x**16 can be implemented as
a sequence of 4 multiplications rather than 15. The right operand
could have been restricted to an integral value, leaving the pow()
function for a floating-point right operand. (A function whose second
argument has to be an integer could do most of the same optimizations.)

It wasn't done because it's not used all that much, because it's a
relatively higher-level operation than C's other built-in operators,
because C's original emphasis was systems programming rather than
mathematics, and because the designers of the language just
arbitrarily decided not to add it. I don't think the language has
particularly suffered from it. You can agree or disagree with the
decision, but we're stuck with it.
 
J

jacob navia

Eric Sosman a écrit :
jacob said:
[...]
The purported exponentiation operator would have to be dyadic:

10 ^^ 3 --> 1000

This would be feasible but the problem is inserting it in
the precedence rules of C

10+4 ^^ 4+5 --> pow(14,9) ? or 10+pow(4,4)+5 ???

There are enomous problems with this approach, and for exponentiation
I think it is just not worth the effort, unless we devise a general
rule about adding new operators.


The "enomous [sic] problems" you mention had already been
solved when I began programming thirty-nine years ago.

2**3**4
is an error in fortran. Should that be also the case in C?

2|3|4 is legal C... Should the operator ** be the same?
Besides, ** is not really good since it is easily mistaken with
multiply by the dereferenced pointre:

a**b is
(a)*(*b)
or
(a)**(b) ???

Etc etc. Once you start you will see it is NOT that easy.
In
FORTRAN the `**' operator means exponentiation, and binds more
tightly than multiplication and division but less tightly than
parentheses and function calls. Expressions in FORTRAN are
structurally similar to those in C, and I'm confident a similar
precedence rule could be worked out easily.
I am not.
But perhaps I'm abusing you needlessly and owe an apology;
you may be referring to the problems of adding user-defined
operators on the fly and at the programmer's whim.

Well, not really by everyone but surely by the commitee.
Those would
indeed be "enomous" problems! But perhaps we need not generalize
from a question about one obviously missing operator to the issue
of accommodating every conceivable (and ill-conceived) operator
a programmer's diseased mind can imagine. If you want APL, you
know where to find it. ;-)

1)
We have operators that have hardware support but not operator
support in C:

char a = 200;
char b = 200;
char c = a |+| b; // c is 255 not 400%255. No 'wrap around'

There is now only the function call syntax to adapt that to
C:

char c = ClampedAdd(a,b,255);

2)
APL did NOT allow for operator overloading, (it had an exponentiation
operator however). I use often APL concepts since it was a language
that I will never forget, like a jewel. Tiny but so perfect somehow.
 
J

jacob navia

Wow Chris, you know APL too!

How nice!

I will never forget that language. Small but powerful, with a
consistent and uniform way of expressing programs.

Yes, it had its drawbacks (like everything, there is nothing
perfect) but it was so advanced for its time!

jacob
 
E

Eric Sosman

jacob navia wrote On 12/23/05 14:34,:
Eric Sosman a écrit :
jacob navia wrote:

[...]
The purported exponentiation operator would have to be dyadic:

10 ^^ 3 --> 1000

This would be feasible but the problem is inserting it in
the precedence rules of C

10+4 ^^ 4+5 --> pow(14,9) ? or 10+pow(4,4)+5 ???

There are enomous problems with this approach, and for exponentiation
I think it is just not worth the effort, unless we devise a general
rule about adding new operators.


The "enomous [sic] problems" you mention had already been
solved when I began programming thirty-nine years ago.


2**3**4
is an error in fortran. Should that be also the case in C?

It's been so long since I used FORTRAN that I don't
remember. If it were up to me, I'd say exponentiation
should be right-associative and let it go at that. It's
not up to me, though.
2|3|4 is legal C... Should the operator ** be the same?
Besides, ** is not really good since it is easily mistaken with
multiply by the dereferenced pointre:

a**b is
(a)*(*b)
or
(a)**(b) ???

Etc etc. Once you start you will see it is NOT that easy.

This is just a question of spelling. Obviously you
can't grab ** or ^ or % to be C's exponentiation operator;
they're already taken for other purposes. # would almost
work, but there'd be niggling problems with line boundaries.
$ would work, but there's a distaste for national characters.
Someone has already suggested ^^, and I think @ would also
be all right. The only question here is the choice of a
character combination that isn't already in use and has
some amount of mnemonic value. We could even do without
the mnemonic: nobody seems to complain about % even though
it's not very suggestive of "remainder."
1)
We have operators that have hardware support but not operator
support in C:

char a = 200;
char b = 200;
char c = a |+| b; // c is 255 not 400%255. No 'wrap around'

The operator I miss even more than exponentiation is
"integer multiply producing double-width product." I've
only run into one non-assembly language that provided such
a thing; that language used * to get a 16-bit product from
two 16-bit integers and '*' (with the quotes) to get a 32-
bit product. Among other things, it gave a very easy way
to "pick a card, any card" with reasonable accuracy:

card = (rand() '*' 52) >> 16

(Please take this with a grain of salt; I remember the '*'
distinctly because it was both unusual and pleasant to have,
but I can't vouch for the spelling of the right-shift
operator or for the name of the pseudo-random source. Read
the idiom, not my idiocy.)

But this is the reverse of the O.P.'s question: he didn't
ask why there aren't operators for all the useful machine
instructions, but why there's no exponentiation operator.
When he says the FAQ offers an excuse rather than an answer
I'm inclined to agree with him. After all, C has no qualms
about requiring things like `long long' and `long double'
support even on 8-bit embedded toaster controllers; why be
squeamish about requiring exponentiation? The FAQ's answer
just doesn't seem to hold a lot of water.

I think the "why not?" question can only be answered
by dmr himself. Anybody else is just speculating.
 
R

Rouben Rostamian

It wouldn't have been entirely unreasonable to have a built-in
exponentiation operator in C. If it had been there from the
beginning, x**y wouldn't have been a problem; if you wanted x * *y,
you'd have to insert a space. It would provide some opportunities for
optimization that a function doesn't; for example, x**2 can be
translated to a simple multiplication, and x**16 can be implemented as
a sequence of 4 multiplications rather than 15. The right operand
could have been restricted to an integral value, leaving the pow()
function for a floating-point right operand. (A function whose second
argument has to be an integer could do most of the same optimizations.)

I completely agree with what you have written here.
Additionally, in my view the distinction between x**y and x * *y
would have been an ugly wart on the language but we would have
gotten used to it. Alas, it wasn't done that way.
It wasn't done because it's not used all that much, because it's a
relatively higher-level operation than C's other built-in operators,
because C's original emphasis was systems programming rather than
mathematics, and because the designers of the language just
arbitrarily decided not to add it.

In the absence of a comment from DMR, these are probably as
plausible explanations as I can think of. I disagree, however,
with "It wasn't done because it's not used all that much".

Probably you meant to say "It wasn't done because it wasn't
used all that much in the early years of C". Otherwise that
statement sounds strange coming from someone from the San Diego
Supercomputer Center. I'll hazard a guess that the bulk of
the CPU time on your computers is spent on numerical analysis
and scientific computing where exponentiation operations
are pervasive.
 
K

Keith Thompson

jacob navia said:
Eric Sosman a écrit :
jacob said:
[...]
The purported exponentiation operator would have to be dyadic:

10 ^^ 3 --> 1000

This would be feasible but the problem is inserting it in
the precedence rules of C

10+4 ^^ 4+5 --> pow(14,9) ? or 10+pow(4,4)+5 ???

There are enomous problems with this approach, and for exponentiation
I think it is just not worth the effort, unless we devise a general
rule about adding new operators.
The "enomous [sic] problems" you mention had already been
solved when I began programming thirty-nine years ago.

2**3**4
is an error in fortran. Should that be also the case in C?

2|3|4 is legal C... Should the operator ** be the same?
Besides, ** is not really good since it is easily mistaken with
multiply by the dereferenced pointre:

a**b is
(a)*(*b)
or
(a)**(b) ???

Etc etc. Once you start you will see it is NOT that easy.

Sure it is.

Let's assume, hypothetically, that we want to add an exponentiation
operator to C. We can't use "**" because x**y already means x * *y.
We can't use "^" because it already means bitwise xor. So let's use
"^^" (since nobody is going to want a short-circuit xor). Or bite the
bullet and use "**", breaking existing code; since the right operand
can't be a pointer, any code that's broken will get a diagnostic and
the programmer can insert the space that should have been there in the
first place. (The latter probably wouldn't get past the committee,
even assuming they'd accept the whole idea in the first place.)

Add a new precedence level, just above the multiplication operators,
so "x*y^^z" means "x*(y^^z)". Update the grammar to reflect this.

There are three choices for associativity: it associates
left-to-right, it associates right-to-left, or it doesn't associate at
all (x^^y^^z is illegal). Pick one.

Either the right operand has to be an integer, making it equivalent to
repeated multiplication, or the right operand can be floating-point,
making it equivalent to pow() (or powf() or powl()). Pick one.

There are some arbitrary choices to be made, but I don't see what's so
difficult about it.

I'm not advocating this, but anyone who thinks it's a good idea could
implement it as an extension in some existing compiler, providing the
existing practice that would make it more likely for the committee to
accept the idea.

The only thing preventing the addition of an exponentiation operator
to C is lack of interest. Defining the syntax and semantics is the
easy part.
 
K

Keith Thompson

In the absence of a comment from DMR, these are probably as
plausible explanations as I can think of. I disagree, however,
with "It wasn't done because it's not used all that much".

Probably you meant to say "It wasn't done because it wasn't
used all that much in the early years of C". Otherwise that
statement sounds strange coming from someone from the San Diego
Supercomputer Center. I'll hazard a guess that the bulk of
the CPU time on your computers is spent on numerical analysis
and scientific computing where exponentiation operations
are pervasive.

And I think most of that code is written in Fortran, though some of it
is written in C.

In any case, the software running on the computers where I work is
hardly typical of C software in general. I suspect (without proof)
that most C software is system-level stuff that doesn't need
exponentiation. It's questionable whether the use of C in scientific
computing is significant enought to justify changing the language.

On the other hand, C99 did add complex arithmetic and the infamous
type-generic math macros, which I suppose refutes what I just wrote.

On the other other hand, the existence of the pow() function means
that an exponentiation operator really isn't necessary. Using
function-call notation may be slightly less convenient, but it does
neatly avoid the issues of precedence and associativity. An
equivalent function whose second argument is an integer might be nice,
but I haven't seen much demand for it.
 
C

carlos

The FAQ points out a perfectly valid reason for omitting any sort
of exponentiation operator. C is not alone among languages in
doing this. Exponentiation is not the most prevalent of operators,
and is normally a subroutine in almost any language.

Historically that is not quite correct. My first language was
Fortran IV, used for my PhD thesis at UCB. In the 70s I briefly used
Burroughs Algol (a derivative of Algol 60-68) and Gnu Pascal in the
80s. The exponentiation operators were **, ^ and **, respectively.
Those 3 languages were widely used in their heyday although
of course were not useful for low-level system programming.

Algol 60 is supposed to have influenced C indirectly,
but the ^ operator was renamed. As I noted, the lack is presently
felt in low-level numerical applications of C. These are
growing rapidly, especially in parallel & multicore processing.

One reason: the ability of C to interact closely with the hardware
and do resource management. This is critical in supercomputers.

Second reason: the "feed" end of the Fortran pipeline is emptying.
Example: our College of Engineering has not taught Fortran to
undergraduates since 1997 (why? industry feedback). Numerical
methods are taught to freshmen in C for low-level components
and Matlab for high level scripts. One of our PhD students joined
Mathworks two yrs ago, and she works primarily in C.

Giving this ongoing enlargement in the scope of C applications,
I see no reason why a new operator (** or ^^) could not be
introduced to meet those needs either in a future standard, or
in a "successor to C" , as discussed in another thread.
It should have a high precedence, just under the dot.
 
J

Jordan Abel

Eric Sosman a écrit :
jacob said:
[...]
The purported exponentiation operator would have to be dyadic:

10 ^^ 3 --> 1000

This would be feasible but the problem is inserting it in
the precedence rules of C

10+4 ^^ 4+5 --> pow(14,9) ? or 10+pow(4,4)+5 ???

There are enomous problems with this approach, and for exponentiation
I think it is just not worth the effort, unless we devise a general
rule about adding new operators.


The "enomous [sic] problems" you mention had already been
solved when I began programming thirty-nine years ago.

2**3**4
is an error in fortran. Should that be also the case in C?

2|3|4 is legal C... Should the operator ** be the same?
Besides, ** is not really good since it is easily mistaken with
multiply by the dereferenced pointre:

a**b is
(a)*(*b)
or
(a)**(b) ???

Etc etc. Once you start you will see it is NOT that easy.

As opposed to a--b being a-- b [a syntax error] rather than the valid
a-(-b)? That's an argument against adding it (silent change) but NOT an
argument for why it shouldn't exist. ++ and -- are both tokens, and //
introduces a comment.
 
C

carlos

18. Keith ThompsonDec 23, 12:08 pm   show options
Newsgroups: comp.lang.c
From: Keith Thompson <[email protected]> - Find messages by this author
Date: Fri, 23 Dec 2005 19:08:11 GMT
Local: Fri, Dec 23 2005 12:08 pm
Subject: Re: exponentiation operator (lack of)
Reply |Reply to Author| Forward| Print| Individual Message| Show
original| Report Abuse


it'd probably be **, but

If we were going to add an exponentiation operator to C, we couldn't
use "**" without breaking existing code.  x**y already means x * *y.
It wouldn't have been entirely unreasonable to have a built-in
exponentiation operator in C.  If it had been there from the
beginning, x**y wouldn't have been a problem; if you wanted x * *y,
you'd have to insert a space.  It would provide some opportunities for
optimization that a function doesn't; for example, x**2 can be
translated to a simple multiplication, and x**16 can be implemented as
a sequence of 4 multiplications rather than 15.  The right operand
could have been restricted to an integral value, leaving the pow()
function for a floating-point right operand.  (A function whose second
argument has to be an integer could do most of the same optimizations.)


Agree. Suppose for example that a naive programmer evaluates a
4-polynomial by writing (assuming ^^ as exp operator)

c = a0 + a1*x + a2*x^^2 + a3*x^^3 + a4*x^^4;

A clever compiler could analyze this and convert it to the Horner
scheme, using less than a dozen fp core registers.
With pow() the analysis and optimization might be more
problematic if the compiler worries about side effects.
Also IMO the purpose of the foregoing expression is
easier to visualize to somebody who didnt write the code.
 
C

Christian Bau

If we were going to add an exponentiation operator to C, we couldn't
use "**" without breaking existing code.  x**y already means x * *y.

To be honest, anyone writing x**y would only get what they deserve if
their code is broken. Now if you can come up with an example where the
character sequence ** would change its meaning and still compile...

(I am assuming that number ** pointer would be an error that the
compiler has to catch).
 
L

lawrence.jones

Eric Sosman said:
The operator I miss even more than exponentiation is
"integer multiply producing double-width product."

The operator is "*". It's fairly simple for a compiler to recognize:

int i, j;
long l;
...
l = (long)i * j;

and avoid the needless widening of i and j.

-Larry Jones

Fortunately, that was our plan from the start. -- Calvin
 
L

lawrence.jones

Keith Thompson said:
It wouldn't have been entirely unreasonable to have a built-in
exponentiation operator in C. If it had been there from the
beginning, x**y wouldn't have been a problem; if you wanted x * *y,
you'd have to insert a space. It would provide some opportunities for
optimization that a function doesn't; for example, x**2 can be
translated to a simple multiplication, and x**16 can be implemented as
a sequence of 4 multiplications rather than 15.

There's nothing preventing a compiler from optimizing calls to the pow()
function the same way.

-Larry Jones

I don't think math is a science, I think it's a religion. -- Calvin
 
K

Keith Thompson

18.Keith ThompsonDec 23, 12:08pm show options
Newsgroups: comp.lang.c
From: Keith Thompson <[email protected]> - Find messages by this author
Date: Fri, 23 Dec 2005 19:08:11 GMT
Local: Fri, Dec 23 2005 12:08pm
Subject: Re: exponentiation operator (lack of)
Reply |Reply to Author| Forward| Print| Individual Message| Show
original| Report Abuse
[snip]

Thank you for trying to quote using the broken Google interface, but
there's a much better way to do it.

See <http://cfaj.freeshell.org/google/>.
 
K

Keith Thompson

There's nothing preventing a compiler from optimizing calls to the pow()
function the same way.

It's slightly more difficult, since both arguments of pow() are
floating-point. The compiler would have to recognize that the second
argument is an integer; in that case, rather than converting it to
double, it would replace the call with code to do repeated
multiplication or whatever is most efficient, or perhaps just a call
to another function that takes an integer as its second argument.

It's certainly feasible, but I don't know whether any compilers do
this. If exponentiation were a built-in operator, I think compiler
writers would have been more strongly motivated to optimize it along
with expression evaluation in general.
 
M

Mark McIntyre

The 15 levels of precedence of C are so messy that nobody
has had the time to devote a man year to find out how
an exponentiation operator could be implemented.

Well, frankly this is nonsense. Why do you not post sensible things?
Is it some sort of fetish?
 
M

Mark McIntyre

That is not an answer, just an excuse.

So?There are lots of mathematical operators that C doesn't define, and
if you look closely, you'll notice that pretty much all of them are
ones you don't find hardware support for except in specialist math
chips. There are also missing operators for 'obvious' things like
addings two strings, adding two arrays, multiplying two matrices etc.
And why isn't there a dot-product operator and a cross-product
operator? I'm sure physicists would find them handy.
C is not assembly language.

Read a history book... :)
 
B

Bart C

This would be feasible but the problem is inserting it in
the precedence rules of C

10+4 ^^ 4+5 --> pow(14,9) ? or 10+pow(4,4)+5 ???

Obviously exponentiation has to have a higher priority than +,-,* or /,
because that's the case with algebra.

And perhaps evaluated right-to-left too, so 10**10**2 is 10**(10**2).

Ideally a superscript would be used, but I can see that has certain
difficulties. With ** ambiguous and ^ taken, ^^ is a good alternative,
although I don't see why an operator has to be a symbol, why not:

10 + 4 pow 4 + 5 ?

What about using ^ as exponentiation operator when either operand is float?

Bart
 
J

Jack Klein

Curious:
Why wasnt a primitive exponentiation operator not added to C99?

There is one. It's named pow(). How is pow(x, y) any more or less
primitive than x ** y?
And, are there requests to do so in the next std revision?

No, we already have pow(), and it does what we need.
Justification for doing so:
C and C++ are increasingly used in low-level
numerical computations, replacing Fortran in newer projects.
Check, for example, sourceforge.net or freshmeat.net

What C++ does or does not do is not relevant here.

What do you think happens when you use the exponentiation operator in
Fortran or Pascal? Perhaps on a very few hardware architectures a
short sequence of floating point unit instructions are added in line.
On most others, a run time support library routine is called.

Nothing at all prevents a C compiler for appropriate architectures to
make the function intrinsic and generate the same in line.
But neither language offers a primitive exp operator.
^ is exclusive OR, which is much less common in numerical
programs than exponentiation. However, ^^ is open.

So what?

By the way, the place to propose new features to the language or the
standard library is not here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top