[PATCH] fix FloatQ reading

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] fix FloatQ reading

Paolo Bonzini-3
Hi all and especially Nicolas,

here is my shotgun approach to fixing the reading of FloatQ.  The
problem lies in Smalltalk's support for arbitrary bases, which does not
allow me to use the optimized strtod function from the C library.

I decided to write my own tiny floating-point math library (I couldn't
decide whether using mpf/mpfr was *more* or *less* shotgun) so that I
can read the FP numbers in 160 bit precision.  This is somewhat dual to
what the Smalltalk code does, which uses fractions and multi-precision
integers, and it is also how GCC works by the way (though they have more
stuff to do because of handling denormals, NaNs and infinities).

While I tried it a bit, there might be bugs, so I ask you all to figure
out some stress tests.  These are needed because at some point all
floats were returned multiplied by 2 :-) and "make" still built...  I
tried on the ones from http://smalltalk.gnu.org/project/issue/313, as
well as a few others like 1q3000/1q2999 or 3.6451995318824746025q-4951
(FloatQ fmin), and they seem to work.  Ideas on how to incorporate these
into floatmath.st as portably as possible are also welcome.

The code is already in git.

Paolo

_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk

gst-real-reading.patch (29K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fix FloatQ reading

Nicolas Cellier-3
Too many lines of C for a source code analysis to my own taste :)
Maybe some very simple tests like:

self assert: 1.3q0 = (13/10) asFloatQ.

I wrote Float>>successor recently in Pharo, that can be a helper iin
such tests...
successor
        | mantissa biasedExponent |
        self isFinite ifFalse: [
                (self isNaN or: [self positive]) ifTrue: [^self].
                ^Float fmax negated].
        self = 0.0 ifTrue: [^Float fmin].
        mantissa := self significandAsInteger.
        (mantissa isPowerOfTwo and: [self negative]) ifTrue: [mantissa :=
mantissa bitShift: 1].
        biasedExponent := self exponent - mantissa highBit + 1.
        ^self sign * (mantissa + self sign) asFloat timesTwoPower: biasedExponent
predecessor
        | mantissa biasedExponent |
        self isFinite ifFalse: [
                (self isNaN or: [self negative]) ifTrue: [^self].
                ^Float fmax].
        self = 0.0 ifTrue: [^Float fmin negated].
        mantissa := self significandAsInteger.
        (mantissa isPowerOfTwo and: [self positive]) ifTrue: [mantissa :=
mantissa bitShift: 1].
        biasedExponent := self exponent - mantissa highBit + 1.
        ^self sign * (mantissa - self sign) asFloat timesTwoPower: biasedExponent

"sanity check in preamble"
self assert: 1.3q0 asExactFraction asFloatQ = 1.3q0.

"Is it the nearest FloatQ?"
self assert: (1.3q0 successor asExactFraction - (13/10)) abs >= (1.3q0
asExactFraction - (13/10)) abs.
self assert: (1.3q0 predecessor asExactFraction - (13/10)) abs >=
(1.3q0 asExactFraction - (13/10)) abs.
"or also written"
self assert: (1.3q0 successor - (13/10) asFloatQ) abs >= (1.3q0 -
(13/10) asFloatQ) abs.
self assert: (1.3q0 predecessor - (13/10) asFloatQ) abs >= (1.3q0 -
(13/10) asFloatQ) abs.

Then instead of 13/10, use some random generator m/(10 raisedTo: n),
generate a string notation from this, read a FloatQ and compare...

2009/7/11 Paolo Bonzini <[hidden email]>:

> Hi all and especially Nicolas,
>
> here is my shotgun approach to fixing the reading of FloatQ.  The problem
> lies in Smalltalk's support for arbitrary bases, which does not allow me to
> use the optimized strtod function from the C library.
>
> I decided to write my own tiny floating-point math library (I couldn't
> decide whether using mpf/mpfr was *more* or *less* shotgun) so that I can
> read the FP numbers in 160 bit precision.  This is somewhat dual to what the
> Smalltalk code does, which uses fractions and multi-precision integers, and
> it is also how GCC works by the way (though they have more stuff to do
> because of handling denormals, NaNs and infinities).
>
> While I tried it a bit, there might be bugs, so I ask you all to figure out
> some stress tests.  These are needed because at some point all floats were
> returned multiplied by 2 :-) and "make" still built...  I tried on the ones
> from http://smalltalk.gnu.org/project/issue/313, as well as a few others
> like 1q3000/1q2999 or 3.6451995318824746025q-4951 (FloatQ fmin), and they
> seem to work.  Ideas on how to incorporate these into floatmath.st as
> portably as possible are also welcome.
>
> The code is already in git.
>
> Paolo
>


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] fix FloatQ reading

Paolo Bonzini-2
On 07/17/2009 12:10 AM, Nicolas Cellier wrote:
> Too many lines of C for a source code analysis to my own taste :)
> Maybe some very simple tests like:
>
> self assert: 1.3q0 = (13/10) asFloatQ.
>
> I wrote Float>>successor recently in Pharo, that can be a helper iin
> such tests...

What about this instead:

predecessor
     | exponent |
     self isFinite ifFalse: [
             (self isNaN or: [self negative]) ifTrue: [^self].
             ^Float fmax].
     self = 0.0 ifTrue: [^Float fmin negated].
     exponent := self exponent.
     ^exponent < self class emin
         ifTrue: [self - Float fminDenormalized]
         ifFalse: [self - (Float epsilon timesTwoPower: exponent)]

and likewise with s/-/+/ for successor?

Feel free to add these to Pharo.

Paolo


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk