]> gitweb.factorcode.org Git - factor.git/commitdiff
math.integers, bignum/f, improve performance.
authorJon Harper <jon.harper87@gmail.com>
Sun, 26 Jul 2015 16:07:10 +0000 (18:07 +0200)
committerJohn Benediktsson <mrjbq7@gmail.com>
Sun, 26 Jul 2015 19:33:55 +0000 (12:33 -0700)
This changes avoids looping many times if the denominator is a power of
2. After this change, the implementation matches the linked sbcl
algorithm.  This was probably a mistake done when porting the algorithm.
Basically, as an optimization, all trailing zeros are removed from the
base2 representation of the denominator to have smaller bignums to
divide. But the previous factor implementation didn't take this into
account when making the initial guess of the shift of the numerator to
obtain a result in the range [2^54-1,2^53]. The loop would then correct
the initial guess by a factor of 2 at each iteration, so it would run as
many iteration as the denominator base2 power reduction, instead of only
a few times. For pathological cases, the speed up is huge (10^4):
1 1000 2^ bignum/f

core/math/integers/integers.factor

index 7d4f8ccb4aa555f2390e6e1afe47059902acea4b..e675db2f6865dd543748389bcc7112267d428e2b 100644 (file)
@@ -124,10 +124,15 @@ M: bignum (log2) bignum-log2 ; inline
 : (epsilon?) ( num shift -- ? )
     dup neg? [ neg 2^ 1 - bitand zero? not ] [ 2drop f ] if ; inline
 
+: scale-numerator ( num den -- epsilon? num' scale )
+    over [ log2 ] bi@ - [
+        54 + [ (epsilon?) ] [ shift ] 2bi
+    ] keep ; inline
+
 : pre-scale ( num den -- epsilon? mantissa den' scale )
-    2dup [ log2 ] bi@ -
-    [ neg 54 + [ (epsilon?) ] [ shift ] 2bi ]
-    [ [ scale-denonimator ] dip + ] bi-curry bi* ; inline
+    scale-denonimator [
+        [ scale-numerator ] keep swap
+    ] dip swap - ; inline
 
 ! Second step: loop
 : (2/-with-epsilon) ( epsilon? num -- epsilon?' num' )