| Anonymous | Login | Signup for a new account | 02-09-2010 15:17 UTC |
| Main | My View | View Issues | Change Log | Docs |
| Viewing Issue Simple Details [ Jump to Notes ] | [ View Advanced ] [ Issue History ] [ Print ] | |||||||||||
| ID | Category | Severity | Reproducibility | Date Submitted | Last Update | |||||||
| 0001631 | [Squeak] Kernel | minor | always | 08-08-05 21:26 | 10-31-09 23:02 | |||||||
| Reporter | lexspoon | View Status | public | |||||||||
| Assigned To | ||||||||||||
| Priority | normal | Resolution | open | |||||||||
| Status | new | Product Version | ||||||||||
| Summary | 0001631: [ENH] floatGlobals-ls | |||||||||||
| Description |
It bothers me that the print string of [Float infinity] is 'Infinity', but you cannot evaluate 'Infinity'; it comes out as an undeclared global variable. Additionally, I find "infinity" to be a useful concept even when working with integers; it seems awkward to write "Float infinity" in the middle of a bunch of integer operations, especially since we don't necessarily need to implement infinity using floats. This changeset fixes the above situation in one simple way: it adds a global variable named #Infinity. It also adds NaN while at it. Unfortunately, this does not handle '-Infinity', because the Squeak compiler only does unary negation for numbers, not on general expressions. Does anyone have a feel for whether things like [-(x + y)] should be considered proper Smalltalk code? If so, then this changeset is complete and we just need to tweak the parser. But, for example, does Tony Hannon's new compiler already generalize in this way? If [-(x+y)] is not proper Smalltalk code (and I'm sympathetic to the idea, simply to keep the grammer small), then I suggest we tweak the parser in a different way and have it recognize [-Infinity] as a single literal, just the way it does with [-3] or [-99.44]. This is also consistent with the Smalltalk strategy of having tremendously complicated literals in order to keep to keep the syntax simple. Either way, this changeset is incomplete, but I thought I'd share the two-line thing as food for thought. "Change Set: floatGlobals-ls Date: 17 September 2004 Author: Lex Spoon Adds globals variables Infinity and NaN. This makes most floats print out to something that is re-readable. An exception is -Infinity, which still does not evaluate." |
|||||||||||
| Additional Information | ||||||||||||
| Attached Files |
|
|||||||||||
|
|
||||||||||||
Notes |
|
|
(0002196 - 670 - 780 - 821 - 821 - 821 - 821) KenCausey 08-08-05 21:27 |
"Andrew Tween" <amtween@hotmail.com>: "> If [-(x+y)] is not proper Smalltalk code (and I'm sympathetic to the > idea, simply to keep the grammer small), then I suggest we tweak the > parser in a different way and have it recognize [-Infinity] as a single > literal, just the way it does with [-3] or [-99.44]. This is also > consistent with the Smalltalk strategy of having tremendously > complicated literals in order to keep to keep the syntax simple. Another option is to change the printString for [Infinity negated] to be 'NegativeInfinity', and to create a NegativeInfinity global. Which is consistent with the naming of the class variables in Float" |
|
(0002197 - 656 - 794 - 833 - 833 - 833 - 833) KenCausey 08-08-05 21:29 |
"Lex Spoon" <lex@cc.gatech.edu>: "This version uses Andrew Tween's excellent idea of using 'NegativeInfinity' for the printString of [Float infinity negated]. Now all Float's print out to something that is recompilable. The only issue I can think of is that it adds three new global variables, but these seem like nice ones to have around, and these concepts actually are global to all code. "Change Set: floatGlobals-ls Date: 17 September 2004 Author: Lex Spoon Adds globals variables Infinity, NegativeInfinity, and NaN. This makes all floats print out to something that is re-compilable"" (attaching floatGlobals-ls.2.cs.gz) |
|
(0002198 - 798 - 944 - 944 - 944 - 944 - 944) KenCausey 08-08-05 21:32 |
bergel@iam.unibe.ch: "I would like to raise two points from your design. I am really wondering the reason of adding a new global variable named Infinity. Adding such a global bindings with such a generic name looks like dangerous for me. If it is needed to have an infinity even with integer, why not to add it in the class Number? It seems that it makes things easier regarding the evaluation of string. I do not see this need strong enough to add new global variables. We have SmallInteger>>maxVal, why not to have Float>>infinity (without having ^ Infinity as implementation) Changing the grammar in order to handle infinity easier? I am really against this proposition. Note that I did not see the code (I can read it using the "code" button in the file list browser)." |
|
(0002199 - 200 - 234 - 275 - 275 - 275 - 275) KenCausey 08-08-05 21:34 |
Alexandre Bergel <bergel@iam.unibe.ch>: "humm... When I reread my post, I think that I was perhaps too crude. If it is the case, I did not want. The late hours might probably be some something..." |
|
(0002200 - 1997 - 2889 - 2967 - 2967 - 2967 - 2967) KenCausey 08-08-05 21:36 |
"Richard A. O'Keefe" <ok@cs.otago.ac.nz>: "Lex Spoon" <lex@cc.gatech.edu> The only issue I can think of is that it adds three new global variables, but these seem like nice ones to have around, and these concepts actually are global to all code. ...... Adds globals variables Infinity, NegativeInfinity, and NaN. This makes all floats print out to something that is re-compilable" Why not just add Float class>> negativeInfinity ^Infinity negated to Float, and then make the floats in question print as (Float infinity) "not Infinity" (Float negativeInfinity) "not NegativeInfinity" (Float nan) "not NaN" or even just (Float infinity) (Float infinity negated) (Float nan) (Float nan negated) Of course, I have to point out that NEITHER the change set in question NOR my proposed revision succeeds in the aim of making all floats print out as something that evaluates to a number with the same bit pattern, because there are 2*(2**53-1) NaN values. For that we'd need (Float nan: 'hex string') or something like that. I really can't feel happy about adding three globals. I'm especially unhappy about this because ANSI Smalltalk mandates *three* floating-point classes (FloatE, FloatD, and FloatQ) and *each* of them would want its own three global variables, because FloatE infinity (if ANSI had it) could not be the same object as FloatD infinity. This is of particular interest because it's clear that Squeak _does_ have two floating-point types. There's "Float" and there's "element of a FloatArray". (Anyone else find it confusing that the elements of FloatArrays are not really Floats?) Float is roughly FloatD and FloarArray is roughly packed array of FloatE. If this were cleaned up by having FloatE class FloatD class (current Float) Float global, bound to FloatD FloatEArray class (current FloatArray) FloatDArray class then having globals for Infinity and NaN would really be a pain." |
|
(0002201 - 4433 - 5122 - 5122 - 5122 - 5122 - 5122) KenCausey 08-08-05 21:38 |
lex@cc.gatech.edu: "Guys, I did not do it that way just because it was easier. If people really prefer "Float infinity", "Float nan", and "Number infinity", I can certainly switch it all around -- it's actually slightly easier that way. Before doing so, though, please consider that Infinity, at the least, is a fundamental value and seems worth having right at ones fingers. It almost as basic as 0 and 1 and -1. NaN and NegativeInfinity I am less attached to. I still added them, though, because: 1. It is consistent with Infinity. 2. They are quite fundamental themselves. But they are less important than Infinity, so it's fine if they are a touch harder to access. I see no reason to absolutely minimize the number of globals. Having few globals is just one design guideline, but we still want to have a usable and *consistent* language. Thus far, Smalltalk has leaned towards having a rich syntax for number literals, despite having a tiny grammer. [Infinity] is consistent with this strategy, while [Float infinity] is not. To make an analogy, we do not need 0, 1 and -1 either. We could have [Integer zero], [Integer zero plusOne], and [Integer zero plusOne negated]. Arguably some of these are okay, but they break with tradition. If we are going to switch floats to having minimal support as literal expressions, then for consistency we ought to do so for other numeric literals, too. To begin with, things like 12rABAB should surely go away. On individual queries: > Of course, I have to point out that NEITHER the change set in question > NOR my proposed revision succeeds in the aim of making all floats print > out as something that evaluates to a number with the same bit pattern, > because there are 2*(2**53-1) NaN values. For that we'd need > (Float nan: 'hex string') or something like that. True. This seems very unimportant, though. NaN's all operate the same (don't they?) And even if you create a NaN with the same bit pattern as another, they will be neither #= nor #== to each other. In fact, the only way to compare two NaN's, unless they happen to be #==, would seem to be using #hex and the like to peek at the bits. Anyway, this seems like a separate matter. > I'm especially unhappy about this because ANSI Smalltalk mandates > *three* floating-point classes (FloatE, FloatD, and FloatQ) and > *each* of them would want its own three global variables, because > FloatE infinity (if ANSI had it) could not be the same object as > FloatD infinity. There's no problem here. [Infinity] can refer to one of them, and the other classes will have to do something more specialized like [EFloat infinity]. It is exactly the same as with 1.52. [1.52] can only evaluate to one kind of float. If there is more than one kind of float, the other 1.52's will have to be printed something like [1.52d] or [1.52ieee96]. That doesn't mean we should give up on using [1.52] for the most common type. Also, I actually meant the Infinity global to be a placeholder for a good infinity object, and not necessarily for [Float infinity]. It just happens that we have no other contenders right now, so [Float infinity] is winning by default. And as long as it is winning, we may as well use short printStrings when possible. Especially if someone types "Infinity" to get this value, it is nice if "Infinity" is how the value prints back out. > This is of particular interest because it's clear that Squeak _does_ > have two floating-point types. There's "Float" and there's "element > of a FloatArray". (Anyone else find it confusing that the elements > of FloatArrays are not really Floats?) It's interesting but it seems well engineered to me. ShortFloatArray might be a better name... or it might be worse, because it sounds like the array is short, not the floats. Overall, it would be nice to have a fuller range of float classes, but as long as no one is volunteering, we seem to be in good shape right now. If we only get to have one float class, then 64-bit seems fine. If we only get to have one float array class, then 32-bit seems fine. So my current thoughts are to kill NegativeInfinity and NaN, just to please the puritans, to update the printString's appropriately, and to leave the global Infinity around. But I'll wait a little while to see how the discussion goes." |
|
(0002202 - 5618 - 7607 - 7685 - 7685 - 7685 - 7685) KenCausey 08-08-05 21:39 |
"Richard A. O'Keefe" <ok@cs.otago.ac.nz>: "lex@cc.gatech.edu wrote: Before doing so, though, please consider that Infinity, at the least, is a fundamental value and seems worth having right at ones fingers. It almost as basic as 0 and 1 and -1. Infinity may be a fundamental value, but Float infinity is not that value. Remember, in an ANSI Smalltalk with more than one kind of Float, each kind has a DIFFERENT Infinity. True. This seems very unimportant, though. NaN's all operate the same (don't they?) No. In fact there are two fairly dramatically different kinds which should not be treated the same. (Doesn't anyone actually _read_ the IEEE standard?) And even if you create a NaN with the same bit pattern as another, they will be neither #= nor #== to each other. Note also that +0.0 and -0.0 _are_ equal according to IEEE rules, but they are different bit patterns. Which is why Float needs a #isSameBitsAs: anotherFloat method. If you pass Floats to foreign code, the bits in a NaN _can_ matter. Amongst other things the foreign code may expect to get back the same bit pattern it gave you in the first place. Anyway, this seems like a separate matter. Not really. If you want to tie up a global variable with a special value, you had better be quite clear about which value it is. Is your global NaN going to be a qNaN or an sNaN? Once you've decided that, what is its sign going to be? (And yes, IEEE-conformant code _can_ determine the sign of a NaN without examining the bit pattern.) > I'm especially unhappy about this because ANSI Smalltalk mandates > *three* floating-point classes (FloatE, FloatD, and FloatQ) and > *each* of them would want its own three global variables, because > FloatE infinity (if ANSI had it) could not be the same object as > FloatD infinity. There's no problem here. [Infinity] can refer to one of them, and the other classes will have to do something more specialized like [EFloat infinity]. But then _one_ of the classes gets to write its Infinity as Infinity and the others have to write (classname infinity). That kind of inconsistency is such a pain. The whole mess with the global variables is more trouble than it's worth. It is exactly the same as with 1.52. [1.52] can only evaluate to one kind of float. If there is more than one kind of float, the other 1.52's will have to be printed something like [1.52d] or [1.52ieee96]. I guess that people not only don't read the IEEE 754 standard, they don't read the ANSI Smalltalk standard either. The output of finite floating point numbers is clearly spelled out there. That doesn't mean we should give up on using [1.52] for the most common type. Nor does the ANSI standard require you to do it. Also, I actually meant the Infinity global to be a placeholder for a good infinity object, and not necessarily for [Float infinity]. But you were talking about printing (Float infinity) as Infinity; if they are _not_ the same kind of object, then this shouldn't be done, and there is no point in introducing an Infinity global *at this stage*. If you want to have a 'good infinity object', fine. *WHEN* you have one, make *that* be the global Infinity, make *it* print as Infinity, and leave the floating point versions printing as (classname infinity). If you introduce Infinity now, changing it to be a 'good infinity object' in the future stands a really excellent chance of breaking working code. It just happens that we have no other contenders right now, so [Float infinity] is winning by default. And as long as it is winning, we may as well use short printStrings when possible. I'm sorry? I can see that it's important for Float infinity to have *a* printString that reads back reliably, and that the printString should be clear to human readers, but why does it need to be short? Surely only frequent things need to be short. Especially if someone types "Infinity" to get this value, it is nice if "Infinity" is how the value prints back out. But if there is no global Infinity variable, nobody *will* type Infinity to get that value. Here you are arguing that if there is such a variable then it is convenient if there is such a variable. Of course, adding such a variable will have nasty effects on any class that has an Infinity class variable, like, oh, Float... > This is of particular interest because it's clear that Squeak _does_ > have two floating-point types. There's "Float" and there's "element > of a FloatArray". (Anyone else find it confusing that the elements > of FloatArrays are not really Floats?) It's interesting but it seems well engineered to me. ShortFloatArray might be a better name... or it might be worse, because it sounds like the array is short, not the floats. Straw man. Float32Array, ArrayOfShortFloat, anyone can make up better names than that straw man. I do not see how it can possibly be 'good engineering' to have "Float" mean "32-bit float" in one name and "64-bit float" in another. So my current thoughts are to kill NegativeInfinity and NaN, just to please the puritans, to update the printString's appropriately, and to leave the global Infinity around. But I'll wait a little while to see how the discussion goes. Precisely *because* you want a real 'good infinity object' *later* you should *not* add a global Infinity variable *now*. No puritan here; my concernes are severly practical. We do not need this global variable mess." |
|
(0002203 - 2740 - 3118 - 3118 - 3118 - 3118 - 3118) KenCausey 08-08-05 21:41 |
lex@cc.gatech.edu: "Richard, these issues are important but mostly they are also answered in the changeset I posted and in the update I mentioned possibly making. Yes, if [Infinity] is not [Float infinity] then [Float infinity printString] had better not be 'Infinity'. But in my changeset they were in fact the same thing, so why not use the nice printString? If and when the number hierarchy changes, then yes the printString's will have to change as well. You keep mentioning different kinds of floats, but there is only one kind of float *object* in Squeak. It's class Float, and it's what you get when you type things like [1.6]. The mini-floats inside of a FloatArray are never reified into full objects. You can't send messages to them, you can't test them for identity, and you can't even assign one to a variable. When you talk about different kind of float *objects*, you are talking about some other language than Squeak of today. I still do not see why it is a big deal that printing a NaN re-reads as the same NaN that you started with. You reiterated that this happens with my changeset--and I believe you--but I do not see why it matters. It seems more important to have nice printString's in the inspectors and workspaces. Barring any serious practical reason, I would prefer if all NaN's printed out as something pretty short, which would seem to bar them from including all 53 bits you say are needed to distinguish them. The example of code trying to re-evaluate printString's is not good code to begin with. It's certainly not portable--how many Smalltalks actually have float printStrings being bit-for-bit re-readable? On the other hand, plenty of Squeakers, over the years, are going to look in an inspector or print something out and see infinities and nans, and those guys are who printString is designed for. Finally, why are you mentioning ANSI? You bring it up but do not seem to mention any relevance it has here. I actually took the time to look this up because you mentioned it, and the spec seems to explicitly allow float printString's to work however the implementation desires. > I guess that people not only don't read the IEEE 754 standard, they don't > read the ANSI Smalltalk standard either. This kind of comment is truly uncalled for. > It's interesting but it seems well engineered to me. ShortFloatArray > might be a better name... or it might be worse, because it sounds like > the array is short, not the floats. > > Straw man. Float32Array, ArrayOfShortFloat, anyone can make up better names > than that straw man. Ah, good ones. Especially "Float32Array" is nice, because it parallels "IntegerArray"." |
|
(0002204 - 4945 - 6425 - 6464 - 6464 - 6464 - 6464) KenCausey 08-08-05 21:43 |
"Richard A. O'Keefe" <ok@cs.otago.ac.nz>: " Yes, if [Infinity] is not [Float infinity] then [Float infinity printString] had better not be 'Infinity'. But in my changeset they were in fact the same thing, so why not use the nice printString? Because you said you want them to be different some day. If and when the number hierarchy changes, then yes the printString's will have to change as well. And that's not *all* that will break. Look, we don't *need* an Infinity global variable. Why not leave it out until we have a real need for it? You keep mentioning different kinds of floats, but there is only one kind of float *object* in Squeak. Squeak currently has two different kinds of floats. It has only one Float class, so only one kind of float can be an object. The mini-floats inside of a FloatArray are never reified into full objects. You can't send messages to them, you can't test them for identity, and you can't even assign one to a variable. This is not something to boast of. It's an inconsistency we'd be better off without. When you talk about different kind of float *objects*, you are talking about some other language than Squeak of today. It's called ANSI Smalltalk. Squeak has taken several big steps towards ANSI compatibility of late. I think someone getting fed up with the current FloatArray (32) -vs- Float (64) nonsense will start by inventing a Float32 class, and then realise that this is just ANSI FloatE, rename it, add a FloatD global, and bingo! Given that Squeak has a current proven USE for 32-bit floats, this seems more likely to me than someone finding real use for Infinity. I still do not see why it is a big deal that printing a NaN re-reads as the same NaN that you started with. You reiterated that this happens with my changeset--and I believe you--but I do not see why it matters. If you do not see why it matters, should you be doing this? It seems more important to have nice printString's in the inspectors and workspaces. Yes, but currently we DO have nice printStrings: Float nan printString => 'NaN'. Now, I can live with that. It suits me just fine, because nobody expects printStrings to read back. The alleged point of your change set was not "nice short printStrings in inspectors and debuggers" and "printStrings that read back". If you just want "nice printString's in the inspectors and workspaces", then there's no point in the changeset. NaN and Infinity and -Infinity are nice printStrings. If you want something that will read back, then NaN or even (Float NaN) won't cut it. I am not objecting to (Float nan) as a printString. In fact, '(Float nan)' is a *better* printString than 'NaN', because if someone doesn't know what a NaN is, '(Float nan)' just might send them to look at the comment in Float>>nan, which begins to tell them. Distinguishing between signalling NaNs and quiet NaNs would be better still, as they have different behaviour. Barring any serious practical reason, I would prefer if all NaN's printed out as something pretty short, which would seem to bar them from including all 53 bits you say are needed to distinguish them. I have no objection to that AS LONG AS you do not claim that the resulting code provides a representation that reads back. But surely that was the point of this change set? The example of code trying to re-evaluate printString's is not good code to begin with. It's certainly not portable--how many Smalltalks actually have float printStrings being bit-for-bit re-readable? Not as many as should. The Scheme standard *does* require that if you write a finite floating point number and read it back again you get EXACTLY the number you started with, to the last bit. Algorithms for doing this have been published; they do require bignum arithmetic, but Smalltalk has that. For the last 10 years or more, there has been no good reason for a maintained Smalltalk system *not* to have float printStrings be bit-for-bit re-readable. On the other hand, plenty of Squeakers, over the years, are going to look in an inspector or print something out and see infinities and nans, and those guys are who printString is designed for. And for them, what we had in Squeak 3.6 works perfectly well. No change required. Finally, why are you mentioning ANSI? You bring it up but do not seem to mention any relevance it has here. I actually took the time to look this up because you mentioned it, and the spec seems to explicitly allow float printString's to work however the implementation desires. That's not the point that ANSI Smalltalk is relevant to. The point ANSI Smalltalk is relevant to is the fact that it has THREE kinds of floating point number, so that it would have THREE kinds of floating-point infinity, and they cannot all be called Infinity." |
|
(0002205 - 903 - 1077 - 1116 - 1116 - 1116 - 1116) KenCausey 08-08-05 21:44 |
"Lex Spoon" <lex@cc.gatech.edu>: "This one is the same except that NaN is no longer around, and two class variables of class Float have been renamed so that they don't conflict with the globals. I believe this is an improvement to Squeak. Richard has identified other areas Squeak could be further improved, but I have no plans to work on them in the near future. If someone later redefines the Infinity global to something else, the SUnit test should fail, thus leading people to realize the Float printString's need to be adjusted. "Change Set: floatGlobals-ls Date: 22 September 2004 Author: Lex Spoon Adds globals variables Infinity and NegativeInfinity and sets them to (Float infinity) and (Float infinity negated). The Float printString's are adjusted accordingly, and class Float's same-named class variables are renamed."" (attaching floatGlobals-ls.3.cs.gz) |
|
(0002206 - 223 - 223 - 223 - 223 - 223 - 223) KenCausey 08-08-05 21:48 |
I seperately loaded all three changesets into 3.8-6665-basic. They generally loaded OK except that the last one (.3.) resulted in a popup asking about sending Infinity to Undeclared. I didn't otherwise tests any of these. |
|
(0002524 - 1017 - 1193 - 1193 - 1193 - 1193 - 1193) tbn 08-24-05 19:03 |
I would not add globals like NaN and Infinity. We are not VB, J... and the like and Smalltalk syntax is much easier with only a few globals like nil, true and friends. I dont have a problem with the current message send... What about having Number(class)>>infinity returning the infinity object and the display string could be "Number infinity" - so it is easy to reconstruct the object from the inspector. You may argue that the superclass then returns an instance of the subclass - but that's just how it is currently implemented. The implementation based on Floats is also a little bit misleading. What's the hex value of infinity? Evaluate "Float infinity hex" and Squeak will tell you that it is '7FF0000000000000'. (why not 42 like in the hitch hikers guide to the galaxy) I think VW has solved this using an Infinity class - but I'm not sure. So we could have Invinity positive or Invinity negative as class methods and the methods in Number dispatching back. bye Torsten |
|
(0002572 - 457 - 525 - 649 - 649 - 649 - 649) tbn 08-29-05 23:16 |
I've set up a project on http://www.squeaksource.com/Infinity/ [^] for a library to deal with infinie magnitudes. After loading you can write "Infinity positive" and "Infinity negative". Note the appropriate print string in the inspector. Basic arithmetic works is not yet full implemented between infinite magnitudes itself (see #* and #+) It comes with a handfull of tests. The project has global read and write access. Feel free to help. Torsten |
|
(0011923 - 243 - 279 - 279 - 367 - 367 - 367) nicolas cellier 03-14-08 22:37 |
Adding globals NaN Infinity and NegativeInfinity is not enough to solve the problem. Example: (Array with: Float nan) storeString. ...is still '#(NaN)', which is interpreted as #(#NaN). At least #isLiteral must be fixed too, see 0006983 |
|
(0011929 - 429 - 483 - 483 - 684 - 684 - 684) nicolas cellier 03-15-08 22:15 |
I addressed the storeString case with a different solution: simple message send, Float nan. Float infinity. Float infinity negated. see Float-storeString-Patch-M1631-nice.1.cs Another advantage is that Float are now stored exactly. Of course, SqNumberParser must be used to reinterpret stored number exactly (see 0006982 ). A prerequisite is the #isFinite message from 0006983 . (Oops, i indicated 6982 in cs preamble...) |
|
(0013375 - 400 - 424 - 424 - 524 - 524 - 524) nicolas cellier 10-31-09 23:02 |
I uploaded Float-storeString-Patch-M1631-nice.1.cs in trunk and then merged 0006695 When SqNumberParser will be responsible for parsing Number without cumulating roundoff errors, then Float will store in a format that can be evaluated back, except for nans which are all restored as (Float nan). That's already a big progress. I did not touch printString, and I don't feel it is necessary for now. |
| Mantis 1.0.8[^]
Copyright © 2000 - 2007 Mantis Group
113 total queries executed. 64 unique queries executed. |