fix a bug in signed modular arithmetic
authorChristophe Rhodes <csr21@cantab.net>
Tue, 4 Dec 2012 20:50:12 +0000 (20:50 +0000)
committerChristophe Rhodes <csr21@cantab.net>
Tue, 4 Dec 2012 20:50:12 +0000 (20:50 +0000)
Sadly not the ones that Eric gently reminds us of every month or so, but
a far more basic one.  If something is a (signed-byte x), its integer-length
will be at most (1- x).  Search appropriately for a signed arithmetic
variant.

src/compiler/srctran.lisp
tests/compiler.pure.lisp

index 3278e7b..7736902 100644 (file)
         (when (and (numberp low) (numberp high))
           (let ((width (max (integer-length high) (integer-length low))))
             (multiple-value-bind (w kind)
-                (best-modular-version width t)
+                (best-modular-version (1+ width) t)
               (when w
                 ;; FIXME: This should be (CUT-TO-WIDTH NODE KIND W T).
                 ;; [ see comment above in LOGAND optimizer ]
index 7d8faf1..8e37cf2 100644 (file)
       (destructuring-bind (orig conservative) pair
         (assert sb-c::(type= (specifier-type cl-user::conservative)
                              (conservative-type (specifier-type cl-user::orig))))))))
+
+(with-test (:name (:smodular64 :wrong-width))
+  (let ((fun (compile nil
+                      '(lambda (x)
+                         (declare (type (signed-byte 64) x))
+                         (sb-c::mask-signed-field 64 (- x 7033717698976965573))))))
+    (assert (= (funcall fun 10038) -7033717698976955535))))
+
+(with-test (:name (:smodular32 :wrong-width))
+  (let ((fun (compile nil '(lambda (x)
+                             (declare (type (signed-byte 31) x))
+                             (sb-c::mask-signed-field 31 (- x 1055131947))))))
+    (assert (= (funcall fun 10038) -1055121909))))