digitalmars.D - More on semantics of opPow: return type
- Don (34/34) Dec 07 2009 As has been mentioned in previous posts, a ^^ b should be right
- Simen kjaeraas (8/42) Dec 07 2009 I believe int^^int should not be defined (it's basically useless, as one
- Andrei Alexandrescu (5/47) Dec 07 2009 Nice analysis. IMHO this should lead us to reconsider the necessity of
- Lars T. Kyllingstad (17/67) Dec 07 2009 It adds a lot of value to the ones that actually use it, even though you...
- Lars T. Kyllingstad (5/75) Dec 07 2009 FORTRAN also has the ISHFT() shift function, which gives about 2000
- Andrei Alexandrescu (18/46) Dec 07 2009 Well I write numerics and I do use exponentiation occasionally, but
- Bill Baxter (19/65) Dec 07 2009 to
- Lars T. Kyllingstad (15/66) Dec 07 2009 Yeah, I get a little carried away. The point I was trying to make is
- bearophile (28/31) Dec 07 2009 It was Don, I think.
- Bill Baxter (7/36) Dec 07 2009 r, complex, this is just an idea) functions too. GCC for example simplif...
- bearophile (7/8) Dec 07 2009 Don't ask me why. Eleven so far, you can't find five of them because in ...
- Bill Baxter (13/19) Dec 07 2009 he beginning another person has filed them for me in a strange way. LLVM...
- Justin Johansson (6/17) Dec 08 2009 Of all the people in this newsgroup, I would have to say that you,
- Andrei Alexandrescu (7/12) Dec 07 2009 Hmmm. Addition, subtraction, multiplication, and division with remainder...
- Bill Baxter (14/24) Dec 07 2009 Uh, but a/b is not a "division with remainder" operator. It's just
- Andrei Alexandrescu (13/38) Dec 07 2009 The result of a/b is the quotient resulting from a division with
- Bill Baxter (23/68) Dec 07 2009 ow
- Andrei Alexandrescu (12/69) Dec 07 2009 I understand where you're coming from. As an old math teacher would say,...
- Bill Baxter (21/102) Dec 07 2009 s
- Andrei Alexandrescu (8/23) Dec 07 2009 But -1^^0.5 is the imaginary constant! Something definitely doesn't add
- Bill Baxter (10/33) Dec 07 2009 p.
- Simen kjaeraas (4/9) Dec 08 2009 And now we'll all be wanting postfix ! for factorial as well, right? :p
- KennyTM~ (18/85) Dec 07 2009 Fortran? I don't think that's D's target audience yet.
- Lars T. Kyllingstad (7/88) Dec 07 2009 I searched for FORTRAN code because that's more or less equivalent to
- bearophile (6/11) Dec 07 2009 I agree, if D plays well its cards it can be used by users of the numeri...
- Joel C. Salomon (4/12) Dec 09 2009 Then we may have to convince Walter not to eliminate the extra
- bearophile (6/8) Dec 09 2009 They don't add that much to the language, while they are not easy to rem...
- Lionello Lunesu (9/12) Dec 07 2009 No, Don's just being awefully thorough. If you'd revisit all existing
- Don (5/20) Dec 07 2009 Exactly. The fallback case is to just make int^^int an int.
- Andrei Alexandrescu (20/40) Dec 08 2009 Walter and I decided to leave the decision of ^^ up to you, Don. You are...
- Bill Baxter (27/42) Dec 08 2009 y
- Andrei Alexandrescu (19/51) Dec 08 2009 Consistency is a good rationale, but math simply doesn't work that way.
- Bill Baxter (36/93) Dec 08 2009 r
- Bill Baxter (7/16) Dec 08 2009 n).
- Don (6/22) Dec 08 2009 I'm bitterly opposed to making int^^negative int return 0. Doing that is...
- Andrei Alexandrescu (3/28) Dec 08 2009 Awesome! Don please please require the exponent to be of unsigned type :...
- Simen kjaeraas (5/33) Dec 09 2009 Yeah. Makes no sense allowing it to be signed.
- Bill Baxter (8/35) Dec 09 2009 =3D=3D 0,
- Lars T. Kyllingstad (9/27) Dec 07 2009 I think it should either be an error, or it should return a
- bearophile (4/8) Dec 07 2009 In Pascal there's the 'div' operator for the integer division and / for ...
- bearophile (19/33) Dec 07 2009 The pow operator in Python seems to give good results (this also shows w...
- Sean Kelly (2/8) Dec 08 2009 Oh, for polysemous values :-) I'm somewhat inclined to say that the res...
As has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).
Dec 07 2009
On Mon, 07 Dec 2009 13:13:34 +0100, Don <nospam nospam.com> wrote:As has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).I believe int^^int should not be defined (it's basically useless, as one would (almost) always want an integer result, and a float result could easily be had by casting). As regards n^^(x >= n.sizeof * 8), I'm not 100% sure. I'm leaning towards only allowing int^^ubyte, but it seems constraining. -- Simen
Dec 07 2009
Don wrote:As has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. Andrei
Dec 07 2009
Andrei Alexandrescu wrote:Don wrote:It adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics. Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D. (I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at least an indication.) -LarsAs has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. Andrei
Dec 07 2009
Lars T. Kyllingstad wrote:Andrei Alexandrescu wrote:FORTRAN also has the ISHFT() shift function, which gives about 2000 results on Google. Still way less than for **.Don wrote:It adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics. Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D.As has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. Andrei(I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortranishft\([0-9a-zA-Z] lang:fortran -Lars
Dec 07 2009
Lars T. Kyllingstad wrote:Andrei Alexandrescu wrote:Well I write numerics and I do use exponentiation occasionally, but never to the extent of yearning for ^^. "Extremely common" would be, I think, quite difficult to argue.Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. AndreiIt adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics.Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D. (I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at least an indication.)Thanks for collecting the evidence. To make it more meaningful, you may want to report it to the total number of lines of code searched. I don't know how to do that with codesearch. FWIW, this search: [0-9a-zA-Z)]\*\*[013456789a-zA-Z(] lang:fortran yields 30,300 results, meaning that almost half the uses of exponentiation is to square things. So I'm not sure what this all is supposed to argue for or against. What I can say is that Don's analysis suggested to me, let's leave all that aggravation to overloads of pow() and call it a day. I was much more in favor of ^^ before I saw how quickly it gets complicated. That kind of stuff just doesn't strike me as the kind of things you put straight in the core language. Andrei
Dec 07 2009
On Mon, Dec 7, 2009 at 11:59 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Lars T. Kyllingstad wrote:toAndrei Alexandrescu wrote:Well I write numerics and I do use exponentiation occasionally, but never=Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. AndreiIt adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics.the extent of yearning for ^^. "Extremely common" would be, I think, quit=edifficult to argue.ve aHere are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't ha=ndD equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() a=D.276 results for LSHIFT(). Yet, left shift apparently deserves a place in=st(I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: =A0 =A0[0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran =A0 =A0ils\([0-9a-zA-Z] lang:fortran =A0 =A0lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at lea=antan indication.)Thanks for collecting the evidence. To make it more meaningful, you may w=to report it to the total number of lines of code searched. I don't know =howto do that with codesearch. FWIW, this search: [0-9a-zA-Z)]\*\*[013456789a-zA-Z(] lang:fortran yields 30,300 results, meaning that almost half the uses of exponentiatio=nis to square things. So I'm not sure what this all is supposed to argue for or against. What I can say is that Don's analysis suggested to me, let's leave all that aggravation to overloads of pow() and call it a day. I was much more in favor of ^^ before I saw how quickly it gets complicated. That kind of st=uffjust doesn't strike me as the kind of things you put straight in the core language.I get [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran --> 57,900 [0-9a-zA-Z)]\*\*2 lang:fortran --> 81,900 141% of uses are for squaring! (I guess that's why you made yours a search for non-squaring, but still it shows something is odd in Google's counts) --bb
Dec 07 2009
Andrei Alexandrescu wrote:Lars T. Kyllingstad wrote:Yeah, I get a little carried away. The point I was trying to make is that it's not as uncommon as some would have it. The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own. I also seem to remember someone (was it Don or bearophile, perhaps?) listing various optimisation possibilities that are more readily available if ^^ is a built-in operator.Andrei Alexandrescu wrote:Well I write numerics and I do use exponentiation occasionally, but never to the extent of yearning for ^^. "Extremely common" would be, I think, quite difficult to argue.Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. AndreiIt adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics....which is still a valid use case, since foo*foo evaluates foo twice and square(foo) is no better than pow(foo, 2).Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D. (I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at least an indication.)Thanks for collecting the evidence. To make it more meaningful, you may want to report it to the total number of lines of code searched. I don't know how to do that with codesearch. FWIW, this search: [0-9a-zA-Z)]\*\*[013456789a-zA-Z(] lang:fortran yields 30,300 results, meaning that almost half the uses of exponentiation is to square things.So I'm not sure what this all is supposed to argue for or against. What I can say is that Don's analysis suggested to me, let's leave all that aggravation to overloads of pow() and call it a day. I was much more in favor of ^^ before I saw how quickly it gets complicated. That kind of stuff just doesn't strike me as the kind of things you put straight in the core language.You could say the same for arrays. T[new] and ~=, anyone? ;) -Lars
Dec 07 2009
Lars T. Kyllingstad:I also seem to remember someone (was it Don or bearophile, perhaps?) listing various optimisation possibilities that are more readily available if ^^ is a built-in operator.It was Don, I think. Those optimizations can be done with the pow, ipow and cpow (real, integer, complex, this is just an idea) functions too. GCC for example simplifies cases when the exponent is 2 or 3 (that are the most common): // C code #include "stdio.h" #include "math.h" #include "stdlib.h" int main() { int x = atoi("100"); printf("%f\n", pow(x, 2)); return 0; } Compiled with: gcc version 4.3.3-dw2-tdm-1 (GCC) gcc -Wall -S -O3 test2.c -o test2.s ... call _atoi pushl %eax fildl (%esp) addl $4, %esp fmul %st(0), %st movl $LC1, (%esp) fstpl 4(%esp) call _printf ... Some weeks ago I have filed a bug asking for a similar optimization in LLVM too (so LDC too will have it). Bye, bearophile
Dec 07 2009
On Mon, Dec 7, 2009 at 2:29 PM, bearophile <bearophileHUGS lycos.com> wrote= :Lars T. Kyllingstad:r, complex, this is just an idea) functions too. GCC for example simplifies= cases when the exponent is 2 or 3 (that are the most common):I also seem to remember someone (was it Don or bearophile, perhaps?) listing various optimisation possibilities that are more readily available if ^^ is a built-in operator.It was Don, I think. Those optimizations can be done with the pow, ipow and cpow (real, intege=// C code #include "stdio.h" #include "math.h" #include "stdlib.h" int main() { =A0 =A0int x =3D atoi("100"); =A0 =A0printf("%f\n", pow(x, 2)); =A0 =A0return 0; } Compiled with: gcc version 4.3.3-dw2-tdm-1 (GCC) gcc -Wall -S -O3 test2.c -o test2.s =A0 =A0... =A0 =A0call =A0 =A0_atoi =A0 =A0pushl =A0 %eax =A0 =A0fildl =A0 (%esp) =A0 =A0addl =A0 =A0$4, %esp =A0 =A0fmul =A0 =A0%st(0), %st =A0 =A0movl =A0 =A0$LC1, (%esp) =A0 =A0fstpl =A0 4(%esp) =A0 =A0call =A0 =A0_printf =A0 =A0... Some weeks ago I have filed a bug asking for a similar optimization in LL=VM too (so LDC too will have it). Holy smokes! You actually file bugs in the LLVM database?! --bb
Dec 07 2009
Bill Baxter:Holy smokes! You actually file bugs in the LLVM database?!Don't ask me why. Eleven so far, you can't find five of them because in the beginning another person has filed them for me in a strange way. LLVM devs have asked me so many times, on IRC. One of those performance bugs has already being half-fixed, with nice results: http://llvm.org/bugs/show_bug.cgi?id=5501 I feel dumb, I understand nearly nothing of what they do and how they do it, it's another (higher) level... I may be fit as their jester. Bye, bearophile
Dec 07 2009
On Mon, Dec 7, 2009 at 2:52 PM, bearophile <bearophileHUGS lycos.com> wrote= :Bill Baxter:he beginning another person has filed them for me in a strange way. LLVM de= vs have asked me so many times, on IRC. Folks have asked you many times here to submit bugs against dmd and/or phobos too. That's why I was surprised. I thought it was some religious thing, this non-filing of bugs. :-)Holy smokes! =A0You actually file bugs in the LLVM database?!Don't ask me why. Eleven so far, you can't find five of them because in t=One of those performance bugs has already being half-fixed, with nice res=ults:http://llvm.org/bugs/show_bug.cgi?id=3D5501Nice. Still hoping for the day when LLVM can do exceptions on Windows...I feel dumb, I understand nearly nothing of what they do and how they do =it, it's another (higher) level... I may be fit as their jester. Yeh, that kind of low level compiler tweaking is pretty much a mystery to me too. --bb
Dec 07 2009
bearophile wrote:Bill Baxter:Of all the people in this newsgroup, I would have to say that you, bearophile, would have to be one of the most polite writers and most entertaining as well. It's always a pleasure to read your posts :-) Beers, Justin JohanssonHoly smokes! You actually file bugs in the LLVM database?!Don't ask me why. Eleven so far, you can't find five of them because in the beginning another person has filed them for me in a strange way. LLVM devs have asked me so many times, on IRC. One of those performance bugs has already being half-fixed, with nice results: http://llvm.org/bugs/show_bug.cgi?id=5501 I feel dumb, I understand nearly nothing of what they do and how they do it, it's another (higher) level... I may be fit as their jester. Bye, bearophile
Dec 08 2009
Lars T. Kyllingstad wrote:The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainder are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic. The more I hear, the more I'm convinced ^^ is just not worth it. And again: I initially liked the idea. Andrei
Dec 07 2009
On Mon, Dec 7, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Lars T. Kyllingstad wrote:Uh, but a/b is not a "division with remainder" operator. It's just division-with-a-remainder-silently-ignored. If you want to define pow in the same way as a "pow with remainder but with the remainder ignored" then there's nothing stopping you. 1^^-1 == 1 2^^-1 == 0 4^^(1/2) == 2 5^^(1/2) == 2 Though I'd rather go the other direction and make the remainder-dropping integer division use a different symbol a la Python. --bbThe fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainder are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic.
Dec 07 2009
Bill Baxter wrote:On Mon, Dec 7, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:The result of a/b is the quotient resulting from a division with remainder. If you want the remainder use a%b (the compiler will peephole-optimize that). I don't see anything wrong with what I said.Lars T. Kyllingstad wrote:Uh, but a/b is not a "division with remainder" operator. It's just division-with-a-remainder-silently-ignored.The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainder are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic.If you want to define pow in the same way as a "pow with remainder but with the remainder ignored" then there's nothing stopping you. 1^^-1 == 1 2^^-1 == 0 4^^(1/2) == 2 5^^(1/2) == 2 Though I'd rather go the other direction and make the remainder-dropping integer division use a different symbol a la Python.You'd need to show that "power with remainder" as you just defined it is useful theoretically and/or practically. The usefulness of integral division is absolutely massive. Anyhow, all I did was to explain that a particular argument that was made is invalid. That doesn't mean other arguments are invalid. All I'd hope is that ^^ doesn't suddenly become a time sink when we have so much other stuff to worry about. Again: ^^ was a lot more attractive to me when it seemed like a slam dunk. Andrei
Dec 07 2009
On Mon, Dec 7, 2009 at 2:56 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:owOn Mon, Dec 7, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Lars T. Kyllingstad wrote:The fundamental reason why I want opPow so badly is in fact not even h=roften I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainde=r.The result of a/b is the quotient resulting from a division with remainde=are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic.Uh, but a/b is not a "division with remainder" operator. =A0It's just division-with-a-remainder-silently-ignored.If you want the remainder use a%b (the compiler will peephole-optimize that). I don't see anything wrong with what I said.ionIf you want to define pow in the same way as a "pow with remainder but with the remainder ignored" then there's nothing stopping you. =A0 =A01^^-1 =3D=3D 1 =A0 =A02^^-1 =3D=3D 0 =A0 =A04^^(1/2) =3D=3D 2 =A0 =A05^^(1/2) =3D=3D 2 Though I'd rather go the other direction and make the remainder-dropping integer division use a different symbol a la Python.You'd need to show that "power with remainder" as you just defined it is useful theoretically and/or practically. The usefulness of integral divis=is absolutely massive. Anyhow, all I did was to explain that a particular argument that was made=isinvalid. That doesn't mean other arguments are invalid. All I'd hope is t=hat^^ doesn't suddenly become a time sink when we have so much other stuff t=oworry about. Again: ^^ was a lot more attractive to me when it seemed lik=e aslam dunk.Seriously, I thought the above behavior would be what you'd get using integer arguments with opPow by analogy with how opDiv behaves. I wasn't expecting there would be any debate about it. I think the feeling that 2^^-1 is not 0 is the same gut feeling that tells all programming newbies that 1/2 should not be 0. But truncating down to the nearest int was the decision made long ago, so we stick with it. But languages like python that cater to newbie programmers are now trying to do something about it by making the difference between truncated integer division and division explicit. I don't really think D is going to go down that route at this late date, so we should just try to be self-consistent. Which to me says 1/2 and 2^^-1 should give the same result. --bb
Dec 07 2009
Bill Baxter wrote:On Mon, Dec 7, 2009 at 2:56 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I understand where you're coming from. As an old math teacher would say, "this is true but uninteresting". You'd have to prove that that behavior of ^^ has some interesting math properties. For starters, you'd need a "remainder" for ^^. But then what kind of interesting things can you do with such a definition? Anyway, maybe things could reach an inflection point. Maybe Don will find some type trickery for ^^ that's very ingenious and very compiler-y. In that case, there would be a strong justification to build special rules for ^^ in the compiler instead of building an imperfect approximation of it with pow() overloads. AndreiBill Baxter wrote:Seriously, I thought the above behavior would be what you'd get using integer arguments with opPow by analogy with how opDiv behaves. I wasn't expecting there would be any debate about it. I think the feeling that 2^^-1 is not 0 is the same gut feeling that tells all programming newbies that 1/2 should not be 0. But truncating down to the nearest int was the decision made long ago, so we stick with it. But languages like python that cater to newbie programmers are now trying to do something about it by making the difference between truncated integer division and division explicit. I don't really think D is going to go down that route at this late date, so we should just try to be self-consistent. Which to me says 1/2 and 2^^-1 should give the same result.On Mon, Dec 7, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:The result of a/b is the quotient resulting from a division with remainder. If you want the remainder use a%b (the compiler will peephole-optimize that). I don't see anything wrong with what I said.Lars T. Kyllingstad wrote:Uh, but a/b is not a "division with remainder" operator. It's just division-with-a-remainder-silently-ignored.The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainder are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic.If you want to define pow in the same way as a "pow with remainder but with the remainder ignored" then there's nothing stopping you. 1^^-1 == 1 2^^-1 == 0 4^^(1/2) == 2 5^^(1/2) == 2 Though I'd rather go the other direction and make the remainder-dropping integer division use a different symbol a la Python.You'd need to show that "power with remainder" as you just defined it is useful theoretically and/or practically. The usefulness of integral division is absolutely massive. Anyhow, all I did was to explain that a particular argument that was made is invalid. That doesn't mean other arguments are invalid. All I'd hope is that ^^ doesn't suddenly become a time sink when we have so much other stuff to worry about. Again: ^^ was a lot more attractive to me when it seemed like a slam dunk.
Dec 07 2009
On Mon, Dec 7, 2009 at 4:04 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:sOn Mon, Dec 7, 2009 at 2:56 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:On Mon, Dec 7, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:The result of a/b is the quotient resulting from a division with remainder. If you want the remainder use a%b (the compiler will peephole-optimize that). I don't see anything wrong with what I said.Lars T. Kyllingstad wrote:Uh, but a/b is not a "division with remainder" operator. =A0It's just division-with-a-remainder-silently-ignored.The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.Hmmm. Addition, subtraction, multiplication, and division with remainder are all closed over integers. Power isn't. It's not even closed over real numbers. That makes it quite special and quite non-basic.If you want to define pow in the same way as a "pow with remainder but with the remainder ignored" then there's nothing stopping you. =A0 1^^-1 =3D=3D 1 =A0 2^^-1 =3D=3D 0 =A0 4^^(1/2) =3D=3D 2 =A0 5^^(1/2) =3D=3D 2 Though I'd rather go the other direction and make the remainder-dropping integer division use a different symbol a la Python.You'd need to show that "power with remainder" as you just defined it i=deuseful theoretically and/or practically. The usefulness of integral division is absolutely massive. Anyhow, all I did was to explain that a particular argument that was ma=ofI understand where you're coming from. As an old math teacher would say, "this is true but uninteresting". You'd have to prove that that behavior =is invalid. That doesn't mean other arguments are invalid. All I'd hope is that ^^ doesn't suddenly become a time sink when we have so much other stuff to worry about. Again: ^^ was a lot more attractive to me when it seemed like a slam dunk.Seriously, I thought the above behavior would be what you'd get using integer arguments with opPow by analogy with how opDiv behaves. =A0I wasn't expecting there would be any debate about it. =A0I think the feeling that 2^^-1 is not 0 is the same gut feeling that tells all programming newbies that 1/2 should not be 0. =A0But truncating down to the nearest int was the decision made long ago, so we stick with it. But languages like python that cater to newbie programmers are now trying to do something about it by making the difference between truncated integer division and division explicit. =A0I don't really think D is going to go down that route at this late date, so we should just try to be self-consistent. =A0Which to me says =A01/2 and 2^^-1 should give the same result.^^ has some interesting math properties. For starters, you'd need a "remainder" for ^^. But then what kind of interesting things can you do w=ithsuch a definition?Negative exponent values are the only ones with an issue. You can't even write square-root etc with pow using only integers. The argument would have to be a float to even express that, so there is no issue. int^^float should be a float just like int/float is a float. So the only things left are those of the form x^^-y. or 1/(x^^y). I don't see a reason to go any further than translating it to exactly that. And that's just division, so the %-like operator corresponding to that is just % itself ( or rather 1%(x^^y) ) I think Don was creating a tempest in a teapot. I don't think any of his proposed alternatives besides treating it as integer division really make sense. They are inconsistent with the rest of D, and so don't merit further consideration unless the behavior of 1/2 is also on the table. --bb
Dec 07 2009
Bill Baxter wrote:Negative exponent values are the only ones with an issue. You can't even write square-root etc with pow using only integers. The argument would have to be a float to even express that, so there is no issue. int^^float should be a float just like int/float is a float.But -1^^0.5 is the imaginary constant! Something definitely doesn't add up. Are you sure you meant int^^float to be float? And what's the deal with the ongoing parallel exegesis with division? A division of reals doesn't result in a complex.So the only things left are those of the form x^^-y. or 1/(x^^y). I don't see a reason to go any further than translating it to exactly that. And that's just division, so the %-like operator corresponding to that is just % itself ( or rather 1%(x^^y) ) I think Don was creating a tempest in a teapot. I don't think any of his proposed alternatives besides treating it as integer division really make sense. They are inconsistent with the rest of D, and so don't merit further consideration unless the behavior of 1/2 is also on the table.To quote a living classic, when disagreeing with Don, you better have your ducks in a row. Andrei
Dec 07 2009
On Mon, Dec 7, 2009 at 4:41 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:p.Negative exponent values are the only ones with an issue. =A0You can't even write square-root etc with pow using only integers. =A0The argument would have to be a float to even express that, so there is no issue. int^^float should be a float just like int/float is a float.But -1^^0.5 is the imaginary constant! Something definitely doesn't add u=Are you sure you meant int^^float to be float? And what's the deal with t=heongoing parallel exegesis with division? A division of reals doesn't resu=ltin a complex.Don already covered that. Floats have nan, so that would be a nan.=A0ISo the only things left are those of the form =A0x^^-y. =A0or 1/(x^^y). =rdon't see a reason to go any further than translating it to exactly that. And that's just division, so the %-like operator corresponding to that is just % itself ( or rather 1%(x^^y) ) I think Don was creating a tempest in a teapot. =A0I don't think any of his proposed alternatives besides treating it as integer division really make sense. =A0They are inconsistent with the rest of D, and so don't merit further consideration unless the behavior of 1/2 is also on the table.To quote a living classic, when disagreeing with Don, you better have you=ducks in a row.Doin' my best here. --bb
Dec 07 2009
Lars T. Kyllingstad <public kyllingen.nospamnet> wrote:The fundamental reason why I want opPow so badly is in fact not even how often I use it. If that was the case, I'd want a special "writefln" operator as well. The main reason is that exponentiation is such a basic mathematical operation, right up there with addition and multiplication, that it deserves an operator of its own.And now we'll all be wanting postfix ! for factorial as well, right? :p -- Simen
Dec 08 2009
On Dec 8, 09 03:03, Lars T. Kyllingstad wrote:Andrei Alexandrescu wrote:Fortran? I don't think that's D's target audience yet. And let's also compare with Python: A search of "lang:python [\w)]\s*\*\*\s*[\w(]" yields 10,700 results, and the first few actual use cases are: 1: bufferSize = 2**2**2**2 2: n,x = 89 >> 90 + 6 / 7 % x + z << 6 + 2 ** 8 3: def cube(n): return n ** 3 4: v1 = stdev(a)**2 v2 = stdev(b)**2 5: self.val = self.val ** 2 6: self._readerLength = self._readerLength * (10**len(m.group(1))) + long(m.group(1)) 7: rtn.append((1 - (1 - rgb[index]) ** correction) ** (1 / correction)) I don't find any appeal for cases 1 to 5. (Also compare with left-shift (lang:python [\w)]\s*<<\s*[\w(]), giving 9,000 results.)Don wrote:It adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics. Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D. (I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at least an indication.) -LarsAs has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. Andrei
Dec 07 2009
KennyTM~ wrote:On Dec 8, 09 03:03, Lars T. Kyllingstad wrote:I searched for FORTRAN code because that's more or less equivalent to searching for numerical code. And I think D's "target audience" is anyone who needs a fast, close-to-the-metal programming language. This definitely includes the scientific community. (There are several of the regulars on this NG who use D for scientific work.) -LarsAndrei Alexandrescu wrote:Fortran? I don't think that's D's target audience yet.Don wrote:It adds a lot of value to the ones that actually use it, even though you may not be one of them. Exponentiation is extremely common in numerics. Here are some statistics for you: A Google code search (see below) for FORTRAN code using the power operator **, which until recently didn't have a D equivalent, yields roughly 56100 results. A search for the FORTRAN equivalents of << yield 400 results for ILS() and 276 results for LSHIFT(). Yet, left shift apparently deserves a place in D. (I've used http://www.google.com/codesearch, with the following search strings for **, ILS and LSHIFT, respectively: [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran ils\([0-9a-zA-Z] lang:fortran lshift\([0-9a-zA-Z] lang:fortran As statistics go, this is probably not a prime example, but it is at least an indication.) -LarsAs has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double? Or should 10^^2 also be a double, but implicitly castable to byte because of the range checking rules? I currently favour making it an error, so that the normal promotion rules apply. It seems reasonable to me to require a cast to floating point in there somewhere. This is analagous to the similar case f ^^ 0.1; where f is known to be negative. This gives a complex result, creating a run-time error (returns a NaN). But, there's no standard error and no NaNs for integer underflow. One could also make int ^^ uint defined (returning an int), but not int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would work, because although uint ^^ uint is an int, it's known to be positive, so would implicitly convert to int. But would making int ^^ int illegal, make it too much of an annoying special case? I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation. Also, should int^^uint generate some kind of overflow error? Although other arithmeic integer operators don't, it's fantastically easy to hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to avoid overflowing a ulong).Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it. Andrei
Dec 07 2009
Lars T. Kyllingstad:I searched for FORTRAN code because that's more or less equivalent to searching for numerical code. And I think D's "target audience" is anyone who needs a fast, close-to-the-metal programming language. This definitely includes the scientific community. (There are several of the regulars on this NG who use D for scientific work.)I agree, if D plays well its cards it can be used by users of the numerical computing group too. I was hoping for the language Fortress to be used for such purposes, because it has several features good for numerical computing, but recently I've seen that for now it's planned to run on the JavaVM (where there are no arrays of structs, this is a significant disadvantage. The structs inside methods are less necessary because recently they have added to HotSpot an escape analysis that works for real), and more importantly I've seen its type system and other things are quite complex, maybe too much complex for the typical programmer scientist. So I think Fortran, Python, and C (and C++) look like the most useful for those purposes. D will have to work a lot to be appreciated more than Python for those purposes, because there are many scientific libs that can be used with Python (NumPy, SciPy, SAGE, MatPlotLib, BioPython, and bindings for almost everything else). Bye, bearophile
Dec 07 2009
On 12/7/2009 5:37 PM, bearophile wrote:Lars T. Kyllingstad:Then we may have to convince Walter not to eliminate the extra comparison operators. —JoelI searched for FORTRAN code because that's more or less equivalent to searching for numerical code. And I think D's "target audience" is anyone who needs a fast, close-to-the-metal programming language. This definitely includes the scientific community. (There are several of the regulars on this NG who use D for scientific work.)I agree, if D plays well its cards it can be used by users of the numerical computing group too.
Dec 09 2009
Joel C. Salomon:Then we may have to convince Walter not to eliminate the extra comparison operators.They don't add that much to the language, while they are not easy to remember and add complexity. So I think that even serious numeric programmers will not miss them too much. But I don't perform that kind of computations all the time, so I can't know, I'm just guessing. If those operators will be needed we can add them back later! This shows what I think is an important design mistake done by D devs: you can't predict all possible usages of a language. So adding everything into it from the beginning is not positive. Serious numerical programmers will develop in D2 if D2 turns out to be fit for such purposes and if D2 is lucky, but it's after that moment and thanks to their work that we'll be able to know what things to add to D2 to help those people in their work. Several details in a language design must come from and after practical need, they can't come from up-front design. Reality is just too much complex for too much up-front design. Bye, bearophile
Dec 09 2009
On 8-12-2009 1:43, Andrei Alexandrescu wrote:Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it.No, Don's just being awefully thorough. If you'd revisit all existing operators with the same thoroughness you would probably give up the whole idea of writing a language. Apart from the int/int division there's the int<<int, "What if I shift more than 31?" "What if I shift with <0?" and of course int+int "What to do on overflow?" etc.. I think ^^ can be made to work just fine. Let's not get carried away trying to make it perfect. L.
Dec 07 2009
Lionello Lunesu wrote:On 8-12-2009 1:43, Andrei Alexandrescu wrote:Exactly. The fallback case is to just make int^^int an int. It's only because I was looking at the range propagation stuff inside the compiler, that I got the idea that we could better than that. But, as Andrei says, maybe it's just not worth any more thought at this stage.Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it.No, Don's just being awefully thorough. If you'd revisit all existing operators with the same thoroughness you would probably give up the whole idea of writing a language. Apart from the int/int division there's the int<<int, "What if I shift more than 31?" "What if I shift with <0?" and of course int+int "What to do on overflow?" etc.. I think ^^ can be made to work just fine. Let's not get carried away trying to make it perfect. L.
Dec 07 2009
Don wrote:Lionello Lunesu wrote:Walter and I decided to leave the decision of ^^ up to you, Don. You are the best positioned to make it. I hope you will piggyback a decision about ^^= to it, too. What I'd like would be a solid rationale for the choice. Off the top of my head and while my hat is off to your math skills and experience, I have trouble understanding the soundness of making int^^int yield an int, for the following reason: For all negative exponents, the result is zero, except when the base is 1 or -1. So I guess I'd suggest you at least make the exponent unsigned - the result is of zero interest (quite literally) for all negative exponents. If that behavior is interesting, it would be great if you provided a rationale for it. One small nit is that the exponential function is increasing very rapidly, much faster than multiplication. So yielding a long may actually be justified. (Some people would argue 32-bit multiplication is in the same league and ought to yield 64-bit results.) But then again, most uses of ^^ only raise things to small powers such as 2 and 3. Anyhow, the power is yours - again quite literally :o). AndreiOn 8-12-2009 1:43, Andrei Alexandrescu wrote:Exactly. The fallback case is to just make int^^int an int. It's only because I was looking at the range propagation stuff inside the compiler, that I got the idea that we could better than that. But, as Andrei says, maybe it's just not worth any more thought at this stage.Nice analysis. IMHO this should lead us to reconsider the necessity of "^^" in the first place. It seems to be adding too little real value compared to the complexity of defining it.No, Don's just being awefully thorough. If you'd revisit all existing operators with the same thoroughness you would probably give up the whole idea of writing a language. Apart from the int/int division there's the int<<int, "What if I shift more than 31?" "What if I shift with <0?" and of course int+int "What to do on overflow?" etc.. I think ^^ can be made to work just fine. Let's not get carried away trying to make it perfect. L.
Dec 08 2009
On Tue, Dec 8, 2009 at 12:01 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:What I'd like would be a solid rationale for the choice. Off the top of m=yhead and while my hat is off to your math skills and experience, I have trouble understanding the soundness of making int^^int yield an int, for =thefollowing reason: For all negative exponents, the result is zero, except when the base is 1=or-1. So I guess I'd suggest you at least make the exponent =A0unsigned - t=heresult is of zero interest (quite literally) for all negative exponents. =Ifthat behavior is interesting, it would be great if you provided a rationa=lefor it.The rationale (exponentiale?) for it is consistency. Yeh, it's of zero interest. But it's simple and consistent and doesn't require a bunch of new rules. In the world of ints, small positive powers really are the only interesting case. (And not just two and three -- sometimes you'll see 2**N used to compute buffer sizes in Python. Or at least that's what I observed in the code searches people posted. Arguably a more direct expression of intent than 1<<N.) You seem to be gunning to make some unneccesarily complicated rules up to handle a case that's not really important, but then at the same time argue that things are getting too complicated so we better axe the whole feature. It doesn't really make sense. To make a comparison, << and >> aren't very useful for floating point numbers, does that mean they shouldn't be in the language? In contrast ^^ is useful for both floats and ints with small positive powers. No, not all ints, but that's better versatility than << andat least.One small nit is that the exponential function is increasing very rapidly=,much faster than multiplication. So yielding a long may actually be justified. (Some people would argue 32-bit multiplication is in the same league and ought to yield 64-bit results.) But then again, most uses of ^=^only raise things to small powers such as 2 and 3.Yep, or raising 2 to something < 32. --bb
Dec 08 2009
Bill Baxter wrote:On Tue, Dec 8, 2009 at 12:01 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Consistency is a good rationale, but math simply doesn't work that way. Matrix multiplication could have been defined to be consistent with matrix addition, but it ain't, because multiplication defined that way is uninteresting.What I'd like would be a solid rationale for the choice. Off the top of my head and while my hat is off to your math skills and experience, I have trouble understanding the soundness of making int^^int yield an int, for the following reason: For all negative exponents, the result is zero, except when the base is 1 or -1. So I guess I'd suggest you at least make the exponent unsigned - the result is of zero interest (quite literally) for all negative exponents. If that behavior is interesting, it would be great if you provided a rationale for it.The rationale (exponentiale?) for it is consistency.Yeh, it's of zero interest. But it's simple and consistent and doesn't require a bunch of new rules. In the world of ints, small positive powers really are the only interesting case. (And not just two and three -- sometimes you'll see 2**N used to compute buffer sizes in Python. Or at least that's what I observed in the code searches people posted. Arguably a more direct expression of intent than 1<<N.)I agree. Then why not require the exponent to be unsigned during compilation? Don said he'd want negative exponent to throw a runtime exception. Why?You seem to be gunning to make some unneccesarily complicated rules up to handle a case that's not really important, but then at the same time argue that things are getting too complicated so we better axe the whole feature. It doesn't really make sense.It does. What I said was that we could be in one of two extremes: ^^ is a simple slam dunk, add it for convenience, versus ^^ is hard to type properly, but compiler support can do it. A wishy-washy middle ground where it's there but not doing something principled... that I don't like. But then again I defer the decision to Don.To make a comparison, << and >> aren't very useful for floating point numbers, does that mean they shouldn't be in the language?Wrong argument. << and >> are closed over integrals. I see a mistaken argument, I point it out :o).In contrast ^^ is useful for both floats and ints with small positive powers. No, not all ints, but that's better versatility than << andI agree. Then at least why not make the type of the exponent unsigned? That gives the type system a fighting chance (via e.g. value range propagation). Give Willy a chance! Andreiat least.
Dec 08 2009
On Tue, Dec 8, 2009 at 9:40 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:rOn Tue, Dec 8, 2009 at 12:01 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:What I'd like would be a solid rationale for the choice. Off the top of my head and while my hat is off to your math skills and experience, I have trouble understanding the soundness of making int^^int yield an int, fo=1the following reason: For all negative exponents, the result is zero, except when the base is=theor -1. So I guess I'd suggest you at least make the exponent =A0unsigned -=.result is of zero interest (quite literally) for all negative exponents=xConsistency is a good rationale, but math simply doesn't work that way. Matrix multiplication could have been defined to be consistent with matri=If that behavior is interesting, it would be great if you provided a rationale for it.The rationale (exponentiale?) for it is consistency.addition, but it ain't, because multiplication defined that way is uninteresting.I'm not arguing consistency with math. I'm arguing consistency in the language. You're talking about consistency within math itself.He figures it's usually an error, so he wants to be helpful. But he's killing a useful feature along with it.=A0Yeh, it's of zero interest. =A0But it's simple and consistent and doesn't require a bunch of new rules. =A0In the world of ints, small positive powers really are the only interesting case. =A0(And not just two and three -- sometimes you'll see 2**N used to compute buffer sizes in Python. =A0 Or at least that's what I observed in the code searches people posted. Arguably a more direct expression of intent than 1<<N.)I agree. Then why not require the exponent to be unsigned during compilation? Don said he'd want negative exponent to throw a runtime exception. Why?reYou seem to be gunning to make some unneccesarily complicated rules up to handle a case that's not really important, but then at the same time argue that things are getting too complicated so we better axe the whole feature. =A0It doesn't really make sense.It does. What I said was that we could be in one of two extremes: ^^ is a simple slam dunk, add it for convenience, versus ^^ is hard to type properly, but compiler support can do it. A wishy-washy middle ground whe=it's there but not doing something principled... that I don't like. But t=henagain I defer the decision to Don.Ok, now I understand your position better. And my position is that we should keep it consistent with how division is treated. No fancy type guessing based on arguments' values. int/int -> int. Doing something more sophisticated with typeof(int^^int) only makes sense to me if we do the same for division. Otherwise you're creating a lopsided an inconsistent language feature.I have no idea what you mean by that. You said that raising integers to negative powers wasn't useful and so it casts a dubious light over the whole feature. I'm saying the fact that an operator isn't universally useful does not imply it is useless. For another example, the fact that ~ isn't useful for numbers at all hasn't dulled our enthusiasm for it, because it *is* useful in the places where it was intended to be useful. Similarly ^^ is useful for floats, and some subset of integers.To make a comparison, << and >> aren't very useful for floating point numbers, does that mean they shouldn't be in the language?Wrong argument. << and >> are closed over integrals. I see a mistaken argument, I point it out :o).atIn contrast =A0^^ is useful for both floats and ints with small positive powers. =A0No, not all ints, but that's better versatility than << andI agree. Then at least why not make the type of the exponent unsigned? Th=at least.gives the type system a fighting chance (via e.g. value range propagation=).Give Willy a chance!Honestly, I don't really understand this concern with range propagation. Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. The result is either undefined, 0 or 1. The range is much greater with a non-negative exponent. Could be undefined, zero, or most any negative or positive number. --bb
Dec 08 2009
On Tue, Dec 8, 2009 at 10:18 AM, Bill Baxter <wbaxter gmail.com> wrote:hatI agree. Then at least why not make the type of the exponent unsigned? T=n).gives the type system a fighting chance (via e.g. value range propagatio=This was meant sincerely, by the way. As in, I am ignorant about this issue (the trouble with range propagation and negative exponents) and would appreciate it if someone could explain it. --bbGive Willy a chance!Honestly, I don't really understand this concern with range propagation. =A0 Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. =A0The result is either undefined, 0 or 1. =A0The range is much greater with a non-negative exponent. =A0Could be undefined, zero, or most any negative or positive number.
Dec 08 2009
Bill Baxter wrote:On Tue, Dec 8, 2009 at 10:18 AM, Bill Baxter <wbaxter gmail.com> wrote:I'm bitterly opposed to making int^^negative int return 0. Doing that is making up a new operation. And it does really bad things. Why is 2^^-1 == 0, and not 1 ? If you're evaluating with the floating point unit, it will be 1 when using "round up" mode. It's foul.This was meant sincerely, by the way. As in, I am ignorant about this issue (the trouble with range propagation and negative exponents) and would appreciate it if someone could explain it. --bbI agree. Then at least why not make the type of the exponent unsigned? That gives the type system a fighting chance (via e.g. value range propagation). Give Willy a chance!Honestly, I don't really understand this concern with range propagation. Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. The result is either undefined, 0 or 1. The range is much greater with a non-negative exponent. Could be undefined, zero, or most any negative or positive number.
Dec 08 2009
Don wrote:Bill Baxter wrote:Awesome! Don please please require the exponent to be of unsigned type :o). AndreiOn Tue, Dec 8, 2009 at 10:18 AM, Bill Baxter <wbaxter gmail.com> wrote:I'm bitterly opposed to making int^^negative int return 0. Doing that is making up a new operation. And it does really bad things. Why is 2^^-1 == 0, and not 1 ? If you're evaluating with the floating point unit, it will be 1 when using "round up" mode. It's foul.This was meant sincerely, by the way. As in, I am ignorant about this issue (the trouble with range propagation and negative exponents) and would appreciate it if someone could explain it. --bbI agree. Then at least why not make the type of the exponent unsigned? That gives the type system a fighting chance (via e.g. value range propagation). Give Willy a chance!Honestly, I don't really understand this concern with range propagation. Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. The result is either undefined, 0 or 1. The range is much greater with a non-negative exponent. Could be undefined, zero, or most any negative or positive number.
Dec 08 2009
On Wed, 09 Dec 2009 05:28:23 +0100, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Don wrote:Yeah. Makes no sense allowing it to be signed. -- SimenBill Baxter wrote:Awesome! Don please please require the exponent to be of unsigned type :o). AndreiOn Tue, Dec 8, 2009 at 10:18 AM, Bill Baxter <wbaxter gmail.com> wrote:I'm bitterly opposed to making int^^negative int return 0. Doing that is making up a new operation. And it does really bad things. Why is 2^^-1 == 0, and not 1 ? If you're evaluating with the floating point unit, it will be 1 when using "round up" mode. It's foul.This was meant sincerely, by the way. As in, I am ignorant about this issue (the trouble with range propagation and negative exponents) and would appreciate it if someone could explain it. --bbI agree. Then at least why not make the type of the exponent unsigned? That gives the type system a fighting chance (via e.g. value range propagation). Give Willy a chance!Honestly, I don't really understand this concern with range propagation. Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. The result is either undefined, 0 or 1. The range is much greater with a non-negative exponent. Could be undefined, zero, or most any negative or positive number.
Dec 09 2009
On Tue, Dec 8, 2009 at 8:07 PM, Don <nospam nospam.com> wrote:Bill Baxter wrote:eOn Tue, Dec 8, 2009 at 10:18 AM, Bill Baxter <wbaxter gmail.com> wrote:I agree. Then at least why not make the type of the exponent unsigned? That gives the type system a fighting chance (via e.g. value range propagation). Give Willy a chance!Honestly, I don't really understand this concern with range propagation. =A0 Seems to me that allowing a negative exponent doesn't much expand the range, if a truncation rule is used. =A0The result is either undefined, 0 or 1. =A0The range is much greater with a non-negative exponent. =A0Could be undefined, zero, or most any negativ==3D=3D 0,I'm bitterly opposed to making int^^negative int return 0. Doing that is making up a new operation. And it does really bad things. Why is 2^^-1 =or positive number.This was meant sincerely, by the way. =A0As in, I am ignorant about this issue (the trouble with range propagation and negative exponents) and would appreciate it if someone could explain it. --bband not 1 ? If you're evaluating with the floating point unit, it will be=1when using "round up" mode. It's foul.That doesn't really amount to much of an argument I can sink my teeth into, but ok. I think you're picking the greater of two evils, but apparently I'm in the minority. --bb
Dec 09 2009
Don wrote:As has been mentioned in previous posts, a ^^ b should be right associative and have a precedence between multiplication and unary operators. That much is clear. Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in). Using the normal promotion rules, 10^^2 is an integer. The range checking already present in D2 could be extended so that the compiler knows it'll even fit in a byte. This gets rid of one of the classic annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast. But the difficult question is, what's the type of 10^^-2 ? Should it be an error? (since the result, 0.01, is not representable as an integer). Should it return zero? (just as 1/2 doesn't return 0.5). For an example of these semantics, see http://www.tcl.tk/cgi-bin/tct/tip/123.html). Or should it return a double?I think it should either be an error, or it should return a floating-point value. I'll even go as far as saying that I think 1/2 should either be an error or a floating-point value -- or perhaps even a special rational type. Integer division is not the same as "ordinary" division, and I think it shouldn't use the same symbol. (A backslash would be better: 5\2 == 2) Of course, I'm arguing the mathematician's point of view here. :) -Lars
Dec 07 2009
Lars T. Kyllingstad:I'll even go as far as saying that I think 1/2 should either be an error or a floating-point value -- or perhaps even a special rational type. Integer division is not the same as "ordinary" division, and I think it shouldn't use the same symbol. (A backslash would be better: 5\2 == 2)In Pascal there's the 'div' operator for the integer division and / for the FP one. In Python they are // and / (even if the semantics is a bit different). Mixing the two is another bad detail of the C design. Bye, bearophile
Dec 07 2009
Just few comments. Don:Operations involving integers are far less obvious (and are actually where a major benefit of an operator can come in).The pow operator in Python seems to give good results (this also shows why dynamic typing can be useful, because the return type of a function like pow can change according to the value of its arguments):10242 ** 10<type 'int'>type(2 ** 10)3.162277660168379510 ** 0.50.0110 ** -2-125-5 ** 3-1.174618943088019-5 ** 0.1(1.1171289999875864+0.36297721532893706j)(-5+0j) ** 0.13162925469512000273381545759794499423612250089L117 ** 225L(117 ** 22) % 115I strongly suspect that x^^y, where x and y are integers, and the value of y is not known at compile time, is an extremely rare operation.This shows about 4000 results for Python, it's not an extremely rare operation: http://www.google.com/codesearch?q=[0-9a-zA-Z%29]\s*\*\*\s*[a-zA-Z%28]+lang%3Apython Having a pow operator is quite handy, in Python I use ** often enough, but it's not necessary, functions too can be enough. But here some optimizations done by the compiler are really useful. For example I can't use pow(foo(),2) in the middle of a hot loop if I know the compiler will not surely translate it with a single multiplication of the result of foo(), etc.. It's like with tail-call optimization: you can write different code if you know it's present. If you aren't sure it's present it's not very useful. Bye, bearophile
Dec 07 2009
Andrei Alexandrescu Wrote:One small nit is that the exponential function is increasing very rapidly, much faster than multiplication. So yielding a long may actually be justified. (Some people would argue 32-bit multiplication is in the same league and ought to yield 64-bit results.) But then again, most uses of ^^ only raise things to small powers such as 2 and 3.Oh, for polysemous values :-) I'm somewhat inclined to say that the result type should be the same as the original type, and if the user wants other behavior they can cast. That keep the simple cases simple, and makes the fancy cases explicit. I'd really rather not have the language trying to second guess me by converting my int to a long just because I used an operation that might overflow.
Dec 08 2009