[squeak-dev] The Trunk: Kernel-nice.1428.mcz
nicolas.cellier.aka.nice at gmail.com
Sun Nov 28 22:15:37 UTC 2021
Note: there might be a minor 2 to 3% penalty for small fractions like 5/3
because this change introduces a super send in the path to Fraction
but IMO, it's not worth the code duplication.
Le dim. 28 nov. 2021 à 22:44, <commits at source.squeak.org> a écrit :
> Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
> ==================== Summary ====================
> Name: Kernel-nice.1428
> Author: nice
> Time: 28 November 2021, 10:44:44.154815 pm
> UUID: a8a214a1-7879-4782-8dd7-910f183fda65
> Ancestors: Kernel-nice.1427
> Simplify code for integer division, and marginally fast up some edge case
> like (SmallInteger / LargeInteger)
> Integer was trying to handle case of exact division (Integer / Integer) by
> performing a quorem operation (digitDiv:neg:), in the hope that avoiding
> the creation of an unecessary Fraction intermediate would fast things up.
> But it appears that digitDiv:neg: does no good nowadays.
> - primitive 10 for SmallInteger/SmallInteger case,
> - primitive 30 for Integer/Integer case (up to 64 bits)
> already handle exact division (their sole purpose if they exist!).
> If 10 & 30 are not implemented (they are optional), probably we do not
> care that much about such micro optimization anyway.
> in mixed cases:
> - (SmallInteger / LargeInteger), division cannot be exact - except for 0
> receiver, so we're just wasting time
> Anyway, digitDiv:neg: creates a LargeInteger object for each SmallInteger
> receiver/argument, and an Array for the resulting quotient and remainder,
> so in term of creating intermediate objects, it's not much better.
> It is also pure waste of time if division is inexact - and division tend
> to not be cheap for LargeInteger.
> Also, gcd: algorithm used in Fraction>>#reduced performs well enough in
> the case of exact division.
> While at it, only handle zero divide in Integer/Integer case.
> Let further dispatching handle the case for mixed Integer/Number
> arithmetic (Integer shall mind its own business).
> Note that Fraction>>#setNumerator:denominator: already signal the
> ZeroDivide, but would not resume: correctly (we send #reduced to the
> result, which assumes that it is a Fraction)
> Warning: benchmarking and understanding the marginal fast-up is not easy,
> because we have:
> - a special bytecode for division
> - special primitive for 64 bits integer range
> - jit for some of those primitives
> that's many cases.
> Thanks to https://github.com/pharo-project/pharo/pull/10385 for asking.
> =============== Diff against Kernel-nice.1427 ===============
> Item was changed:
> ----- Method: Integer>>/ (in category 'arithmetic') -----
> / aNumber
> "Refer to the comment in Number / "
> - | quoRem |
> aNumber isInteger ifTrue:
> + [aNumber isZero
> + ifTrue: [^(ZeroDivide dividend: self) signal].
> + ^ (Fraction numerator: self denominator: aNumber) reduced].
> - [quoRem := self divideByInteger: aNumber.
> - (quoRem at: 2) = 0
> - ifTrue: [^ (quoRem at: 1) normalize]
> - ifFalse: [^ (Fraction numerator: self denominator:
> aNumber) reduced]].
> ^ aNumber adaptToInteger: self andSend: #/!
> Item was changed:
> ----- Method: SmallInteger>>/ (in category 'arithmetic') -----
> / aNumber
> "Primitive. This primitive (for /) divides the receiver by the
> and returns the result if the division is exact. Fail if the
> result is not a
> whole integer. Fail if the argument is 0 or is not a SmallInteger.
> No Lookup. See Object documentation whatIsAPrimitive."
> <primitive: 10>
> + ^super / aNumber!
> - aNumber isZero ifTrue: [^(ZeroDivide dividend: self) signal].
> - ^(aNumber isMemberOf: SmallInteger)
> - ifTrue: [(Fraction numerator: self denominator: aNumber)
> - ifFalse: [super / aNumber]!
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Squeak-dev