[movitz-cvs] CVS update: movitz/losp/muerte/integers.lisp
Frode Vatvedt Fjeld
ffjeld at common-lisp.net
Tue Jul 13 19:45:39 UTC 2004
Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory common-lisp.net:/tmp/cvs-serv6538
Modified Files:
integers.lisp
Log Message:
Two fixes: Comparison of bignums was flawed, because the bigits were
compared as signed values, while they in fact are unsigned. So <, >,
=, etc would return the wrong answer in 50% of the cases.
Secondly, added a linear-complexity algorithm for truncate, rather
than the idiotic quadratic one.
Date: Tue Jul 13 12:45:38 2004
Author: ffjeld
Index: movitz/losp/muerte/integers.lisp
diff -u movitz/losp/muerte/integers.lisp:1.50 movitz/losp/muerte/integers.lisp:1.51
--- movitz/losp/muerte/integers.lisp:1.50 Tue Jul 13 07:17:05 2004
+++ movitz/losp/muerte/integers.lisp Tue Jul 13 12:45:38 2004
@@ -9,7 +9,7 @@
;;;; Created at: Wed Nov 8 18:44:57 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: integers.lisp,v 1.50 2004/07/13 14:17:05 ffjeld Exp $
+;;;; $Id: integers.lisp,v 1.51 2004/07/13 19:45:38 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -570,12 +570,22 @@
(:cmpl :ecx
(:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
(:je 'positive-compare-loop)
- (:ret)
- positive-compare-lsb ; it's down to the LSB bigits.
- (:movl (:ebx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx)
- (:cmpl :ecx
- (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ positive-compare-lsb
+ ;; Now make the compare unsigned..
+ (:movzxw (:ebx :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx) ; First compare upper 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx)
+ (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
+ (:jne 'upper-16-decisive)
+ (:movzxw (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
+ upper-16-decisive
(:ret)
compare-negatives
@@ -1424,10 +1434,23 @@
(cond
((= number divisor) (values 1 0))
((< number divisor) (values 0 number))
- (t (do ((q 0 (1+ q))
- (r number (- r divisor)))
- ((< r divisor) (values q r))))))
- ))))
+ (t (let* ((msb-pos (1- (* 2 (%bignum-bigits divisor))))
+ (msb (memref divisor -2 msb-pos :unsigned-byte16)))
+ (when (= 0 msb)
+ (decf msb-pos)
+ (setf msb (memref divisor -2 msb-pos :unsigned-byte16))
+ (assert (plusp msb)))
+ (do ((msb+1 (1+ msb))
+ (q 0) (r number))
+ ((< r divisor) (values q r))
+ (let ((guess (truncate r msb+1)))
+ (dotimes (i msb-pos)
+ (setf guess (truncate guess #x10000)))
+ (if (= 0 guess)
+ (setf q (1+ q)
+ r (- r divisor))
+ (setf q (+ q guess)
+ r (- r (* divisor guess))))))))))))))
(defun / (number &rest denominators)
(declare (dynamic-extent denominators))
More information about the Movitz-cvs
mailing list