Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-nice.1044.mcz==================== Summary ====================
Name: Kernel-nice.1044
Author: nice
Time: 2 October 2016, 3:14:21.098209 pm
UUID: ee2cb17e-948a-4227-836c-bcb58e3f26c7
Ancestors: Kernel-nice.1043
Fix two more problems with nthRoot:
1) last fix introduced a possibility of infinite loop where guess and nextGuess would alternate around the solution
2) contrarily to what was written in comment, the result was not rounded to nearest Float but subject to double-rounding problem.
=============== Diff against Kernel-nice.1043 ===============
Item was changed:
----- Method: Integer>>nthRoot: (in category 'mathematical functions') -----
nthRoot: aPositiveInteger
"Answer the nth root of the receiver.
Answer an Integer if root is exactly this Integer, else answer the Float nearest the exact root."
+ | guess excess scaled nBits |
- | guess p |
-
guess := self nthRootRounded: aPositiveInteger.
+ excess := (guess raisedTo: aPositiveInteger) - self.
+ excess = 0 ifTrue: [ ^ guess ].
- (guess raisedTo: aPositiveInteger) = self
- ifTrue: [ ^ guess ].
+ nBits := Float precision - guess highBitOfMagnitude.
+ nBits <= 0 ifTrue: [ ^(Fraction numerator: guess * 4 - excess sign denominator: 4) asFloat].
- p := Float precision - guess highBitOfMagnitude.
- p < 0 ifTrue: [ ^ guess asFloat ].
+ scaled := self << (nBits * aPositiveInteger).
+ guess := scaled nthRootRounded: aPositiveInteger.
+ excess := (guess raisedTo: aPositiveInteger) - scaled.
+ ^(Fraction numerator: guess * 4 - excess sign denominator: 1 << (nBits + 2)) asFloat!
- guess := self << (p * aPositiveInteger) nthRootRounded: aPositiveInteger.
- ^(guess / (1 << p)) asFloat!
Item was changed:
----- Method: Integer>>nthRootTruncated: (in category 'mathematical functions') -----
nthRootTruncated: aPositiveInteger
"Answer the integer part of the nth root of the receiver."
| guess guessToTheNthMinusOne nextGuess |
self = 0 ifTrue: [^0].
self negative
ifTrue:
[aPositiveInteger even ifTrue: [ ArithmeticError signal: 'Negative numbers don''t have even roots.' ].
^(self negated nthRootTruncated: aPositiveInteger) negated].
guess := 1 bitShift: self highBitOfMagnitude + aPositiveInteger - 1 // aPositiveInteger.
[
guessToTheNthMinusOne := guess raisedTo: aPositiveInteger - 1.
nextGuess := (aPositiveInteger - 1 * guess * guessToTheNthMinusOne + self) // (guessToTheNthMinusOne * aPositiveInteger).
+ nextGuess >= guess ] whileFalse:
- nextGuess = guess ] whileFalse:
[ guess := nextGuess ].
( guess raisedTo: aPositiveInteger) > self ifTrue:
[ guess := guess - 1 ].
^guess!