[Pkg] The Trunk: Kernel-nice.1111.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Aug 13 22:03:16 UTC 2017

```Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-nice.1111.mcz

==================== Summary ====================

Name: Kernel-nice.1111
Author: nice
Time: 14 August 2017, 12:02:46.695166 am
UUID: 280f8152-036b-48e1-b3f3-038fa2611ea7
Ancestors: Kernel-tpr.1110

Avoid costly and useless LargeInteger arithmetics when evaluating:
(2009/2000) raisedTo: (3958333/100000)

These large integer operations were helping to find the nearest Float approximation to the #nthRoot: but
1) they do not scale when the radical increases,
2) we then spoil the accuracy by raising the root to an Integer power naively and inacurately.

Instead, if the result is inexact, fall back to a ln/exp formulation which is a few ulp off but at least fast.

=============== Diff against Kernel-tpr.1110 ===============

Item was changed:
----- Method: Fraction>>nthRoot: (in category 'mathematical functions') -----
nthRoot: aPositiveInteger

+ 	| guess |
+ 	guess := (numerator nthRootTruncated: aPositiveInteger) / (denominator nthRootTruncated: aPositiveInteger).
+ 	(guess raisedTo: aPositiveInteger) = self ifTrue: [^guess].
+ 	"There is no exact nth root, so answer a Float approximation"
+ 	^(self abs ln / aPositiveInteger) exp * self sign!
- 	| d n |
- 	n := numerator nthRoot: aPositiveInteger.
- 	d := denominator nthRoot: aPositiveInteger.
- 	"The #sqrt method in integer will only answer a Float if there's no exact square root.
- 	So, we need a float anyway."
- 	(n isInfinite or: [ d isInfinite ]) ifTrue: [
- 		^self asFloat nthRoot: aPositiveInteger ].
- 	^n / d!

+ ----- Method: Fraction>>raisedToFraction: (in category 'mathematical functions') -----
+ raisedToFraction: aFraction
+ 	| root |
+ 	root := (self numerator nthRootTruncated: aFraction denominator) / (self denominator nthRootTruncated: aFraction denominator).
+ 	(root raisedToInteger: aFraction denominator) = self ifTrue: [^root raisedToInteger: aFraction numerator].
+ 	^super raisedToFraction: aFraction!

+ ----- Method: Integer>>raisedToFraction: (in category 'mathematical functions') -----
+ raisedToFraction: aFraction
+ 	| root |
+ 	root := self nthRootTruncated: aFraction denominator.
+ 	(root raisedToInteger: aFraction denominator) = self ifTrue: [^root raisedToInteger: aFraction numerator].
+ 	^super raisedToFraction: aFraction!

Item was changed:
----- Method: Number>>raisedTo: (in category 'mathematical functions') -----
raisedTo: aNumber

aNumber isInteger ifTrue: [
"Do the special case of integer power"
^ self raisedToInteger: aNumber].
aNumber isFraction ifTrue: [
"Special case for fraction power"
+ 		^ self raisedToFraction: aNumber].
- 		^ (self nthRoot: aNumber denominator) raisedToInteger: aNumber numerator ].
self negative ifTrue: [
^ ArithmeticError signal: 'Negative numbers can''t be raised to float powers.' ].
aNumber isZero ifTrue: [^ self class one].	"Special case of exponent=0"
1 = aNumber ifTrue: [^ self].	"Special case of exponent=1"
self isZero ifTrue: [				"Special case of self = 0"
aNumber negative
ifTrue: [^ (ZeroDivide dividend: 1) signal]
ifFalse: [^ self]].
^ (aNumber * self ln) exp		"Otherwise use logarithms"!

+ ----- Method: Number>>raisedToFraction: (in category 'mathematical functions') -----
+ raisedToFraction: aFraction
+ 	self isZero
+ 		ifTrue:
+ 			[aFraction negative ifTrue: [^ (ZeroDivide dividend: 1) signal].
+ 			^self].
+ 	self negative ifFalse: [^(self ln * aFraction) exp].
+ 	aFraction denominator even
+ 		ifTrue: [^ ArithmeticError signal: 'nth root only defined for positive Integer n.'].
+ 	^(self negated ln * aFraction) exp negated!