;;; -*- Mode:LISP; Package:SYSTEM-INTERNALS; Lowercase:T; Base:10; Readtable:ZL -*- ;; these two are actually initialized by the cold-load builder (defconstant most-negative-fixnum (%logdpb 1 %%q-boxed-sign-bit 0) "Any integer smaller than this must be a bignum.") (defconstant most-positive-fixnum (%logdpb 0 %%q-boxed-sign-bit -1) "Any integer larger than this must be a bignum.") (defconstant single-float-exponent-offset #o2000) (defconstant single-float-mantissa-length 31.) (defconstant single-float-exponent-length 11.) (defconstant single-float-implicit-sign-bit-p nil) (defconstant short-float-exponent-offset #o200) ;was #o100 in 98. (defconstant short-float-mantissa-length 17.) (defconstant short-float-exponent-length 7) ;was 6 in 98. (defconstant short-float-implicit-sign-bit-p t) (defsubst %short-float-exponent (short-float) "Extracts the 8-bit exponent of short-floats as a fixnum, including the sign bit." (ldb (byte 8. 17.) (%pointer short-float))) ;was (byte 7 17) in 98. (defsubst %single-float-exponent (single-float) "Extracts the 11-bit exponent of single-floats as a fixnum, including the sign bit." (%p-ldb-offset (byte 11. 8.) single-float 0)) (defsubst %short-float-mantissa (short-float) "Extracts the 17-bit mantissa of short-floats as a fixnum, including the implied sign bit." (ldb (byte 17. 0) (%pointer short-float))) (defsubst %single-float-mantissa (single-float) "Extracts the 32-bit mantissa of short-floats as a fixnum, including the sign bit." (dpb (%p-ldb-offset (byte 8. 0) single-float 0) (byte 8. 24.) (dpb (%p-ldb-offset (byte 8. 16.) single-float 1) ;Extra DPB fixes negative (byte 8. 16.) ;fixnum lossages (%p-ldb-offset (byte 16. 0) single-float 1)))) (defsetf %single-float-mantissa (single-float) (value) `(progn (setf (%p-ldb-offset (byte 8. 0) ,single-float 0) (ldb (byte 8. 24.) ,value)) (setf (%p-ldb-offset (byte 24. 0) ,single-float 1) (ldb (byte 24. 0) ,value)) ,value)) ;;; A rational is of type DTP-EXTENDED-NUMBER and occupies three words. ;;; The second word is the numerator, and the third is the denominator. ;;; Rationals with denominator 0 or 1 are never created. ;;; A complex looks like a rational except it contains %HEADER-TYPE-COMPLEX. ;;; The second word is the real part and the third is the imaginary part. ;;; Rational complexes with imaginary part 0 are not created. ;;; The real and imaginary parts of complexes are either both rational or ;;; both flonums of the same type (defsubst %rational-numerator (number) (%p-contents-offset number 1)) (defsubst %rational-denominator (number) (%p-contents-offset number 2)) (defsubst %complex-real-part (number) (%p-contents-offset number 1)) (defsubst %complex-imag-part (number) (%p-contents-offset number 2)) ;; now microcoded ;; Used only in the macro that follows. ;(defconstant complex-header (dpb %header-type-complex %%header-type-field 0)) ;(defsubst %complex-cons (realpart imagpart) ; (let ((object ; (%allocate-and-initialize dtp-extended-number dtp-header ; complex-header ; 0 number-cons-area 3))) ; (setf (%complex-real-part object) realpart) ; (setf (%complex-imag-part object) imagpart) ; object)) ;;; lower-level than complex -- performs no error checks, but does ;;; complex rational (imagpart=0 => real) canonicalization (defsubst %complex (realpart imagpart) (if (eq imagpart 0) realpart (%complex-cons realpart imagpart))) ;; now microcoded ;; Used only in the macro that follows. ;(defconstant ratio-header (dpb %header-type-rational %%header-type-field 0)) ;(defsubst %ratio-cons (numerator denominator) ; "Return a rational number with specified numerator and denominator. ;This can be used to construct rationals not in lowest terms, ;but should not normally be so used." ; (let ((object ; (%allocate-and-initialize dtp-extended-number dtp-header ; ratio-header ; 0 number-cons-area 3))) ; (setf (%rational-numerator object) numerator) ; (setf (%rational-denominator object) denominator) ; object)) ;; now microcoded ;(defsubst complexp (x) ; "T if X is a complex number. ;Note that this may include complex numbers with an imaginary part of 0.0! ;To avoid this problem, use you may wany to use (NOT (REALP X)) instead." ; (and (eq (%data-type x) '#,dtp-extended-number) ; (eq (%p-ldb-offset %%header-type-field x 0) ; %header-type-complex))) (defsubst realp (x) "T if X is a real number, or a complex number with zero imaginary part." (cond ((complexp x) (zerop (%complex-imag-part x))) ((numberp x) t) (t nil))) ;; now microcoded ;(defsubst rationalp (x) ; "T if X is an exact rational number (which includes integers). ;ie either a fixnum or a ratio." ; (or (integerp x) ; (and (eq (%data-type x) '#,dtp-extended-number) ; (memq (%p-ldb-offset %%header-type-field x 0) ; '(#,%header-type-bignum ; #,%header-type-rational)) ; t))) (defsubst bigp (x) "Return T if X is a bignum." (and (integerp x) (not (fixnump x)))) ;;; now microcoded ;(defsubst ratiop (object) ; "T if OBJECT is a ratio -- a rational number which is not an integer." ; (and (= (%data-type object) dtp-extended-number) ; (= (%p-ldb %%header-type-field object) %header-type-rational) ; t)) ;;; single-float-p really... (defsubst flonump (object) "T if OBJECT is a full precision flonum." (and (floatp object) (not (small-floatp object)))) ;;; but is this faster than (+ x (- y y)) ?? (defun %numeric-contage (x y &aux tem) "Coerce the number X to be of a supertype of the types (TYPE-OF X) and (TYPE-OF Y)" (typecase x (rational (typecase y (rational x) (short-float (small-float x)) (float (float x)) (t (typecase (%complex-real-part y) (rational x) ;complex rational canonicalization ; -- should this really be done? (short-float (%complex-cons (coerce x 'short-float) 0.0s0)) (t (%complex-cons (coerce x 'single-float) 0.0f0)))))) (short-float (typecase y ((or rational short-float) x) (float (float x)) (t (typecase (%complex-real-part y) ((or rational short-float) (%complex-cons x 0.0s0)) (t (%complex-cons (coerce x 'single-float) 0.0f0)))))) (float (typecase y ((not complex) x) (t (%complex-cons x 0.0f0)))) (t (setq tem (%numeric-contage (%complex-real-part x) y)) (if (eql tem (%complex-real-part x)) x (typecase tem (short-float (%complex-cons tem (coerce (%complex-imag-part x) 'short-float))) (t (%complex-cons tem (coerce (%complex-imag-part x) 'single-float)))))))) ;;; Does no error checking that NUMBER is a valid number (defsubst zero-of-type (number) "Returns a zero of the same type as NUMBER." (typecase number (rational 0) (short-float 0.0s0) (float 0f0) (t (typecase (%complex-real-part number) (rational 0) (short-float 0.0s0+0.0s0i) (t 0f0+0f0i))))) ;;; returns ANS in stronger type -- should we use %numeric-contage??? (defsubst numeric-contage (ans influencer) "Return a number = ANS and of the weakest type stronger than both ANS and INFLUENCER." (+ ans (- influencer influencer))) (defun float-coerce (ans influencer) "Return a number = ANS and of the same type as INFLUENCER. Both ANS and INFLUENCER are assumed to be of type '(OR FLOAT (COMPLEX FLOAT))" (typecase influencer (short-float (float ans 0s0)) (float (float ans 0f0)) (t (typecase (%complex-real-part influencer) (short-float (typecase ans (short-float (%complex-cons ans 0s0)) (float (%complex-cons (float ans 0s0) 0s0)) (t (typecase (%complex-real-part ans) (short-float ans) (t (%complex-cons (float (%complex-real-part ans) 0s0) (float (%complex-imag-part ans) 0s0))))))) (t (typecase ans (short-float (%complex-cons (float ans 0f0) 0f0)) (float (%complex-cons ans 0f0)) (t (typecase (%complex-real-part ans) (short-float (%complex-cons (float (%complex-real-part ans) 0f0) (float (%complex-imag-part ans) 0f0))) (t ans))))))))) (defun flonum-exponent (float) "Return the exponent of FLONUM to go with (FLONUM-MANTISSA FLONUM). This exponent, if used to scale the integer which FLONUM-MANTISSA returns, will produce the original argument. This is not the same as FLOAT-EXPONENT!" (etypecase float (short-float (- (%short-float-exponent float) short-float-mantissa-length short-float-exponent-offset)) (float (- (%single-float-exponent float) single-float-mantissa-length single-float-exponent-offset)))) (defun flonum-mantissa (float) "Return the mantissa of FLOAT as an integer." (if (zerop float) 0 (etypecase float (short-float (%short-float-mantissa float)) (float (%single-float-mantissa float)))))