<div dir="ltr"><div>Thanks Chris,<br></div>It's not very noble and beautiful math, but very applied and finally accessible.<br>Floating point is trade off and only trade off, so it leave place for arts and crafts, a domain where human still have added value if sufficiently patient ;)<br></div><div class="gmail_extra"><br><div class="gmail_quote">2017-08-15 5:59 GMT+02:00 Chris Cunningham <span dir="ltr"><<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">I would just like to say that I really enjoy reading your math related changes. I usually learn something new - but always get a enjoy the opportunity to think about these things in a different light. <div dir="auto"><br></div><div dir="auto">Thanks,</div><div dir="auto">cbc </div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Aug 13, 2017 3:03 PM,  <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Nicolas Cellier uploaded a new version of Kernel to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Kernel-nice.1111.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk<wbr>/Kernel-nice.1111.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Kernel-nice.1111<br>
Author: nice<br>
Time: 14 August 2017, 12:02:46.695166 am<br>
UUID: 280f8152-036b-48e1-b3f3-038fa2<wbr>611ea7<br>
Ancestors: Kernel-tpr.1110<br>
<br>
Avoid costly and useless LargeInteger arithmetics when evaluating:<br>
(2009/2000) raisedTo: (3958333/100000)<br>
<br>
These large integer operations were helping to find the nearest Float approximation to the #nthRoot: but<br>
1) they do not scale when the radical increases,<br>
2) we then spoil the accuracy by raising the root to an Integer power naively and inacurately.<br>
<br>
Instead, if the result is inexact, fall back to a ln/exp formulation which is a few ulp off but at least fast.<br>
<br>
=============== Diff against Kernel-tpr.1110 ===============<br>
<br>
Item was changed:<br>
  ----- Method: Fraction>>nthRoot: (in category 'mathematical functions') -----<br>
  nthRoot: aPositiveInteger<br>
        "Answer the nth root of the receiver."<br>
<br>
+       | guess |<br>
+       guess := (numerator nthRootTruncated: aPositiveInteger) / (denominator nthRootTruncated: aPositiveInteger).<br>
+       (guess raisedTo: aPositiveInteger) = self ifTrue: [^guess].<br>
+       "There is no exact nth root, so answer a Float approximation"<br>
+       ^(self abs ln / aPositiveInteger) exp * self sign!<br>
-       | d n |<br>
-       n := numerator nthRoot: aPositiveInteger.<br>
-       d := denominator nthRoot: aPositiveInteger.<br>
-       "The #sqrt method in integer will only answer a Float if there's no exact square root.<br>
-       So, we need a float anyway."<br>
-       (n isInfinite or: [ d isInfinite ]) ifTrue: [<br>
-               ^self asFloat nthRoot: aPositiveInteger ].<br>
-       ^n / d!<br>
<br>
Item was added:<br>
+ ----- Method: Fraction>>raisedToFraction: (in category 'mathematical functions') -----<br>
+ raisedToFraction: aFraction<br>
+       | root |<br>
+       root := (self numerator nthRootTruncated: aFraction denominator) / (self denominator nthRootTruncated: aFraction denominator).<br>
+       (root raisedToInteger: aFraction denominator) = self ifTrue: [^root raisedToInteger: aFraction numerator].<br>
+       ^super raisedToFraction: aFraction!<br>
<br>
Item was added:<br>
+ ----- Method: Integer>>raisedToFraction: (in category 'mathematical functions') -----<br>
+ raisedToFraction: aFraction<br>
+       | root |<br>
+       root := self nthRootTruncated: aFraction denominator.<br>
+       (root raisedToInteger: aFraction denominator) = self ifTrue: [^root raisedToInteger: aFraction numerator].<br>
+       ^super raisedToFraction: aFraction!<br>
<br>
Item was changed:<br>
  ----- Method: Number>>raisedTo: (in category 'mathematical functions') -----<br>
  raisedTo: aNumber<br>
        "Answer the receiver raised to aNumber."<br>
<br>
        aNumber isInteger ifTrue: [<br>
                "Do the special case of integer power"<br>
                ^ self raisedToInteger: aNumber].<br>
        aNumber isFraction ifTrue: [<br>
                "Special case for fraction power"<br>
+               ^ self raisedToFraction: aNumber].<br>
-               ^ (self nthRoot: aNumber denominator) raisedToInteger: aNumber numerator ].<br>
        self negative ifTrue: [<br>
                ^ ArithmeticError signal: 'Negative numbers can''t be raised to float powers.' ].<br>
        aNumber isZero ifTrue: [^ self class one].      "Special case of exponent=0"<br>
        1 = aNumber ifTrue: [^ self].   "Special case of exponent=1"<br>
        self isZero ifTrue: [                           "Special case of self = 0"<br>
                aNumber negative<br>
                        ifTrue: [^ (ZeroDivide dividend: 1) signal]<br>
                        ifFalse: [^ self]].<br>
        ^ (aNumber * self ln) exp               "Otherwise use logarithms"!<br>
<br>
Item was added:<br>
+ ----- Method: Number>>raisedToFraction: (in category 'mathematical functions') -----<br>
+ raisedToFraction: aFraction<br>
+       self isZero<br>
+               ifTrue:<br>
+                       [aFraction negative ifTrue: [^ (ZeroDivide dividend: 1) signal].<br>
+                       ^self].<br>
+       self negative ifFalse: [^(self ln * aFraction) exp].<br>
+       aFraction denominator even<br>
+               ifTrue: [^ ArithmeticError signal: 'nth root only defined for positive Integer n.'].<br>
+       ^(self negated ln * aFraction) exp negated!<br>
<br>
Item was added:<br>
+ ----- Method: ScaledDecimal>>raisedToFractio<wbr>n: (in category 'mathematical functions') -----<br>
+ raisedToFraction: aFraction<br>
+       | result |<br>
+       result := self asFraction raisedToFraction: aFraction.<br>
+       ^result isFloat<br>
+               ifTrue: [result]<br>
+               ifFalse: [result asScaledDecimal: scale]!<br>
<br>
<br>
</blockquote></div></div>
</div></div><br><br>
<br></blockquote></div><br></div>