** :ALLOW-OTHER-KEYS NIL is now accepted in an initarg list.
changes in sbcl-0.8.0 relative to sbcl-0.8alpha.0
+ * minor incompatible change: the :NEGATIVE-ZERO-IS-NOT-ZERO feature
+ no longer has any effect, as the code controlled by this feature
+ has been deleted. (As far as we know, no-one has ever built using
+ this feature, and its semantics were confused in any case).
* SB-MOP:DIRECT-SLOT-DEFINITION-CLASS and
SB-MOP:EFFECTIVE-SLOT-DEFINITION-CLASS now have the
specified-by-AMOP lambda list of (CLASS &REST INITARGS).
;; to. It doesn't seem to be needed for X86 systems anyway.
; :32x16-divide
- ;; This is probably true for some processor types, but not X86. It
- ;; affects a lot of floating point code.
- ; :negative-zero-is-not-zero
-
;; This is set in classic CMU CL, and presumably there it means
;; that the floating point arithmetic implementation
;; conforms to IEEE's standard. Here it definitely means that the
(if (consp high)
(1- (type-bound-number high))
high)))
- #!+negative-zero-is-not-zero
- (float
- ;; Canonicalize a low bound of (-0.0) to 0.0, and a high
- ;; bound of (+0.0) to -0.0.
- (values (if (and (consp low)
- (floatp (car low))
- (zerop (car low))
- (minusp (float-sign (car low))))
- (float 0.0 (car low))
- low)
- (if (and (consp high)
- (floatp (car high))
- (zerop (car high))
- (plusp (float-sign (car high))))
- (float -0.0 (car high))
- high)))
(t
;; no canonicalization necessary
(values low high)))
;;;
;;; This is for comparing bounds of the same kind, e.g. upper and
;;; upper. Use NUMERIC-BOUND-TEST* for different kinds of bounds.
-#!-negative-zero-is-not-zero
(defmacro numeric-bound-test (x y closed open)
`(cond ((not ,y) t)
((not ,x) nil)
(,open ,x (car ,y))
(,closed ,x ,y)))))
-#!+negative-zero-is-not-zero
-(defmacro numeric-bound-test-zero (op x y)
- `(if (and (zerop ,x) (zerop ,y) (floatp ,x) (floatp ,y))
- (,op (float-sign ,x) (float-sign ,y))
- (,op ,x ,y)))
-
-#!+negative-zero-is-not-zero
-(defmacro numeric-bound-test (x y closed open)
- `(cond ((not ,y) t)
- ((not ,x) nil)
- ((consp ,x)
- (if (consp ,y)
- (numeric-bound-test-zero ,closed (car ,x) (car ,y))
- (numeric-bound-test-zero ,closed (car ,x) ,y)))
- (t
- (if (consp ,y)
- (numeric-bound-test-zero ,open ,x (car ,y))
- (numeric-bound-test-zero ,closed ,x ,y)))))
-
;;; This is used to compare upper and lower bounds. This is different
;;; from the same-bound case:
;;; -- Since X = NIL is -infinity, whereas y = NIL is +infinity, we
;;; return true if *either* arg is NIL.
;;; -- an open inner bound is "greater" and also squeezes the interval,
;;; causing us to use the OPEN test for those cases as well.
-#!-negative-zero-is-not-zero
(defmacro numeric-bound-test* (x y closed open)
`(cond ((not ,y) t)
((not ,x) t)
(,open ,x (car ,y))
(,closed ,x ,y)))))
-#!+negative-zero-is-not-zero
-(defmacro numeric-bound-test* (x y closed open)
- `(cond ((not ,y) t)
- ((not ,x) t)
- ((consp ,x)
- (if (consp ,y)
- (numeric-bound-test-zero ,open (car ,x) (car ,y))
- (numeric-bound-test-zero ,open (car ,x) ,y)))
- (t
- (if (consp ,y)
- (numeric-bound-test-zero ,open ,x (car ,y))
- (numeric-bound-test-zero ,closed ,x ,y)))))
-
;;; Return whichever of the numeric bounds X and Y is "maximal"
;;; according to the predicates CLOSED (e.g. >=) and OPEN (e.g. >).
;;; This is only meaningful for maximizing like bounds, i.e. upper and
(cond ((not (and low-bound high-bound)) nil)
((and (consp low-bound) (consp high-bound)) nil)
((consp low-bound)
- #!-negative-zero-is-not-zero
(let ((low-value (car low-bound)))
(or (eql low-value high-bound)
(and (eql low-value -0f0) (eql high-bound 0f0))
(and (eql low-value 0f0) (eql high-bound -0f0))
(and (eql low-value -0d0) (eql high-bound 0d0))
- (and (eql low-value 0d0) (eql high-bound -0d0))))
- #!+negative-zero-is-not-zero
- (eql (car low-bound) high-bound))
+ (and (eql low-value 0d0) (eql high-bound -0d0)))))
((consp high-bound)
- #!-negative-zero-is-not-zero
(let ((high-value (car high-bound)))
(or (eql high-value low-bound)
(and (eql high-value -0f0) (eql low-bound 0f0))
(and (eql high-value 0f0) (eql low-bound -0f0))
(and (eql high-value -0d0) (eql low-bound 0d0))
- (and (eql high-value 0d0) (eql low-bound -0d0))))
- #!+negative-zero-is-not-zero
- (eql (car high-bound) low-bound))
- #!+negative-zero-is-not-zero
- ((or (and (eql low-bound -0f0) (eql high-bound 0f0))
- (and (eql low-bound -0d0) (eql high-bound 0d0))))
+ (and (eql high-value 0d0) (eql low-bound -0d0)))))
((and (eq (numeric-type-class low) 'integer)
(eq (numeric-type-class high) 'integer))
(eql (1+ low-bound) high-bound))
(let (ms numbers)
(dolist (m (remove-duplicates members))
(typecase m
- #!-negative-zero-is-not-zero
(float (if (zerop m)
(push m ms)
(push (ctype-of m) numbers)))
(long-float (typep num 'long-float))
((nil) (floatp num))))
((nil) t)))
- #!-negative-zero-is-not-zero
(flet ((bound-test (val)
(let ((low (numeric-type-low type))
(high (numeric-type-high type)))
(bound-test (imagpart object))))
(:real
(and (not (complexp object))
- (bound-test object)))))
- #!+negative-zero-is-not-zero
- (labels ((signed-> (x y)
- (if (and (zerop x) (zerop y) (floatp x) (floatp y))
- (> (float-sign x) (float-sign y))
- (> x y)))
- (signed->= (x y)
- (if (and (zerop x) (zerop y) (floatp x) (floatp y))
- (>= (float-sign x) (float-sign y))
- (>= x y)))
- (bound-test (val)
- (let ((low (numeric-type-low type))
- (high (numeric-type-high type)))
- (and (cond ((null low) t)
- ((listp low)
- (signed-> val (car low)))
- (t
- (signed->= val low)))
- (cond ((null high) t)
- ((listp high)
- (signed-> (car high) val))
- (t
- (signed->= high val)))))))
- (ecase (numeric-type-complexp type)
- ((nil) t)
- (:complex
- (and (complexp object)
- (bound-test (realpart object))
- (bound-test (imagpart object))))
- (:real
- (and (not (complexp object))
(bound-test object)))))))
(array-type
(and (arrayp object)
;;; Test whether the numeric-type ARG is within in domain specified by
;;; DOMAIN-LOW and DOMAIN-HIGH, consider negative and positive zero to
-;;; be distinct as for the :NEGATIVE-ZERO-IS-NOT-ZERO feature. With
-;;; the :NEGATIVE-ZERO-IS-NOT-ZERO feature this could be handled by
-;;; the numeric subtype code in type.lisp.
+;;; be distinct.
(defun domain-subtypep (arg domain-low domain-high)
(declare (type numeric-type arg)
(type (or real null) domain-low domain-high))
;;; result, which occurs for the parts of ARG not in the DOMAIN.
;;;
;;; Negative and positive zero are considered distinct within
-;;; DOMAIN-LOW and DOMAIN-HIGH, as for the :negative-zero-is-not-zero
-;;; feature.
+;;; DOMAIN-LOW and DOMAIN-HIGH.
;;;
;;; DEFAULT-LOW and DEFAULT-HIGH are the lower and upper bounds if we
;;; can't compute the bounds using FCN.
;;; are equal to an intermediate convention for which they are
;;; considered different which is more natural for some of the
;;; optimisers.
-#!-negative-zero-is-not-zero
(defun convert-numeric-type (type)
(declare (type numeric-type type))
;;; Only convert real float interval delimiters types.
;;; Convert back from the intermediate convention for which -0.0 and
;;; 0.0 are considered different to the standard type convention for
;;; which and equal.
-#!-negative-zero-is-not-zero
(defun convert-back-numeric-type (type)
(declare (type numeric-type type))
;;; Only convert real float interval delimiters types.
type))
;;; Convert back a possible list of numeric types.
-#!-negative-zero-is-not-zero
(defun convert-back-numeric-type-list (type-list)
(typecase type-list
(list
(push type misc-types)))
#!+long-float
(when (null (set-difference '(-0l0 0l0) members))
- #!-negative-zero-is-not-zero
(push (specifier-type '(long-float 0l0 0l0)) misc-types)
- #!+negative-zero-is-not-zero
- (push (specifier-type '(long-float -0l0 0l0)) misc-types)
(setf members (set-difference members '(-0l0 0l0))))
(when (null (set-difference '(-0d0 0d0) members))
- #!-negative-zero-is-not-zero
(push (specifier-type '(double-float 0d0 0d0)) misc-types)
- #!+negative-zero-is-not-zero
- (push (specifier-type '(double-float -0d0 0d0)) misc-types)
(setf members (set-difference members '(-0d0 0d0))))
(when (null (set-difference '(-0f0 0f0) members))
- #!-negative-zero-is-not-zero
(push (specifier-type '(single-float 0f0 0f0)) misc-types)
- #!+negative-zero-is-not-zero
- (push (specifier-type '(single-float -0f0 0f0)) misc-types)
(setf members (set-difference members '(-0f0 0f0))))
(if members
(apply #'type-union (make-member-type :members members) misc-types)
(defun one-arg-derive-type (arg derive-fcn member-fcn
&optional (convert-type t))
(declare (type function derive-fcn)
- (type (or null function) member-fcn)
- #!+negative-zero-is-not-zero (ignore convert-type))
+ (type (or null function) member-fcn))
(let ((arg-list (prepare-arg-for-derive-type (continuation-type arg))))
(when arg-list
(flet ((deriver (x)
;; Otherwise convert to a numeric type.
(let ((result-type-list
(funcall derive-fcn (convert-member-type x))))
- #!-negative-zero-is-not-zero
(if convert-type
(convert-back-numeric-type-list result-type-list)
- result-type-list)
- #!+negative-zero-is-not-zero
- result-type-list)))
+ result-type-list))))
(numeric-type
- #!-negative-zero-is-not-zero
(if convert-type
(convert-back-numeric-type-list
(funcall derive-fcn (convert-numeric-type x)))
- (funcall derive-fcn x))
- #!+negative-zero-is-not-zero
- (funcall derive-fcn x))
+ (funcall derive-fcn x)))
(t
*universal-type*))))
;; Run down the list of args and derive the type of each one,
(defun two-arg-derive-type (arg1 arg2 derive-fcn fcn
&optional (convert-type t))
(declare (type function derive-fcn fcn))
- #!+negative-zero-is-not-zero
- (declare (ignore convert-type))
- (flet (#!-negative-zero-is-not-zero
- (deriver (x y same-arg)
+ (flet ((deriver (x y same-arg)
(cond ((and (member-type-p x) (member-type-p y))
(let* ((x (first (member-type-members x)))
(y (first (member-type-members y)))
(convert-back-numeric-type-list result)
result)))
(t
- *universal-type*)))
- #!+negative-zero-is-not-zero
- (deriver (x y same-arg)
- (cond ((and (member-type-p x) (member-type-p y))
- (let* ((x (first (member-type-members x)))
- (y (first (member-type-members y)))
- (result (with-float-traps-masked
- (:underflow :overflow :divide-by-zero)
- (funcall fcn x y))))
- (if result
- (make-member-type :members (list result)))))
- ((and (member-type-p x) (numeric-type-p y))
- (let ((x (convert-member-type x)))
- (funcall derive-fcn x y same-arg)))
- ((and (numeric-type-p x) (member-type-p y))
- (let ((y (convert-member-type y)))
- (funcall derive-fcn x y same-arg)))
- ((and (numeric-type-p x) (numeric-type-p y))
- (funcall derive-fcn x y same-arg))
- (t
*universal-type*))))
(let ((same-arg (same-leaf-ref-p arg1 arg2))
(a1 (prepare-arg-for-derive-type (continuation-type arg1)))
;;; binds specified by TYPE. BASE is the name of the base type, for
;;; declaration. We make SAFETY locally 0 to inhibit any checking of
;;; this assertion.
-#!-negative-zero-is-not-zero
(defun transform-numeric-bound-test (n-object type base)
(declare (type numeric-type type))
(let ((low (numeric-type-low type))
`((< (the ,base ,n-object) ,(car high)))
`((<= (the ,base ,n-object) ,high))))))))
-#!+negative-zero-is-not-zero
-(defun transform-numeric-bound-test (n-object type base)
- (declare (type numeric-type type))
- (let ((low (numeric-type-low type))
- (high (numeric-type-high type))
- (float-type-p (csubtypep type (specifier-type 'float)))
- (x (gensym))
- (y (gensym)))
- `(locally
- (declare (optimize (safety 0)))
- (and ,@(when low
- (if (consp low)
- `((let ((,x (the ,base ,n-object))
- (,y ,(car low)))
- ,(if (not float-type-p)
- `(> ,x ,y)
- `(if (and (zerop ,x) (zerop ,y))
- (> (float-sign ,x) (float-sign ,y))
- (> ,x ,y)))))
- `((let ((,x (the ,base ,n-object))
- (,y ,low))
- ,(if (not float-type-p)
- `(>= ,x ,y)
- `(if (and (zerop ,x) (zerop ,y))
- (>= (float-sign ,x) (float-sign ,y))
- (>= ,x ,y)))))))
- ,@(when high
- (if (consp high)
- `((let ((,x (the ,base ,n-object))
- (,y ,(car high)))
- ,(if (not float-type-p)
- `(< ,x ,y)
- `(if (and (zerop ,x) (zerop ,y))
- (< (float-sign ,x) (float-sign ,y))
- (< ,x ,y)))))
- `((let ((,x (the ,base ,n-object))
- (,y ,high))
- ,(if (not float-type-p)
- `(<= ,x ,y)
- `(if (and (zerop ,x) (zerop ,y))
- (<= (float-sign ,x) (float-sign ,y))
- (<= ,x ,y)))))))))))
-
;;; Do source transformation of a test of a known numeric type. We can
;;; assume that the type doesn't have a corresponding predicate, since
;;; those types have already been picked off. In particular, CLASS
(define-vop (=0/single-float float-test)
(:translate =)
(:args (x :scs (single-reg)))
- #!-negative-zero-is-not-zero
(:arg-types single-float (:constant (single-float 0f0 0f0)))
- #!+negative-zero-is-not-zero
- (:arg-types single-float (:constant (single-float -0f0 0f0)))
(:variant #x40))
(define-vop (=0/double-float float-test)
(:translate =)
(:args (x :scs (double-reg)))
- #!-negative-zero-is-not-zero
(:arg-types double-float (:constant (double-float 0d0 0d0)))
- #!+negative-zero-is-not-zero
- (:arg-types double-float (:constant (double-float -0d0 0d0)))
(:variant #x40))
#!+long-float
(define-vop (=0/long-float float-test)
(:translate =)
(:args (x :scs (long-reg)))
- #!-negative-zero-is-not-zero
(:arg-types long-float (:constant (long-float 0l0 0l0)))
- #!+negative-zero-is-not-zero
- (:arg-types long-float (:constant (long-float -0l0 0l0)))
(:variant #x40))
(define-vop (<0/single-float float-test)
(:translate <)
(:args (x :scs (single-reg)))
- #!-negative-zero-is-not-zero
(:arg-types single-float (:constant (single-float 0f0 0f0)))
- #!+negative-zero-is-not-zero
- (:arg-types single-float (:constant (single-float -0f0 0f0)))
(:variant #x01))
(define-vop (<0/double-float float-test)
(:translate <)
(:args (x :scs (double-reg)))
- #!-negative-zero-is-not-zero
(:arg-types double-float (:constant (double-float 0d0 0d0)))
- #!+negative-zero-is-not-zero
- (:arg-types double-float (:constant (double-float -0d0 0d0)))
(:variant #x01))
#!+long-float
(define-vop (<0/long-float float-test)
(:translate <)
(:args (x :scs (long-reg)))
- #!-negative-zero-is-not-zero
(:arg-types long-float (:constant (long-float 0l0 0l0)))
- #!+negative-zero-is-not-zero
- (:arg-types long-float (:constant (long-float -0l0 0l0)))
(:variant #x01))
(define-vop (>0/single-float float-test)
(:translate >)
(:args (x :scs (single-reg)))
- #!-negative-zero-is-not-zero
(:arg-types single-float (:constant (single-float 0f0 0f0)))
- #!+negative-zero-is-not-zero
- (:arg-types single-float (:constant (single-float -0f0 0f0)))
(:variant #x00))
(define-vop (>0/double-float float-test)
(:translate >)
(:args (x :scs (double-reg)))
- #!-negative-zero-is-not-zero
(:arg-types double-float (:constant (double-float 0d0 0d0)))
- #!+negative-zero-is-not-zero
- (:arg-types double-float (:constant (double-float -0d0 0d0)))
(:variant #x00))
#!+long-float
(define-vop (>0/long-float float-test)
(:translate >)
(:args (x :scs (long-reg)))
- #!-negative-zero-is-not-zero
(:arg-types long-float (:constant (long-float 0l0 0l0)))
- #!+negative-zero-is-not-zero
- (:arg-types long-float (:constant (long-float -0l0 0l0)))
(:variant #x00))
#!+long-float
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8alpha.0.7"
+"0.8alpha.0.8"