Skip to content

Commit

Permalink
Improve speed of gcd.
Browse files Browse the repository at this point in the history
Remove large powers of two before passing arguments to gcd.

This showed up in this code for log of exact arguments:

     (let* ((wn (##integer-length (##numerator x)))
            (wd (##integer-length (##denominator x)))
            (p  (##fx- wn wd))
            (float-p (##fixnum->flonum p))
            (partial-result (##fllog
                             (##exact->inexact
                              (##* x (##expt 2 (##fx- p))))))) ;; <<<
       (##fl+ (##fl* float-p
                     (macro-inexact-log-2))
              partial-result)))

At <<< we can be multiplying a bignum with 1/2^p, with p large,
and rational normalization requires a gcd of that bignum with 2^p.

This is an important enough special case that we should fix the code.
  • Loading branch information
gambiteer committed Aug 9, 2017
1 parent a44589a commit 6790170
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions lib/_num.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1790,10 +1790,36 @@
y)
((##eqv? y 0)
x)
((and (##fixnum? x) (##fixnum? y))
(fixnum-base x y))
((##fixnum? x)
(if (##fixnum? y)
(fixnum-base x y)
(fixnum-base x (##remainder y x))))
((##fixnum? y)
(fixnum-base y (##remainder x y)))
(else
(##fast-gcd x y)))))
(let* ((first-x-bit
(##first-bit-set x))
(first-y-bit
(##first-bit-set y))
(shift-x?
(fx> (fx* 2 first-x-bit) (##integer-length x)))
(shift-y?
(fx> (fx* 2 first-y-bit) (##integer-length y)))
(x
(if shift-x?
(##arithmetic-shift x (##fx- first-x-bit))
x))
(y
(if shift-y?
(##arithmetic-shift y (##fx- first-y-bit))
y)))
(if (or shift-x? shift-y?)
;; we've shifted out all the powers of two in at
;; least one argument, so we need to put them back
;; in the gcd.
(##arithmetic-shift (##gcd x y)
(##fxmin first-x-bit first-y-bit))
(##fast-gcd x y)))))))

(cond ((##not (##integer? x))
(type-error-on-x))
Expand Down

0 comments on commit 6790170

Please sign in to comment.