[comp.lang.c] Power operator?

mcdonald@uxe.cso.uiuc.edu (01/06/88)

I've been wondering why there is no power operator in C. Did the ANSI 
committee consider adding one, and if so, why wasn't it done? I'm
referring to the construct in fortran  X**2  or X**7 . This would seem
to be extremely useful and trivial to implement.

Doug McDonald

chris@mimsy.UUCP (Chris Torek) (01/07/88)

In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
>I've been wondering why there is no power operator in C.

There is:

	#include <math.h>
	...
		double a, x;
		...
		a = pow(x, 7.);

Unless you write `#undef pow' after `#include <math.h>', you may
get in line code (fpushf (fp-4); fftod; fpushd $0d7.0; fexpd etc).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
>I've been wondering why there is no power operator in C. Did the ANSI 
>committee consider adding one, and if so, why wasn't it done? I'm
>referring to the construct in fortran  X**2  or X**7 . This would seem
>to be extremely useful and trivial to implement.
>
>Doug McDonald

Useful, yes, but fortran syntax (x**y) already means "fetch the value at address
y and multiply by x".  For example,

	double	x =	2;
	double	y =	3;
	double	*z =	&y;
	printf( "%f\n", x**z );

prints "6".  My only complaint about C's operator symbols is that "*" is
grossly overworked.  For example, the following code might look o.k., 
but do you see what's wrong?  In fact, it even compiled (!) with no error
messages or warnings on the Berkeley Unix's cc a few years back (no,
it didn't run properly).

	f( x, y )
		double	*x, *y;
	{
		return	*x/*y;
	}

Of course, Everyone Knows that polynomials should never be calculated as, e.g.
a*x**4 + b*x**3 + c*x**2 + d*x + e (using fortran notation), so that an
exponential operator shouldn't be used here, but there are other important
uses such as (again using fortran)

	f(x) ** 2

where I don't want to call f() twice, and I don't want to clutter up my code 
with temporaries.
	
The syntax x^y is bad because this is already defined for integers as bit-wise
exclusive or.
x^^y is a possibility, altho those who want ^^ for logical
exclusive or will I'm sure complain.
x%%y would probably be o.k., but it looks pretty wierd.
I suppose x!y would work, but I would guess that the
numerical people who want exponentiation as an operator would confuse ! with
factorial.
How about x@y ?
How about x..y ?
How about some better suggestions?

-- 

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

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

In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
>I've been wondering why there is no power operator in C. Did the ANSI 
>committee consider adding one, and if so, why wasn't it done?

Yes, X3J11 considered this and numerous other obvious suggestions
for additions to the language.  It reaffirmed the original deliberate
C design decision to not build in an exponentiation operator, but
rather leave it to a library function (pow()).  The idea is that an
exponentiation operator hides a potentially large amount of
computation, which runs counter to "the spirit of C".  It is true
that (for example)
	expression ** 2
would be convenient, for much the same reasons as C's op= operators.
However, this did not overcome the reasons for the original design.

REMINDER:  This is my personal opinion.  If you feel strongly about
this, comment to X3J11 during the second formal public review.  Be
sure to provide overwhelming reasons for making the change.

cik@l.cc.purdue.edu (Herman Rubin) (01/07/88)

In article <10063@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
> >I've been wondering why there is no power operator in C.
> 
> There is:
> 
> 	#include <math.h>
> 	...
> 		double a, x;
> 		...
> 		a = pow(x, 7.);
> 
> Unless you write `#undef pow' after `#include <math.h>', you may
> get in line code (fpushf (fp-4); fftod; fpushd $0d7.0; fexpd etc).

I think everyone should consider this unsatisfactory. 

One reason is that requiring the writing of a subroutine call is that
this requires people to use that notation instead of writing 

	x = y ** z	or x = y ! z.

Similar thinking would require one to write x = sub(y, z) instead of
x = y - z.  This is a major design flaw in all HLLs which I know.

Another is that there are _several_ power functions; the one in the standard
math library is the slowest one, which must be used if the exponent is non-
integral.  Standard FORTRAN treats y ** z to be of the type of y if z is
typed integer, and most implementations use the binary representation of z to
compute the result in that case, and even to have several of the most important
cases "precoded", i.e, y ** 2 is usually done as y * y; even if this is not
done, in Torek's example, if it is known that the 7 is an integer the resulting
code will run at least an order of magnitude faster than the pow function.


-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU (Stan Horwitz) (01/08/88)

  Chris Torek says the function pow(x,y) in C's math library is C's power
operator.  Sorry Chris, the pow(x,y) is not an operator, it is a FUNCTION.
Syntactically, there is a difference, though the result is the same.
The question still stands.  Why does C have no symbol to serve as a power
operator.  There are so many symbols to use, and it would be easy to implement.
  Stan Horwitz   V4039 at TEMPLEVM

pardo@uw-june.UUCP (David Keppel) (01/08/88)

[Why isn't there a power (e.g., a**2) operator in C?]

The original intent of C was simplicity.  Having ** is a fine idea,
but we have to draw a line somewhere and it was defaulted for us by K&R
a long time ago.  If we have ** then perhaps we should also have ||= ?

Worried about runtime overhead of calling pow(3m)?  Talk to somebody
about inline code expansion or use C++.

	;-D on  (Does anybody have a C->Cobol Compiler ?-)  Pardo

chris@mimsy.UUCP (Chris Torek) (01/08/88)

>In article <10063@mimsy.UUCP> I wrote:
>>	a = pow(x, 7.);
>>Unless you write `#undef pow' after `#include <math.h>', you may
>>get in line code (fpushf (fp-4); fftod; fpushd $0d7.0; fexpd etc).

In article <646@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>I think everyone should consider this unsatisfactory. 
>
>One reason is that requiring the writing of a subroutine call is that
>this requires people to use that notation . . . .

This is indeed an annoyance, as there is no way to define a shorthand
version.  Writing `x = plus(y, z)' instead of `x = y + z' is less
familiar.  On the other hand, I know of no language that lets me
write

		      4
		   3 x
	a = ------------------
		     2
	    (b - c/7)  (k - x)

as a statement.  I do not believe this is a serious problem, just
as I do not believe that `:=' is particularly better or worse than
`=' for assignment.  It is just different.  (Well, `:=' requires
shift-unshift, and the two keys are under the same finger for touch
typists, which is bad.)

>Similar thinking would require one to write x = sub(y, z) instead of
>x = y - z.  This is a major design flaw in all HLLs which I know.

(One solution to the dichotomy between builtin operators and other
functions is to eliminate all the builtin operators.  I happen to
LIKE this idea.)

>Another is that there are _several_ power functions; the one in
>the standard math library is the slowest one....  [at worst] if it
>is known that the 7 is an integer the resulting code will run at
>least an order of magnitude faster than the pow function.

What pow function?  Who said we were calling the pow function? :-)

*You* see `pow'; the compiler sees `_builtin_pow', as defined in
<math.h>.  _builtin_pow can be arbitrarily fancy, including testing
its second argument to see whether it is an integral value.  You
might get this inline code instead:

	fpushf (fp-4)		# x
	fdupf
	fsquaref		# pow(x,2)
	fdupf
	fsquaref		# pow(x,4)
	faddf			# pow(x,6)
	faddf			# pow(x,7)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chris@mimsy.UUCP (Chris Torek) (01/08/88)

In article <11169@brl-adm.ARPA> V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU
(Stan Horwitz) writes:
>  Chris Torek says the function pow(x,y) in C's math library is C's power
>operator.  Sorry Chris, the pow(x,y) is not an operator, it is a FUNCTION.

Is not!  See the dpANS.  If you want a function, you must `#undef pow'.

>Syntactically, there is a difference. . . .

True.  I think this should be ignored.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

If someone wants to propose a good syntax for a built-in exponentiation
operator, send it in during the second public review of the draft
standard.  I wouldn't mind having one, although the only way it is
likely to occur at this point is if some other problem forces a third
public review anyway (i.e., it won't be caused by adding the
exponentiation operator).

The x ** y syntax conflicts with existing C, which already ascribes
a different meaning to this, although I do think that anyone who has
been writing ** without a space in between deserves problems anyway.

x ^ y is also already taken.

lupin3@UCSCB.UCSC.EDU (-=/ Larry Hastings /=-) (01/08/88)

+-In article <6982@brl-smoke.ARPA>, gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) wrote:-
+----------
|
| If someone wants to propose a good syntax for a built-in exponentiation
| operator,
| ....
| The x ** y syntax conflicts with existing C, which already ascribes
| a different meaning to this, although I do think that anyone who has
| been writing ** without a space in between deserves problems anyway.
| 
| x ^ y is also already taken.
|
+----------

  And me, in my half-delirious state.. suggest   x *^ y .....

  Think about it; "multiply to the power of" or something.  Sure, it looks
kind of dorky, but a) it's not used and b) there really ought to be SOMETHING.

  Or how about x tothepowerof y ..... :-)
-- 
.. .  .   .    .     .      .       .        .         .          .           .
.. .  .   .    .     .      .       .        .         .          .           .
|   _  _ _   _ |_| _  _ |_ -__  _  _ ARPA: lupin3@ucscb.ucsc.EDU
L_ (_\( ( (_/  | |(_\_\ (_ || )(_)_\ UUCP: ...!ucbvax!ucscc!ucscb!lupin3
larry      /   hastings        _/    BITNET: lupin3@ucscb@ucscc.BITNET
     ^v^v^vBoy, I'm glad I don't live in an alternate universe!^v^v^v
Disclaimer: All original text above was pointless & random, & it makes me proud.
.           .          .         .        .       .      .     .    .   .  . ..
.           .          .         .        .       .      .     .    .   .  . ..

kers@otter.HP.COM (Christopher Dollin) (01/08/88)

Someone writes:

>Similar thinking would require one to write x = sub(y, z) instead of
>!

kers@otter.HP.COM (Christopher Dollin) (01/08/88)

GRR!
Sorry for the previous two responses; I messed up using vi (spit) then pressed
"w" instead of "W" in notes ....

Chris Torke quotes Herman Rubin as saying ...

[lots of preamble]
>Similar thinking would require one to write x = sub(y, z) instead of
>x = y - z.  This is a major design flaw in all HLLs which I know.
[lots of postamble]

Pop11 allows any word to be declared as an operator with a particular
precedence. Such a word must be a variable (or constant) having a procedure
as its value; the effect of writing the wortd as an operartor is just to 
call its procedure value. All the built-in operators work this way (of course
the compiler can optimise some of them to in-line code).

A word can be a C-like name or one composed out of signs. So the user can
declare operators like "--" or "<=>", or "cat", "pow", "without", etc.

Regards,
Kers                                    | Why Lisp if you can talk Poperly?

V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU (Stan Horwitz) (01/09/88)

  One more comment about the power operator.  So far most of the arguments
against it's use are reasonable, but not acceptable.  If C can have an
operator for such as % for modulo divide, why not one for exponentiation?
Surely the same arguments against such a request can also be made against
the inclusion of %.  Anyway, sorry to drag down the group with this topic.

nather@ut-sally.UUCP (Ed Nather) (01/09/88)

In article <11169@brl-adm.ARPA>, V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU (Stan Horwitz) writes:
> 
>   Chris Torek says the function pow(x,y) in C's math library is C's power
> operator.  Sorry Chris, the pow(x,y) is not an operator, it is a FUNCTION.
> Syntactically, there is a difference, though the result is the same.

As a matter of interest, would there be any ambiguity in using

      a ^^ b

instead of

      pow(a,b)

?

I can see how the Fortran notation  a**b is ambiguous if "b" could be a
pointer ...


-- 
Ed Nather
Astronomy Dept, U of Texas @ Austin
{allegra,ihnp4}!{noao,ut-sally}!utastro!nather
nather@astro.AS.UTEXAS.EDU

fujiirm@yendor.UUCP (Roger Fujii) (01/09/88)

In article <646@l.cc.purdue.edu>, cik@l.cc.purdue.edu (Herman Rubin) writes:
> In article <10063@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> > 
> > 	#include <math.h>
> > 	...
> > 		double a, x;
> > 		...
> > 		a = pow(x, 7.);
> 
> I think everyone should consider this unsatisfactory. 

I suppose that strcpy, strcmp... are also unsatisfactory also.

> One reason is that requiring the writing of a subroutine call is that
> this requires people to use that notation instead of writing 
> 
> 	x = y ** z	or x = y ! z.
> 
> Similar thinking would require one to write x = sub(y, z) instead of
> x = y - z.  This is a major design flaw in all HLLs which I know.

Depends on what point of view.  From a mathematical point of view, sure.
But then, from a mathematical point of view, variable assignment (x = 1)
makes no sense either (unless x never changes), even though its meaning is
obvious in most programming languages.

I think a *lot* of people are forgetting/misunderstanding exactly what 'c' is.
C is basically an "abstract assember".  All the actual language knows about
are data types (ints, floats, doubles, structs...), certain *ELEMENTARY*
operators (+, -, *, /, data copy, data compare..... - things that have a fair
probability of having an assember equivalent), and control statements
(ifs, gotos, subroutine calls...). [ I know this is a *gross* simplification,
but this is what I think a fair assement of the language is ].

*EVERYTHING* else is done via function call.  Therefore, having pow() makes
much more *sense* than having a ** (this is not to say that it makes more
intuitive sense, but rather that knowing the language, you would not expect
the compiler to do this).

I really don't think "well, FORTRAN has it" is really a valid reason for
mucking up the language.  This is not to say I do not want the language
changed, but rather that I would like to see it changed within its "scope"
or flavor, rather than because people want to make it look like another
language.

-- 
Roger Fujii - ACT, Reston, VA			Phone:		(703)471-9433
Internet: fujiirm@cml.rpi.edu
UUCP: ..!{mimsy,sundc}!{prometheus,hqda-ai}!yendor!fujiirm

noise@eneevax.UUCP (Johnson Noise) (01/09/88)

In article <3933@uw-june.UUCP> pardo@uw-june.UUCP (David Keppel) writes:
>[Why isn't there a power (e.g., a**2) operator in C?]
>
>The original intent of C was simplicity.  Having ** is a fine idea,
>but we have to draw a line somewhere and it was defaulted for us by K&R
>a long time ago.  If we have ** then perhaps we should also have ||= ?
>

	I can concur with that.  But, if you really MUST have a power
operator, why not define one using the preprocessor? (I'm sure someone
must have already suggested this, but so what).  The subject of a power
operator is a bit sundry, I think.  I'm not sure, (correct me if I'm
wrong), but I think there are even languages that do not have bit operators
like &, |, !, ^, >>, << etc.  I remember back in the days of FORTRAN
when I actually had to write assembly routines to perform bit operations
on integers. Lots of silly overhead just for one instruction.
Anyway, C was designed to be used mostly for systems implementation, not
necessarily for number crunching.

jima@hplsla.HP.COM ( Jim Adcock) (01/09/88)

Don't use ANSI-C, use C++, and overload the -> operator.
Then you can write: twoToTheTenth = 2.0->10.0;

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

In article <10088@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>What pow function?  Who said we were calling the pow function? :-)
[Implying that "pow" might be implemented as a builtin]

I have several problems with using pow() for integer powers.  Unue, I dislike
having to use floating point in otherwise "pure" integer code.  ("difftime()",
yuck.)  Due, I suspect that most vendors will not optimize the statement
"j = (int)pow((double)ifunc(), 2.0)" into what I want.  Trie, it's possible
that the cast to double throws away the lower bits of my left argument, which
would yield an incorrect result.  Kvare, it's just too verbose (and I won't
remove the casts; some compilers would emit warnings without them).

The proposals I've seen so far include:
x ** y     Already means "multiply by what y points to".
x ^ y      Already means "exclusive or".
x ^^ y     Some people want this reserved for logical (not bitwise) xor.
x ! y      Doesn't extend to an assignment form, since "!=" is taken.
x *^ y     Not bad; I could live with it.  However, ANSI is unlikely to
           introduce new operator syntax anyway.
pow(x,y)   See above paragraph.

I counterpropose "int ipow(int, int);", "long lpow(long, int);", and
"double fpow(double, int);".  These are easy to implement as either functions
or builtins, and vendors will probably be more willing to inline-expand these
functions than the full pow() function.

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

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

In article <646@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
.In article <10063@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
.. In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
...I've been wondering why there is no power operator in C.
.. 
.. There is:
.. 		a = pow(x, 7.);
.I think everyone should consider this unsatisfactory. 
.
.One reason is that requiring the writing of a subroutine call is that
.this requires people to use that notation instead of writing 
.
.	x = y ** z	or x = y ! z.
.
.Similar thinking would require one to write x = sub(y, z) instead of
.x = y - z.  This is a major design flaw in all HLLs which I know.

In other words, are you saying that all functions of two variables which do not
modify the variables should always be declared with infix notation??  I have a
hard enough time remembering all the infix operators now (there are at least
19) and their order of precedence and associativity. :-)  How would you define
the order of precedence and associativity for these functions?

.
.Another is that there are _several_ power functions; the one in the standard
.math library is the slowest one, which must be used if the exponent is non-
.integral.  Standard FORTRAN treats y ** z to be of the type of y if z is
.typed integer, and most implementations use the binary representation of z to
.compute the result in that case, and even to have several of the most important
.cases "precoded", i.e, y ** 2 is usually done as y * y; even if this is not
.done, in Torek's example, if it is known that the 7 is an integer the resulting
.code will run at least an order of magnitude faster than the pow function.

Write a function (call it mypow()) to call the correct pow() function depending
on its arguments; why should this be built in to the language if you can easily
define it with the operators given?  That was fine for Fortran, a language
designed to handle large amounts of number crunching.  C is more
general-purpose than that.  (BTW, I really don't understand your 'use the
binary implementation of z ...' remark.)
-- 
 _ __			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

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

There are two power operators:
	<any> ** double -> double	/* pow() */
and	<any> ** int -> double		/* rtp() -- MISSING */
A quick check though a couple of books of statistical algorithms in
Fortran showed me that <expr> ** k for k an integer known at compile
time appeared roughly once each in fewer than 10% of the functions.
The equivalent of pow() was even rarer.  Having to write rtp(X, 3)
instead of X**3 doesn't seem like such a big deal to me.  It's not
that common.  What irks me is having to write my own rtp().  I know
how to do it, but it's not as fast as the vendor could provide, and
the vendor-provided one might even do IEEE-854-sensible things.

Just to make it clear that pow() is not what is wanted:
	rtp(-2.0, 3) is -8.0
	pow(-2.0, 3.0) involves taking the logarithm of -2.0 ...

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

In article <10026@ut-sally.UUCP> nather@ut-sally.UUCP (Ed Nather) writes:
>      a ^^ b

I think this is about as good a notation as we can get that is
compatible with existing code.

If several of you will please send in this suggestion, along
with strong arguments, as formal public comments (when it's
time, not just yet), I'll be happy to push for getting it
adopted.  I think the only way a substantive change like this
could stand any chance of adoption at this point would be for
some other substantive change to have already been accepted,
so that this item would not be the sole cause for another
delay in publishing the final standard.

The strongest case I can think of that would justify a built-in
exponentiation operator is
	messy_expression ** 2
(Note that is an integral power that can be highly optimized
over the use of pow() to do the same job.)

farren@gethen.UUCP (Michael J. Farren) (01/09/88)

Seems to me that providing a power operator would violate, somewhat,
one of the most important aspects of C - the relatively simple mapping
between C operators and few, or even one, machine instruction.  I can't
think of any of the basic operators which don't map into a very small
number of machine instructions; even floating point numbers do if you
have some sort of floating point accelerator, even the most primitive.
Exponentiation, generally, does not map so easily.  Nor, for that matter,
do any of the trig functions, and I don't hear a lot of complaints about
the lack of a sine operator (whose symbol would be ~, of course :-)

-- 
Michael J. Farren             | "INVESTIGATE your point of view, don't just 
{ucbvax, uunet, hoptoad}!     | dogmatize it!  Reflect on it and re-evaluate
        unisoft!gethen!farren | it.  You may want to change your mind someday."
gethen!farren@lll-winken.llnl.gov ----- Tom Reingold, from alt.flame 

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

In article <3312@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>(BTW, I really don't understand your 'use the
>binary implementation of z ...' remark.)

A fast way to implement a general integer-to-the-integer-power
routine is to "think binary" about the exponent.  If you can't
figure out how this would work, I think it's shown in Gries'
"The Science of Computer Programming".

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

In article <7007@brl-smoke.ARPA> I wrote:
>>      a ^^ b
>I think this is about as good a notation as we can get ...

However, as Karl pointer out, this would make a good logical exclusive-or
operator also, and I can see that the "strong argument" for exponentiation
would also apply, somewhat more weakly, to exclusive-or, which I've often
needed and have had to kludge ((a != 0) ^ (b != 0)).

You see what a can of worms is opened up, once you start admitting
extensions?  Or, to mix metaphors, once you let a foot get in the door?

>	messy_expression ** 2

Of course this Fortran notation should be changed to whatever for the
proposed C extension.

dant@tekla.TEK.COM (Dan Tilque;1893;92-789;LP=A;60aC) (01/09/88)

Stan Horwitz writes:
>
>  One more comment about the power operator.  So far most of the arguments
>against it's use are reasonable, but not acceptable.  If C can have an
>operator for such as % for modulo divide, why not one for exponentiation?
>Surely the same arguments against such a request can also be made against
>the inclusion of %.  Anyway, sorry to drag down the group with this topic.


The historical reason for having modulo but not power is that C was
originally a systems language.  The modulo operator is much more useful
that exponentiation for that purpose.  Now that C is used for many
different applications, perhaps it should be added.  However, if it is
added I think it should be restricted to having the exponent be an
integer.  If float exponents are desired, the user should have to invoke a
library routine.

---
Dan Tilque

Now, if I could talk them into putting in a division operator which also
returns the remainder (combined / and %)...

wong@llama.rtech.UUCP (J. Wong) (01/10/88)

In article <11169@brl-adm.ARPA> V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU (Stan Horwitz) writes:
>
>The question still stands.  Why does C have no symbol to serve as a power
>operator.  There are so many symbols to use, and it would be easy to implement.

One of the original motivations of the people who designed C was
that no operation should result in a function call being generated
in order to implement the language.  Although, structure assignment
and return might seem to violate this, it's true on some machines
that they can be implemented through machine instructions.  So, in
general I think that the orginal motivation is still valid, and no
operation (such as a power operator) should be introduced if the
only way it can be implemented is through a function call.

				J. Wong		ucbvax!mtxinu!rtech!wong

****************************************************************
You start a conversation, you can't even finish it.
You're talking alot, but you're not saying anything.
When I have nothing to say, my lips are sealed.
Say something once, why say it again.		- David Byrne

bs@alice.UUCP (01/10/88)

jima @ HP Lake Stevens, WA writes

 > Don't use ANSI-C, use C++, and overload the -> operator.
 > Then you can write: twoToTheTenth = 2.0->10.0;

and there has been other references to C++ in this debate so I think
it will be in place to explain what C++ can and cannot do vis a vis
a power operator.

(1) C++ does NOT enable you to change the meaning of operators
    applied to the built-in types. This implies that 2.0->10.0
    is a plain C expression and therefore an error: you cannot
    use -> to dereference the floating point number 2.0 and even
    if you could -> requires a member name as its right hand
    operand so 10.0 would not do.

    Even if you had been able to make -> mean exponentiation, I
    would have cautioned against it: it is strongly recommended
    to use operator overloading ONLY where there is an established
    notation in some field of application to adopt.

(2) C++ does NOT enable you to define new operators or in other
    ways change the syntax of C++. This implies that you cannot
    simply say: I'll make ** (or ^^ or *^ or) an operator (of some
    binding strength and associativity). So unless the ANSI C
    committe suddenly decides to reverse its stand on this issue
    and provides an exponentiation operator for C you cannot
    get it in C++.

C++ does however offer two features that might help: function name
overloading and inlining:

	overload pow;
	double pow(long, int);		// simple integer algorithm
	double pow(double, int);	// fairly simple algorithm
	double pow(double, double);
	complex pow(complex, double);	// complex algorithm
	complex pow(complex,complex);	// very complex algorithm

There are other alternatives, but I hope the point is clear. The
compiler has sufficient information to chose the right (i.e. simplest
and/or fastest) pow() function on a per call basis. You don't need to
pollute your name space with lipow(), dipow(), etc.

	pow(6,2);	// call long pow(long,int);
	pow(6.0,2);	// call long pow(double,int);
	pow(2,6.0);	// call long pow(double,double);

If you use inlining there is room for further refinement:

	inline double pow(long l, int i) {
		if (i==2)
			return l*l;
		else if ((i&~pow2_mask)==0)
			return _pow2_pow(l,i);
		else
			return _lipow(l,i); 
	}

now
	pow(x,2)	will generate	x*x
	pow(x,8)	will generate	_pow2_pow(l,8)
	pow(x,i)	will generate	_lipow(l,i)	

Note that the if-then-else business is handled at compile time and causes
no spurious code to be emitted. The `code emitted' for the trivial example
pow(6,2) above is simply the constant 36.

cik@l.cc.purdue.edu (Herman Rubin) (01/10/88)

In article <3312@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
> In article <646@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
> .In article <10063@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> .. In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:

> .Similar thinking would require one to write x = sub(y, z) instead of
> .x = y - z.  This is a major design flaw in all HLLs which I know.
> 
> In other words, are you saying that all functions of two variables which do not
> modify the variables should always be declared with infix notation??  I have a
> hard enough time remembering all the infix operators now (there are at least
> 19) and their order of precedence and associativity. :-)  How would you define
> the order of precedence and associativity for these functions?

There is a vast difference between requiring infix notation and permitting
infix notation.  As far as precedence is concerned, who remembers the order
for most combinations?  I would just as soon require parentheses for this
problem.  What is the relative precedence of << (shift) and +?  The various
people I asked came up with the _same_ answer.  The C compiler on the Pyramid
came up with the other.


> .Another is that there are _several_ power functions; the one in the standard
> .math library is the slowest one, which must be used if the exponent is non-
> .integral.  Standard FORTRAN treats y ** z to be of the type of y if z is
> .typed integer, and most implementations use the binary representation of z to
> .compute the result in that case, and even to have several of the most important
> .cases "precoded", i.e, y ** 2 is usually done as y * y; even if this is not
> .done, in Torek's example, if it is known that the 7 is an integer the resulting
> .code will run at least an order of magnitude faster than the pow function.
> 
> Write a function (call it mypow()) to call the correct pow() function depending
> on its arguments; why should this be built in to the language if you can easily
> define it with the operators given?  That was fine for Fortran, a language
> designed to handle large amounts of number crunching.  C is more
> general-purpose than that.  (BTW, I really don't understand your 'use the
> binary implementation of z ...' remark.)

That C is more general than a number-crunching language is no reason for C to
do a bad job of number-crunching.  We do not need any tradeoffs here.  Your 
argument about introducing a new function mypow() completely misunderstands the
problem.  How would mypow() possibly know that the second argument is of type
integer, and that in that case it should proceed according to the type of the
first argument?  Now you may say that I should also feed it the types of the
arguments.  This is contrary to the whole idea of overloaded operators.  If we
did not have this, instead of the 19 binary operations you mentioned above, we
would have more than 50 and have to remember all their names and precedences.

The most common case of power is that in which the exponent is an integer,
frequently a small integer.  If the integer is a small fixed integer (this
is decided by the compiler), the operation should be unrolled by the compiler
into a sequence of multiplications, including squarings, with an inversion if
the exponent is negative.

The other important special case is that in which the exponent is either a
large integer or a variable integer.  In that case the operation should 
either be a loop using a sequence of multiplications, some of which are
squaring operations, based on the binary representation of the exponent,
with an inversion if the exponent is negative.  Whether this should be
inline or a function call is machine dependent; I suspect that on most
machines it should be inline.

Only if the exponent is not of an integer type should a function like pow()
be called.  Possibly this function should check whether in fact the 
exponent is an integer; the various costs would have to be analyzed to
decide whether this is worthwhile.  But this is the most that could be
with your suggestion of a function mypow().  It is unusual that one
is interested whether a real exponent happens to be an integer, but it
is not unusual to have an exponent something that is known to be an
integer.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (01/11/88)

In article <1559@rtech.UUCP>, wong@llama.rtech.UUCP (J. Wong) writes:
> One of the original motivations of the people who designed C was
> that no operation should result in a function call being generated
> in order to implement the language.  Although, structure assignment
> and return might seem to violate this, it's true on some machines
> that they can be implemented through machine instructions.  So, in
> general I think that the orginal motivation is still valid, and no
> operation (such as a power operator) should be introduced if the
> only way it can be implemented is through a function call.
> 
> 				J. Wong		ucbvax!mtxinu!rtech!wong

   Actually any operation in a languge need not generate functions calls -
have we heard of inline expansion?  Assuming what you really meant
was that there should be hardware support for the operation, well
I don't think this case should be ruled by precedence.  That is
even if what you state was a design goal of the language.

  As I stand on my soap box .... Computer languages should be designed
with providing a reasonable abstraction for a programming model
while keeping in mind that the constructs used should be inexpensive to
implement.  I don't think anyone will question the reasonableness
of an infixed notion for exponentiation.  So the question remains
is it too expensive to implement.

 On machines with hardware support, the answers should be no.  In fact,
it may be worst to use a function format because of some optimizations
that can be realized when operands have special properties. These
properties become harder to detect when using a functional format
(integers must be typed coerced into doubles).  On machines with
no hardware support for exponetiation, the answer maybe one could
do better with an fix notion then without it.  Not only are
the optimizations harder to detected with functional format, but also
optimization coded by the programmer may have detrimental effects on timing.
A classic of mine is the sqr(x) ((x)*(x)) macro.  A seemingly harmless 
macro.  When used in the context sqrt((double) sqr(x1-x2) + sqr(y1-y2)) 
you may start to realize its affects.  The expressions (x1-x2) and
(y1-y2) may be evaluated twice, that is unless the compiler does
some common subexpression elimination.

  Aside : this last example illustrates  a point I was trying to 
make to someone else about the side effects of macros.  Some of the
side effects macros may have are very illusive.


						
-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

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

In article <5260001@hplsla.HP.COM> jima@hplsla.HP.COM (              Jim Adcock) writes:
>Don't use ANSI-C, use C++, and overload the -> operator.
>Then you can write: twoToTheTenth = 2.0->10.0;

So when will C++ be available on enough machines that we numerical users
can write in it and be assured of support when we change employers/machines?

The C code that is emitted by CC is *not* portable, chiefly because things
like getchar() are already expanded into their machine-specific inline code.
Even if this problem could be gotten around, I would hate to have to maintain
that C code.

I like your choice for the operator.  It seems to me this would work nicely
if ANSI-C adopted it.  It will *not* work for the example you give (2.0->10.0)
because at least one operand of an overloaded operator must be a class object.
(See Stroustrup's book p. 172).
Supplying a trivial floating point class and supplying identity-operation
constructors for it should do the trick, but you still won't be able to do

	constant -> constant

without using a cast.  If I'm wrong about this, or C++ has been extended to
allow overloading of operators on basic types when the basic types don't
have a normal meaning with an operator, I would like to hear about it.

-- 

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

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

In article <1559@rtech.UUCP>, wong@llama.rtech.UUCP (J. Wong) writes:
> One of the original motivations of the people who designed C was
> that no operation should result in a function call being generated
> in order to implement the language.
On the PDP-11, not only did 32-bit integer *, /, and % generate
subroutine calls, but C function entry and exit involved subroutine
calls.  These operations *could* have been performed by in-line code,
but the space overhead would have been rather high.  On quite a few
machines the shift operators involve a function call when the shift
count is not a constant.

I hate to disillusion people (:-) but the plain fact is that the set of
operators in C is (almost) identical to the set of operators in BCPL.
There is one important exception:  in BCPL the operators ~, &, and |
are like !, &&, and || in "truth-value" context (argument of 'if',
'while', &c) or like ~, &, and | in "bit" context (assignment, argument
passing).  Here is a table in order of precedence:

Construct	BCPL			C

Constant	10, #47, #xFE		10, 047, 0xFE (examples)
		"string*N" 'c'		"string\n" 'c'
		(expr)			(expr)
Cast		{no types, not present}	(type)expr
Call		expr(arg,...,arg)	expr(arg,...,arg)
Field		field :: expr		expr.field
subscript	array!wordoffset	array[subscript]
		array%byteoffset	{also array[subscript]}
Address	of	@lvalue			&lvalue
Indirect	!rvalue			*rvalue
Arithmetic	e1 * e2			e1 * e2
		e1 / e2			e1 / e2
		e1 rem e2		e1 % e2
		e1 + e2			e1 + e2
		+ e1			{omitted}
		e1 - e2			e1 - e2
		- e1			- e1
Relational	= ~= < <= > >=		== != < <= > >=
Shift		<< >>			<< >>
Logical		~			~ (bit context)
		{also ~}		! (truth-value context)
		&			& and &&
		|			| and ||
		e1 eqv e2		{use e1 ^~ e2}
		e1 neqv e2		e1 ^ e2 {^^ omitted}
Conditional	e1 -> e2, e3		e1 ? e2 : e3
Assignment	e1 := e2		e1 = e2
Sequence	e1 <> e2		e1, e2		

The floating-point operations are (in the versions of BCPL that have
them):	#* #/ #+ #- #= #~= #<= #>= #< #> (no power operator!).  Since
everything is a "word", one has 36-bit integers and 36-bit floats,
or 32-bit integers and 32-bit floats, or whatever.

It is only at the statement and declaration level that C departs
significantly from BCPL.  In particular, C's switch() statement is
almost identical to BCPL's SWITCHON(), except for one change that
has never made sense to me.  In BCPL, cases are terminated by
ENDCASE, not by BREAK.  So if you have a SWITCHON inside a loop,
you can BREAK out of the loop without needing a goto.  Confusing
ENDCASE and BREAK has never made sense to me.

Is there some deep reason for the choice of what is an operator and
what isn't in BCPL?  Almost certainly not, as it is a simplification
of CPL which made so few concessions to hardware that I don't think
it was ever fully implemented.

I think the moral of it all is, go to the primary sources!

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

In article <622@PT.CS.CMU.EDU>, edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
1>    Actually any operation in a languge need not generate functions calls -
1> have we heard of inline expansion?
...
2> implement.  I don't think anyone will question the reasonableness
2> of an infixed notion for exponentiation.
...
3> properties become harder to detect when using a functional format
3> (integers must be typed coerced into doubles).  On machines with
3> no hardware support for exponetiation, the answer maybe one could

His points (1) and (3) contradict each other.
In fact his point (3) is the direct opposite of C's defaults:
at present, whenever you do
	X <operator> Y
"the usual conversions" are done, which means amongst other things
that if one operand is double, the other *will* be converted (which
Wyatt says *won't* happen), whereas if you call a function integers
will only be promoted to 'int'.  In C, functional *syntax* gives us
the freedom to have operands of different types:
	extern double pow(double base, double expt);
-vs-	extern double rtp(double base, int power);
Note that these are quite different functions: rtp(-3.0, 2) is well
defined, but pow(-3.0, 2.0) is illegal and should signal a matherr.
(In Common Lisp, (EXPT -3.0 2.0) --> #C(9.0 0.0), a complex number.)

Just to play devil's advocate, I'll question the reasonableness of
an infix operator for exponentiation.
Point 1:
	Many correspondents seem not to realise that there are TWO
	distinct operations (which happen to coincide for strictly
	positive bases).  It would be unwise to provide special
	syntax for something so little understood.

Point 2:
	At present, all the arithmetic operators apply "the usual
	conversions".  Now the operation most commonly wanted is
	base ** k for k a constant integer expression, and base
	some size of float.  The fact that k isn't (and mustn't) be
	converted makes "*%" unlike other operators.  But there is
	nothing surprising about the function rtp().

	Suppose we add an operator for pow().  This *would* apply
	"the usual conversions".  Which means that if someone wrote
	"*$" when they really meant "*%" their program would appear
	to work when the base happened to be positive, though with
	some loss of precision.

Point 3:
	Just what are the syntactic properties of "**"?  I have used
	programming languages where it was left associative, where it
	was right associative, ones where "a ** -1" was legal, and ones
	where it wasn't (because unary minus had same precedence as
	infix -), and ones where "a ** -1" was legal but "a ** -j" was
	not.  I deny that there is a single set of properties which all
	(or even most) programmers would agree on.

Point 4:
	There is not the slightest reason why an operator should be
	"more efficient" than functional notation.  In BCPL, one writes
	    LET BLOCK = VEC 1000 IN $(
		statements
	    $)
	whereas in C one writes
	    {   int *block = (int*)malloc(1000 * sizeof *block);
		statements
	    }
	Does anyone reading this seriously suppose that the BCPL version
	is more efficient?  Fortran uses functional syntax (MOD, IAND)
	where C uses operators (%, &).  Does anyone seriously suppose
	that this makes a difference?

Point 5:
	Inline expansion of pow() seems unwise unless the machine has
	an instruction to support it directly.  Even if you have a
	floating-point chip which provides exp() and ln() instructions,
	*you should not use them*.  To quote Cody & Waite, chapter 7:
	"   The FORTRAN ** operator is defined mathematically as
		x ** y = exp(y * ln(x))
	    The obvious implementation of this definition using existing
	    software for the exponential and logarithm functions results
	    in large errors independent of those associated with the
	    elementary function software used.  ...
	    The algorithms we present for this computation are far more
	    complicated than any other algorithms presented in this manual."
	The 80287 and 80387 have "y * log2(x)" and "y * log2(x+1)"
	instructions, but these should only be used when that is the result
	you want.  Using one of these instructions and then taking exp() is
	pretty much the combination Cody & Waite warn against.  (These
	operations may use sufficient extra internal precision that you can
	get away with it, but I'd advise you to run the test program at the
	end of chapter 7.)

	This is not, of course, an argument against using an operator.
	The point is that pow() is a costly operation, which is going to
	be implemented as a subroutine on almost any existing machine,
	so why not be honest about it?

Point 6:
	Not only is pow() costly, it is very rarely used even in number
	crunching programs.  The saving is at best |pow(_,_)| - |_**_|
	= 4 characters.  For this we should change the language?
	rtp() is another matter.  But even that is pretty rare.  I have
	some experience with numerical packages written in Fortran, and
	float**int was just not a common operation.  In fact, I would
	claim that it is sufficiently rare that using a name for it
	rather than some exotic sequence of characters would make the
	code *more* readable and *more* maintainable.

I wonder why no Pascal admirers have pointed out that Pascal *does*
have a notation for what is far the commonest case, namely
	SQR(expr) = (expr)**2
Mind you, that is a very bad name for the operation, but it does exist.

Given that the X3J11 is *standardising* C, not *inventing* it, leaving
the two exponentiation operators out is the right thing for them to do.
But we really should have the rtp() *operation* as well as pow().

wfp@dasys1.UUCP (William Phillips) (01/11/88)

If you really want an exponentiation operator in ANSI C (as it happens, I
don't) here's a candidate: <<

I'm implementing a compiler for a special purpose language that looks a lot
like C.  The language spec that I was given specifies that the << and >>
operators, when applied to floating point objects, act as exponentiation
and inverse exponentiation operators; a logical sort of extension of
right and left shifts of integer objects, isnt it?


-- 
William Phillips                 {allegra,philabs,cmcl2}!phri\
Big Electric Cat Public Unix           {bellcore,cmcl2}!cucard!dasys1!wfp
New York, NY, USA                (-: Just say "NO" to OS/2! :-)

eric@snark.UUCP (Eric S. Raymond) (01/12/88)

In article <7007@brl-smoke.ARPA>, Doug Gwyn writes:
>In article <10026@ut-sally.UUCP> nather@ut-sally.UUCP (Ed Nather) writes:
>>      a ^^ b
>
>I think this is about as good a notation as we can get that is
>compatible with existing code.

I disagree. I can't look at ^^ and see anything but logical exclusive-or.

Sigh. What happened to "no prior art"?
-- 
      Eric S. Raymond
      UUCP:  {{seismo,ihnp4,rutgers}!cbmvax,sdcrdcf!burdvax,vu-vlsi}!snark!eric
      Post:  22 South Warren Avenue, Malvern, PA 19355    Phone: (215)-296-5718

jay@splut.UUCP (Jay Maynard) (01/12/88)

In article <6982@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> If someone wants to propose a good syntax for a built-in exponentiation
> operator, send it in during the second public review of the draft
> standard. [...]

I must have missed how to do this...besides, I'm not a C guru (a
barely-reformed Turbo Pascal hacker!)...

> The x ** y syntax conflicts with existing C, which already ascribes
> a different meaning to this, although I do think that anyone who has
> been writing ** without a space in between deserves problems anyway.

(my smart remark suppressed) Does anyone really write it this way, instead
of x * *y?

> x ^ y is also already taken.

So it is. How about (WARNING: KLUDGE-O-MATIC OUTPUT COMING) :

x *^ y

Well, it was an idea...kinda gives the flavor of a multiplicative operation,
and I don't think ^ is legal as a monadic operator...

-- 
Jay Maynard, K5ZC (@WB5BBW)...>splut!< | GEnie: JAYMAYNARD  CI$: 71036,1603
uucp: {uunet!nuchat,academ!uhnix1,{ihnp4,bellcore,killer}!tness1}!splut!jay
Never ascribe to malice that which can adequately be explained by stupidity.
The opinions herein are shared by none of my cats, much less anyone else.

jay@splut.UUCP (Jay Maynard) (01/12/88)

In article <326@splut.UUCP>, I wrote, as a suggested power operator:
> x *^ y

Unfortunately, due to newsfeed constipation, I wrote this before I saw
someone-or-another's posting suggesting this very thing. Something about
great minds...

Then I got to thinking about the objections about putting a full-fledged
exponentiator into the language as an operator. It struck me that it could
be defined as analogous to % - only useful if the second operand is integer.
That, in turn, raised another question: What does % do if you  feed it
something like x % 6.39?

Maybe this idea ios getting better? Maybe worse? Like I said in the last
message, I'm not a C guru - just a semi-converted Turbo Pascal hacker...

-- 
Jay Maynard, K5ZC (@WB5BBW)...>splut!< | GEnie: JAYMAYNARD  CI$: 71036,1603
uucp: {uunet!nuchat,academ!uhnix1,{ihnp4,bellcore,killer}!tness1}!splut!jay
Never ascribe to malice that which can adequately be explained by stupidity.
The opinions herein are shared by none of my cats, much less anyone else.

john13@garfield.UUCP (John Russell) (01/12/88)

In article <11169@brl-adm.ARPA> V4039%TEMPLEVM.BITNET@CUNYVM.CUNY.EDU (Stan Horwitz) writes:
>The question still stands.  Why does C have no symbol to serve as a power
>operator.  There are so many symbols to use, and it would be easy to implement.

Because there are *so many* different ways to implement it, each optimal for
specific cases.

2 ^ (int) with shifts; this is what I use most frequently and there _is_ an
operator for it (<< and >>).

(int) ^ (int) with various algorithms depending on the size of the exponent.

(double) ^ (double) as pow() does it I rarely use, but you can see it requires 
a different approach to deal with the fractional exponent.

John
-- 
"Operating systems room, prepare for shutdown."
"I never thought I'd be HAPPY to see our ratings do DOWN!"
		-- lots of these were sprinkled throughout the 
		   last broadcast episode of _Max_Headroom_

feg@clyde.ATT.COM (Forrest Gehrke) (01/13/88)

In article <7014@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <7007@brl-smoke.ARPA> I wrote:
> >>      a ^^ b
> >I think this is about as good a notation as we can get ...
> 
> However, as Karl pointer out, this would make a good logical exclusive-or
> operator also, and I can see that the "strong argument" for exponentiation
> would also apply, somewhat more weakly, to exclusive-or, which I've often
> needed and have had to kludge ((a != 0) ^ (b != 0)).
> 
> You see what a can of worms is opened up, once you start admitting
> extensions?  Or, to mix metaphors, once you let a foot get in the door?





 
If the argument for adding extensions is to avoid kludges, then let me
be next in line: how about complex algebra notation (a + jb)?
Exponentiation of complex variables could make good use of the
exponent operator---and no one has mentioned root extraction yet.
We could turn C into Ada++ overnight!

Forrest Gehrke
 

franka@mmintl.UUCP (Frank Adams) (01/13/88)

In article <6982@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>If someone wants to propose a good syntax for a built-in exponentiation
>operator, send it in during the second public review of the draft standard.

I would vote for x ! y.  It doesn't strike me as all that important a
feature to add at this stage, though.

Another thought: how about an #if pragma(name) construct, similar to
#if defined(name), to test whether a pragma is defined by the
implementation?
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

kurt@hi.unm.edu (Kurt Zeilenga) (01/13/88)

We had this plotting package here at UNM that has used the
notation a#b to represent the expression a raised to the
expression b.  I always thought it was bizzarre, but then
they are probably up the same proverbial creek.

I think they should use '@' instead of '*' (the unary
operator).  This would free up '**' for the power operator.  :-)

-- 
	Kurt (zeilenga@hc.dspo.gov)

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

In article <651@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>In article <3312@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
.. In article <646@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
.. .In article <10063@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
.. .. In article <47000029@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
>
.. .Similar thinking would require one to write x = sub(y, z) instead of
.. .x = y - z.  This is a major design flaw in all HLLs which I know.
.. 
.. In other words, are you saying that all functions of two variables which do not
.. modify the variables should always be declared with infix notation??  I have a
.. hard enough time remembering all the infix operators now (there are at least
.. 19) and their order of precedence and associativity. :-)  How would you define
.. the order of precedence and associativity for these functions?
>
>There is a vast difference between requiring infix notation and permitting
>infix notation.  As far as precedence is concerned, who remembers the order
>for most combinations?  I would just as soon require parentheses for this
>problem.  What is the relative precedence of << (shift) and +?  The various
>people I asked came up with the _same_ answer.  The C compiler on the Pyramid
>came up with the other.

Then the people you know do not know K&R C.  Look in section 2.12
of K&R for precedence and order of associativity of operators; it is very well
defined there.  ('<<' and '..' are just below '+' and '-' (subtract, not minus)
and both have left-to-right associativity.)  Are you telling me that you
*never* use the fact that multiplication has higher precedence than addition??
And without *any* definition of precedence, your compiler would have to flag
expressions like 'a + b POWER c' (where 'POWER' is your power operator) as an
error; it is ambiguous.  Your addition would add ambiguity to a pretty
unambiguous language (I KNOW I'll get flames for that last phrase :-)).
>
>
.. .Another is that there are _several_ power functions; the one in the standard
.. .math library is the slowest one, which must be used if the exponent is non-
.. .integral.

I said:
.. Write a function (call it mypow()) to call the correct pow() function depending
.. on its arguments; why should this be built in to the language if you can easily
.. define it with the operators given?

>
>That C is more general than a number-crunching language is no reason for C to
>do a bad job of number-crunching.  We do not need any tradeoffs here.  Your 
>argument about introducing a new function mypow() completely misunderstands the
>problem.  How would mypow() possibly know that the second argument is of type
>integer, and that in that case it should proceed according to the type of the
>first argument?  Now you may say that I should also feed it the types of the
>arguments.  This is contrary to the whole idea of overloaded operators.  If we
>did not have this, instead of the 19 binary operations you mentioned above, we
>would have more than 50 and have to remember all their names and precedences.

Since you, the programmer, know if the second argument is an integer, you can
call a special routine (call it ipow(), for example) to implement your
algorithm.  C is very loosely typed and it does not permit the programmer
himself to overload operators.  Your application is very easy to define in a
language like C++; it allows overloading of operators, inlining functions, and
calling different routines based on different types.  It is not necessary to
expand C to C++; just USE C++ instead of C (and get this discussion out of here
:-)).
-- 
 _ __			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

tanner@ki4pv.uucp (Dr. T. Andrews) (01/14/88)

In article <7007@brl-smoke.ARPA>, gwyn@brl-smoke.UUCP writes:
) In article <10026@ut-sally.UUCP> nather@ut-sally.UUCP (Ed Nather) writes:
) >      a ^^ b
) I think this is about as good a notation as we can get that is
) compatible with existing code.

I fear that this would cause some confusion.  While there is not
CURRENTLY a "logical" xor operator, consider the following table:

symbol	op		symbol	op
&	b-and		&&	l-and
|	b-or		||	l-or
^	b-xor		^^	power
=	cause equality	==	test equality
(b-operation=bitwise; l-operation=logical)

I don't know why there is no "logical" xor operation (same effect as
((op1 != 0)^(op2 != 0)) construction), but if one were to use the
"^^" symbol, it would seem reasonable to expect it to yield a logical
xor.

Also, is that a kitchen sink I see hidden away under the rationale?
Back behind that old stack of "codifying existing practice" bumper
stickers?
-- 
{allegra clyde!codas decvax!ucf-cs ihnp4!codas killer}!ki4pv!tanner

dam@mtgzz.UUCP (XMRN40000[kvm]-d.a.morano) (01/14/88)

In article <22773@hi.unm.edu>, kurt@hi.unm.edu (Kurt Zeilenga) writes:
> I think they should use '@' instead of '*' (the unary
> operator).  This would free up '**' for the power operator.  :-)

Obviously, we can not change unary '*' to '@' and still have C, but this 
would have been an excellent choice for indirection back when K&R started
to think about this.  Those with a background of programming in DEC's
assembly languages for the PDP-11 (and VAX) can appreciate this.  

As mentioned previously, the '**' can still be used for
the power operator since the types of the operands can not be 'pointer to
something'.  In the following its use can be determined unambiguously when
given a binary operator precedence :

	int	a, *b, *c[], d ;

	d = a ** d ;
	d = a ***b ;		/* is (a ** (*b)) */
	d = *b****c ;		/* although hard to see ((*b) ** (*(*c))) */


Dave Morano	- AT&T

ray@micomvax.UUCP (Ray Dunn) (01/14/88)

In article <646@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:

>> [ description of power function rather than power operator ]
>
>I think everyone should consider this unsatisfactory. 
>
>One reason is that requiring the writing of a subroutine call is that
>this requires people to use that notation instead of writing 
>
>	x = y ** z	or x = y ! z.
>
>Similar thinking would require one to write x = sub(y, z) instead of
>x = y - z.  This is a major design flaw in all HLLs which I know.
>

Not all.  POP-2 (An AI language from Edinburgh Univ) allows (simplified):

operator <precedence> <operator name> ( <parameter list> )

as an option of

<function name> ( <parameter list> )

to allow new operators to be defined.  

This together with the fact that you could define identifier names as
combinations of signs ( e.g. *+*), was a very useful feature.


>Another is that there are _several_ power functions;

This is of course a contradiction to your statement above!  Because there
are several different versions is a very good reason to NOT have a power
function built into the language as a standard operator.  Which one should
it be!

No.  Lets add the ability to define new infix operators in C instead (:-)!

(Actually even the ability to define infixed pre-processor macros would
 add something ... just dreaming, not thinking!)

Ray Dunn.  ..philabs!micomvax!ray

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

In article <3492@mtgzz.UUCP> dam@mtgzz.UUCP (XMRN40000[kvm]-d.a.morano) writes:
>As mentioned previously, the '**' can still be used for
>the power operator since the types of the operands can not be 'pointer to
>something'.

	int a, *b, c;

	c = a ** b;	/* means c = a * *b; */

peter@sugar.UUCP (Peter da Silva) (01/14/88)

	C doesn't currently use @ or $, though some systems require that
these symbols be valid in variable names.

	Also, since there is no short-circuit xor function (grin), you could
use ^^.
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

halvers@iraq.steinmetz (peter c halverson) (01/14/88)

As long as we're asking for an exponentiation operator '**', what about
hyperexponentiation? i.e.

        ... (y times)   
      x
    x
  x
                                                                n
We could use '***'.  Even better, why not generalize, and have *
be the operator for the nth Ackermann's function?

:-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-)
~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
Pete Halverson                       ARPA: halverson@ge-crd.ARPA
General Electric Company             UUCP: uunet!steinmetz!iraq!halvers
Corporate R & D                            
Schenectady, NY

"Trust me; I know what I'm doing."
                                    --- Inspector Sledge Hammer

peter@sugar.UUCP (Peter da Silva) (01/15/88)

If the power operator is so important, how come Fortran includes all the
mentioned variants of it as functions? It's handy, no denying that.
Important enough to add to the language when the Fortran language
committee still found that functional variants were needed, even 
though it's already in the language? I don't think so.
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

has@eagle.ukc.ac.uk (H.A.Shaw) (01/17/88)

Expires:

Sender:

Followup-To:


This may look like a flame.  It is not supposed to be, but I feel strongly
that we are wasting our time with questions that have no relavence to C as a
language.

What people appear to be forgetting is what C is for.  When I started to learn
coding, the process of turning an algrothim into a real computer program, I
was told that the first thing to do is to chose the language to use.  You
should not do complex mathematical work in C, in the same way that you don't
solve simultainous equations in troff (I have seen this done!) if you want a
long life without ulsers.  What we need is to reduce C to it's basics.  C is
one of a nearly infinite group of languages, each is good at only ONE job.  We
have forgotten that C was originally a system programmers language.  Who needs
pow() in a pager or line printer demon?  If you want maths, use FORTRAN, to
teach, use BASIC/PASCAL, to drive a robot, use LOGO, etc., etc.  Why do you
think we have so many languages?

The C language was a radical change from what went before it.  There is still
very little like it.  It has a unique place in the scheme of things because of
two very important principles that are buried deep in it.

1)         The programmer knows what he is doing and it is none
           of the language's business to try and stop him.
2)         Just because you *MAY* do something does not mean
	   mean that you *SHOULD* do it.

Therefore C allows things like:
	int	a[], i;
	a[i++] = a[i++] + (int)&i + (int)&(a[i++]);
or:
	struct one { int a, b;} var1;
	struct two { float c, d;} var2;
	var1.c = var2.b;
If you are stupid enough to write such rubbish, then what business is it
of the compiler to try and stop your madness.  The intermable complaints about
compiler dependent constructs are due to people trained on other languages
not understanding principle 2) and the trust that a C compiler has in it's
users.

I was told to think of C as a macro-assemblier for the hardware you are on.
It defines do{}while, for(){}, while(){} and switch(){} as macros in terms of
"if" and "goto".  A struct is just a name, and the elements within it are
numeric offsets.  Function calls are just JSR instructiuons with a bit of
stack work first.  (Therefore we get VARARGS etc. for free.)  A variable is
just a name with some memory behind it, you can reference it in any way you
like.

C is one of very few languages that has direct access to the addressing modes
of the underlieing machine.  Things like [i++], * and & are fine if you know
the machine, and ALL C programmers are assumed to have infinite knowledge.

As a final point, when I was an undergrad in Physics, the Computing Lab refused
to teach C, as it was possible to pick up very bad habits from its freedom.
We were told that programming was like walking.  One should learn in a
cushoned, small space before being let out into a big field where if you fall
nobody will catch you.  I wholeheartedly agree, and hope I write better C
programs now for three years of BASIC/PASCAL/FORTRAN/FORTH first.  They did
teach it to third year Computer Scientists sometimes.

PS:
	If hack had been written in DDL or something similar, would
net.sources.bugs have all the traffic it now does?
-- 
 UUCP: ...seismo!mcvax!ukc!has              | Howard A. Shaw.
  or : has@ukc.uucp                         | Room 12, Physics Lab.,
JANET: has@uk.ac.ukc                        | The University,
Phone: +44 227 764000 Ext. 3282             | Canterbury, England.  CT2 7NZ.

cik@l.cc.purdue.edu (Herman Rubin) (01/19/88)

In article <4186@eagle.ukc.ac.uk>, has@eagle.ukc.ac.uk (H.A.Shaw) writes:
> This may look like a flame.  It is not supposed to be, but I feel strongly
> that we are wasting our time with questions that have no relavence to C as a
> language.

I have left out much of the original article.  I hope I have not omitted
anything important.

> What people appear to be forgetting is what C is for.  
> You should not do complex mathematical work in C,
>     If you want maths, use FORTRAN, 

I find that I can do much better mathematical programming in C than in
FORTRAN.  By better programming, I mean that I can use constructs in C
which are convenient and produce efficient code, and which FORTRAN does
not know the first thing about.  The only advantages of FORTRAN are the
power operator and multi-dimensional arrays.  The major disadvantages are
the lack of indirection and casting, and the requirement that a function has
an argument.  Also C lets you use the rest of the instruction set (although
it makes it difficult, sometimes very difficult).

> 1)         The programmer knows what he is doing and it is none
>            of the language's business to try and stop him.

That is exactly what I am getting at.  This is why C should attempt to be
a flexible language, and if the programmer wants to use a useful construct,
the language should at least allow it.

> 2)         Just because you *MAY* do something does not mean
> 	   mean that you *SHOULD* do it.

Who decides what should be done?  From comment 1), it must be the programmer!
Therefore let the programmer do it!

> I was told to think of C as a macro-assemblier for the hardware you are on.

Then let that be done; that is what I want and do not find.

> C is one of very few languages that has direct access to the addressing modes
> of the underlieing machine.  

And this is not important in numerical analysis?

>  I wholeheartedly agree, and hope I write better C programs now for
> three years of BASIC/PASCAL/FORTRAN/FORTH first.

What would enable one to do a good programming job is to understand the machine
first, so that one can know when the language is inadequate.  I will modify my
algorithm if the machine architecture calls for it.  In a flexible language,
most of the modifications can be indicated by comments.  An example of an
algorithm which should never have been programmed in C, and which should have
been inline, is the infamous 4.2BSD frexp.  That a construct is machine
independent does not mean that its implementation should be.  Actually, the
power operator would be nearly machine independent; the major implementation
differences would be where to stop treating special case of small integer
exponents.

In case you think that C++ should be used for some of these things, the answer
is frequently _no_!  If C++ were produced anew, it _might_ do a fair job.
However, since it is a C preprocessor, whenever C produces bad code, it is
likely to do worse.  The language should help the programmer who knows the
problem and the machine.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

franka@mmintl.UUCP (Frank Adams) (01/19/88)

In article <2516@dasys1.UUCP> wfp@dasys1.UUCP (William Phillips) writes:
>I'm implementing a compiler for a special purpose language that looks a lot
>like C.  The language spec that I was given specifies that the << and >>
>operators, when applied to floating point objects, act as exponentiation
>and inverse exponentiation operators; a logical sort of extension of
>right and left shifts of integer objects, isnt it?

No, it isn't.

Besides the fact that under this interpretation 3 << 3 means something
*entirely* different from 3.0 << 3, there is the fact that I want to raise
integers to powers, too, not just floats.

In fact, I believe that the single most common use of exponentiation, in
languages which have operators for it, is to square an integer.  (This is
based only on my intuition, and obviously varies depending on the nature of
the application.)

If I were to apply a meaning to 3.0 << 3, it would be "3.0 times 2 to the
third", or 24.0.  Note that this is a function which many machines can
implement with simple in-line code.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

flaps@dgp.toronto.edu (Alan J Rosenthal) (01/19/88)

In article <3492@mtgzz.UUCP> dam@mtgzz.UUCP (XMRN40000[kvm]-d.a.morano) writes:
>the '**' can still be used for the power operator since the types of
>the operands cannot be 'pointer to something'.

the lexer cannot determine this, so this is effectively operator
overloading.  rather a complication to introduce into C at this time
just to provide a slight syntactic advantage for an obscure operator.
-- 
"noalias considered sailaon"

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

In article <4186@eagle.ukc.ac.uk> has@ukc.ac.uk (H.A.Shaw) writes:
>You should not do complex mathematical work in C, ...

I've been involved in several large "scientific" applications that
for one reason or another were written in C, including one undergoing
coding at this very moment.  There is no way that any of them would
have been feasible in Fortran, which lacks support for data structures,
dynamic memory allocation, interface specification files (headers), and
other essential features that C provides.

I used to be quite proficient in Fortran, and even did "systems
programming" in it (yes, it was painful), but I've never found a need
to revert to Fortran now that I have C to use.

>	If hack had been written in DDL or something similar, would
>net.sources.bugs have all the traffic it now does?

Hack's problems are not due to the language it is written in, but
to the fact that it was developed by amateurs.  Even a cursory
examination of its source code shows that its authors were not in
command of the language.

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

In article <2649@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
>[If there should be a power operator,] I would vote for x ! y.

As I pointed out in a previous article, that doesn't allow for a corresponding
compound assignment operator (since "!=" is taken).  Besides, it seems a waste
to use a one-character operator for something so seldom necessary.

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

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

In article <4186@eagle.ukc.ac.uk> has@ukc.ac.uk (H.A.Shaw) writes:
>What people appear to be forgetting is what C is for....
>You
>should not do complex mathematical work in C, in the same way that you don't
>solve simultainous equations in troff (I have seen this done!) if you want a
>long life without ulsers.  What we need is to reduce C to it's basics.  C is
>one of a nearly infinite group of languages, each is good at only ONE job.  We
>have forgotten that C was originally a system programmers language.  Who needs
>pow() in a pager or line printer demon?  If you want maths, use FORTRAN, to
>teach, use BASIC/PASCAL, to drive a robot, use LOGO, etc., etc.  Why do you
>think we have so many languages?

The problem is, there are a million reasons *not* to use fortran for
numeric work.  For instance, on a machine running Berkely unix,

1.	f77 compiles about 50% slower than cc, on comparable source code.

2.	on a Celerity, the famous "hello world\n" program, in C, has
	a 30kbytes executable file (stripped),  whereas the fortran version
	is 100kbytes!  Essentially every fortran executable is 70kbytes larger
	than the equivalent program in C.

3.	You can't reasonably write user-friendly i/o schemes for numeric work
	in fortran.  In C you can do a lot of very nice stuff with lex and yacc.

4.	In Unix, fortran users are second-class citizens.  The symbolic
	debugger (dbx) is almost unusable with fortran.  There are two
	beautifier programs for C (cb and indent), none for fortran.  Other
	system utilities, such as awk, bc, and sh borrow much of there
	syntax from C.  If there is
	something wrong with the C compiler it gets instant attention, because
	the whole system depends on it.  For instance, a colleague's research
	ground to a halt when we upgraded from 4.1bsd to 4.2.  NONE of his
	programs worked anymore, because "print *, ..." statements no longer
	worked.  I doubt a "bug" of such magnitude would have been allowed
	to slip out in the C compiler.

5.	fortran, compared to C, is a very nasty language to write in.  The
	only time I do is when I need complex arithmetic, and then,
	I write only those subroutines I need in it.  When C++ compilers become
	widespread, I won't use fortran ever again.  (At that time I won't
	use C ever again, but that's another story).

6.	On PC's, C compilers are cheap and readily available.  Fortran
	compilers are expensive and might not fit on your machine.

Anyway, back to the issue, which is additions to the C standard to make
numeric work on C attractive.  I realize that system programmers can't live
with inside-parenthesis-only optimizations, and that numeric people will
never muck up there already difficult to read mathematical expressions
with a zillion more parentheses and unary plusses.
That is why I whole-heartedly support the previously proposed use of
[]'s to mean groupings which cannot be rearranged.  It's orthogonal,
it's mathematical looking, it's elegant, it overloads []'s no more
than parentheses are already overloaded, it's [insert your favorite
buzzword].

If a power operator is too much trouble, o.k., forget it.  But this
evaluation order thing is crucial.

I wish there were a language designed just for numerical work that was
better than C.  But nothing comes close.
-- 

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

dsill@NSWC-OAS.arpa (Dave Sill) (01/20/88)

In article <658@l.cc.purdue.edu> Herman Rubin <cik@l.cc.purdue.EDU> writes:
>...  The only advantages of FORTRAN are the power operator and
>multi-dimensional arrays. ...

Huh?                   

>In case you think that C++ should be used for some of these things, the answer
>is frequently _no_!  If C++ were produced anew, it _might_ do a fair job.
>However, since it is a C preprocessor, whenever C produces bad code, it is
>likely to do worse.

Strickly speaking, C++ is a compiler, not a preprocessor.  However,
your point that the quality of C++ code depends on the quality of
the C compiler still stands.  That's not a fault of C++, though.
It's a truism that the performance of an application depends on the
software that compiled it.

By the way, GNU's version of C++, G++, doesn't generate C code.  It
generates object code directly.  That doesn't mean it's any better
than C++, because it really just has a built-in C compiler.

=========
The opinions expressed above are mine.

"I shed, therefore, I am."
					-- ALF