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 |
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 |
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 |
Free forum by Nabble | Edit this page |