[comp.lang.c] Power proposal for ANSI C

dgh%dgh@Sun.COM (David Hough) (01/10/88)

	I didn't think X3J11 would ever go for it,
but now Doug Gwyn at least says he might support adding 
a power operator IF ANSI C has to go through a third 
public review period for some OTHER reason.

	With that degree of encouragement (coupled with
the recent outpouring on comp.lang.c on this subject)
I've added the following item to my list of 25 suggestions
to be submitted to X3J11 at the next public review.
Interestingly enough, although over 100 mathematical
software people have looked at previous versions of my
commentary, none of them so far has made a big deal
about a power operator.  Like me, they may not have
thought it would ever be accepted.


Comment #9, Section 3.3.4:      add power operator for
-------  -  ------- - - -       --- ----- -------- ---
integral exponents
-------- ---------

     C does not provide a power or exponentiation operator,
like Pascal (which however provides a squaring operator),
but unlike Fortran ** or Basic ^ .  C's original system
programming motivation does not require such an operator,
and C's general approach is that operations that can not be
implemented in a few machine instructions should be invoked
as functions.  Based on Fortran experience, this is
excellent design; it discourages the common Fortran codings
"x**0.5" and "x**2.0".  Conversely, omitting an easy way to
say "x**2" for complicated expressions x is a C oversight
that adds gratuitous complexity to code.

     The complexity of general exponentiation to a
floating-point power is sufficiently attested by the fact
that such an operator was dropped from the final MC68881
architecture due to lack of microcode space in the initial
implementation.  Therefore I don't advocate that C add an
operator notation for floating-point powers (although later
--------
I advocate that pow() be made an operator in functional
                                             ----------
notation).  I do advocate that an operator notation for
exponentiation to integral powers be added.  That some
convenient syntax be standardized is more important than the
specific syntax, and X3J11 is probably best qualified to
choose from various alternative candidates such as **, ^^,
->, etc.  Anybody who has written x**y or x ** y in old C
code, intending x * *y, has probably done some other things
that won't pass an ANSI C compiler.  But ANSI C could be
defined to accept x**y in its old meaning as well as x**y in
its new since y must be a pointer in the first case and an
integral expression in the second.  But I doubt that's
worthwhile.

     To best correspond to the usage of mathematics and
other computer languages, the precedence of ** must be
greater than that of a multiplicative or additive operator.

     Recommendation: Add a power operator **, with the
     --------------
precedence of a cast operator, so that a cast expression can
be

        cast-expression ** cast-expression

In b ** n, the base expression b may be an integral or
floating expression, but the exponent expression n must be
an integral expression.  If n == 0, then the result is 1
cast to the type of b.  If n > 0, then the result is the usual:
the value of b is multiplied together n-1 times.  If n < 0,
then the result is the reciprocal of b ** (-n), which is 0
if b is an integral expression >= 2.  Note that unlike other
operators, the "usual arithmetic conversions" are not made
to b and n; the type of the result is always that of b.

     The Rationale should encourage compilers to be clever
when n is constant -1, 0, 1, or 2, but not so clever with
other n that the intermediate results overflow or underflow
unnecessarily.  The Rationale should also encourage
compilers to compute, wherever possible, "x * b ** n" by a
shift instruction when b is the base of integer arithmetic,
and by ldexp(x,n) when b is the base of floating-point
arithmetic.


David Hough

ARPA: dhough@sun.com
UUCP: {ucbvax,decvax,allegra,decwrl,cbosgd,ihnp4,seismo}!sun!dhough

dik@cwi.nl (Dik T. Winter) (01/10/88)

In article <38384@sun.uucp> dgh%dgh@Sun.COM (David Hough) writes:
 >      Recommendation: Add a power operator **, with the
 >      --------------
 > precedence of a cast operator, so that a cast expression can
 > be
 > 
 >         cast-expression ** cast-expression
 > 
 > In b ** n, the base expression b may be an integral or
 > floating expression, but the exponent expression n must be
 > an integral expression.  If n == 0, then the result is 1
 > cast to the type of b.  If n > 0, then the result is the usual:
 > the value of b is multiplied together n-1 times.  If n < 0,
 > then the result is the reciprocal of b ** (-n), which is 0
 > if b is an integral expression >= 2.

Note that these semantics are wrong.  What if n<0 and b**(-n)
overflows while b**n does not underflow?  According to the stated
semantics this should trap an overflow or return 0.0.  On the
other hand if b**n for negative n is defined as (1/b)**(-n) we
lose precision.  So is there anybody who can come up with a proper
definition of the power operator?
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

ix426@sdcc6.ucsd.EDU (tom stockfish) (01/11/88)

In article <38384@sun.uucp> dgh%dgh@Sun.COM (David Hough) writes:
>     Recommendation: Add a power operator **, with the
>     --------------
>precedence of a cast operator, so that a cast expression can
>be
>
>        cast-expression ** cast-expression
>
>In b ** n, the base expression b may be an integral or
>floating expression, but the exponent expression n must be
>an integral expression.
>
>David Hough

This proposal will never fly as it stands.
1.	It is not in the spirit of C.
	Unlike any other C operator, a lexical analyzer will not be able to
	recognize it, since it is indistinguishable from very common
	pointer declarations, e.g., "char **argv".
2.	The meaning of C expressions is almost always independent of white
	space.  The one exception being
		a+++b
	versus
		a+ ++b.
	Even this one, however, is disambiguated by the "the longest possible
	token is the next one" rule.  You would have to invent something
	else to disambiguate
		x ** y
	from
		x * (*y).
3.	I'm not sure what precedence/associativity you have chosen for "**".
	From your posting I assume you mean that
		(double)2 ** 3
	should group as
		( (double)2 ) ** 3.
	This is disastrous.  Since unary minus has the same precedence
	as casts,
		-x**2 + x - 10
	would have to group as
		(-x) ** 2  +  x  -  10
	which is equivalent to
		x**2 + x - 10.
	(The arbitrary precision language bc(1) actually has this precedence!
	Has any other numeric user used bc for serious work?  I'd like to swap
	bug lists with you.)
	What associativity did you plan for "**"?  Left to right, or right to
	left?  All other binary operators are left to right, but this would be
	trivial for "**" since it would just collapse the exponents together:
		(x**y)**z == x**(y*z).
	Right to left associativity would be more useful, but would break the
	general rule for other C operators.  You could make it non-associative
	like fortran originally did, but then it would be C's only
	non-associative operator.

I think a good proposal would give the power operator a precedence above
unary and below primary, with right to left associativity (I believe this
is how fortran currently has it).  The only thing left to decide is how
it interacts with pre- or post-fix ++,--, and I'm not sure how that should
be done.  This should be well thought ought, and preferably implemented in
some compiler, before a proposal is submitted to X3J11.
-- 

||  Tom Stockfisch, UCSD Chemistry   tps@chem.ucsd.edu

karl@haddock.ISC.COM (Karl Heuer) (01/14/88)

In article <38384@sun.uucp> dgh%dgh@Sun.COM (David Hough) writes:
>Comment #9, Section 3.3.4:  add power operator for integral exponents

As you said, ANSI can pick whatever syntax they want; but to avoid ambiguity
Let's use "*^" when we're just arguing semantics.  I've edited the quoted
material accordingly.

>To best correspond to the usage of mathematics and other computer languages,
>the precedence of *^ must be greater than that of a multiplicative or
>additive operator.

If this were the only criterion, I'd say it should be put into a new
precedence class between unary and multiplicative.  However, this makes -x*^2
mean the "wrong" thing.  If this is a problem (apparently bc users don't
mind), my recommendation is to give it a precedence between postfix unary and
prefix unary.  (Note that "->id", ".id", "[expr]", and "(arglist)" can all be
considered postfix unary, just as "(type)" can be considered prefix unary.)
More precisely:

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

