Simplify (and robustify) regular PACKing
[sbcl.git] / src / code / bignum.lisp
index 29a69bc..054e6df 100644 (file)
@@ -20,7 +20,7 @@
 ;;;       bignum-ashift-right bignum-ashift-left bignum-gcd
 ;;;       bignum-to-float bignum-integer-length
 ;;;       bignum-logical-and bignum-logical-ior bignum-logical-xor
-;;;       bignum-logical-not bignum-load-byte bignum-deposit-byte
+;;;       bignum-logical-not bignum-load-byte
 ;;;       bignum-truncate bignum-plus-p bignum-compare make-small-bignum
 ;;;       bignum-logbitp bignum-logcount
 ;;;   These symbols define the interface to the compiler:
@@ -28,7 +28,7 @@
 ;;;       %bignum-length %bignum-set-length %bignum-ref %bignum-set
 ;;;       %digit-0-or-plusp %add-with-carry %subtract-with-borrow
 ;;;       %multiply-and-add %multiply %lognot %logand %logior %logxor
-;;;       %fixnum-to-digit %floor %fixnum-digit-with-correct-sign %ashl
+;;;       %fixnum-to-digit %bigfloor %fixnum-digit-with-correct-sign %ashl
 ;;;       %ashr %digit-logical-shift-right))
 
 ;;; The following interfaces will either be assembler routines or code
@@ -67,7 +67,7 @@
 ;;;    LDB
 ;;;       %FIXNUM-TO-DIGIT
 ;;;    TRUNCATE
-;;;       %FLOOR
+;;;       %BIGFLOOR
 ;;;
 ;;; Note: The floating routines know about the float representation.
 ;;;
   (%lognot digit))
 
 ;;; Each of these does the digit-size unsigned op.
-#!-sb-fluid (declaim (inline %logand %logior %logxor))
+(declaim (inline %logand %logior %logxor))
 (defun %logand (a b)
   (declare (type bignum-element-type a b))
   (logand a b))
 ;;; dividing the first two as a 2*digit-size integer by the third.
 ;;;
 ;;; Do weird LET and SETQ stuff to bamboozle the compiler into allowing
-;;; the %FLOOR transform to expand into pseudo-assembler for which the
+;;; the %BIGFLOOR transform to expand into pseudo-assembler for which the
 ;;; compiler can later correctly allocate registers.
