[movitz-cvs] CVS update: movitz/losp/muerte/integers.lisp
Frode Vatvedt Fjeld
ffjeld at common-lisp.net
Fri Jul 16 00:03:05 UTC 2004
Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory common-lisp.net:/tmp/cvs-serv2747
Modified Files:
integers.lisp
Log Message:
Improved ash. Fixed a bug wrt. carry-propagation in - for bignums.
Date: Thu Jul 15 17:03:05 2004
Author: ffjeld
Index: movitz/losp/muerte/integers.lisp
diff -u movitz/losp/muerte/integers.lisp:1.66 movitz/losp/muerte/integers.lisp:1.67
--- movitz/losp/muerte/integers.lisp:1.66 Thu Jul 15 14:07:08 2004
+++ movitz/losp/muerte/integers.lisp Thu Jul 15 17:03:05 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.66 2004/07/15 21:07:08 ffjeld Exp $
+;;;; $Id: integers.lisp,v 1.67 2004/07/16 00:03:05 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -516,8 +516,11 @@
(:jne 'sub-loop)
(:subl :ecx
(:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:jc '(:sub-program (should-not-happen)
- (:int 107)))
+ (:jnc 'bignum-sub-done)
+ propagate-carry
+ (:addl 4 :edx)
+ (:subl 1 (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:jc 'propagate-carry)
bignum-sub-done
)))))
(((integer 0 *) (integer * -1))
@@ -1088,14 +1091,63 @@
(defun ash (integer count)
(cond
- ((not (minusp count))
- (do () ((< count 16))
- (setf integer (no-macro-call * #x10000 integer))
- (decf count 16))
- (dotimes (i count integer)
- (setf integer (no-macro-call * 2 integer))))
- (t (dotimes (i (- count) integer)
- (setf integer (truncate integer 2))))))
+ ((= 0 count)
+ integer)
+ ((plusp count)
+ (let ((result-length (+ (integer-length integer) count)))
+ (cond
+ ((<= result-length 29)
+ (with-inline-assembly (:returns :eax)
+ (:compile-two-forms (:eax :ecx) integer count)
+ (:shrl #.movitz:+movitz-fixnum-shift+ :ecx)
+ (:shll :cl :eax)))
+ (t (check-type integer (integer 0 *))
+ (multiple-value-bind (long short)
+ (truncate count 16)
+ (let ((result (%make-bignum (truncate (+ result-length 31) 32))))
+ (dotimes (i long)
+ (setf (memref result -2 i :unsigned-byte16) 0))
+ (etypecase integer
+ (fixnum
+ (when (>= integer #x10000)
+ (setf (memref result -2 (1+ long) :unsigned-byte16)
+ (ldb (byte 16 16) integer)))
+ (setf (memref result -2 long :unsigned-byte16)
+ (ldb (byte 16 0) integer)))
+ (bignum
+ (dotimes (i (* 2 (%bignum-bigits integer)))
+ (setf (memref result -2 (+ i long) :unsigned-byte16)
+ (memref integer -2 i :unsigned-byte16)))))
+ (setf result (%bignum-canonicalize result))
+ (dotimes (i short)
+ (setf result (* 2 result)))
+ result))))))
+ (t (let ((count (- count)))
+ (etypecase integer
+ (fixnum
+ (with-inline-assembly (:returns :eax :type fixnum)
+ (:compile-two-forms (:eax :ecx) integer count)
+ (:shrl #.movitz:+movitz-fixnum-shift+ :ecx)
+ (:std)
+ (:sarl :cl :eax)
+ (:andl -4 :eax)
+ (:cld)))
+ (positive-bignum
+ (let* ((result-length (- (integer-length integer) count))
+ (result (%make-bignum (truncate (+ result-length 31) 32))))
+ (multiple-value-bind (long short)
+ (truncate count 16)
+ (let ((src-max-bigit (* 2 (%bignum-bigits integer))))
+ (dotimes (i (* 2 (%bignum-bigits result)))
+ (let ((src (+ i long)))
+ (setf (memref result -2 i :unsigned-byte16)
+ (if (< src src-max-bigit)
+ (memref integer -2 src :unsigned-byte16)
+ 0)))))
+ (setf result (%bignum-canonicalize result))
+ (dotimes (i short result)
+ (setf result (truncate result 2)))
+ result))))))))
;;;;
@@ -1317,10 +1369,16 @@
;; X is the biggest factor.
(let ((r 0) (f 0))
(dotimes (half-bigit (* 2 (%bignum-bigits y)))
- (setf r (+ r (ash (* (memref y -2 half-bigit :unsigned-byte16) x)
- f)))
+ (incf r (ash (* (memref y -2 half-bigit :unsigned-byte16) x)
+ f))
(incf f 16))
- r))))))
+ r)))
+ ((t (integer * -1))
+ (%negatef (* x (- y)) x y))
+ (((integer * -1) t)
+ (%negatef (* (- x) y) x y))
+ (((integer * -1) (integer * -1))
+ (* (- x) (- y))))))
(do-it)))
(t (&rest factors)
(declare (dynamic-extent factors))
@@ -1461,18 +1519,15 @@
(setf msb (+ (* #x10000 msb)
(* #x100 (memref divisor -2 (1+ msb-pos) :unsigned-byte8))
(memref divisor -2 msb-pos :unsigned-byte8)))
- (multiple-value-bind (long-shift short-shift)
- ;; This shifting stuff should be replaced by ash,
- ;; when ash is properly implemented.
- (truncate msb-pos 3)
+ (let ((guess-shift (- (* msb-pos 8))))
(do ((msb+1 (1+ msb))
(q 0) (r number))
((< r divisor) (values q r))
- (let ((guess (truncate r msb+1)))
- (dotimes (i long-shift)
- (setf guess (truncate guess #x1000000)))
- (dotimes (i short-shift)
- (setf guess (truncate guess #x100)))
+ (let ((guess (ash (truncate r msb+1) guess-shift)))
+;;; (dotimes (i long-shift)
+;;; (setf guess (truncate guess #x1000000)))
+;;; (dotimes (i short-shift)
+;;; (setf guess (truncate guess #x100)))
(if (= 0 guess)
(setf q (1+ q)
r (- r divisor))
More information about the Movitz-cvs
mailing list