Float hierarchy for 64-bit Spur
Hi All, 64-bit Spur can usefully provide an immediate float, a 61-bit subset of the ieee double precision float. The scheme steals bits from the mantissa to use for the immediate's 3-bit tag pattern. So values have the same precision as ieee doubles, but can only represent the subset with exponents between 10^-38 and 10^38, the single-precision range. The issue here is how to organize the class hierarchy. The approach that looks best to me is to modify class Float to be an abstract class, and add two subclasses, BoxedFloat and SmallFloat, such that existing boxed instances of Float outside the SmallFloat range will become instances of BoxedFloat and instances within that range will be replaced by references to the relevant SmallFloat. With this approach ... - Float pi etc can still be used, even though they will answer instances of SmallFloat. But tests such as "self assert: result class == Float." will need to be rewritten to e.g. "self assert: result isFloat". - BoxedFloat and SmallFloat will not be mentioned much at all since floats print themselves literally, and so the fact that the classes have changed won't be obvious. - the boxed Float primitives (receiver is a boxed float) live in BoxedFloat and the immediate ones live in SmallFloat. Making SmallFloat a subclass of Float poses problems for all the primitives that do a super send to retry, since the boxed Float prims will be above the unboxed ones and so the boxed ones would have to test for an immediate receiver. An alternative, that VW took (because it has both Float and Double) is to add a superclass, e.g. LimitedPrecisionReal, move most of the methods into it, and keep Float as Float, and add SmallFloat as a subclass of LimitedPrecisionReal. Then while class-side methods such as pi would likely be implemented in LimitedPrecisionReal class, sends to Float to access them find them via inheritance. An automatic reorganization which moves only primitives out of LimitedPrecisionReal is easy to write. Thoughts? -- best, Eliot
Eliot Miranda wrote:
Hi All,
64-bit Spur can usefully provide an immediate float, a 61-bit subset of the ieee double precision float.
I wonder if class SmallDouble would be more intention revealing? In practice 61 bits will be "more than enough"(tm) for anyone. But I can envisage in a business environment environment software needing to comply with (sometimes irrelevant) feature checklists, with one of those likely being full 64 bit compliant IEEE Doubles. Can Pharo aim to have such a class, to which 61 bit floats are auto-promoted as required?
The scheme steals bits from the mantissa to use for the immediate's 3-bit tag pattern. So values have the same precision as ieee doubles, but can only represent the subset with exponents between 10^-38 and 10^38, the single-precision range. The issue here is how to organize the class hierarchy.
The approach that looks best to me is to modify class Float to be an abstract class, and add two subclasses, BoxedFloat and SmallFloat, such that existing boxed instances of Float outside the SmallFloat range will become instances of BoxedFloat and instances within that range will be replaced by references to the relevant SmallFloat.
My first few pages of search results lead to a few references in conversation, but nothing that described what a boxed float is. Can someone explain? btw, http://www.ctan.org/pkg/float also mentioned boxed float, ruled float and plainÂtop float Anyone familiar with those?
With this approach ...
- Float pi etc can still be used, even though they will answer instances of SmallFloat. But tests such as "self assert: result class == Float." will need to be rewritten to e.g. "self assert: result isFloat".
- BoxedFloat and SmallFloat will not be mentioned much at all since floats print themselves literally, and so the fact that the classes have changed won't be obvious.
- the boxed Float primitives (receiver is a boxed float) live in BoxedFloat and the immediate ones live in SmallFloat. Making SmallFloat a subclass of Float poses problems for all the primitives that do a super send to retry, since the boxed Float prims will be above the unboxed ones and so the boxed ones would have to test for an immediate receiver.
An alternative, that VW took (because it has both Float and Double) is to add a superclass, e.g. LimitedPrecisionReal, move most of the methods into it, and keep Float as Float, and add SmallFloat as a subclass of LimitedPrecisionReal. Then while class-side methods such as pi would likely be implemented in LimitedPrecisionReal class, sends to Float to access them find them via inheritance. An automatic reorganization which moves only primitives out of LimitedPrecisionReal is easy to write.
A Float is defined as a limited precision real [1] having several types of precision, so I like the first option. [1] http://en.wikipedia.org/wiki/Floating_point cheers -ben
On Thu, Nov 20, 2014 at 05:51:42PM -0800, Eliot Miranda wrote:
Hi All,
64-bit Spur can usefully provide an immediate float, a 61-bit subset of the ieee double precision float. The scheme steals bits from the mantissa to use for the immediate's 3-bit tag pattern. So values have the same precision as ieee doubles, but can only represent the subset with exponents between 10^-38 and 10^38, the single-precision range. The issue here is how to organize the class hierarchy.
The approach that looks best to me is to modify class Float to be an abstract class, and add two subclasses, BoxedFloat and SmallFloat, such that existing boxed instances of Float outside the SmallFloat range will become instances of BoxedFloat and instances within that range will be replaced by references to the relevant SmallFloat.
With this approach ...
- Float pi etc can still be used, even though they will answer instances of SmallFloat. But tests such as "self assert: result class == Float." will need to be rewritten to e.g. "self assert: result isFloat".
- BoxedFloat and SmallFloat will not be mentioned much at all since floats print themselves literally, and so the fact that the classes have changed won't be obvious.
- the boxed Float primitives (receiver is a boxed float) live in BoxedFloat and the immediate ones live in SmallFloat. Making SmallFloat a subclass of Float poses problems for all the primitives that do a super send to retry, since the boxed Float prims will be above the unboxed ones and so the boxed ones would have to test for an immediate receiver.
An alternative, that VW took (because it has both Float and Double) is to add a superclass, e.g. LimitedPrecisionReal, move most of the methods into it, and keep Float as Float, and add SmallFloat as a subclass of LimitedPrecisionReal. Then while class-side methods such as pi would likely be implemented in LimitedPrecisionReal class, sends to Float to access them find them via inheritance. An automatic reorganization which moves only primitives out of LimitedPrecisionReal is easy to write.
Thoughts?
I have always felt that the mapping of Float to 64-bit double and FloatArray to 32-bit float is awkward. It may be that 32-bit floats are becoming less relevant nowadays, but if short float values are still important, then it would be nice to be able to represent them directly. I like the idea of having a Float class and a Double class to represent the two most common representations. A class hierarchy that could potentially support this sounds like a good idea to me. I have no experience with VW, but a LimitedPrecisionReal hierachy sounds like a reasonable approach. Dave
I have always felt that the mapping of Float to 64-bit double and FloatArray to 32-bit float is awkward. It may be that 32-bit floats are becoming less relevant nowadays, but if short float values are still important, then it
From the sense that a lot of computing is addressing fuzzy pattern matching, 32-bit speed and space are actually becoming more relevant.
would be nice to be able to represent them directly. I like the idea of having a Float class and a Double class to represent the two most common representations. A class hierarchy that could potentially support this sounds like a good idea to me.
I have no experience with VW, but a LimitedPrecisionReal hierachy sounds like a reasonable approach.
Dave
Le 21/11/14 02:51, Eliot Miranda a écrit :
Hi All,
64-bit Spur can usefully provide an immediate float, a 61-bit subset of the ieee double precision float. The scheme steals bits from the mantissa to use for the immediate's 3-bit tag pattern. So values have the same precision as ieee doubles, but can only represent the subset with exponents between 10^-38 and 10^38, the single-precision range. The issue here is how to organize the class hierarchy.
The approach that looks best to me is to modify class Float to be an abstract class, and add two subclasses, BoxedFloat and SmallFloat, such that existing boxed instances of Float outside the SmallFloat range will become instances of BoxedFloat and instances within that range will be replaced by references to the relevant SmallFloat.
With this approach ...
- Float pi etc can still be used, even though they will answer instances of SmallFloat. But tests such as "self assert: result class == Float." will need to be rewritten to e.g. "self assert: result isFloat".
- BoxedFloat and SmallFloat will not be mentioned much at all since floats print themselves literally, and so the fact that the classes have changed won't be obvious.
- the boxed Float primitives (receiver is a boxed float) live in BoxedFloat and the immediate ones live in SmallFloat. Making SmallFloat a subclass of Float poses problems for all the primitives that do a super send to retry, since the boxed Float prims will be above the unboxed ones and so the boxed ones would have to test for an immediate receiver.
An alternative, that VW took (because it has both Float and Double) is to add a superclass, e.g. LimitedPrecisionReal, move most of the methods into it, and keep Float as Float, and add SmallFloat as a subclass of LimitedPrecisionReal. Then while class-side methods such as pi would likely be implemented in LimitedPrecisionReal class, sends to Float to access them find them via inheritance. An automatic reorganization which moves only primitives out of LimitedPrecisionReal is easy to write.
Eliot the solution proposed by VM is nice in the sense that we can continue to use Float pi... On the other hand, I like the design used on objective-c when the superclass act as a factory for its subclass hidding concrete implementation classes. Now I do not know if his would make sense for Float. Another point, I do not really like Boxed because this is the first time we use it. May be SmallFloat would be in the same spirit than SmallInteger.
Thoughts? -- best, Eliot
participants (5)
-
Ben Coman -
Chris Muller -
David T. Lewis -
Eliot Miranda -
stepharo