Topic: Exponentiation operator proposal
Author: jimad@microsoft.com (Jim Adcock)
Date: 14 Oct 92 22:57:25 GMT Raw View
In article <23663@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
>How frequent is a**p anyway? (has anyone got any data?) How confusing...
I just ran a quick measurement on a convenient sample of 85,000 lines of
C and C++ code. Based on this sample "**" appears on average about once
per every 200 lines of code. This is a pretty high occurance. For comparison
"^" [XOR] appears on average once per 3000 lines of code! Based on this
measure I'd much rather see "^^" used for exponentiation, since the potential
for confusion would seem to be much much lower. Too bad "^" was misused to
mean XOR in the first place or the problem would be solved!
Author: sdm@cs.brown.edu (Scott Meyers)
Date: Thu, 15 Oct 1992 03:02:29 GMT Raw View
In article <1992Oct14.225725.16486@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
| I just ran a quick measurement on a convenient sample of 85,000 lines of
| C and C++ code. Based on this sample "**" appears on average about once
| per every 200 lines of code. This is a pretty high occurance. For comparison
| "^" [XOR] appears on average once per 3000 lines of code!
How many of these are in declarations versus in expressions? After all,
"&" already has different semantics depending on whether it's in a
declaration or an expression. If we could do the same thing with "**", it
would improve the language considerably, because one of the biggest
drawbacks to C++ as it currently stands is that it's too easy to
understand.
:-)
Scott
-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence? "Hello, Mr. Mayor."
Author: corbett@lupa.Eng.Sun.COM (Robert Corbett)
Date: 15 Oct 1992 03:12:01 GMT Raw View
In article <1992Oct14.225725.16486@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>In article <23663@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
>>How frequent is a**p anyway? (has anyone got any data?) How confusing...
>
>I just ran a quick measurement on a convenient sample of 85,000 lines of
>C and C++ code. Based on this sample "**" appears on average about once
>per every 200 lines of code. This is a pretty high occurance. For comparison
>"^" [XOR] appears on average once per 3000 lines of code! Based on this
>measure I'd much rather see "^^" used for exponentiation, since the potential
>for confusion would seem to be much much lower. Too bad "^" was misused to
>mean XOR in the first place or the problem would be solved!
I find it hard to believe that there are that many instances of
multiplication following indirect referencing. How many of those
instances of ** are of the form
/*
** Commentary
*/
?
Yours truly,
Robert Corbett
Author: matt@physics2.berkeley.edu (Matt Austern)
Date: 14 Oct 92 22:47:24 Raw View
In article <ldpoc1INNbe7@exodus.Eng.Sun.COM> corbett@lupa.Eng.Sun.COM (Robert Corbett) writes:
> >I just ran a quick measurement on a convenient sample of 85,000 lines of
> >C and C++ code. Based on this sample "**" appears on average about once
> >per every 200 lines of code. This is a pretty high occurance.
...
> I find it hard to believe that there are that many instances of
> multiplication following indirect referencing. How many of those
> instances of ** are of the form
>
> /*
> ** Commentary
> */
> ?
I can't speak for Jim (I haven't seen the code that he used for his
sample), but my guess is that most of the **'s he found weren't
comments, but, rather, double pointer dereference. (For example, how
many times has the sequence **argv occurred in your programs?)
This wouldn't cause any direct ambiguity with ** as an exponentiation
operator, since exponentiation is an infix operator. However, note
that it would still be necessary to define unary ** as a new operator
meaning double pointer dereference. The parser would interpret ** as
a single token, whether it appears in a unary or a binary context.
There are a few expressions that would have their meaning changed if
we made ** into an operator---probably rare ones, but I'm sure that
they do crop up occasionally in real code. (a/b**c, for example) I
think we probably would be better off using a different token for
exponentiation.
--
Matthew Austern Just keep yelling until you attract a
(510) 644-2618 crowd, then a constituency, a movement, a
austern@lbl.bitnet faction, an army! If you don't have any
matt@physics.berkeley.edu solutions, become a part of the problem!
Author: matt@physics.berkeley.edu (Matt Austern)
Date: 16 Oct 92 17:19:45 GMT Raw View
In article <Bw8ADK.144@news.orst.edu> myersn@hobo.ECE.ORST.EDU (Nathan Myers) writes:
> I have long ignored "exponentiation proposal" notes, but it seems
> time to point out that there is no operator~(T,T) defined yet.
> Simply allowing it to be defined would permit experimentation,
> without committing anybody to a bigger language if the use didn't
> "catch on".
Binary operator~ is certainly one possibility for exponentiation.
operator*^ and operator^^ are other possibilities; of the three, I
think that *^ is the best.
Regardless of the name, however, I feel strongly that a real
exponentiation operator is far better than an operator which can be
defined as exponentiation by the user. First, a compiler is much more
likely to optimize exponentiation aggressively if it is built into the
language than if it's something the user tacks on. (Depending on
exactly what is inline and in scope, it might not even be possible to
do certain optimizations with a user-defined operator.)
Second, if users each define this operator for themselves, then each
programmer will almost certainly define it slightly differently. This
is likely to cause subtle bugs and conflicts when the work of
different programmers is put together.
Finally, and most important: things like exponentiation simply belong
either in the language or in the library; users should not be forced
to write them for themselves, any more than users should be forced to
implement malloc() or sin() or qsort(). Defining commonly used
operations and functions is what languages and libraries are for.
--
Matthew Austern Just keep yelling until you attract a
(510) 644-2618 crowd, then a constituency, a movement, a
austern@lbl.bitnet faction, an army! If you don't have any
matt@physics.berkeley.edu solutions, become a part of the problem!
Author: myersn@hobo.ECE.ORST.EDU (Nathan Myers)
Date: 16 Oct 92 19:05:38 GMT Raw View
I have long ignored "exponentiation proposal" notes, but it seems
time to point out that there is no operator~(T,T) defined yet.
Simply allowing it to be defined would permit experimentation,
without committing anybody to a bigger language if the use didn't
"catch on".
Nathan Myers
myersn@roguewave.com
Author: asher@qtp.ufl.edu (Robert L. Asher)
Date: 20 Oct 92 22:19:57 GMT Raw View
In article <Bw8ADK.144@news.orst.edu> myersn@hobo.ECE.ORST.EDU (Nathan Myers) writes:
>
>I have long ignored "exponentiation proposal" notes, but it seems
>time to point out that there is no operator~(T,T) defined yet.
>Simply allowing it to be defined would permit experimentation,
>without committing anybody to a bigger language if the use didn't
>"catch on".
>
>Nathan Myers
>myersn@roguewave.com
I'd like to see the ability to allow new operartors in a general way. There
are a lot of operations which the programmer may never consider, but are
constantly used in chemistry/physics/mathematics.
Robert
--
Robert L. Asher | "They're right, I don't have any experience...
Department of Chemistry | in running up a 4 trillion dollar deficit."
University of Florida | Ross Perot (first debate)
asher@qtp.ufl.edu |
Author: sakkinen@jyu.fi (Markku Sakkinen)
Date: Fri, 18 Sep 1992 06:08:57 GMT Raw View
In article <1992Sep15.201801.26417@murdoch.acc.Virginia.EDU> gs4t@virginia.edu (Gnanasekaran Swaminathan) writes:
> ...
>Did you consider operator () for exponentiation?
>It seems to have correct precedence and doesn't need new tokens to be
>introduced.
> ...
You are kidding, of course?
Parentheses already have so many different meanings that this would be
a sure road to confusion and difficult programming errors.
----------------------------------------------------------------------
Markku Sakkinen (sakkinen@jytko.jyu.fi)
SAKKINEN@FINJYU.bitnet (alternative network address)
Department of Computer Science and Information Systems
University of Jyvaskyla (a's with umlauts)
PL 35
SF-40351 Jyvaskyla (umlauts again)
Finland
----------------------------------------------------------------------
Author: jcoxhead@acorn.co.uk (Jonathan Coxhead)
Date: 18 Sep 92 11:40:23 GMT Raw View
In article "Re: Exponentiation operator proposal" sm86+@andrew.cmu.edu
(Stefan Monnier) writes:
Are you sure it is always the case [that
logical_exclusive_or (a, b) is equivalent to !a != !b]? The '!=' can
be implemented as 'xor' or as 'minus'!! And what's the use of '!' in
'!a' and '!b'? I may be missing something!
I think you are. Think of a truth table:
a | b | !a | !b | !a != !b
---------------+----------------+----+----+---------
equal to 0 | equal to 0 | 1 | 1 | 0
equal to 0 | not equal to 0 | 1 | 0 | 1
not equal to 0 | equal to 0 | 0 | 1 | 1
not equal to 0 | not equal to 0 | 0 | 0 | 0
/|
(_|/
/|
(_/
Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Sun, 20 Sep 1992 03:09:11 GMT Raw View
In article <1992Sep18.060857.29383@jyu.fi> sakkinen@jyu.fi (Markku Sakkinen) writes:
>In article <1992Sep15.201801.26417@murdoch.acc.Virginia.EDU> gs4t@virginia.edu (Gnanasekaran Swaminathan) writes:
>> ...
>>Did you consider operator () for exponentiation?
>>It seems to have correct precedence and doesn't need new tokens to be
>>introduced.
>> ...
>
>You are kidding, of course?
>Parentheses already have so many different meanings that this would be
>a sure road to confusion and difficult programming errors.
>
Real (C) programmers *love* confusion and difficult bugs :-)
After all, the definition of 'program' is "the tracks left by
thousands of bugs".
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 12 Sep 92 18:30:53 GMT Raw View
Comments on Mat Austern's proposal for an exponentiation
operator in C++ (posted to comp.lang.std and, I think,
also to comp.lang.c++).
(1) I think overloading and inlining can be used a bit
more effectively than is assumed in tht proposal.
For example:
double pow(double,double); // what C gives us
double _pow(double,int); // general pow(double,int)
inline double pow(double d, int i) // inlining to catch
// important special cases
{
if (i == 2) return d*d;
else if (i == 3) return d*d*d;
else _pow(d,i);
}
void f(double d, int i)
{
pow(d,d);
pow(d,i);
pow(d,2);
pow(d,3);
pow(d,4);
}
will generate better code for small integer powers.
This technique is fairly gaeneral and does not depend on
cleverness beyond the average C++ compiler.
I agree that a clever compiler can do better, but for now
this technique might be helpful to some.
(2) I think we could actually get ** as the exponentiation operator.
Consider the well-known counter-example:
int a;
int* p;
a**b;
For C compatibility, a**b must mean a * (*b). However,
with a minor sleigh of hand this can be achieved even
if we introduce and exponentiation operator represented
by the single token **.
All we need to do is to say that the exponentiation
operator ** given a first operand `a' of arithmetic type
and a second operand `b' of pointer type (that is, `a**b')
mean multiply the first operand with the dereference value
of the second operand (that is, `a*(*b)'). This would not
be quite 100% compatible because a*b**p where p is a pointer
would mean a*(b*(*p)) rather than (a*b)*(*p), but I suspect
that it would be compatible enough.
Similarly the token ** when used in a declarator must mean
* * (that is pointer to pointer.
I think this would take care of the compatibility problems.
There may be other minor details to consider, but I don't
see any insurmountable problems.
Author: karl@ima.isc.com (Karl Heuer)
Date: Sun, 13 Sep 1992 19:35:07 GMT Raw View
In article <23660@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
>Comments on Mat Austern's proposal for an exponentiation operator
I missed that one, but I've posted about exponentiation a few times myself.
>(1) I think overloading and inlining ...
My only objection to this method (other than the perceived aesthetic
superiority of an infix operator) is that the later example
> void f(double d, int i) { ... pow(d,i); ... }
inline-expands to something that always runtime-compares the variable i with
certain small integers before invoking the true function _pow(). In some
sense it would be better to do this only when i is a constant (in which case
it's a compile-time compare), and have the non-constant-exponent case simply
call the true function immediately.
This could be accomplished with one addition to the language:
isconstant(expr) - an operator that returns 1 if expr is a
constant expression, or 0 if not. If the operand involves
formal parameters to an inline function, the actual arguments
are used.
>(2) I think we could actually get ** as the exponentiation operator.
>[By defining `**' to have semantics of TIMES FETCH when the right operand
>is a pointer]
I considered this when I wrote my exponentiation essay. I decided that it
might be possible, but it's way too confusing! This would be a kludge of the
highest order. It's much better to use syntax that's not already taken --
I've adopted "*^", as suggested by someone else some years ago. (A hybrid of
"**" and "^", sort of.)
Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
Author: rr@world.std.com (Robert I Ransbottom)
Date: Sun, 13 Sep 1992 23:58:39 GMT Raw View
In article <1992Sep13.193507.27813@ima.isc.com> karl@ima.isc.com (Karl Heuer) writes:
>In article <23660@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
>>Comments on Mat Austern's proposal for an exponentiation operator
>>[By defining `**' to have semantics of TIMES FETCH when the right operand
>I considered this when I wrote my exponentiation essay. I decided that it
>might be possible, but it's way too confusing! This would be a kludge of the
>highest order. It's much better to use syntax that's not already taken --
>I've adopted "*^", as suggested by someone else some years ago. (A hybrid of
>"**" and "^", sort of.)
I agree ** is confusing, given the potential frequency of both "dat**ptr" and
"dat**dat" it seems like a waste to deciphering such. The proponents
of **expon want a convenience.
I think that ^^ would be more satisfying to both pointer-ers and math-ers.
1. Its not already taken!
2. Its not already taken!
3. Its not already taken!
. . . . .
. . . . .
n. Its easier to type than Karl's *^.
n+1. No more damaging if mistyped.
n+2. The contexts of exponentiation and exclusive-or have less overlap
than multiplication & indirection and exponentiation.
My vote is behind a keyword like
operator consistent { *=, /=, -=, += }
which would shorthand consistent derivatives X= from X and =.
The longhand is simple enough to generate, but is more difficult to
read/verify given alien code.
--
rr@world.std.com Robert Ransbottom
"Maintaining correct attributions is extremely important." -- anonymous
Author: karl@ima.isc.com (Karl Heuer)
Date: 14 Sep 92 07:39:52 GMT Raw View
In article <BuJJxs.8Hx@world.std.com> rr@world.std.com (Robert I Ransbottom) writes:
>[How about spelling it "^^", then?]
Some people still hope to adopt that symbol for boolean xor. (I don't,
but I don't want to stand in the way of those who do.)
Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 14 Sep 92 14:27:49 GMT Raw View
karl@ima.isc.com (Karl Heuer) writes
> >(2) I think we could actually get ** as the exponentiation operator.
> >[By defining `**' to have semantics of TIMES FETCH when the right operand
> >is a pointer]
> I considered this when I wrote my exponentiation essay. I decided that it
> might be possible, but it's way too confusing! This would be a kludge of the
> highest order. It's much better to use syntax that's not already taken --
> I've adopted "*^", as suggested by someone else some years ago. (A hybrid of
> "**" and "^", sort of.)
Of course it is a hack. It is a compatibility hack of the first order,
but I see few TECHNICAL problems with it.
and rr@world.std.com (Robert I Ransbottom) writes
> I agree ** is confusing, given the potential frequency of both "dat**ptr" and
> "dat**dat" it seems like a waste to deciphering such. The proponents
> of **expon want a convenience.
>
> I think that ^^ would be more satisfying to both pointer-ers and math-ers.
>
> 1. Its not already taken!
> . . . . .
> n. Its easier to type than Karl's *^.
The reason I mentioned ** is that I think that every alternative mentioned
so far has something wrong with it. I see ^ as xor and ^^ bothers me.
As it happens *^ doesn't bother me but my feeling was that 99% of the
deamand for an exponentiation operator comes from current or past Fortran
users and - in my experience - they always ask for ** and are unsatisfied
with the explanations of why they can't have that syntax.
How frequent is a**p anyway? (has anyone got any data?) How confusing
would it really be? Many people use spaces to clarify (to their eyes,
if not to everyone else's) code, e.g. a * *p. Also, not all overloading
creates confusion, especially when identifier names are chosen with
a minimum of care (want would x**e mean? a**xptr mean?). I doubt the
case is clear cut.
I am not arguing that ** is THE right solution, but that given the
demand for it and the lack of ginuinely nice alternatives ** should
not be written off without a thought and/or in the belief that it
is technically infeasible to provide it.
Author: jbuck@ohm.berkeley.edu (Joe Buck)
Date: 14 Sep 1992 17:30:30 GMT Raw View
>How frequent is a**p anyway? (has anyone got any data?) How confusing
>would it really be? Many people use spaces to clarify (to their eyes,
>if not to everyone else's) code, e.g. a * *p. Also, not all overloading
>creates confusion, especially when identifier names are chosen with
>a minimum of care (want would x**e mean? a**xptr mean?). I doubt the
>case is clear cut.
About the most frequent operation in digital signal processing is some
form of the dot product. Consider
double dotProduct(double *x, double *y, int n) {
double sum = 0.0;
while (--n >= 0) sum += *x++ * *y++;
return sum;
}
I guarantee (as someone who's written a large amount of numerical C
and C++ code) that there is a great deal of code of the above type,
and while I'm generally careful to space it as above, I've seen code
that doesn't have this spacing.
You'd break programs, no ifs, ands, or buts about it. It's true that
this breakage would be detected at compile time (the right argument to
'**' would be a pointer).
As Dr. Stroustrup suggested, an alternative would be to have '*' '*'
mean exponentiation and handle x '*' '*' ptr as a special case, so
it would keep its meaning of dereference-and-multiply. That would
work, as best I can tell, for C, but in C++, '*' might be overloaded
for the unary or binary case. This hack wouldn't work then or would
cause nasty surprises.
I think Matt Austern's analysis is basically correct: the exponentiation
operator should be a token, one not appearing in the language currently
so that it cannot break existing programs. Those in favor of ** must
show, IMHO, that it would break virtually no programs, and this can't
be done without introducing a series of hacks. If every other language
used **, this would be a strong argument in its favor, but many languages
use ^ instead.
Furthermore, there are three other considerations: the ability to construct
the corresponding assignment operator (eliminating !), the
internationalization issues (eliminating several characters like @ that
aren't on all keyboards), and avoiding breaking analogies between
operators (there is a relation between & and &&, and | and ||, which
should not be violated for ^ and ^^).
>I am not arguing that ** is THE right solution, but that given the
>demand for it and the lack of ginuinely nice alternatives ** should
>not be written off without a thought and/or in the belief that it
>is technically infeasible to provide it.
Before Fortran, no one thought ** should mean exponentiation. Any
reasonable token choice that doesn't violate one of the above
considerations will work. Austern's *^ is as good as any.
--
Joe Buck jbuck@ohm.berkeley.edu
Author: hbf@durin.uio.no (Hallvard B Furuseth)
Date: Mon, 14 Sep 1992 19:53:33 GMT Raw View
Sorry, I just cancelled an article where a rather essential part was
deleted (I just intended to move it...) Here is next attempt -
In article <23660@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
> (2) I think we could actually get ** as the exponentiation operator.
> (...)
> All we need to do is to say that the exponentiation
> operator ** given a first operand `a' of arithmetic type
> and a second operand `b' of pointer type (that is, `a**b')
> mean multiply the first operand with the dereference value
> of the second operand (that is, `a*(*b)').
The few times I use a**b, a and *b are usually class objects. operator*
could be cross product or a set operation. b.operator*() may exist too,
but to me that is less important. To allow both this and Complex
operator**(Complex&,Complex&), I think the rule must be something like
"** is exponentiation unless that is an error". I do not volunteer to
write the parser though. A binary operator~ is my favorite.
--
Hallvard
Author: jk87377@cc.tut.fi (Juhana Kouhia)
Date: Tue, 15 Sep 92 05:42:26 GMT Raw View
Hi,
I'm very new in C++ world; I have not done any programs so far;
and I'm currently reading C++ Primer books on chapter 3 :-)
Instead of making exponential operator; I would like to get
a new basic operation which allows programmer to define new
operations like 'a ** b'; that is, the '**' is defined.
('a pow b' is also good.)
The operation '**' may hide freely some other operations;
like, maybe, 'c ** **p' which should be written 'c ** (**p)'
(maybe poor example; I write always clearly anyway and don't
study those ****a*******b**** hacker tricks).
Juhana Kouhia
Author: matt@physics2.berkeley.edu (Matt Austern)
Date: 14 Sep 92 22:50:05 Raw View
Recently, Bjarne Stroustrup suggested that it would be possible for
the exponentiation operator to be denoted **. At first sight this
appears to be impossible, since ** already has a very different
meaning in C++, and previous discussions of an exponentiation operator
(mine included) have dismissed this possibility without further
analysis.
This has been excessively hasty. Exponentiation is only defined if
both operands are of a numeric type; conversely, ** is currently
meaningful only if it precedes a pointer. There is no overlap, so it
might, therefore, be possible to use type information to disambiguate
these different uses of **.
Specifically, we might consider the following proposal:
--------------------------------------------------------------------
Two new tokens, ** and **=, will be added to the C++ language. **
will be both a unary and a binary operator. Unary ** will have
the same precedence as the other unary operators, and binary **
will have a new precedence level between the multiplicative
operators and the pointer-to-member operators.
Unary ** is defined only for an operand which is a pointer to a
pointer, and it will mean to dereference that operand twice.
If the arguments to binary ** are both of a numeric type, then it
denotes exponentiation, and its semantics will be those described
by my earlier proposal. If its first operand is of a numeric type
and its second is a pointer to a number, then it means to multiply
the first operand by the contents of the second. For other
combinations of argument types, binary ** is undefined.
**= is defined only for the case where the first operand is a
modifiable lvalue of a numeric type and the second operand is an
object of a numeric type; it is defined the same way as the other
op= operators.
**=, and unary and binary **, may be overloaded by the user if
at least one argument is a class.
----------------------------------------------------------------------
This proposal does, at least, implement ** as an exponentiation
operator while continuing to allow its current uses. However, it
presents several difficulties.
First, it breaks existing code. To see why it must do so, notice that
in current C++, ** is not a single token; it is a sequence of either a
binary operator followed by a unary operator, or else two unary
operators. The difficulty is that the binary and the unary operators
have different precedence. So, in particular, consider the expression
x/y**p,
which, by the current language definition, is equivalent to
(x/y) * (*p).
According to the proposal above, however, ** is a single token with a
precedence higher than division, so this expression will mean
x / (y * (*p)).
I don't know how much code actually contains expressions like this,
but it isn't unreasonable to assume that at least some does.
Second, even in code which won't be broken by this change in the
behavior of **, users will have to examine their code to make sure
that it still means what they thought it did. ** is a common enough
character sequence (consider, for example, the idiom **argv) that most
programmers will at least have to glance at their code, even if
nothing actually needs to be changed.
Third, the disambiguation rules don't go far enough: they solve the
problem for built-in types, but not for class types. Users who define
``smart pointers'' will want the dereference operator to work the same
way for their smart pointers as for ordinary C pointers, so, if they
overload unary * to mean smart pointer dereference, they will
similarly be forced to overload unary and binary **. This imposes an
additional burden on people who use a rather common programming
technique.
** does have one potential advantage over *^ as an exponentiation
operator: that is how exponentiation is denoted in FORTRAN. I regard
that as a small advantage, however; there is nothing particularly
natural about FORTRAN's use of that symbol, and I believe that
scientific programmers could get used to *^ just as easily as they got
used to the once-unfamiliar **. In fact, it isn't completely clear to
me that ** would really be more readable as a C++ exponentiation
operator than *^ would be: scientific programmers, like other
programmers, would have to cope with the multiple meanings of **.
I believe that an exponentiation operator would be of genuine benefit
to C++ scientific programmers, and I believe that we who write
scientific code are justified in asking that it be included. I don't
think, however, that we are justified in asking for a change to the
language that makes life harder for other C++ programmers. Using **
to denote exponentiation does exactly that: it changes the meaning of
legal C++ code, and it makes a useful programming technique more
difficult.
It is possible to implement an exponentiation operator so that the
extension to the language will have no effect at all for people who
don't deliberately use the new feature. This is a better idea.
--
Matthew Austern Just keep yelling until you attract a
(510) 644-2618 crowd, then a constituency, a movement, a
austern@lbl.bitnet faction, an army! If you don't have any
matt@physics.berkeley.edu solutions, become a part of the problem!
Author: dag@control.lth.se (Dag Bruck)
Date: Tue, 15 Sep 1992 06:16:26 GMT Raw View
In <comp.std.c++,comp.lang.c++> bs@alice.att.com (Bjarne Stroustrup) writes:
>
>How frequent is a**p anyway?
I asked the net how frequent exponentiation is, and got very few
answers back; there are some interesting observations, though. Nobody
took the offer to look at the really big FORTRAN libraries. In my
view the results are inconclusive at this point.
I haven't looked at the latest version of the proposal, but I strongly
ask the authors to support their requests with solid user's experience
from related applications, not necessarily in C++. If you can show
that exponentiation is more common than division (just as an example),
that is indeed a very strong argument. Sorry to nit pick if you have
already done it.
In any case, here follows the answers I got, somewhat edited for
clarity:
-- Dag
========================================================================
From: matt@physics.berkeley.edu (Matt Austern)
Subject: Re: Power operator for C++
Date: 6 Jul 92 14:28:39
Organization: Lawrence Berkeley Laboratory (Theoretical Physics Group)
In article <1992Jul5.133125.5575@lth.se> dag@control.lth.se (Dag Bruck) writes:
> I ask someone with access to a lot of numerical code (perhaps written
> in FORTRAN) to do us a favour: gather some statistics that can tell us
> how common exponentiation is compared to other operators, such as,
> addition, subtraction, multiplication and division. Compared to
> square root?
I just did a bit of grepping on a moderate-sized (30,000 lines)
Fortran program, called Papageno. I suspect that it is fairly typical
of code used in particle physics.
Some statistics:
Operator Number of lines containing operator
-------- -----------------------------------
total 32000
+ 10711
* 6805
- 6253
/ 3382
** 1481
The result, then, is that exponentiation is about half as common in
this program as division. To me, at least, this qualifies as
"common". Certainly nobody would suggest that a division operator is
unnecessary just because it is used only half as much as subtraction!
(Many lines uses exponentiation more than once; in total, the operator
** is used 4496 times in PAPAGENO.)
Looking over the code, by the way, it seems that the vast majority of
the time, ** is used to raise a quantity to an integral power. (I
didn't gather statistics; that would require more effort than a simple
grep!) This suggests that pow(double,double) is not a good
substitute; a better substitute would be pow(double,int), which is not
in the standard library.
From: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Subject: Re: Power operator for C++
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Mon, 6 Jul 1992 06:22:57 GMT
I have a program which calculates gaussian dispersion of
toxic materials in air. In the bits that do calculations work,
here are the scores in terms of line counts
[I did grep token file | wc]
Lines total: 172
+ 27
- 24
* 25
/ 32
% 2
=,==,etc 79
pow 13
fsqr 12 // inline to square number
sqrt 3
IMHO if you cheat a bit and add the last three you get 28, second
only to use of '/'. I'd be happy to post the code if that was
desired [minus flames on style :-)
Date: Tue, 7 Jul 92 17:11:44 -0700
From: Paul Kunz <pfkeb@KAON.SLAC.Stanford.EDU>
Subject: Power operator for C++
I asked Bill Atwood about what happen to **2 type constructs in
Gismo. He looked puzzled. He agrees that in the FORTRAN programs
the code is littered with **2, but he's not sure what happened to
such constructs in the Gismo C++ code. Perhaps they have disappeared
into member functions of some base or low level classes so they are
not so visible anymore. We don't know.
Author: menden@Informatik.TU-Muenchen.DE (Juergen Menden)
Date: Tue, 15 Sep 1992 09:41:46 GMT Raw View
Hi,
just an idea: how about
a ^^ b;
--
Juergen Menden menden@informatik.tu-muenchen.de
Author: pjl@sparc10.cs.uiuc.edu (Paul Lucas)
Date: Tue, 15 Sep 1992 14:00:27 GMT Raw View
In <1992Sep15.054226.4126@cc.tut.fi> jk87377@cc.tut.fi (Juhana Kouhia) writes:
>Hi,
>I'm very new in C++ world; I have not done any programs so far;
>and I'm currently reading C++ Primer books on chapter 3 :-)
>Instead of making exponential operator; I would like to get
>a new basic operation which allows programmer to define new
>operations like 'a ** b'; that is, the '**' is defined.
>('a pow b' is also good.)
*****> The short answer is that it's a _real_ pain. The somewhat
longer answer is that making new operators means that you have
to also establish the precedence and associativity of the new
operator relative to all the other operators *AND* any other
operators created by other people. Every time an operator is
added, the hierarchy would have to be readjusted.
For new operators, the precedence and associativity may seem
arbitary at the time of creation, but it may later be realised,
after experience, that it could have been done better...of
course it's too late to change it now because code would break.
Also, if you were to use library X and library Y, each could use
the same operator for different reasons, and the two operators
were developed without regard to the others precedence and
associativity; how would the compiler resolve this? (I'm not
looking for people to show how smart they are here by telling me
how a compiler could resolve this...the point is that even if
the compiler could do it, most _people_ would have a tough time
looking at the code.)
It's more trouble than its worth. The _point_ of operator
overloading is to give an operator a _natural_ extension to
another type. People shouldn't sit around trying to figure out
how to force an operator (square peg) to be used for a new type
(round hole). If the operator's use in a new context isn't
intuitively obvious, forget it and use function-notation.
--
- Paul J. Lucas University of Illinois
AT&T Bell Laboratories at Urbana-Champaign
Naperville, IL pjl@cs.uiuc.edu
Author: sjm@bcrki65.bnr.ca (Stuart MacMartin)
Date: Tue, 15 Sep 1992 14:19:40 GMT Raw View
In article <23663@alice.att.com> bs@alice.att.com (Bjarne Stroustrup) writes:
>How frequent is a**p anyway? (has anyone got any data?)
I always avoid ** when I mean a mixture of multiplication and dereference
(in C). I use parentheses to make it clear what is dereference and what
is multiplication. Thus I would always write: a * (*p)
Or, in the case of a***p, I would write: a * (**p)
There are two situations where I might have generated a**p accidentally:
1. #define THE_VALUE *p /* This is C code. Should be (*p) anyway */
a*THE_VALUE
2. a*i
global change of i to *p
Case 1 should not show up in C++ code and is poor style in C code
because of the missing parentheses in the #define.
Case 2 should be a global change to (*p) anyway because of the
danger of a/i being changed to a/*p (comment!)
So no, I do not intentionally generate code of the problem form.
I have seen such code, but only in code that I consider a nightmare
to read and maintain anyway. Keep in mind also that I know of the
"global change results in comment" problem, so that means there must
be some a**p code around here generated that way.
Stuart
--
: Stuart MacMartin email: sjm@bnr.ca :
: Bell-Northern Research phone: (613) 763-5625 :
: PO Box 3511, Stn C, Ottawa, K1Y-4H7, CANADA Standard disclaimers apply. :
Author: hosken@spss.com (Bill Hosken)
Date: 15 Sep 92 14:51:19 GMT Raw View
In article <1992Sep15.140027.17387@sunb10.cs.uiuc.edu>, pjl@sparc10.cs.uiuc.edu (Paul Lucas) writes:
> In <1992Sep15.054226.4126@cc.tut.fi> jk87377@cc.tut.fi (Juhana Kouhia) writes:
>
> >Hi,
>
> >I'm very new in C++ world; I have not done any programs so far;
> >and I'm currently reading C++ Primer books on chapter 3 :-)
>
> >Instead of making exponential operator; I would like to get
> >a new basic operation which allows programmer to define new
> >operations like 'a ** b'; that is, the '**' is defined.
> >('a pow b' is also good.)
>
> *****> The short answer is that it's a _real_ pain. The somewhat
> longer answer is that making new operators means that you have
> to also establish the precedence and associativity of the new
> operator relative to all the other operators *AND* any other
> operators created by other people. Every time an operator is
> added, the hierarchy would have to be readjusted.
>
> For new operators, the precedence and associativity may seem
> arbitary at the time of creation, but it may later be realised,
> after experience, that it could have been done better...of
> course it's too late to change it now because code would break.
>
> Also, if you were to use library X and library Y, each could use
> the same operator for different reasons, and the two operators
> were developed without regard to the others precedence and
> associativity; how would the compiler resolve this? (I'm not
> looking for people to show how smart they are here by telling me
> how a compiler could resolve this...the point is that even if
> the compiler could do it, most _people_ would have a tough time
> looking at the code.)
>
> It's more trouble than its worth. The _point_ of operator
> overloading is to give an operator a _natural_ extension to
> another type. People shouldn't sit around trying to figure out
> how to force an operator (square peg) to be used for a new type
> (round hole). If the operator's use in a new context isn't
> intuitively obvious, forget it and use function-notation.
To illustrate these points, consider the << operator.
cout << 1 ? 2 : 3 ;
The result is a little hard to figure out until you remember
the precedence rules.
---------------
Bill.
Author: jk87377@cc.tut.fi (Juhana Kouhia)
Date: Tue, 15 Sep 92 17:32:59 GMT Raw View
In article <1992Sep15.140027.17387@sunb10.cs.uiuc.edu>
pjl@sparc10.cs.uiuc.edu (Paul Lucas) writes:
>In <1992Sep15.054226.4126@cc.tut.fi> jk87377@cc.tut.fi (Juhana
>Kouhia) writes:
>
>>Instead of making exponential operator; I would like to get
>>a new basic operation which allows programmer to define new
>>operations like 'a ** b'; that is, the '**' is defined.
>>('a pow b' is also good.)
>
>*****> The short answer is that it's a _real_ pain. The somewhat
> longer answer is that making new operators means that you have
> to also establish the precedence and associativity of the new
> operator relative to all the other operators *AND* any other
> operators created by other people. Every time an operator is
> added, the hierarchy would have to be readjusted.
I didn't thought this.
> For new operators, the precedence and associativity may seem
> arbitary at the time of creation
At the compile time; just like functions are created.
Am I missing something? In what order the compiling the X and
the Y happens?
If X and Y provides the same function with different meanings,
how this is handled? I think the same apply to new operation.
That is, compile time error.
The same scope rules apply to the new operation too.
Lets suppose both X and Y makes the new operation to the
default operation precedence and associativity data set.
If they both offers the same operation, it is compile time error.
If both offers different operations, then this is valid.
But how to make the common operation predence and associativity
data set? I have to think about this a bit.
Just by adding the both operations to the same level?
For example,
Default set:
Level 1: * /
Level 2: + -
X:
Level 1: * / foo
Level 2: + -
Y:
Level 1: * /
Level 2: + - bar
The common set:
Level 1: * / foo
Level 2: + - bar
Juhana Kouhia
Author: gs4t@virginia.edu (Gnanasekaran Swaminathan)
Date: Tue, 15 Sep 1992 20:18:01 GMT Raw View
matt@physics2.berkeley.edu (Matt Austern) writes:
: I believe that an exponentiation operator would be of genuine benefit
: to C++ scientific programmers, and I believe that we who write
: scientific code are justified in asking that it be included. I don't
: think, however, that we are justified in asking for a change to the
: language that makes life harder for other C++ programmers. Using **
: to denote exponentiation does exactly that: it changes the meaning of
: legal C++ code, and it makes a useful programming technique more
: difficult.
:
: It is possible to implement an exponentiation operator so that the
: extension to the language will have no effect at all for people who
: don't deliberately use the new feature. This is a better idea.
Did you consider operator () for exponentiation?
It seems to have correct precedence and doesn't need new tokens to be
introduced.
// if op () is available for exp
double e= -10(2); // e = -100.0
double d=10;
double *p = &e;
e = d(3) - (*p)(2) + d + 3; // e = -8987.0
// status quo
class Double {
double d;
public:
Double(double f): d(f) {}
operator double () { return d; }
Double operator - () { return -d; }
Double operator () (int i) { ... }
Double operator () (double f) { return pow(d,f); }
// other ops ...
};
Double a(10); // a = 10.0
double d=a(5); // d = 10000.0
a = a(3.0)*2.5; // a = 2500.0
Double b(2); // b = 2
a = -b(4) + 3*b(3) - 2*b(2) + b + 3; // a = 5.0
Similary you can define your own Int as well and use it wherever
you want int and exp op.
-Sekar
Author: jfc@athena.mit.edu (John F Carr)
Date: Wed, 16 Sep 1992 00:57:48 GMT Raw View
I have implemented the exponentiation proposal for gcc and g++. Here are
the changes. This was a very quick implementation, and is intended only for
people to gain experience using the feature. I am certain there are bugs
and missing features.
Your line numbers may vary as the patches here are for the gcc development
sources, not the 2.2.2 release.
This requires one additional library routine: double __ipow(double, int)
which is like pow() except for the argument types.
add to expr.c:expand_expr()
case EXPON_EXPR:
if (target == 0)
target = gen_reg_rtx (tmode != VOIDmode
? tmode : TYPE_MODE (TREE_TYPE (exp)));
return expand_pow (exp, target);
add to expr.c:
static rtx expand_pow (exp, target)
register tree exp;
rtx target;
{
enum machine_mode tmode;
register rtx op0, op1;
tree arg0, arg1;
arg0 = TREE_OPERAND (exp, 0);
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
arg1 = TREE_OPERAND (exp, 1);
op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
tmode = GET_MODE (target);
/* Special case: -1 *^ j */
if (op0 == constm1_rtx
&& (GET_CODE (op1) == CONST_INT
|| GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT))
{
enum machine_mode op1mode = (GET_CODE (op1) == CONST_INT
? tmode : (enum machine_mode)GET_MODE (op1));
#if BITS_BIG_ENDIAN
return extract_bit_field (op1, 1, GET_MODE_BITSIZE (op1mode), 0,
target, op1mode, tmode,
GET_MODE_BITSIZE (op1mode),
GET_MODE_BITSIZE (op1mode));
#else
return extract_bit_field (op1, 1, 0, 0, target, op1mode, tmode,
GET_MODE_BITSIZE (op1mode),
GET_MODE_BITSIZE (op1mode));
#endif
}
/* Optimize small integer exponents. */
if (GET_CODE (op1) == CONST_INT)
{
rtx tmp = op0;
switch (INTVAL (op1))
{
case 0:
return const_tiny_rtx[1][tmode];
case 1:
return op0;
case 3:
tmp = expand_mult (tmode, op0, op0, NULL_RTX, 0);
/* fall through */
case 2:
return expand_mult (tmode, op0, tmp, target, 0);
case -1:
if (GET_MODE_CLASS (tmode) == MODE_FLOAT)
return expand_binop (tmode, flodiv_optab, const_tiny_rtx[1][tmode],
op0, target, 0, OPTAB_LIB_WIDEN);
}
}
/* For now, always pass a floating point first argument to the
library function. */
if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE)
{
rtx tmp = gen_reg_rtx (DFmode);
expand_float (tmp, op0, 0);
op0 = tmp;
}
if (GET_CODE (op1) == CONST_INT
|| GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT)
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__ipow"), 1,
DFmode, 2, op0, DFmode, op1, SImode);
else
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "pow"), 1,
DFmode, 2, op0, DFmode,
convert_to_mode (DFmode, op1, 0),
DFmode);
if (GET_MODE_CLASS (GET_MODE (target)) == MODE_INT)
expand_fix (target, hard_libcall_value (DFmode), 0);
else
convert_move (target, hard_libcall_value (DFmode));
return target;
}
add to c-typeck.c:build_binary_op and cp-typeck.c:build_binary_op_nodefault()
case EXPON_EXPR:
/* Rules for exponent: type of result is always converted type of LHS.
If RHS is integer, no conversions.
If RHS is real and LHS is integer, convert LHS to RHS. */
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& code1 == INTEGER_TYPE)
{
result_type = type0;
converted = 1;
}
else if (code0 == REAL_TYPE && code1 == REAL_TYPE)
{
result_type = type0;
converted = 1;
}
else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
{
op0 = convert (type1, op0);
result_type = type1;
converted = 1;
}
break;
*** cp-parse.y.orig Thu Sep 3 22:27:15 1992
--- cp-parse.y Sat Sep 12 13:11:06 1992
***************
*** 190,195 ****
--- 190,196 ----
%left <code> '+' '-'
%left <code> '*' '/' '%'
%right <code> UNARY PLUSPLUS MINUSMINUS
+ %right <code> EXPON
%left HYPERUNARY
%left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
%left <code> POINTSAT POINTSAT_STAR '.' DOT_STAR '(' '['
***************
*** 1209,1214 ****
--- 1210,1217 ----
{ $$ = build_x_binary_op ($2, $$, $3); }
| expr_no_commas '*' expr_no_commas
{ $$ = build_x_binary_op ($2, $$, $3); }
+ | expr_no_commas EXPON expr_no_commas
+ { $$ = build_x_binary_op ($2, $$, $3); }
| expr_no_commas '/' expr_no_commas
{ $$ = build_x_binary_op ($2, $$, $3); }
| expr_no_commas '%' expr_no_commas
***************
*** 3736,3741 ****
--- 3739,3746 ----
operator_name:
OPERATOR '*'
{ $$ = ansi_opname[MULT_EXPR]; }
+ | OPERATOR EXPON
+ { $$ = ansi_opname[EXPON_EXPR]; }
| OPERATOR '/'
{ $$ = ansi_opname[TRUNC_DIV_EXPR]; }
| OPERATOR '%'
*** c-parse.y Wed Aug 26 20:42:25 1992
--- c-parse.y Sun Sep 13 12:30:22 1992
***************
*** 130,135 ****
--- 130,136 ----
%left <code> '+' '-'
%left <code> '*' '/' '%'
%right <code> UNARY PLUSPLUS MINUSMINUS
+ %right <code> EXPON
%left HYPERUNARY
%left <code> POINTSAT '.' '(' '['
***************
*** 402,407 ****
--- 403,410 ----
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas '*' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
+ | expr_no_commas EXPON expr_no_commas
+ { $$ = parser_build_binary_op ($2, $$, $3); }
| expr_no_commas '/' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas '%' expr_no_commas
*** c-lex.c Tue Sep 1 20:23:56 1992
--- c-lex.c Sun Sep 13 12:34:45 1992
***************
*** 1889,1894 ****
--- 1889,1910 ----
}
else if ((c == '-') && (c1 == '>'))
{ value = POINTSAT; goto done; }
+ else if (c == '*' && c1 == '^')
+ {
+ yylval.code = EXPON_EXPR;
+ token_buffer[2] = c1 = getc (finput);
+ if (c1 == '=')
+ {
+ value = ASSIGN;
+ goto done;
+ }
+ ungetc (c1, finput);
+ token_buffer[2] = 0;
+ value = EXPON;
+ goto done;
+ }
+
+
ungetc (c1, finput);
token_buffer[1] = 0;
*** cp-lex.c.orig Thu Sep 3 22:27:06 1992
--- cp-lex.c Sat Sep 12 13:30:12 1992
***************
*** 480,485 ****
--- 485,492 ----
ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
+ ansi_opname[(int) EXPON_EXPR] = get_identifier ("__exp");
+ IDENTIFIER_OPNAME_P (ansi_opname[(int) EXPON_EXPR]) = 1;
ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
***************
*** 658,663 ****
--- 665,671 ----
opname_tab[(int) PLUS_EXPR] = "+";
opname_tab[(int) MINUS_EXPR] = "-";
opname_tab[(int) MULT_EXPR] = "*";
+ opname_tab[(int) EXPON_EXPR] = "*^";
opname_tab[(int) TRUNC_DIV_EXPR] = "/";
opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
***************
*** 707,712 ****
--- 715,721 ----
assignop_tab[(int) MINUS_EXPR] = "-=";
assignop_tab[(int) NEGATE_EXPR] = "-=";
assignop_tab[(int) MULT_EXPR] = "*=";
+ assignop_tab[(int) MULT_EXPR] = "*^=";
assignop_tab[(int) INDIRECT_REF] = "*=";
assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
***************
*** 3592,3597 ****
--- 3605,3626 ----
token_buffer);
goto done;
}
+ else if (c == '*' && c1 == '^')
+ {
+ c1 = getch ();
+ yylval.code = EXPON_EXPR;
+ if (c1 == '=')
+ {
+ value = ASSIGN;
+ nextchar = -1;
+ }
+ else
+ {
+ value = EXPON;
+ nextchar = c1;
+ }
+ goto done;
+ }
nextchar = c1;
token_buffer[1] = 0;
*** c-common.c.orig Tue Jul 28 23:46:51 1992
--- c-common.c Sat Sep 12 13:45:45 1992
***************
*** 476,481 ****
--- 476,483 ----
case LROTATE_EXPR:
case RROTATE_EXPR:
opname = "rotate"; break;
+ case EXPON_EXPR:
+ opname = "exponentiation"; break;
}
error ("invalid operands to binary %s", opname);
}
--
John Carr (jfc@athena.mit.edu)
Author: kers@hplb.hpl.hp.com (Chris Dollin)
Date: Wed, 16 Sep 1992 08:34:22 GMT Raw View
Why not just give all ``new'' operators the same precedence and associativity?
Advantages: easy for the machine to parse. Easy for *people* to parse -- you
don't need to see the operator declaration to know the operand binding. Even
the *compiler* doesn't need to have seen the operator declaration (not useful
in C++, apart from avoiding peculiar syntax errors, but generally noteworthy).
Disadvantages: Can't mimic the ``natural'' precedences of some domains
collection of operators. If the standard precedence is ``wrong'', it will all
be horrid to read anyway.
I think the ads outweigh the diss, but I'm hardly a fair sample. I'd also vote
for a way of making *any* dyadic function infix, as in (say)
e1 @f e2 => f( e1, e2 ) or e1.f( e2 )
-- such infixes to have the same precedence os the user-operators, of course.
Note that ``f'' might well be an expression (and thus will often need to be in
parentheses when it's not an indetifier).
I'd much rather write ``n @max m'' than ``max( n, m )'', and even more so with
an expression such as ``n @max m @max p''.
For the record, I'd pick left associative, and a precedence just a little more
binding than ``=''.
--
Regards, | "If taking devious pains was a sign of laziness, he was quite
Kers. | prepared to call Hazelton the laziest man alive." Blish (m-o-l)
Author: jcoxhead@acorn.co.uk (Jonathan Coxhead)
Date: 16 Sep 92 11:59:30 GMT Raw View
I think ^^ would be best for exponentiation: the only reasons I have seen
against it are that it looks as though it should be a logical exclusive
disjunction.
This seems to me to be a false analogy. Consider
(&, &&) bitwise vs logical conjunction
(|, ||) bitwise vs logical disjunction
(<, <<) comparison vs left shift
(>, >>) oomparison vs right shift
(=, ==) assignment vs equality
(+, ++) sum or identity vs increment (pre or post)
(-, --) difference or negation vs decrement
and even
(/, //) quotient vs comment (!)
There is no pattern here - surely it isn't too hard to think of
(^, ^^) bitwise exclusive disjunction vs exponentiation
in the same spirit?
The argument that ^^ be reserved for possible use as logical exclusive
disjunction is even further weakened by two more facts: the fact that it
doesn't make sense as a sequencing operator (you always need to evaluate
both operands), and the fact that it's already in the language, at least
between operands already known to be 0 or 1, although it's spelled '!='
rather than '^^' (and even in the general case, 'log_xor (a, b)' is just
'!a != !b').
/|
(_|/
/|
(_/
Author: somerville@BAEPV3.NCSU.EDU (SOMERVILLE)
Date: Wed, 16 Sep 1992 14:30:08 GMT Raw View
In article <18680@acorn.co.uk>, jcoxhead@acorn.co.uk (Jonathan Coxhead) writes:
> I think ^^ would be best for exponentiation: the only reasons I have seen
>against it are that it looks as though it should be a logical exclusive
>disjunction.
>
>There is no pattern here - surely it isn't too hard to think of
>
> (^, ^^) bitwise exclusive disjunction vs exponentiation
>
>in the same spirit?
I agree.
We might think that FORTRAN programmers want ** as the operator.
As it is, perhaps they must look twice whenever they see **, and
remind themselves that ** is not exponentiation in C++.
If ** is chosen for the operator, they will almost certainly
have to look twice. C programmers now must look twice also,
and remind themselves that ** is the exponentiation operator.
At least using ^^ doesn't cause anyone to look twice. And as
Jonathan points out above, its relationship to operator ^ is
no lacking than some other operators.
--
Garth Somerville
somerville@bae.ncsu.edu
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 16 Sep 92 17:35:27 GMT Raw View
kers@hplb.hpl.hp.com (Chris Dollin @ Hewlett-Packard Laboratories, Bristol, UK.) writes
> Why not just give all ``new'' operators the same precedence and associativity?
> ...
> For the record, I'd pick left associative, and a precedence just a little more
> binding than ``=''.
One problem is that this will leave people wanting an exponentiation
operator unhappy because
a * b pow c
would mean
(a*b) pow c.
The other ``obious'' alternative for precedence, a little above
multiply, solves this case, but has in my experience always generated
similar objections from other users.
Author: cflatter@nrao.edu (Chris Flatters)
Date: Wed, 16 Sep 1992 16:51:38 GMT Raw View
In article 92Sep16093422@cdollin.hpl.hp.com, kers@hplb.hpl.hp.com (Chris Dollin) writes:
>
>Why not just give all ``new'' operators the same precedence and associativity?
>
>Advantages: easy for the machine to parse. Easy for *people* to parse -- you
>don't need to see the operator declaration to know the operand binding. Even
>the *compiler* doesn't need to have seen the operator declaration (not useful
>in C++, apart from avoiding peculiar syntax errors, but generally noteworthy).
>
>Disadvantages: Can't mimic the ``natural'' precedences of some domains
>collection of operators. If the standard precedence is ``wrong'', it will all
>be horrid to read anyway.
This is essentially what happens in Fortran 90: defined unary operators are
given highest precedence and defined binary operators are given lowest precedence.
Defined operators must also match a specific token pattern (specifically,
"." (letter)+ "."); if the form of the defined operator was unconstrained it
would be unrealistically difficult to write a lexer that could identify
programmer-defined operators.
Chris Flatters
cflatter@nrao.edu
Author: Stefan Monnier <sm86+@andrew.cmu.edu>
Date: Wed, 16 Sep 1992 14:32:55 -0400 Raw View
Excerpts from netnews.comp.lang.c++: 15-Sep-92 Re: Exponentiation
operator.. G. Swaminathan@virginia. (1548)
> matt@physics2.berkeley.edu (Matt Austern) writes:
> Did you consider operator () for exponentiation?
> It seems to have correct precedence and doesn't need new tokens to be
> introduced.
> // if op () is available for exp
> double e= -10(2); // e = -100.0
> double d=10;
> double *p = &e;
> e = d(3) - (*p)(2) + d + 3; // e = -8987.0
> // status quo
> class Double {
> double d;
> public:
> Double(double f): d(f) {}
> operator double () { return d; }
> Double operator - () { return -d; }
> Double operator () (int i) { ... }
> Double operator () (double f) { return pow(d,f); }
> // other ops ...
> };
> Similary you can define your own Int as well and use it wherever
> you want int and exp op.
> -Sekar
Well, instead of ** or ^^ or (), I suggest #$%^&%$# !
It isn't used right now, and you can type it with power !
Seriously: what's the problem with pow(a,b) ?
As far as I can see, a lot of special chars are already used, so
that either you add a new char or you use the function call
notation. Characters left are (as far as I know):
#, %%, @
If I had to choose, I would choose @ (but I heard that some
keyboard don't have it...)
Stefan Monnier
Author: Stefan Monnier <sm86+@andrew.cmu.edu>
Date: Wed, 16 Sep 1992 20:42:17 -0400 Raw View
Excerpts from netnews.comp.lang.c++: 16-Sep-92 Re: Exponentiation
operator.. Jonathan Coxhead@acorn.c (1243)
> I think ^^ would be best for exponentiation: the only reasons I have seen
> against it are that it looks as though it should be a logical exclusive
> disjunction.
> This seems to me to be a false analogy. Consider
> (&, &&) bitwise vs logical conjunction
> (|, ||) bitwise vs logical disjunction
> (<, <<) comparison vs left shift
> (>, >>) oomparison vs right shift
> (=, ==) assignment vs equality
> (+, ++) sum or identity vs increment (pre or post)
> (-, --) difference or negation vs decrement
&,| are boolean operators. <, >, =, +, - and even / are not !
> and even
> (/, //) quotient vs comment (!)
> There is no pattern here - surely it isn't too hard to think of
> (^, ^^) bitwise exclusive disjunction vs exponentiation
> in the same spirit?
> The argument that ^^ be reserved for possible use as logical exclusive
> disjunction is even further weakened by two more facts: the fact that it
> doesn't make sense as a sequencing operator (you always need to evaluate
> both operands), and the fact that it's already in the language, at least
> between operands already known to be 0 or 1, although it's spelled '!='
> rather than '^^' (and even in the general case, 'log_xor (a, b)' is just
> '!a != !b').
Are you sure it is always the case ?
the '!=' can be implemented as 'xor' or as 'minus' !!
And what's the use of '!' in '!a' and '!b' ? I may be missing something !
> /|
> (_|/
> /|
> (_/
Stefan Monnier
-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------
Author: kenk@sdc.com (Ken Konecki)
Date: 16 Sep 92 13:40:13 GMT Raw View
In article <1992Sep14.073952.5239@ima.isc.com> karl@ima.isc.com (Karl Heuer) writes:
>In article <BuJJxs.8Hx@world.std.com> rr@world.std.com (Robert I Ransbottom) writes:
>>[How about spelling it "^^", then?]
>
>Some people still hope to adopt that symbol for boolean xor. (I don't,
>but I don't want to stand in the way of those who do.)
I know I'm coming in late on this, but do we really need an
operator for something that can be done quite succinctly via an inline
function or macro:
#define LXOR(a,b) ((!(a)&&(b)) || (!(b)&&(a)))
inline int lxor(int a, int b) { return ((!(a)&&(b)) || (!(b)&&(a))); }
Seems like operator bloat to me.
Cheers,
-Ken K
--
Ken Konecki
e-mail:kenk@sdc.com -or- ...!uunet!tellab5!sdc!kenk
"I just found out that the brain is like a computer. If that's true,
then there really aren't any stupid people. Just people running DOS."
Author: kers@hplb.hpl.hp.com (Chris Dollin)
Date: Thu, 17 Sep 1992 08:53:45 GMT Raw View
In article ... bs@alice.att.com (Bjarne Stroustrup) writes:
kers@hplb.hpl.hp.com (Chris Dollin @ HP Laboratories, Bristol, UK.) writes
> Why not just give all ``new'' operators the same precedence and
>associativity?
> ...
> For the record, I'd pick left associative, and a precedence just a
>little more binding than ``=''.
One problem is that this will leave people wanting an exponentiation
operator unhappy because
a * b pow c
would mean
(a*b) pow c.
The other ``obious'' alternative for precedence, a little above
multiply, solves this case, but has in my experience always generated
similar objections from other users.
Yes, I agree -- for ** it is an unfortunate choice. I intended my remark to
apply to those operators that J. Random would introduce; I think there's a good
case for the exponentiation operator being known to the language.
Of course, owners of other interesting operators might wish to make the same
case ...
--
Regards, | "If taking devious pains was a sign of laziness, he was quite
Kers. | prepared to call Hazelton the laziest man alive." Blish (m-o-l)