unary-expression:
	power-expression
	++ unary-expression
	-- unary-expression
	unary-operator cast-expression
	sizeof unary-expression
	sizeof ( type-name )

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

>Note that unlike other operators, the "usual arithmetic conversions" are not
>made to b and n; the type of the result is always that of b.

I'd like to mention that there is already a precedent: 1<<1L is 2, not 2L.

>If n < 0, then the result is the reciprocal of b *^ (-n), which is 0 if b is
>an integral expression >= 2.

I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.

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

dricej@drilex.UUCP (Craig Jackson) (01/18/88)

As a side note to this discussion: many people have put the famous
a+++b as one of the few seemingly ambiguous parts of C.  But a few years
ago, a colleague of mine found a bigger one: dividing by a de-referenced 
pointer:

{
   double a,b,*pc;

   . . . Give everything values

   a = b/*c;

   . . . rest of program

}

My friend spent two days looking for that one...'fortutunately', he didn't
comment the rest of the code, so he did get an 'unexpected EOF' message.
Just think of how long it would have taken to find the problem in
well-commented code.
-- 
Craig Jackson
UUCP: {harvard!axiom,linus!axiom,ll-xn}!drilex!dricej
BIX:  cjackson

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/18/88)

In article <434@drilex.UUCP> dricej@drilex.UUCP (Craig Jackson) writes:
>   a = b/*c;
>My friend spent two days looking for that one...

Did your friend learn his lesson and start using white space?

ok@quintus.UUCP (Richard A. O'Keefe) (01/18/88)

In article <434@drilex.UUCP>, dricej@drilex.UUCP (Craig Jackson) writes:
> 
>    a = b/*c;
> 
> My friend spent two days looking for that one...

When I've spent more than a few minutes on such a problem
I use 'cc -E foo.c | cb' or 'cc -E foo.c | indent' depending on
which system I'm on to see exactly what the preprocessor has
done with it.  This strips out comments too, which is why it's
a good dodge for this kind of problem.  (Couldn't happen in BCPL...)

On UNIX, it's a good idea to have a little script around:

#!/bin/sh
#NAME        badcom
#SYNOPSIS    badcom foobaz.c
#DESCRIPTION Finds (some) suspicious comment lines, namely
#	     lines where /* occurs, is not the first thing
#	     on its line, and hasn't got */ on the same line,
#	     also lines where */ occurs, is not the last
#	     thing on the line, and hasn't got /* on the
#	     same line
#OPTIONS     none
#BUGS        Doesn't know about ".." or #if 0
#	     Misses other kinds of comment error
egrep -n -e '[^ \t].*/\*|\*/.*[^ \t]' $1 | \
egrep -v -e '/\*.*\*/'

{When entering this script, replace \t by actual TAB characters.}

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/19/88)

In article <2252@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>
>mean the "wrong" thing.  If this is a problem (apparently bc users don't
>mind), my recommendation is to give it a precedence between postfix unary and
>prefix unary.  (Note that "->id", ".id", "[expr]", and "(arglist)" can all be
>considered postfix unary, just as "(type)" can be considered prefix unary.)
>More precisely:
>
>power-expression:
>	postfix-expression
>	postfix-expression *^ cast-expression
>
>unary-expression:
>	power-expression
>	++ unary-expression
>	-- unary-expression

What about 'unary-expression ++'?  Currently, this is on the same level as
pre-incrementing with the distinction being associativity.  Would you split
these two and put power between them?  Also, what would the associativity be
for power?  Would 2 *^3 *^5 be equal to 2 *^ 15 or to 2 *^ 243?

>I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.

