Bug 3481 – PATCH: opPow(), x ^^ y as a power operator

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2009-11-06T13:03:00Z
Last change time
2015-06-09T01:27:04Z
Keywords
patch
Assigned to
nobody
Creator
clugdbug

Attachments

IDFilenameSummaryContent-TypeSize
492powPatch.patchPatch against DMD2 svn 241text/plain8723

Comments

Comment #0 by clugdbug — 2009-11-06T13:03:01Z
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.