Changeset 8405


Ignore:
Timestamp:
Feb 3, 2008, 6:22:37 AM (17 years ago)
Author:
Gary Byers
Message:

Slightly better bignum * fixnum multiply.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/level-0/l0-bignum64.lisp

    r7624 r8405  
    283283;;;; Multiplication.
    284284
    285 #|
     285#||
    286286;;; These parameters match GMP's.
    287287(defvar *sqr-basecase-threshold* 5)
     
    745745                         c)
    746746                        tt)))))))))))
    747 |#
     747||#
    748748
    749749(defun multiply-bignums (a b)
     
    779779(defun multiply-bignum-and-fixnum (bignum fixnum)
    780780  (declare (type bignum-type bignum) (fixnum fixnum))
    781   (with-small-bignum-buffers ((big-fix fixnum))
    782     (multiply-bignums bignum big-fix)))
     781  (let* ((big-len (%bignum-length bignum))
     782         (big-neg (bignum-minusp bignum))
     783         (signs-differ (not (eq big-neg (minusp fixnum)))))
     784    (flet ((multiply-unsigned-bignum-and-2-digit-fixnum (a len-a high low)
     785             (declare (bignum-type a)
     786                      (bignum-element-type high low)
     787                      (bignum-index len-a)
     788                      (optimize (speed 3) (safety 0)))
     789             (let* ((len-res (+ len-a 2))
     790                    (res (%allocate-bignum len-res)) )
     791               (declare (bignum-index len-a  len-res))
     792               (dotimes (i len-a)
     793                 (declare (type bignum-index i))
     794                 (let* ((carry-digit 0)
     795                        (x (bignum-ref a i))
     796                        (k i))
     797                   (declare (fixnum k))
     798                   (multiple-value-bind (big-carry res-digit)
     799                       (%multiply-and-add4 x
     800                                           low
     801                                           (bignum-ref res k)
     802                                           carry-digit)
     803                     (setf (bignum-ref res k) res-digit
     804                           carry-digit big-carry
     805                           k (1+ k)))
     806                   (multiple-value-bind (big-carry res-digit)
     807                       (%multiply-and-add4 x
     808                                           high
     809                                           (bignum-ref res k)
     810                                           carry-digit)
     811                     (setf (bignum-ref res k) res-digit
     812                           carry-digit big-carry
     813                           k (1+ k)))
     814                   (setf (bignum-ref res k) carry-digit)))
     815               res))
     816           (multiply-unsigned-bignum-and-1-digit-fixnum (a len-a fix)
     817             (declare (bignum-type a)
     818                      (bignum-element-type fix)
     819                      (bignum-index len-a)
     820                      (optimize (speed 3) (safety 0)))
     821             (let* ((len-res (+ len-a 1))
     822                    (res (%allocate-bignum len-res)) )
     823               (declare (bignum-index len-a  len-res))
     824               (dotimes (i len-a)
     825                 (declare (type bignum-index i))
     826                 (let* ((carry-digit 0)
     827                        (x (bignum-ref a i))
     828                        (k i))
     829                   (declare (fixnum k))
     830                   (multiple-value-bind (big-carry res-digit)
     831                       (%multiply-and-add4 x
     832                                           fix
     833                                           (bignum-ref res k)
     834                                           carry-digit)
     835                     (setf (bignum-ref res k) res-digit
     836                           carry-digit big-carry
     837                           k (1+ k)))
     838                   (setf (bignum-ref res k) carry-digit)))
     839               res)))
     840      (let* ((low (logand (1- (ash 1 32)) fixnum))
     841             (high (unless (<= (%fixnum-intlen fixnum) 32)
     842                     (ldb (byte 32 32) fixnum)))
     843             (res (if big-neg
     844                    (let* ((neg-len (1+ big-len)))
     845                      (declare (type bignum-index neg-len))
     846                      (with-bignum-buffers ((neg neg-len))
     847                        (negate-bignum bignum nil neg)
     848                        (if high
     849                          (multiply-unsigned-bignum-and-2-digit-fixnum
     850                           neg
     851                           neg-len
     852                           high
     853                           low)
     854                          (multiply-unsigned-bignum-and-1-digit-fixnum
     855                           neg
     856                           neg-len
     857                           low))))
     858                    (if high
     859                      (multiply-unsigned-bignum-and-2-digit-fixnum
     860                       bignum
     861                       big-len
     862                       high
     863                       low)
     864                      (multiply-unsigned-bignum-and-1-digit-fixnum
     865                       bignum
     866                       big-len
     867                       low)))))
     868        (if signs-differ (negate-bignum-in-place res))
     869        (%normalize-bignum-macro res)))))
    783870
    784871
Note: See TracChangeset for help on using the changeset viewer.