Since we are defining the 'power' operator and not the 'integer power'
operator, 2 *^ (-1) should return (double)0.5 and then be demoted
to an integer class, if necessary.  The power operator should not return two
different numbers (other than with respect to precision) based on the types of
the arguments.  This is one of the major reasons I don't like the intro of the
power operator into C.
(BTW, maybe ANSI should define (1 << -1) as right-shifting by 1--any
response to this out there?)

Your example (2 *^-1, no parentheses around -1) is undefined because of the
way you defined your precedence; i.e., 2 *^ -1 groups as (2 *^ -) 1 (sort of).
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

ONGKENTH%NUSVM.BITNET@CUNYVM.CUNY.EDU (kenneth ong) (01/19/88)

please remove me from the info-c list. thanks!

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/20/88)

In article <2252@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
.
.If this were the only criterion, I'd say it should be put into a new
.precedence class between unary and multiplicative.  However, this makes -x*^2
.mean the "wrong" thing.  If this is a problem (apparently bc users don't
.mind), my recommendation is to give it a precedence between postfix unary and
.prefix unary.  (Note that "->id", ".id", "[expr]", and "(arglist)" can all be
.considered postfix unary, just as "(type)" can be considered prefix unary.)

Looking at my chart on precedence and associativity, I noticed that all the
unary operators are grouped together, group right to left, and are above all
the binary operators.  Putting the power operator above the unary operators
would produce lots of uncompilable statements;i.e., (++a POW ++b) would be
illegal.  (Note:  I do not consider (), [], ., or -> to be either unary or
binary; they are special operators and cannot be grouped in with the other
unary operators).  As I have said before, I do not believe that we should split
up the unary operators; too many programs are dependent on the fact that they
all have the same precedence (splitting the unaries into prefix and postfix
groups would fix the example above, however).

.I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.

One of the reasons I can't agree with this is that 2 *^ ((float)(-1)) would
work, but 2 *^ (-1) would not.  (I stated in another article what I believe 2
*^ (-1) should do *IF* we were to add the power operator, which I am against
doing.)
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

karl@haddock.ISC.COM (Karl Heuer) (01/20/88)

In article <3421@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>In article <2252@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>>power-expression:
>>	postfix-expression
>>	postfix-expression *^ cast-expression
>>
>>unary-expression:
>>	power-expression
>>	++ unary-expression
>>	-- unary-expression
[	unary-operator cast-expression
]
>What about 'unary-expression ++'?  Currently, this is on the same level as
>pre-incrementing with the distinction being associativity.

That's the way it's usually described, but an equivalent formulation is that
postfix unary has a higher precedence than prefix unary (and there's no need
to talk about "associativity" of a unary operator).  This is already in the
ANSI grammar at the "postfix-expression" level.

>Would you split these two and put power between them?

Yes.  That's what I said in the grammar as well as the English text.

>Also, what would the associativity be for power?  [2 *^ 3 *^ 5]

I believe the grammar is unambiguous.  Omitting a few trivial productions,

expression("2*^3*^5")
power-expression("2*^3*^5")
postfix-expression("2") *^ cast-expression("3*^5")
                           unary-expression("3*^5")
                           power-expression("3*^5")
                           postfix-expression("3") *^ cast-expression("5")

Thus, the parsing is 2*^(3*^5).  It can't parse as (2*^3)*^5 because "2*^3"
(without parens) is not a postfix-expression.

>>I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.
>
>Since we are defining the 'power' operator and not the 'integer power'
>operator, 2 *^ (-1) should return (double)0.5 and then be demoted
>to an integer class, if necessary.  The power operator should not return two
>different numbers ... based on the types of the arguments.  This is one of
>the major reasons I don't like the intro of the power operator into C.

Actually, we are defining several operators which share a common symbol.  Just
as the "/" symbol invokes the integer-divide operator when both operands are
integers (it most certainly does *not* invoke floating-point divide and then
truncate the result), "*^" should invoke the integer-power operator when both
operands are integers.  I thought that was the whole point!