-(defun %floor (a b c)
+(defun %bigfloor (a b c)
   (let ((a a) (b b) (c c))
     (declare (type bignum-element-type a b c))
     (setq a a b b c c)
-    (%floor a b c)))
+    (%bigfloor a b c)))
 
 ;;; Convert the digit to a regular integer assuming that the digit is signed.
 (defun %fixnum-digit-with-correct-sign (digit)
 
 ;;; These take two digit-size quantities and compare or contrast them
 ;;; without wasting time with incorrect type checking.
-#!-sb-fluid (declaim (inline %digit-compare %digit-greater))
+(declaim (inline %digit-compare %digit-greater))
 (defun %digit-compare (x y)
   (= x y))
 (defun %digit-greater (x y)
 ;;; function to call that fixes up the result returning any useful values, such
 ;;; as the result. This macro may evaluate its arguments more than once.
 (sb!xc:defmacro subtract-bignum-loop (a len-a b len-b res len-res return-fun)
-  (let ((borrow (gensym))
-        (a-digit (gensym))
-        (a-sign (gensym))
-        (b-digit (gensym))
-        (b-sign (gensym))
-        (i (gensym))
-        (v (gensym))
-        (k (gensym)))
+  (with-unique-names (borrow a-digit a-sign b-digit b-sign i v k)
     `(let* ((,borrow 1)
             (,a-sign (%sign-digit ,a ,len-a))
             (,b-sign (%sign-digit ,b ,len-b)))
                                 from-end)
   (sb!int:once-only ((n-dest dest)
                      (n-src src))
-    (let ((n-start1 (gensym))
-          (n-end1 (gensym))
-          (n-start2 (gensym))
-          (n-end2 (gensym))
-          (i1 (gensym))
-          (i2 (gensym))
-          (end1 (or end1 `(%bignum-length ,n-dest)))
-          (end2 (or end2 `(%bignum-length ,n-src))))
-      (if from-end
-          `(let ((,n-start1 ,start1)
-                 (,n-start2 ,start2))
-             (do ((,i1 (1- ,end1) (1- ,i1))
-                  (,i2 (1- ,end2) (1- ,i2)))
-                 ((or (< ,i1 ,n-start1) (< ,i2 ,n-start2)))
-               (declare (fixnum ,i1 ,i2))
-               (%bignum-set ,n-dest ,i1
-                            (%bignum-ref ,n-src ,i2))))
-          `(let ((,n-end1 ,end1)
-                 (,n-end2 ,end2))
-             (do ((,i1 ,start1 (1+ ,i1))
-                  (,i2 ,start2 (1+ ,i2)))
-                 ((or (>= ,i1 ,n-end1) (>= ,i2 ,n-end2)))
-               (declare (type bignum-index ,i1 ,i2))
-               (%bignum-set ,n-dest ,i1
-                            (%bignum-ref ,n-src ,i2))))))))
+    (with-unique-names (n-start1 n-end1 n-start2 n-end2 i1 i2)
+      (let ((end1 (or end1 `(%bignum-length ,n-dest)))
+            (end2 (or end2 `(%bignum-length ,n-src))))
+        (if from-end
+            `(let ((,n-start1 ,start1)
+                   (,n-start2 ,start2))
+              (do ((,i1 (1- ,end1) (1- ,i1))
+                   (,i2 (1- ,end2) (1- ,i2)))
+                  ((or (< ,i1 ,n-start1) (< ,i2 ,n-start2)))
+                (declare (fixnum ,i1 ,i2))
+                (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i2))))
+            (if (eql start1 start2)
+                `(let ((,n-end1 (min ,end1 ,end2)))
+                  (do ((,i1 ,start1 (1+ ,i1)))
+                      ((>= ,i1 ,n-end1))
+                    (declare (type bignum-index ,i1))
+                    (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i1))))
+                `(let ((,n-end1 ,end1)
+                       (,n-end2 ,end2))
+                  (do ((,i1 ,start1 (1+ ,i1))
+                       (,i2 ,start2 (1+ ,i2)))
+                      ((or (>= ,i1 ,n-end1) (>= ,i2 ,n-end2)))
+                    (declare (type bignum-index ,i1 ,i2))
+                    (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i2))))))))))
 
 (sb!xc:defmacro with-bignum-buffers (specs &body body)
   #!+sb-doc
 ;;; it, we pay a heavy price in BIGNUM-GCD when compiled by the
 ;;; cross-compiler. -- CSR, 2004-07-19
 (declaim (ftype (sfunction (bignum-type bignum-index bignum-type bignum-index)
-                           sb!vm::positive-fixnum)
+                           (and unsigned-byte fixnum))
                 bignum-factors-of-two))
 (defun bignum-factors-of-two (a len-a b len-b)
   (declare (type bignum-index len-a len-b) (type bignum-type a b))
     (declare (type (unsigned-byte #.sb!vm:n-word-bits) ud vd umask imask m))
     (dotimes (i digit-size)
       (setf umask (logior umask imask))
-      (unless (zerop (logand ud umask))
+      (when (logtest ud umask)
         (setf ud (modularly (- ud vd)))
         (setf m (modularly (logior m imask))))
       (setf imask (modularly (ash imask 1)))
     (declare (type (unsigned-byte #.(integer-length #.sb!vm:n-word-bits)) d)
              (type (unsigned-byte #.sb!vm:n-word-bits) n))
     (gcd-assert (>= d 0))
-    (unless (zerop (logand (%bignum-ref u 0) n))
+    (when (logtest (%bignum-ref u 0) n)
       (let ((tmp1-len
              (multiply-bignum-buffer-and-smallnum-to-buffer v v-len
                                                             (logand n (bmod u
         (setf u-len (make-gcd-bignum-odd u u-len))
         (rotatef u v)
         (rotatef u-len v-len))
+      (bignum-abs-buffer u u-len)
       (setf u (copy-bignum u u-len))
       (let ((n (bignum-mod-gcd v1 u)))
         (ash (bignum-mod-gcd u1 (if (fixnump n)
 
 ;;; This negates bignum-len digits of bignum, storing the resulting digits into
 ;;; result (possibly EQ to bignum) and returning whatever end-carry there is.
-(sb!xc:defmacro bignum-negate-loop (bignum
-                                    bignum-len
-                                    &optional (result nil resultp))
-  (let ((carry (gensym))
-        (end (gensym))
-        (value (gensym))
-        (last (gensym)))
+(sb!xc:defmacro bignum-negate-loop
+    (bignum bignum-len &optional (result nil resultp))
+  (with-unique-names (carry end value last)
     `(let* (,@(if (not resultp) `(,last))
             (,carry
              (multiple-value-bind (,value ,carry)
           (res-len-1 (1- res-len))
           ,@(if result `((,result (%allocate-bignum res-len)))))
      (declare (type bignum-index res-len res-len-1))
-     (do ((i ,start-digit i+1)
-          (i+1 (1+ ,start-digit) (1+ i+1))
+     (do ((i ,start-digit (1+ i))
           (j 0 (1+ j)))
          ,termination
-       (declare (type bignum-index i i+1 j))
+       (declare (type bignum-index i j))
        (setf (%bignum-ref ,(if result result source) j)
              (%logior (%digit-logical-shift-right (%bignum-ref ,source i)
                                                   ,start-pos)
-                      (%ashl (%bignum-ref ,source i+1)
+                      (%ashl (%bignum-ref ,source (1+ i))
                              high-bits-in-first-digit))))))
 
 ) ; EVAL-WHEN
          (res-len-1 (1- res-len))
          (res (or res (%allocate-bignum res-len))))
     (declare (type bignum-index res-len res-len-1))
-    (do ((i 0 i+1)
-         (i+1 1 (1+ i+1))
+    (do ((i 0 (1+ i))
          (j (1+ digits) (1+ j)))
         ((= j res-len-1)
          (setf (%bignum-ref res digits)
          (if resp
              (%normalize-bignum-buffer res res-len)
              (%normalize-bignum res res-len)))
-      (declare (type bignum-index i i+1 j))
+      (declare (type bignum-index i j))
       (setf (%bignum-ref res j)
             (%logior (%digit-logical-shift-right (%bignum-ref bignum i)
                                                  remaining-bits)
-                     (%ashl (%bignum-ref bignum i+1) n-bits))))))
+                     (%ashl (%bignum-ref bignum (1+ i)) n-bits))))))
 \f
 ;;;; relational operators
 
 
     (cond
      ;; Round down if round bit is 0.
-     ((zerop (logand round-bit low))
+     ((not (logtest round-bit low))
       (float-from-bits shifted len))
      ;; If only round bit is set, then round to even.
      ((and (= low round-bit)
         (floor index digit-size)
       (if (>= word-index len)
           (not (bignum-plus-p bignum))
-          (not (zerop (logand (%bignum-ref bignum word-index)
-                              (ash 1 bit-index))))))))
+          (logbitp bit-index (%bignum-ref bignum word-index))))))
 
 (defun bignum-logcount (bignum)
   (declare (type bignum-type bignum))
     (setf (%bignum-ref res i) (%logxor sign (%bignum-ref b i))))
   (%normalize-bignum res len-b))
 \f
-;;;; LDB (load byte)
-
-#|
-FOR NOW WE DON'T USE LDB OR DPB. WE USE SHIFTS AND MASKS IN NUMBERS.LISP WHICH
-IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
-
-(defconstant maximum-fixnum-bits (- sb!vm:n-word-bits sb!vm:n-lowtag-bits))
-
-(defun bignum-load-byte (byte bignum)
-  (declare (type bignum-type bignum))
-  (let ((byte-len (byte-size byte))
-        (byte-pos (byte-position byte)))
-    (if (< byte-len maximum-fixnum-bits)
-        (bignum-ldb-fixnum-res bignum byte-len byte-pos)
-        (bignum-ldb-bignum-res bignum byte-len byte-pos))))
-
-;;; This returns a fixnum result of loading a byte from a bignum. In order, we
-;;; check for the following conditions:
-;;;    Insufficient bignum digits to start loading a byte --
-;;;       Return 0 or byte-len 1's depending on sign of bignum.
-;;;    One bignum digit containing the whole byte spec --
-;;;       Grab 'em, shift 'em, and mask out what we don't want.
-;;;    Insufficient bignum digits to cover crossing a digit boundary --
-;;;       Grab the available bits in the last digit, and or in whatever
-;;;       virtual sign bits we need to return a full byte spec.
-;;;    Else (we cross a digit boundary with all bits available) --
-;;;       Make a couple masks, grab what we want, shift it around, and
-;;;       LOGIOR it all together.
-;;; Because (< maximum-fixnum-bits digit-size) and
-;;;      (< byte-len maximum-fixnum-bits),
-;;; we only cross one digit boundary if any.
-(defun bignum-ldb-fixnum-res (bignum byte-len byte-pos)
-  (multiple-value-bind (skipped-digits pos) (truncate byte-pos digit-size)
-    (let ((bignum-len (%bignum-length bignum))
-          (s-digits+1 (1+ skipped-digits)))
-      (declare (type bignum-index bignum-len s-digits+1))
-      (if (>= skipped-digits bignum-len)
-          (if (%bignum-0-or-plusp bignum bignum-len)
-              0
-              (%make-ones byte-len))
-          (let ((end (+ pos byte-len)))
-            (cond ((<= end digit-size)
-                   (logand (ash (%bignum-ref bignum skipped-digits) (- pos))
-                           ;; Must LOGAND after shift here.
-                           (%make-ones byte-len)))
-                  ((>= s-digits+1 bignum-len)
-                   (let* ((available-bits (- digit-size pos))
-                          (res (logand (ash (%bignum-ref bignum skipped-digits)
-                                            (- pos))
-                                       ;; LOGAND should be unnecessary here
-                                       ;; with a logical right shift or a
-                                       ;; correct digit-sized one.
-                                       (%make-ones available-bits))))
-                     (if (%bignum-0-or-plusp bignum bignum-len)
-                         res
-                         (logior (%ashl (%make-ones (- end digit-size))
-                                        available-bits)
-                                 res))))
-                  (t
-                   (let* ((high-bits-in-first-digit (- digit-size pos))
-                          (high-mask (%make-ones high-bits-in-first-digit))
-                          (low-bits-in-next-digit (- end digit-size))
-                          (low-mask (%make-ones low-bits-in-next-digit)))
-                     (declare (type bignum-element-type high-mask low-mask))
-                     (logior (%ashl (logand (%bignum-ref bignum s-digits+1)
-                                            low-mask)
-                                    high-bits-in-first-digit)
-                             (logand (ash (%bignum-ref bignum skipped-digits)
-                                          (- pos))
-                                     ;; LOGAND should be unnecessary here with
-                                     ;; a logical right shift or a correct
-                                     ;; digit-sized one.
-                                     high-mask))))))))))
-
-;;; This returns a bignum result of loading a byte from a bignum. In order, we
-;;; check for the following conditions:
-;;;    Insufficient bignum digits to start loading a byte --
-;;;    Byte-pos starting on a digit boundary --
-;;;    Byte spec contained in one bignum digit --
-;;;       Grab the bits we want and stick them in a single digit result.
-;;;       Since we know byte-pos is non-zero here, we know our single digit
-;;;       will have a zero high sign bit.
-;;;    Else (unaligned multiple digits) --
-;;;       This is like doing a shift right combined with either masking
-;;;       out unwanted high bits from bignum or filling in virtual sign
-;;;       bits if bignum had insufficient bits. We use SHIFT-RIGHT-ALIGNED
-;;;       and reference lots of local variables this macro establishes.
-(defun bignum-ldb-bignum-res (bignum byte-len byte-pos)
-  (multiple-value-bind (skipped-digits pos) (truncate byte-pos digit-size)
-    (let ((bignum-len (%bignum-length bignum)))
-      (declare (type bignum-index bignum-len))
-      (cond
-       ((>= skipped-digits bignum-len)
-        (make-bignum-virtual-ldb-bits bignum bignum-len byte-len))
-       ((zerop pos)
-        (make-aligned-ldb-bignum bignum bignum-len byte-len skipped-digits))
-       ((< (+ pos byte-len) digit-size)
-        (let ((res (%allocate-bignum 1)))
-          (setf (%bignum-ref res 0)
-                (logand (%ashr (%bignum-ref bignum skipped-digits) pos)
-                        (%make-ones byte-len)))
-          res))
-       (t
-        (make-unaligned-ldb-bignum bignum bignum-len
-                                   byte-len skipped-digits pos))))))
-
-;;; This returns bits from bignum that don't physically exist. These are
-;;; all zero or one depending on the sign of the bignum.
-(defun make-bignum-virtual-ldb-bits (bignum bignum-len byte-len)
-  (if (%bignum-0-or-plusp bignum bignum-len)
-      0
-      (multiple-value-bind (res-len-1 extra) (truncate byte-len digit-size)
-        (declare (type bignum-index res-len-1))
-        (let* ((res-len (1+ res-len-1))
-               (res (%allocate-bignum res-len)))
-          (declare (type bignum-index res-len))
-          (do ((j 0 (1+ j)))
-              ((= j res-len-1)
-               (setf (%bignum-ref res j) (%make-ones extra))
-               (%normalize-bignum res res-len))
-            (declare (type bignum-index j))
-            (setf (%bignum-ref res j) all-ones-digit))))))
-
-;;; Since we are picking up aligned digits, we just copy the whole digits
-;;; we want and fill in extra bits. We might have a byte-len that extends
-;;; off the end of the bignum, so we may have to fill in extra 1's if the
-;;; bignum is negative.
-(defun make-aligned-ldb-bignum (bignum bignum-len byte-len skipped-digits)
-  (multiple-value-bind (res-len-1 extra) (truncate byte-len digit-size)
-    (declare (type bignum-index res-len-1))
-    (let* ((res-len (1+ res-len-1))
-           (res (%allocate-bignum res-len)))
-      (declare (type bignum-index res-len))
-      (do ((i skipped-digits (1+ i))
-           (j 0 (1+ j)))
-          ((or (= j res-len-1) (= i bignum-len))
-           (cond ((< i bignum-len)
-                  (setf (%bignum-ref res j)
-                        (logand (%bignum-ref bignum i)
-                                (the bignum-element-type (%make-ones extra)))))
-                 ((%bignum-0-or-plusp bignum bignum-len))
-                 (t
-                  (do ((j j (1+ j)))
-                      ((= j res-len-1)
-                       (setf (%bignum-ref res j) (%make-ones extra)))
-                    (setf (%bignum-ref res j) all-ones-digit))))
-           (%normalize-bignum res res-len))
-      (declare (type bignum-index i j))
-      (setf (%bignum-ref res j) (%bignum-ref bignum i))))))
-
-;;; This grabs unaligned bignum bits from bignum assuming byte-len causes at
-;;; least one digit boundary crossing. We use SHIFT-RIGHT-UNALIGNED referencing
-;;; lots of local variables established by it.
-(defun make-unaligned-ldb-bignum (bignum
-                                  bignum-len
-                                  byte-len
-                                  skipped-digits
-                                  pos)
-  (multiple-value-bind (res-len-1 extra) (truncate byte-len digit-size)
-    (shift-right-unaligned
-     bignum skipped-digits pos (1+ res-len-1)
-     ((or (= j res-len-1) (= i+1 bignum-len))
-      (cond ((= j res-len-1)
-             (cond
-              ((< extra high-bits-in-first-digit)
-               (setf (%bignum-ref res j)
-                     (logand (ash (%bignum-ref bignum i) minus-start-pos)
-                             ;; Must LOGAND after shift here.
-                             (%make-ones extra))))
-              (t
-               (setf (%bignum-ref res j)
-                     (logand (ash (%bignum-ref bignum i) minus-start-pos)
-                             ;; LOGAND should be unnecessary here with a logical
-                             ;; right shift or a correct digit-sized one.
-                             high-mask))
-               (when (%bignum-0-or-plusp bignum bignum-len)
-                 (setf (%bignum-ref res j)
-                       (logior (%bignum-ref res j)
-                               (%ashl (%make-ones
-                                       (- extra high-bits-in-first-digit))
-                                      high-bits-in-first-digit)))))))
-            (t
-             (setf (%bignum-ref res j)
-                   (logand (ash (%bignum-ref bignum i) minus-start-pos)
-                           ;; LOGAND should be unnecessary here with a logical
-                           ;; right shift or a correct digit-sized one.
-                           high-mask))
-             (unless (%bignum-0-or-plusp bignum bignum-len)
-               ;; Fill in upper half of this result digit with 1's.
-               (setf (%bignum-ref res j)
-                     (logior (%bignum-ref res j)
-                             (%ashl low-mask high-bits-in-first-digit)))
-               ;; Fill in any extra 1's we need to be byte-len long.
-               (do ((j (1+ j) (1+ j)))
-                   ((>= j res-len-1)
-                    (setf (%bignum-ref res j) (%make-ones extra)))
-                 (setf (%bignum-ref res j) all-ones-digit)))))
-      (%normalize-bignum res res-len))
-     res)))
-\f
-;;;; DPB (deposit byte)
-
-(defun bignum-deposit-byte (new-byte byte-spec bignum)
-  (declare (type bignum-type bignum))
-  (let* ((byte-len (byte-size byte-spec))
-         (byte-pos (byte-position byte-spec))
-         (bignum-len (%bignum-length bignum))
-         (bignum-plusp (%bignum-0-or-plusp bignum bignum-len))
-         (byte-end (+ byte-pos byte-len))
-         (res-len (1+ (max (ceiling byte-end digit-size) bignum-len)))
-         (res (%allocate-bignum res-len)))
-    (declare (type bignum-index bignum-len res-len))
-    ;; Fill in an extra sign digit in case we set what would otherwise be the
-    ;; last digit's last bit. Normalize at the end in case this was
-    ;; unnecessary.
-    (unless bignum-plusp
-      (setf (%bignum-ref res (1- res-len)) all-ones-digit))
-    (multiple-value-bind (end-digit end-bits) (truncate byte-end digit-size)
-      (declare (type bignum-index end-digit))
-      ;; Fill in bits from bignum up to byte-pos.
-      (multiple-value-bind (pos-digit pos-bits) (truncate byte-pos digit-size)
-        (declare (type bignum-index pos-digit))
-        (do ((i 0 (1+ i))
-             (end (min pos-digit bignum-len)))
-            ((= i end)
-             (cond ((< i bignum-len)
-                    (unless (zerop pos-bits)
-                      (setf (%bignum-ref res i)
-                            (logand (%bignum-ref bignum i)
-                                    (%make-ones pos-bits)))))
-                   (bignum-plusp)
-                   (t
-                    (do ((i i (1+ i)))
-                        ((= i pos-digit)
-                         (unless (zerop pos-bits)
-                           (setf (%bignum-ref res i) (%make-ones pos-bits))))
-                      (setf (%bignum-ref res i) all-ones-digit)))))
-          (setf (%bignum-ref res i) (%bignum-ref bignum i)))
-        ;; Fill in bits from new-byte.
-        (if (typep new-byte 'fixnum)
-            (deposit-fixnum-bits new-byte byte-len pos-digit pos-bits
-                                 end-digit end-bits res)
-            (deposit-bignum-bits new-byte byte-len pos-digit pos-bits
-                                 end-digit end-bits res)))
-      ;; Fill in remaining bits from bignum after byte-spec.
-      (when (< end-digit bignum-len)
-        (setf (%bignum-ref res end-digit)
-              (logior (logand (%bignum-ref bignum end-digit)
-                              (%ashl (%make-ones (- digit-size end-bits))
-                                     end-bits))
-                      ;; DEPOSIT-FIXNUM-BITS and DEPOSIT-BIGNUM-BITS only store
-                      ;; bits from new-byte into res's end-digit element, so
-                      ;; we don't need to mask out unwanted high bits.
-                      (%bignum-ref res end-digit)))
-        (do ((i (1+ end-digit) (1+ i)))
-            ((= i bignum-len))
-          (setf (%bignum-ref res i) (%bignum-ref bignum i)))))
-    (%normalize-bignum res res-len)))
-
-;;; This starts at result's pos-digit skipping pos-bits, and it stores bits
-;;; from new-byte, a fixnum, into result. It effectively stores byte-len
-;;; number of bits, but never stores past end-digit and end-bits in result.
-;;; The first branch fires when all the bits we want from new-byte are present;
-;;; if byte-len crosses from the current result digit into the next, the last
-;;; argument to DEPOSIT-FIXNUM-DIGIT is a mask for those bits. The second
-;;; branch handles the need to grab more bits than the fixnum new-byte has, but
-;;; new-byte is positive; therefore, any virtual bits are zero. The mask for
-;;; bits that don't fit in the current result digit is simply the remaining
-;;; bits in the bignum digit containing new-byte; we don't care if we store
-;;; some extra in the next result digit since they will be zeros. The last
-;;; branch handles the need to grab more bits than the fixnum new-byte has, but
-;;; new-byte is negative; therefore, any virtual bits must be explicitly filled
-;;; in as ones. We call DEPOSIT-FIXNUM-DIGIT to grab what bits actually exist
-;;; and to fill in the current result digit.
-(defun deposit-fixnum-bits (new-byte byte-len pos-digit pos-bits
-                            end-digit end-bits result)
-  (declare (type bignum-index pos-digit end-digit))
-  (let ((other-bits (- digit-size pos-bits))
-        (new-byte-digit (%fixnum-to-digit new-byte)))
-    (declare (type bignum-element-type new-byte-digit))
-    (cond ((< byte-len maximum-fixnum-bits)
-           (deposit-fixnum-digit new-byte-digit byte-len pos-digit pos-bits
-                                 other-bits result
-                                 (- byte-len other-bits)))
-          ((or (plusp new-byte) (zerop new-byte))
-           (deposit-fixnum-digit new-byte-digit byte-len pos-digit pos-bits
-                                 other-bits result pos-bits))
-          (t
-           (multiple-value-bind (digit bits)
-               (deposit-fixnum-digit new-byte-digit byte-len pos-digit pos-bits
-                                     other-bits result
-                                     (if (< (- byte-len other-bits) digit-size)
-                                         (- byte-len other-bits)
-                                         digit-size))
-             (declare (type bignum-index digit))
-             (cond ((< digit end-digit)
-                    (setf (%bignum-ref result digit)
-                          (logior (%bignum-ref result digit)
-                                  (%ashl (%make-ones (- digit-size bits)) bits)))
-                    (do ((i (1+ digit) (1+ i)))
-                        ((= i end-digit)
-                         (setf (%bignum-ref result i) (%make-ones end-bits)))
-                      (setf (%bignum-ref result i) all-ones-digit)))
-                   ((> digit end-digit))
-                   ((< bits end-bits)
-                    (setf (%bignum-ref result digit)
-                          (logior (%bignum-ref result digit)
-                                  (%ashl (%make-ones (- end-bits bits))
-                                         bits))))))))))
-
-;;; This fills in the current result digit from new-byte-digit. The first case
-;;; handles everything we want fitting in the current digit, and other-bits is
-;;; the number of bits remaining to be filled in result's current digit. This
-;;; number is digit-size minus pos-bits. The second branch handles filling in
-;;; result's current digit, and it shoves the unused bits of new-byte-digit
-;;; into the next result digit. This is correct regardless of new-byte-digit's
-;;; sign. It returns the new current result digit and how many bits already
-;;; filled in the result digit.
-(defun deposit-fixnum-digit (new-byte-digit byte-len pos-digit pos-bits
-                             other-bits result next-digit-bits-needed)
-  (declare (type bignum-index pos-digit)
-           (type bignum-element-type new-byte-digit next-digit-mask))
-  (cond ((<= byte-len other-bits)
-         ;; Bits from new-byte fit in the current result digit.
-         (setf (%bignum-ref result pos-digit)
-               (logior (%bignum-ref result pos-digit)
-                       (%ashl (logand new-byte-digit (%make-ones byte-len))
-                              pos-bits)))
-         (if (= byte-len other-bits)
-             (values (1+ pos-digit) 0)
-             (values pos-digit (+ byte-len pos-bits))))
-        (t
-         ;; Some of new-byte's bits go in current result digit.
-         (setf (%bignum-ref result pos-digit)
-               (logior (%bignum-ref result pos-digit)
-                       (%ashl (logand new-byte-digit (%make-ones other-bits))
-                              pos-bits)))
-         (let ((pos-digit+1 (1+ pos-digit)))
-           ;; The rest of new-byte's bits go in the next result digit.
-           (setf (%bignum-ref result pos-digit+1)
-                 (logand (ash new-byte-digit (- other-bits))
-                         ;; Must LOGAND after shift here.
-                         (%make-ones next-digit-bits-needed)))
-           (if (= next-digit-bits-needed digit-size)
-               (values (1+ pos-digit+1) 0)
-               (values pos-digit+1 next-digit-bits-needed))))))
-
-;;; This starts at result's pos-digit skipping pos-bits, and it stores bits
-;;; from new-byte, a bignum, into result. It effectively stores byte-len
-;;; number of bits, but never stores past end-digit and end-bits in result.
-;;; When handling a starting bit unaligned with a digit boundary, we check
-;;; in the second branch for the byte spec fitting into the pos-digit element
-;;; after after pos-bits; DEPOSIT-UNALIGNED-BIGNUM-BITS expects at least one
-;;; digit boundary crossing.
-(defun deposit-bignum-bits (bignum-byte byte-len pos-digit pos-bits
-                            end-digit end-bits result)
-  (declare (type bignum-index pos-digit end-digit))
-  (cond ((zerop pos-bits)
-         (deposit-aligned-bignum-bits bignum-byte pos-digit end-digit end-bits
-                                      result))
-        ((or (= end-digit pos-digit)
-             (and (= end-digit (1+ pos-digit))
-                  (zerop end-bits)))
-         (setf (%bignum-ref result pos-digit)
-               (logior (%bignum-ref result pos-digit)
-                       (%ashl (logand (%bignum-ref bignum-byte 0)
-                                      (%make-ones byte-len))
-                              pos-bits))))
-        (t (deposit-unaligned-bignum-bits bignum-byte pos-digit pos-bits
-                                          end-digit end-bits result))))
-
-;;; This deposits bits from bignum-byte into result starting at pos-digit and
-;;; the zero'th bit. It effectively only stores bits to end-bits in the
-;;; end-digit element of result. The loop termination code takes care of
-;;; picking up the last digit's bits or filling in virtual negative sign bits.
-(defun deposit-aligned-bignum-bits (bignum-byte pos-digit end-digit end-bits
-                                    result)
-  (declare (type bignum-index pos-digit end-digit))
-  (let* ((bignum-len (%bignum-length bignum-byte))
-         (bignum-plusp (%bignum-0-or-plusp bignum-byte bignum-len)))
-    (declare (type bignum-index bignum-len))
-    (do ((i 0 (1+ i ))
-         (j pos-digit (1+ j)))
-        ((or (= j end-digit) (= i bignum-len))
-         (cond ((= j end-digit)
-                (cond ((< i bignum-len)
-                       (setf (%bignum-ref result j)
-                             (logand (%bignum-ref bignum-byte i)
-                                     (%make-ones end-bits))))
-                      (bignum-plusp)
-                      (t
-                       (setf (%bignum-ref result j) (%make-ones end-bits)))))
-               (bignum-plusp)
-               (t
-                (do ((j j (1+ j)))
-                    ((= j end-digit)
-                     (setf (%bignum-ref result j) (%make-ones end-bits)))
-                  (setf (%bignum-ref result j) all-ones-digit)))))
-      (setf (%bignum-ref result j) (%bignum-ref bignum-byte i)))))
-
-;;; This assumes at least one digit crossing.
-(defun deposit-unaligned-bignum-bits (bignum-byte pos-digit pos-bits
-                                      end-digit end-bits result)
-  (declare (type bignum-index pos-digit end-digit))
-  (let* ((bignum-len (%bignum-length bignum-byte))
-         (bignum-plusp (%bignum-0-or-plusp bignum-byte bignum-len))
-         (low-mask (%make-ones pos-bits))
-         (bits-past-pos-bits (- digit-size pos-bits))
-         (high-mask (%make-ones bits-past-pos-bits))
-         (minus-high-bits (- bits-past-pos-bits)))
-    (declare (type bignum-element-type low-mask high-mask)
-             (type bignum-index bignum-len))
-    (do ((i 0 (1+ i))
-         (j pos-digit j+1)
-         (j+1 (1+ pos-digit) (1+ j+1)))
-        ((or (= j end-digit) (= i bignum-len))
-         (cond
-          ((= j end-digit)
-           (setf (%bignum-ref result j)
-                 (cond
-                  ((>= pos-bits end-bits)
-                   (logand (%bignum-ref result j) (%make-ones end-bits)))
-                  ((< i bignum-len)
-                   (logior (%bignum-ref result j)
-                           (%ashl (logand (%bignum-ref bignum-byte i)
-                                          (%make-ones (- end-bits pos-bits)))
-                                  pos-bits)))
-                  (bignum-plusp
-                   (logand (%bignum-ref result j)
-                           ;; 0's between pos-bits and end-bits positions.
-                           (logior (%ashl (%make-ones (- digit-size end-bits))
-                                          end-bits)
-                                   low-mask)))
-                  (t (logior (%bignum-ref result j)
-                             (%ashl (%make-ones (- end-bits pos-bits))
-                                    pos-bits))))))
-          (bignum-plusp)
-          (t
-           (setf (%bignum-ref result j)
-                 (%ashl (%make-ones bits-past-pos-bits) pos-bits))
-           (do ((j j+1 (1+ j)))
-               ((= j end-digit)
-                (setf (%bignum-ref result j) (%make-ones end-bits)))
-             (declare (type bignum-index j))
-             (setf (%bignum-ref result j) all-ones-digit)))))
-      (declare (type bignum-index i j j+1))
-      (let ((digit (%bignum-ref bignum-byte i)))
-        (declare (type bignum-element-type digit))
-        (setf (%bignum-ref result j)
-              (logior (%bignum-ref result j)
-                      (%ashl (logand digit high-mask) pos-bits)))
-        (setf (%bignum-ref result j+1)
-              (logand (ash digit minus-high-bits)
-                      ;; LOGAND should be unnecessary here with a logical right
-                      ;; shift or a correct digit-sized one.
-                      low-mask))))))
-|#
+;;;; There used to be a bunch of code to implement "efficient" versions of LDB
+;;;; and DPB here.  But it apparently was never used, so it's been deleted.
+;;;;   --njf, 2007-02-04
 \f
 ;;;; TRUNCATE
 
@@ -2025,27 +1557,51 @@ IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
         ;;; normalization.
         ;;;
         ;;; We don't have to worry about shifting Y to make its most
-        ;;; significant digit sufficiently large for %FLOOR to return
+        ;;; significant digit sufficiently large for %BIGFLOOR to return
         ;;; digit-size quantities for the q-digit and r-digit. If Y is
         ;;; a single digit bignum, it is already large enough for
-        ;;; %FLOOR. That is, it has some bits on pretty high in the
+        ;;; %BIGFLOOR. That is, it has some bits on pretty high in the
         ;;; digit.
         ((bignum-truncate-single-digit (x len-x y)
            (declare (type bignum-index len-x))
-           (let ((q (%allocate-bignum len-x))
-                 (r 0)
-                 (y (%bignum-ref y 0)))
-             (declare (type bignum-element-type r y))
-             (do ((i (1- len-x) (1- i)))
-                 ((minusp i))
-               (multiple-value-bind (q-digit r-digit)
-                   (%floor r (%bignum-ref x i) y)
-                 (declare (type bignum-element-type q-digit r-digit))
-                 (setf (%bignum-ref q i) q-digit)
-                 (setf r r-digit)))
-             (let ((rem (%allocate-bignum 1)))
-               (setf (%bignum-ref rem 0) r)
-               (values q rem))))
+           (let ((y (%bignum-ref y 0)))
+             (declare (type bignum-element-type y))
+             (if (not (logtest y (1- y)))
+                 ;; Y is a power of two.
+                 ;; SHIFT-RIGHT-UNALIGNED won't do the right thing
+                 ;; with a shift count of 0 or -1, so special case this.
+                 (cond ((= y 0)
+                        (error 'division-by-zero))
+                       ((= y 1)
+                        ;; We could probably get away with (VALUES X 0)
+                        ;; here, but it's not clear that some of the
+                        ;; normalization logic further down would avoid
+                        ;; mutilating X.  Just go ahead and cons, consing's
+                        ;; cheap.
+                        (values (copy-bignum x len-x) 0))
+                       (t
+                        (let ((n-bits (1- (integer-length y))))
+                          (values
+                           (shift-right-unaligned x 0 n-bits len-x
+                                                  ((= j res-len-1)
+                                                   (setf (%bignum-ref res j)
+                                                         (%ashr (%bignum-ref x i) n-bits))
+                                                   res)
+                                                  res)
+                           (logand (%bignum-ref x 0) (1- y))))))
+                 (do ((i (1- len-x) (1- i))
+                      (q (%allocate-bignum len-x))
+                      (r 0))
+                     ((minusp i)
+                      (let ((rem (%allocate-bignum 1)))
+                        (setf (%bignum-ref rem 0) r)
+                        (values q rem)))
+                   (declare (type bignum-element-type r))
+                   (multiple-value-bind (q-digit r-digit)
+                       (%bigfloor r (%bignum-ref x i) y)
+                     (declare (type bignum-element-type q-digit r-digit))
+                     (setf (%bignum-ref q i) q-digit)
+                     (setf r r-digit))))))
         ;;; This returns a guess for the next division step. Y1 is the
         ;;; highest y digit, and y2 is the second to highest y
         ;;; digit. The x... variables are the three highest x digits
@@ -2070,7 +1626,7 @@ IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
            (declare (type bignum-element-type y1 y2 x-i x-i-1 x-i-2))
            (let ((guess (if (%digit-compare x-i y1)
                             all-ones-digit
-                            (%floor x-i x-i-1 y1))))
+                            (%bigfloor x-i x-i-1 y1))))
              (declare (type bignum-element-type guess))
              (loop
                  (multiple-value-bind (high-guess*y1 low-guess*y1)
@@ -2217,7 +1773,7 @@ IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
         ;;; digit-size.
         ;;;
         ;;; We shift y to make it sufficiently large that doing the
-        ;;; 2*digit-size by digit-size %FLOOR calls ensures the quotient and
+        ;;; 2*digit-size by digit-size %BIGFLOOR calls ensures the quotient and
         ;;; remainder fit in digit-size.
          (shift-y-for-truncate (y)
            (let* ((len (%bignum-length y))
@@ -2303,246 +1859,11 @@ IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
                         (%normalize-bignum rem (%bignum-length rem))))))))))
 
 \f
-;;;; %FLOOR primitive for BIGNUM-TRUNCATE
-
-;;; When a machine leaves out a 2*digit-size by digit-size divide
-;;; instruction (that is, two bignum-digits divided by one), we have to
-;;; roll our own (the hard way).  Basically, we treat the operation as
-;;; four digit-size/2 digits divided by two digit-size/2 digits. This
-;;; means we have duplicated most of the code above to do this nearly
-;;; general digit-size/2 digit bignum divide, but we've unrolled loops
-;;; and made use of other properties of this specific divide situation.
-
-;;;; %FLOOR for machines with a 32x32 divider.
-
-#!+(and 32x16-divide (not sb-fluid))
-(declaim (inline 32x16-subtract-with-borrow 32x16-add-with-carry
-                 32x16-divide 32x16-multiply 32x16-multiply-split))
-
-#!+32x16-divide
-(defconstant 32x16-base-1 (1- (ash 1 (/ sb!vm:n-word-bits 2))))
-
-#!+32x16-divide
-(deftype bignum-half-element-type () `(unsigned-byte ,(/ sb!vm:n-word-bits 2)))
-#!+32x16-divide
-(defconstant half-digit-size (/ digit-size 2))
-
-;;; This is similar to %SUBTRACT-WITH-BORROW. It returns a
-;;; half-digit-size difference and a borrow. Returning a 1 for the
-;;; borrow means there was no borrow, and 0 means there was one.
-#!+32x16-divide
-(defun 32x16-subtract-with-borrow (a b borrow)
-  (declare (type bignum-half-element-type a b)
-           (type (integer 0 1) borrow))
-  (let ((diff (+ (- a b) borrow 32x16-base-1)))
-    (declare (type (unsigned-byte #.(1+ half-digit-size)) diff))
-    (values (logand diff (1- (ash 1 half-digit-size)))
-            (ash diff (- half-digit-size)))))
-
-;;; This adds a and b, half-digit-size quantities, with the carry k. It
-;;; returns a half-digit-size sum and a second value, 0 or 1, indicating
-;;; whether there was a carry.
-#!+32x16-divide
-(defun 32x16-add-with-carry (a b k)
-  (declare (type bignum-half-element-type a b)
-           (type (integer 0 1) k))
-  (let ((res (the fixnum (+ a b k))))
-    (declare (type (unsigned-byte #.(1+ half-digit-size)) res))
-    (if (zerop (the fixnum (logand (ash 1 half-digit-size) res)))
-        (values res 0)
-        (values (the bignum-half-element-type (logand (1- (ash 1 half-digit-size)) res))
-                1))))
-
-;;; This is probably a digit-size by digit-size divide instruction.
-#!+32x16-divide
-(defun 32x16-divide (a b c)
-  (declare (type bignum-half-element-type a b c))
-  (floor (the bignum-element-type
-              (logior (the bignum-element-type (ash a 16))
-                      b))
-         c))
-
-;;; This basically exists since we know the answer won't overflow
-;;; bignum-element-type. It's probably just a basic multiply instruction, but
-;;; it can't cons an intermediate bignum. The result goes in a non-descriptor
-;;; register.
-#!+32x16-divide
-(defun 32x16-multiply (a b)
-  (declare (type bignum-half-element-type a b))
-  (the bignum-element-type (* a b)))
-
-;;; This multiplies a and b, half-digit-size quantities, and returns the
-;;; result as two half-digit-size quantities, high and low.
-#!+32x16-divide
-(defun 32x16-multiply-split (a b)
-  (let ((res (32x16-multiply a b)))
-    (declare (the bignum-element-type res))
-    (values (the bignum-half-element-type (logand (1- (ash 1 half-digit-size)) (ash res (- half-digit-size))))
-            (the bignum-half-element-type (logand (1- (ash 1 half-digit-size)) res)))))
-
-;;; The %FLOOR below uses this buffer the same way BIGNUM-TRUNCATE uses
-;;; *truncate-x*. There's no y buffer since we pass around the two
-;;; half-digit-size digits and use them slightly differently than the
-;;; general truncation algorithm above.
-#!+32x16-divide
-(defvar *32x16-truncate-x* (make-array 4 :element-type 'bignum-half-element-type
-                                       :initial-element 0))
-
-;;; This does the same thing as the %FLOOR above, but it does it at Lisp level
-;;; when there is no 64x32-bit divide instruction on the machine.
-;;;
-;;; It implements the higher level tactics of BIGNUM-TRUNCATE, but it
-;;; makes use of special situation provided, four half-digit-size digits
-;;; divided by two half-digit-size digits.
-#!+32x16-divide
-(defun %floor (a b c)
-  (declare (type bignum-element-type a b c))
-  ;; Setup *32x16-truncate-x* buffer from a and b.
-  (setf (aref *32x16-truncate-x* 0)
-        (the bignum-half-element-type (logand (1- (ash 1 half-digit-size)) b)))
-  (setf (aref *32x16-truncate-x* 1)
-        (the bignum-half-element-type
-             (logand (1- (ash 1 half-digit-size))
-                     (the bignum-half-element-type (ash b (- half-digit-size))))))
-  (setf (aref *32x16-truncate-x* 2)
-        (the bignum-half-element-type (logand (1- (ash 1 half-digit-size)) a)))
-  (setf (aref *32x16-truncate-x* 3)
-        (the bignum-half-element-type
-             (logand (1- (ash 1 half-digit-size))
-                     (the bignum-half-element-type (ash a (- half-digit-size))))))
-  ;; From DO-TRUNCATE, but unroll the loop.
-  (let* ((y1 (logand (1- (ash 1 half-digit-size)) (ash c (- half-digit-size))))
-         (y2 (logand (1- (ash 1 half-digit-size)) c))
-         (q (the bignum-element-type
-                 (ash (32x16-try-bignum-truncate-guess
-                       (32x16-truncate-guess y1 y2
-                                             (aref *32x16-truncate-x* 3)
-                                             (aref *32x16-truncate-x* 2)
-                                             (aref *32x16-truncate-x* 1))
-                       y1 y2 1)
-                      16))))
-    (declare (type bignum-element-type q)
-             (type bignum-half-element-type y1 y2))
-    (values (the bignum-element-type
-                 (logior q
-                         (the bignum-half-element-type
-                              (32x16-try-bignum-truncate-guess
-                               (32x16-truncate-guess
-                                y1 y2
-                                (aref *32x16-truncate-x* 2)
-                                (aref *32x16-truncate-x* 1)
-                                (aref *32x16-truncate-x* 0))
-                               y1 y2 0))))
-            (the bignum-element-type
-                 (logior (the bignum-element-type
-                              (ash (aref *32x16-truncate-x* 1) 16))
-                         (the bignum-half-element-type
-                              (aref *32x16-truncate-x* 0)))))))
-
-;;; This is similar to TRY-BIGNUM-TRUNCATE-GUESS, but this unrolls the two
-;;; loops. This also substitutes for %DIGIT-0-OR-PLUSP the equivalent
-;;; expression without any embellishment or pretense of abstraction. The first
-;;; loop is unrolled, but we've put the body of the loop into the function
-;;; 32X16-TRY-GUESS-ONE-RESULT-DIGIT.
-#!+32x16-divide
-(defun 32x16-try-bignum-truncate-guess (guess y-high y-low low-x-digit)
-  (declare (type bignum-index low-x-digit)
-           (type bignum-half-element-type guess y-high y-low))
-  (let ((high-x-digit (+ 2 low-x-digit)))
-    ;; Multiply guess and divisor, subtracting from dividend simultaneously.
-    (multiple-value-bind (guess*y-hold carry borrow)
-        (32x16-try-guess-one-result-digit guess y-low 0 0 1 low-x-digit)
-      (declare (type bignum-half-element-type guess*y-hold)
-               (fixnum carry borrow))
-      (multiple-value-bind (guess*y-hold carry borrow)
-          (32x16-try-guess-one-result-digit guess y-high guess*y-hold
-                                            carry borrow (1+ low-x-digit))
-        (declare (type bignum-half-element-type guess*y-hold)
-                 (fixnum borrow)
-                 (ignore carry))
-        (setf (aref *32x16-truncate-x* high-x-digit)
-              (32x16-subtract-with-borrow (aref *32x16-truncate-x* high-x-digit)
-                                          guess*y-hold borrow))))
-    ;; See whether guess is off by one, adding one Y back in if necessary.
-    (cond ((zerop (logand (ash 1 (1- half-digit-size))
-                          (aref *32x16-truncate-x* high-x-digit)))
-           ;; The subtraction result is zero or positive.
-           guess)
-          (t
-           ;; If subtraction has negative result, add one divisor value back
-           ;; in. The guess was one too large in magnitude.
-           (multiple-value-bind (v carry)
-               (32x16-add-with-carry y-low
-                                     (aref *32x16-truncate-x* low-x-digit)
-                                     0)
-             (declare (type bignum-half-element-type v))
-             (setf (aref *32x16-truncate-x* low-x-digit) v)
-             (multiple-value-bind (v carry)
-                 (32x16-add-with-carry y-high
-                                       (aref *32x16-truncate-x*
-                                             (1+ low-x-digit))
-                                       carry)
-               (setf (aref *32x16-truncate-x* (1+ low-x-digit)) v)
-               (setf (aref *32x16-truncate-x* high-x-digit)
-                     (32x16-add-with-carry (aref *32x16-truncate-x* high-x-digit)
-                                           carry 0))))
-           (if (zerop (logand (ash 1 (1- half-digit-size)) guess))
-               (1- guess)
-               (1+ guess))))))
-
-;;; This is similar to the body of the loop in TRY-BIGNUM-TRUNCATE-GUESS that
-;;; multiplies the guess by y and subtracts the result from x simultaneously.
-;;; This returns the digit remembered as part of the multiplication, the carry
-;;; from additions done on behalf of the multiplication, and the borrow from
-;;; doing the subtraction.
-#!+32x16-divide
-(defun 32x16-try-guess-one-result-digit (guess y-digit guess*y-hold
-                                         carry borrow x-index)
-  (multiple-value-bind (high-digit low-digit)
-      (32x16-multiply-split guess y-digit)
-    (declare (type bignum-half-element-type high-digit low-digit))
-    (multiple-value-bind (low-digit temp-carry)
-        (32x16-add-with-carry low-digit guess*y-hold carry)
-      (declare (type bignum-half-element-type low-digit))
-      (multiple-value-bind (high-digit temp-carry)
-          (32x16-add-with-carry high-digit temp-carry 0)
-        (declare (type bignum-half-element-type high-digit))
-        (multiple-value-bind (x temp-borrow)
-            (32x16-subtract-with-borrow (aref *32x16-truncate-x* x-index)
-                                        low-digit borrow)
-          (declare (type bignum-half-element-type x))
-          (setf (aref *32x16-truncate-x* x-index) x)
-          (values high-digit temp-carry temp-borrow))))))
-
-;;; This is similar to BIGNUM-TRUNCATE-GUESS, but instead of computing
-;;; the guess exactly as described in the its comments (digit by digit),
-;;; this massages the digit-size/2 quantities into digit-size quantities
-;;; and performs the
-#!+32x16-divide
-(defun 32x16-truncate-guess (y1 y2 x-i x-i-1 x-i-2)
-  (declare (type bignum-half-element-type y1 y2 x-i x-i-1 x-i-2))
-  (let ((guess (if (= x-i y1)
-                   (1- (ash 1 half-digit-size))
-                   (32x16-divide x-i x-i-1 y1))))
-    (declare (type bignum-half-element-type guess))
-    (loop
-      (let* ((guess*y1 (the bignum-element-type
-                            (ash (logand (1- (ash 1 half-digit-size))
-                                         (the bignum-element-type
-                                              (32x16-multiply guess y1)))
-                                 16)))
-             (x-y (%subtract-with-borrow
-                   (the bignum-element-type
-                        (logior (the bignum-element-type
-                                     (ash x-i-1 16))
-                                x-i-2))
-                   guess*y1
-                   1))
-             (guess*y2 (the bignum-element-type (%multiply guess y2))))
-        (declare (type bignum-element-type guess*y1 x-y guess*y2))
-        (if (%digit-greater guess*y2 x-y)
-            (decf guess)
-            (return guess))))))
+;;;; There used to be a pile of code for implementing division for bignum digits
+;;;; for machines that don't have a 2*digit-size by digit-size divide instruction.
+;;;; This happens to be most machines, but all the SBCL ports seem to be content
+;;;; to implement SB-BIGNUM:%BIGFLOOR as a VOP rather than using the code here.
+;;;; So it's been deleted.  --njf, 2007-02-04
 \f
 ;;;; general utilities
 
@@ -2612,6 +1933,6 @@ IS LESS EFFICIENT BUT EASIER TO MAINTAIN. BILL SAYS THIS CODE CERTAINLY WORKS!
       (let ((xi (%bignum-ref x i)))
         (mixf result
               (logand most-positive-fixnum
-                      xi
-                      (ash xi -7)))))
+                      (logxor xi
+                              (ash xi -7))))))
     result))