Created attachment 492
Patch against DMD2 svn 241
Requests for an exponential operator have come up numerous times on the
newsgroup.
This patch introduces a new binary operator ^^ which performs exponentiation:
x ^^ y is pow(x, y).
Likewise x ^^= y is x = pow(x, y).
The corresponding overloaded operators are opPow, opPow_r, and opPowAssign.
In the patch, ^^ is supported for integral and floating-point types.
Two special cases are supported:
x ^^ 1 becomes x;
x ^^ 0.5 becomes sqrt(x);
x ^^ y becomes pow(x, y);
This requires pow() and/or sqrt() to be defined, typically by importing
std.math.
IE, this is just syntax sugar.
BUGS: I'm translating x^^=y into x = pow(x, y). This means x gets evaluated
twice.
If this patch is accepted, there is much that can be done with the
implementation.
Most importantly by adding back-end support for x ^^ 2.
However, this simple implementation would give us the semantics.
Comment #1 by dsimcha — 2009-11-06T13:07:53Z
I've been wanting an exponentiation operator since the Stone Age, but it seemed like too small an issue to really make a point about. This is terrific. However, can we at least consider making ^ the exponentiation op and moving xor to ^^? Yes, it breaks C compatibility, but who the heck really uses bitwise xor except in really low-level code anyhow?
Comment #2 by andrei — 2009-11-06T13:16:46Z
Sweet. Suggestion: rewrite x^^=y into powAssign(x, y) and define powAssign appropriately, e.g.:
ref B powAssign(B, E)(ref B b, E e) if (isNumeric!B && isNumeric!E);
That way you don't need any trick to evaluate x only once etc.
Comment #3 by clugdbug — 2009-11-06T13:48:51Z
(In reply to comment #1)
> I've been wanting an exponentiation operator since the Stone Age, but it seemed
> like too small an issue to really make a point about. This is terrific.
> However, can we at least consider making ^ the exponentiation op and moving xor
> to ^^? Yes, it breaks C compatibility, but who the heck really uses bitwise
> xor except in really low-level code anyhow?
That's not possible, because things like int y = x ^ 2; would continue to compile, but silently change meaning. x ^^ y causes no problems, because it never had a meaning. I agree it's unfortunate that C grabbed the best symbols and used them for some relatively obscure operations (~ is a classic example) -- but it's too late now. I actually think we're lucky that ^^ is available.
(In reply to comment #2)
> Sweet. Suggestion: rewrite x^^=y into powAssign(x, y) and define powAssign
> appropriately, e.g.:
>
> ref B powAssign(B, E)(ref B b, E e) if (isNumeric!B && isNumeric!E);
>
> That way you don't need any trick to evaluate x only once etc.
It's not really a big problem to do the whole thing properly. I just implemented the bare minimum to get started. Really, it should support constant folding, and generate back-end code for squaring, etc. That's not technically difficult, but it involves changes to many different bits of code in the compiler, which makes it a difficult patch for Walter to evaluate and integrate (and hence, less likely to be accepted).
Comment #4 by leandro.lucarella — 2009-11-06T13:51:45Z
I'm sorry to bring the bike shed discussion here, but I would like to consider ** exponentiation. The reason is that writing ^^ for people with keyboards with "dead keys" (to write accents for example) is very hard, because you have to write "^" like this: shift+6 space (3 keystrokes), or even worse (unless you use Emacs ;): shift+alt_gr+6.
I'm not sure if ** is even possible (because of pointers), but in case it is, I will like you to give it a thought.
This is, of course, a minor detail. I like the idea of introducing an exponentiation operator, I just don't feel very well about depending on importing any module, but if that can be changed/fixed in the future, it's fine with me.
Comment #5 by smjg — 2009-11-07T18:47:17Z
(In reply to comment #1)
> I've been wanting an exponentiation operator since the Stone Age, but it seemed
> like too small an issue to really make a point about. This is terrific.
> However, can we at least consider making ^ the exponentiation op and moving xor
> to ^^? Yes, it breaks C compatibility, but who the heck really uses bitwise
> xor except in really low-level code anyhow?
Are we going to change around the other bitwise vs. logical operators as well?
Confusion with the bitwise operators is why I'm against the choice of ^ or ^^ for exponentiation. Sooner or later, someone's going to expect ^^ to be the logical xor operator.
But I don't know what would be a good symbol for it. I'm not sure I've ever really liked **, aside from the current meanings of those two characters in sequence. Maybe if only ↑ had remained on keyboards beyond ZX Spectrum days....
Comment #6 by clugdbug — 2009-11-07T22:26:45Z
(In reply to comment #5)
> (In reply to comment #1)
> > I've been wanting an exponentiation operator since the Stone Age, but it seemed
> > like too small an issue to really make a point about. This is terrific.
> > However, can we at least consider making ^ the exponentiation op and moving xor
> > to ^^? Yes, it breaks C compatibility, but who the heck really uses bitwise
> > xor except in really low-level code anyhow?
>
> Are we going to change around the other bitwise vs. logical operators as well?
>
> Confusion with the bitwise operators is why I'm against the choice of ^ or ^^
> for exponentiation. Sooner or later, someone's going to expect ^^ to be the
> logical xor operator.
Logical xor is already in the language, its symbol is !=.
> But I don't know what would be a good symbol for it. I'm not sure I've ever
> really liked **, aside from the current meanings of those two characters in
> sequence. Maybe if only ↑ had remained on keyboards beyond ZX Spectrum
> days....
Comment #7 by smjg — 2009-11-08T06:55:47Z
(In reply to comment #6)
> Logical xor is already in the language, its symbol is !=.
Not quite. For example, 1 != 2 evaluates to true, whereas if ^^ is defined as a logical xor, 1 ^^ 2 would evaluate to false.
But if the operands are guaranteed to be boolean or at least 0 or 1, then != is effectively a logical xor. To get logical xor when other values are possible, one would have to do something like negate the operands.
So essentially, a ^^ b would be equivalent to !a != !b.
Comment #8 by bugzilla — 2009-11-28T15:42:40Z
Thoughts on if the ^^= variant is needed?
Comment #9 by bugzilla — 2009-11-28T20:59:29Z
I checked in changes as 269, but only for the ^^.
Comment #10 by dfj1esp02 — 2009-11-30T07:01:11Z
(In reply to comment #4)
> I'm sorry to bring the bike shed discussion here, but I would like to consider
> ** exponentiation. The reason is that writing ^^ for people with keyboards with
> "dead keys" (to write accents for example) is very hard, because you have to
> write "^" like this: shift+6 space (3 keystrokes), or even worse (unless you
> use Emacs ;): shift+alt_gr+6.
If remeber it correctly, you don't have to type space in this case, just hit shift+6 two times. Yes, the first hit will be the dead key hit, but the second will yield ^^ at once.
Comment #11 by leandro.lucarella — 2009-11-30T14:01:10Z
(In reply to comment #10)
> (In reply to comment #4)
> > I'm sorry to bring the bike shed discussion here, but I would like to consider
> > ** exponentiation. The reason is that writing ^^ for people with keyboards with
> > "dead keys" (to write accents for example) is very hard, because you have to
> > write "^" like this: shift+6 space (3 keystrokes), or even worse (unless you
> > use Emacs ;): shift+alt_gr+6.
>
> If remeber it correctly, you don't have to type space in this case, just hit
> shift+6 two times. Yes, the first hit will be the dead key hit, but the second
> will yield ^^ at once.
Not with my keyboard configuration, I can hit Shift+6 twice, but that yields only one ^, so I have to press Shift+6 four times to get ^^ :)
Comment #12 by torhu — 2009-12-02T12:13:51Z
(In reply to comment #11)
> Not with my keyboard configuration, I can hit Shift+6 twice, but that yields
> only one ^, so I have to press Shift+6 four times to get ^^ :)
I have to do that too, but only on Linux. On Windows, it only takes two presses. This is using a Norwegian keyboard, where the caret is on a different key, but you still have to hold down the shift key.
Maybe it's time to upgrade to Windows?
Comment #13 by dfj1esp02 — 2009-12-04T05:31:01Z
It's strange, I tried english-international and french layouts - they work as I described.
Comment #14 by bugzilla — 2009-12-06T00:54:25Z
Fixed dmd 2.037
Comment #15 by witold.baryluk+d — 2009-12-08T21:35:13Z
Just wanted to write: Thanks!
I have about 10 classes with already deffinied opPow just waiting to this for years.
About Walters question about opPowAssgn, i have few place where i'm for. example squering in place, or (in. for computing exponent of interval matrix), this isn't actually inplace, but makes code more readble, other i example in my libraries i see units library, where i see something like this:
Self opPowAssign(int b) {
if (b >= 0) {
nom = pow(cast(int)nom, b);
denom = pow(cast(int)denom, b);
} else {
auto newnom = pow(cast(int)denom, -b);
denom = pow(cast(int)nom, -b);
nom = newnom;
}
return this;
}
Clearly first can use opPowAssign, of course in such simple example compiler should be detect that x = x ^^ y, for simple types can be done in place. And this opPowAssign is used in few places also.
Or clearly like this:
Self opPowAssign(int b) {
nom ^^= b;
denom ^^= b;
if (b < 0) {
swap(nom, denom);
}
return this;
}
I have also few places with something like:
new_step = pow(previous_step, f(x))
it can be changed to: step ^^= f(x).
and new_step is not nacassarly float or double, it can be slightly more complex structure like interval vector (and exponentation of it can be done in-place).
I also think that sometimes pepole will have not enaugh operators, and for the sake of consistency it is good to have opPowAssign. :) Not nacassarly good for clearity of code if it will use ALL opXAssign for very diferent things.
Comment #16 by witold.baryluk+d — 2009-12-08T22:11:40Z
It is also usefull to have opPowAssign for vector operations:
float a[],. b[];
a[] ^^= 2;
a[] ^^= b[];
It should be easier to compiler to generate better code, than from this:
a[] = a[] ^^ 2;
a[] = a[] ^^ b[];
BTW is ^^ supported as operator in array operations? IT definietly SHOULD.