>Your example (2 *^-1, no parentheses around -1) is undefined because of the
>way you defined your precedence; i.e., 2 *^ -1 groups as (2 *^ -) 1 (sort of).

I already thought of that problem.  It's covered by the grammar.

power-expression("2*^-1")
postfix-expression("2") *^ cast-expression("-1")
                           unary-expression("-1")
                           unary-operator("-") cast-expression("1")

>(BTW, maybe ANSI should define (1 << -1) as right-shifting by 1--any
>response to this out there?)

Bad idea.  It would require the compiler to generate extra code if the right
operand is nonconstant.

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

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/22/88)

In article <2335@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <3421@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>>What about 'unary-expression ++'?  Currently, this is on the same level as
>>pre-incrementing with the distinction being associativity.
>
>That's the way it's usually described, but an equivalent formulation is that
>postfix unary has a higher precedence than prefix unary (and there's no need
>to talk about "associativity" of a unary operator).  This is already in the
>ANSI grammar at the "postfix-expression" level.

Not entirely true.  Expressions such as *--pointer still require knowledge of
associativity to be correctly evaluated.  But I think that you are right about
being able to split up postfix and prefix (I'll have to think about it some
more).

>
>>Would you split these two and put power between them?
>
>Yes.  That's what I said in the grammar as well as the English text.

Assuming this is your order (from highest to lowest):
1.	(); []; .; ->	(left to right)
2.	postfix unary	(right to left)
3.	power		(right to left)
4.	prefix unary	(right to left)
5.	*; /; %		(left to right)
6 and below.	the same as K&R

