Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.641.mcz
==================== Summary ====================
Name: Kernel-nice.641 Author: nice Time: 19 October 2011, 8:44:12.297 pm UUID: e31730ef-2db4-42e3-aa0e-299e45c955ac Ancestors: Kernel-nice.640
Correct #nthRootTruncated: (it did call #nthRootFloor:) Let #nthRoot: retry in exact arithmetic if ever Float overflows.
=============== Diff against Kernel-nice.640 ===============
Item was changed: ----- Method: Integer>>nthRoot: (in category 'mathematical functions') ----- nthRoot: aPositiveInteger "Answer the nth root of the receiver."
| selfAsFloat floatResult guess raised higher lower delta | selfAsFloat := self asFloat. floatResult := selfAsFloat nthRoot: aPositiveInteger.
+ "If we can't do Float arithmetic, then look for an exact answer in exact arithmetic" - "If we can't do Float arithmetic, currently we can't look for an exact answer" floatResult isInfinite ifTrue: [ + guess := self nthRootTruncated: aPositiveInteger. + (guess raisedToInteger: aPositiveInteger) = self ifTrue: [^guess]. ^floatResult ].
guess := floatResult rounded.
"If got an exact answer, answer it." raised := guess raisedToInteger: aPositiveInteger. raised = self ifTrue: [ ^ guess ].
"In this case, maybe it failed because we are such a big integer that the Float method gets inexact, even if we are a whole square number. Note (jmv): The algorithms I found for computing the nthRoot would havily use very large fractions. I wrote this one, that doesn't create fractions." selfAsFloat abs >= (Float maxExactInteger asFloat raisedToInteger: aPositiveInteger) ifTrue: [ raised > self ifTrue: [ higher := guess. delta := floatResult predecessor - floatResult. [ floatResult := floatResult + delta. lower := floatResult rounded. (lower raisedToInteger: aPositiveInteger) > self ] whileTrue: [ delta := delta * 2. higher := lower ] ] ifFalse: [ lower := guess. delta := floatResult successor - floatResult. [ floatResult := floatResult + delta. higher := floatResult rounded. (higher raisedToInteger: aPositiveInteger) < self ] whileTrue: [ delta := delta * 2. lower := higher ]]. [ higher - lower > 1 ] whileTrue: [ guess := lower + higher // 2. raised := guess raisedToInteger: aPositiveInteger. raised = self ifTrue: [ ^ guess ]. raised > self ifTrue: [ higher := guess ] ifFalse: [ lower := guess ]]].
"We need an approximate result" ^floatResult!
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 delta | self = 0 ifTrue: [^0]. self negative ifTrue: [aPositiveInteger even ifTrue: [ ArithmeticError signal: 'Negative numbers don''t have even roots.' ]. + ^(self negated nthRootTruncated: aPositiveInteger) negated]. - ^(self negated nthRootFloor: aPositiveInteger) negated]. guess := 1 bitShift: self highBitOfMagnitude + aPositiveInteger - 1 // aPositiveInteger. [ guessToTheNthMinusOne := guess raisedTo: aPositiveInteger - 1. delta := (guess * guessToTheNthMinusOne - self) // (guessToTheNthMinusOne * aPositiveInteger). delta = 0 ] whileFalse: [ guess := guess - delta ]. ( (guess := guess - 1) raisedTo: aPositiveInteger) > self ifTrue: [ guess := guess - 1 ]. ^guess!
packages@lists.squeakfoundation.org