Then --a power --b cannot be done. It would be grouped as (-- ((a power --) b),
which is illegal.  If power were to be added (PLEASE DON'T), I believe it
should have a precedence below the unaries but above {*; /; and %) and
associate left to right; it would match closer to the mathematical definition
this way.  Also, notice that all the right to left operators are either
assignment or unary; having an augmented assignment operator for an operator
which groups right to left seems inconsistent (and if power is to be added the
corresponding augmented operator should be added, too).

Also , by your method
(++a pow b) == ++(a pow b)
and
(a pow b++) == (a pow (b++))
are how groupings would be done.  This does not look intuitive at all.


>
>>>I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.
>>
>>Since we are defining the 'power' operator and not the 'integer power'
>>operator, 2 *^ (-1) should return (double)0.5 and then be demoted
>>to an integer class, if necessary.  The power operator should not return two
>>different numbers ... based on the types of the arguments.  This is one of
>>the major reasons I don't like the intro of the power operator into C.
>
>Actually, we are defining several operators which share a common symbol.  Just
>as the "/" symbol invokes the integer-divide operator when both operands are
>integers (it most certainly does *not* invoke floating-point divide and then
>truncate the result), "*^" should invoke the integer-power operator when both
>operands are integers.  I thought that was the whole point!

Good point here.  But, I would rather have (2 pow (-1)) evaluate to 0, (1 pow
(-1)) evaluate to 1 than to just be 'undefined'; i.e., crash my program!

>>way you defined your precedence; i.e., 2 *^ -1 groups as (2 *^ -) 1 (sort of).
>I already thought of that problem.  It's covered by the grammar.
>
>power-expression("2*^-1")
>postfix-expression("2") *^ cast-expression("-1")
>                           unary-expression("-1")
>                           unary-operator("-") cast-expression("1")
>
Then you are not clearly defining the precedence, in English.  Please describe
precisely how you want evaluation to go.


>>(BTW, maybe ANSI should define (1 << -1) as right-shifting by 1--any
>>response to this out there?)
>
>Bad idea.  It would require the compiler to generate extra code if the right
>operand is nonconstant.

What does it do now if the the right operand is negative and inside a variable
or an expression?
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

karl@haddock.ISC.COM (Karl Heuer) (01/23/88)

In article <3474@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>>an equivalent formulation is that postfix unary has a higher precedence than
>>prefix unary (and there's no need to talk about "associativity" of a unary
>>operator).
>
>Not entirely true.  Expressions such as *--pointer still require knowledge of
>associativity to be correctly evaluated.

No, it's completely unambiguous.  You seem to be thinking that, unless some
type of "associativity" is defined, it will parse as (* --) pointer.  That
doesn't make sense, because "*" expects an expression (not another operator)
as its operand.  Even if "*" had a higher precedence than "--", it would
still parse correctly.

Or to put it another way, that's not what *I* mean by associativity.

>Assuming this is your order (from highest to lowest):
>1.	(); []; .; ->	(left to right)
>2.	postfix unary	(right to left)
>3.	power		(right to left)
>4.	prefix unary	(right to left)
>5.	*; /; %		(left to right)
>6 and below.	the same as K&R

Yes, except that classes 1 and 2 can be combined, as in the ANSI grammar.

>Then --a power --b cannot be done. It would be grouped as
>(-- ((a power --) b), which is illegal.

It would not be grouped that way, because (a *^ --) is not a valid parsing.

>>I already thought of that problem [2 *^ -1].  It's covered by the grammar.
>>
>>power-expression("2*^-1")
>>postfix-expression("2") *^ cast-expression("-1")
>>                           unary-expression("-1")
>>                           unary-operator("-") cast-expression("1")
>>
>Then you are not clearly defining the precedence, in English.  Please describe
>precisely how you want evaluation to go.

I included the grammar fragment as the precise definition.  You want English?
"*^ has a lower precedence than postfix unary, but higher than prefix unary."
I don't think I can make it any clearer.

>If power were to be added (PLEASE DON'T), I believe it should have a
>precedence [just below unary] and associate left to right; it would match
>closer to the mathematical definition this way.

Think again -- the mathematical definition is right to left.

>Also, notice that all the right to left operators are either assignment or
>unary;

And the ternary operator.

>having an augmented assignment operator for an operator which groups right to
>left seems inconsistent

(You've lost me.  It's inconsistent for both *^ and *^= to be R-to-L?)  I
don't see any problem with this.  I figure that the reason "/" is L-to-R is
because that makes better mathematical sense; for the same reason, "*^" should
be R-to-L.

>Also , by your method
>(++a pow b) == ++(a pow b)
>and
>(a pow b++) == (a pow (b++))
>are how groupings would be done.  This does not look intuitive at all.

I agree.  But if "++" and "-" are to have the same precedence, one can't have
"++a *^ 2" and "- a*^2" both do the right thing.  After rethinking this, I've
decided that it's not so important for "- a*^2" to work (and it could be
caught by lint, anyway).  So the best precedence would probably be just below
unary, as you said.  The revised grammar would be:

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

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

>>>>I think 2 *^ -1 should be undefined (as is 1 << -1), rather than zero.
>
>... I would rather have (2 pow (-1)) evaluate to 0, (1 pow (-1)) evaluate to
>1 than to just be 'undefined'; i.e., crash my program!

The question is, would anybody ever use int-expr *^ negative-int-expr and
depend on the result being zero?  I'd think that such a situation is probably
a program error anyway, in which case it doesn't matter what happens.

>>>(BTW, maybe ANSI should define (1 << -1) as right-shifting by 1--any
>>>response to this out there?)
>>
>>Bad idea.  It would require the compiler to generate extra code if the right
>>operand is nonconstant.
>
>What does it do now if the the right operand is negative and inside a variable
>or an expression?

Officially, it's "undefined".  In practice, you get whatever the architecture
gives you.  On some, it really is a right shift; on others, you get zero.
There may even be some where it causes a trap.

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

karl@haddock.ISC.COM (Karl Heuer) (01/23/88)

In article <3461@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>In article <7139@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>>... the squaring operator (expr ** 2) is quite heavily used.
>
>Yes, but if you know that you are going to be squaring you can replace it
>with (expr * expr) (possibly needing temp variables depending on the side
>effects concerning expr)

That's the point -- having to use the temp variables is a pain.  If the only
expressions I ever wanted to square were simple variables, I wouldn't mind
using the multiply.  It's because of the things with side effects (or even
side-effect-free expressions that are complicated) that we want a power op.

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

ix426@sdcc6.ucsd.EDU (tom stockfish) (01/23/88)

In article <3474@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
> _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
>
>1.	(); []; .; ->	(left to right)
>2.	postfix unary	(right to left)
>3.	power		(right to left)
>4.	prefix unary	(right to left)
>5.	*; /; %		(left to right)
>6 and below.	the same as K&R
>
>....  If power were to be added (PLEASE DON'T), I believe it
>should have a precedence below the unaries but above {*; /; and %) and
>associate left to right; it would match closer to the mathematical definition
>this way.

No, please don't propose this precedence.  Expressions like
	
	-x*^2 + 5

will occur often and will make people hate C (where "*^" is the
proposed power op).  Any power operator proposal *must* get
this one right.

>Also, notice that all the right to left operators are either
>assignment or unary;

Wrong.  "? :" groups right to left (K&R appendix notwithstanding).

>having an augmented assignment operator for an operator
>which groups right to left seems inconsistent (and if power is to be added the
>corresponding augmented operator should be added, too).

This seems pretty trivial.  It follows the rule

	a OP= b  <==>  a = a OP b  (except for side effects)

just fine, which is good enough for me.

>Also , by your method
>(++a pow b) == ++(a pow b)
>and
>(a pow b++) == (a pow (b++))
>are how groupings would be done.  This does not look intuitive at all.

Of course not.  Neither does
	
	a+b / c+d

You would write these (if you ever did) as
	
	++ a*^b		/* illegal */

or

	(++a)*^b
and

	a *^ b++ .

I would never try to guess intuitively how "*^" interacted with "++"/"--"
without looking it up in the standard.  Even then, I would add
parens since this would be such an unusual situation.  The expression

	-x*^2 + 5

is an entirely different (and far more important) matter.
	
-- 

||  Tom Stockfisch, UCSD Chemistry   tps@chem.ucsd.edu

nevin1@ihlpf.ATT.COM (00704a-Liber) (01/28/88)

In article <2370@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
.>In article <7139@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
.>>... the squaring operator (expr ** 2) is quite heavily used.
.
.That's the point -- having to use the temp variables is a pain.  If the only
.expressions I ever wanted to square were simple variables, I wouldn't mind
.using the multiply.  It's because of the things with side effects (or even
.side-effect-free expressions that are complicated) that we want a power op.

That is what macros are for!  And a good optimizing compiler should get rid of
those variables when you are squaring simple variables.  The storage of the
value has to be made somewhere; I don't think it should be implicit when the
optimized code produced should be about the same either way.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

karl@haddock.ISC.COM (Karl Heuer) (01/29/88)

In article <2397@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <3594@sdcc6.ucsd.EDU> ix426@sdcc6.ucsd.edu.UUCP (tom stockfish) writes:
>>No, please don't propose this precedence ["*^" just above "*"].  Expressions
>>like "-x*^2 + 5" will occur often and will make people hate C....  Any power
>>operator proposal *must* get this one right...
>
>[The alternative is worse, so] it looks like the solution is to write your
>example as either "5 - x*^2" or "-(x*^2) + 5" ...

It occurs to me that there is a third plausible precedence, which does the
"right" thing for the usual examples without breaking existing code.

1.  postfix operators ("primary" and "postfix unary")
2.  prefix operators other than unary minus
3.  exponentiation
4.  unary minus
5.  multiplicative operators

The drawback is that it creates *two* new precedence levels, by introducing
exponentiation and splitting off unary minus.  Is it worth it?  I dunno.

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