Fix -sb-unicode
[sbcl.git] / src / code / cross-float.lisp
blob118cdc98fdeb1f4800f9cd4c51b2ef1a27370caa
1 ;;;; portable implementations or stubs for nonportable floating point
2 ;;;; things, useful for building Python as a cross-compiler when
3 ;;;; running under an ordinary ANSI Common Lisp implementation
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
8 ;;;; This software is derived from the CMU CL system, which was
9 ;;;; written at Carnegie Mellon University and released into the
10 ;;;; public domain. The software is in the public domain and is
11 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
12 ;;;; files for more information.
14 (in-package "SB-IMPL")
16 (defun float-sign-bit (float)
17 (declare (type float float))
18 (logand (ash (flonum-bits float)
19 (- (1- (etypecase float
20 (single-float 32)
21 (double-float 64)))))
22 1))
23 (defun float-sign-bit-set-p (float)
24 (declare (type float float))
25 (= (float-sign-bit float) 1))
26 (declaim (inline flonum-minus-zero-p))
27 (defun flonum-minus-zero-p (flonum)
28 (or (eq flonum -0.0f0) (eq flonum -0.0d0)))
30 (defun pick-result-format (&rest args)
31 (flet ((target-num-fmt (num)
32 (cond ((rationalp num) 'rational)
33 ((floatp num) (type-of num))
34 (t (error "What? ~S" num)))))
35 (let* ((result-fmt 'rational)
36 (result-contagion 0))
37 (dolist (arg args result-fmt)
38 (let* ((arg-fmt (target-num-fmt arg))
39 ;; This is inadequate for complex numbers,
40 ;; but we don't need them.
41 (arg-contagion
42 (position arg-fmt
43 '(rational short-float single-float double-float long-float))))
44 (when (cl:> arg-contagion result-contagion)
45 (setq result-fmt arg-fmt result-contagion arg-contagion)))))))
47 (defun pick-float-result-format (&rest args)
48 (let ((format (apply #'pick-result-format args)))
49 (if (eq format 'rational)
50 'single-float
51 format)))
53 (defun rationalize (x)
54 (if (rationalp x)
56 (let ((rational (rational x)))
57 (if (integerp rational)
58 rational
59 (error "Won't do (RATIONALIZE ~S) due to possible precision loss" x)))))
61 (defun xfloat-coerce (object type)
62 (declare (number object))
63 (when (member type '(integer rational real))
64 ;; This branch won't accept (coerce x 'real) if X is one of our
65 ;; target-floats. We don't need that apparently.
66 (assert (if (eq type 'integer) (integerp object) (rationalp object)))
67 (return-from xfloat-coerce object))
68 (unless (member type '(float short-float single-float double-float long-float))
69 (error "Can't COERCE ~S ~S" object type))
70 (when (and (floatp object)
71 (or (eq type 'float) (eq (type-of object) type)))
72 (return-from xfloat-coerce object))
73 (with-memoized-math-op (coerce (list object type))
74 (cond ((not (realp object))
75 (error "Can't COERCE ~S ~S" object type))
76 ((and (flonum-minus-zero-p object)
77 (member type '(double-float single-float)))
78 (ecase type (single-float -0.0f0) (double-float -0.0d0)))
79 ((and (floatp object)
80 (float-infinity-p object))
81 (ecase type
82 (single-float
83 (if (float-sign-bit-set-p object)
84 single-float-negative-infinity
85 single-float-positive-infinity))
86 (double-float
87 (if (float-sign-bit-set-p object)
88 double-float-negative-infinity
89 double-float-positive-infinity))))
91 (let ((actual-type (if (member type '(double-float long-float))
92 'double-float
93 'single-float))
94 (source-value (rational object)))
95 (flonum-from-rational source-value actual-type))))))
97 (defun xfloat-abs (x)
98 (if (float-sign-bit-set-p x)
99 (sb-xc:- x)
102 ;;; Signum should return -0 of the correct type for -0 input.
103 ;;; We don't need it currently.
104 (defun xfloat-signum (x)
105 (if (zerop x)
107 (float-sign x)))
109 (macrolet ((define (name float-fun)
110 (declare (ignore name))
111 `(defun ,float-fun (number divisor)
112 (declare (ignore number divisor))
113 (error "Unimplemented"))))
114 (define mod xfloat-mod)
115 (define rem xfloat-rem))
117 (macrolet ((define (name float-fun)
118 (let ((clname (intern (string name) "CL")))
119 `(defun ,float-fun (number divisor)
120 (let ((type (pick-float-result-format number divisor)))
121 (with-memoized-math-op (,name (list number divisor))
122 (if (flonum-minus-zero-p number)
123 (values 0
124 (coerce (if (< divisor 0) 0 -0.0) type))
125 (multiple-value-bind (q r)
126 (,clname (rational number) (rational divisor))
127 (values q (flonum-from-rational r type))))))))))
128 (define floor xfloat-floor)
129 (define ceiling xfloat-ceiling)
130 (define truncate xfloat-truncate)
131 (define round xfloat-round))
133 (defun sgn (thing)
134 ;; return 1 or -1 if the sign bit of THING (as if converted to
135 ;; FLONUM) is unset or set respectively.
136 (typecase thing
137 ((eql 0) 1)
138 (rational (signum thing))
139 (float (if (float-sign-bit-set-p thing) -1 1))))
141 (macrolet ((define (name clname)
142 `(defun ,name (number &optional (divisor 1 divisorp))
143 (with-memoized-math-op (,name (if divisorp (list number divisor) number))
144 (multiple-value-bind (q r)
145 (,clname (rational number) (rational divisor))
146 (let* ((type (pick-float-result-format number divisor))
147 (format (pick-result-format number divisor))
148 (remainder (if (eql format 'rational)
150 (flonum-from-rational r format))))
151 (if (cl:= q 0)
152 (values (coerce (if (cl:= (sgn number) (sgn divisor)) 0 -0.0)
153 type)
154 remainder)
155 (values (flonum-from-rational q type) remainder))))))))
156 (define fceiling cl:ceiling)
157 (define ffloor cl:floor)
158 (define fround cl:round)
159 (define ftruncate cl:truncate))
161 (defun xfloat-expt (base power)
162 (if (not (integerp power))
163 (error "Unimplemented: EXPT with non-integer power")
164 (with-memoized-math-op (expt (list base power))
165 (if (zerop power)
166 (coerce 1 (type-of base))
167 (flonum-from-rational
168 (cl:expt (rational base) power)
169 (pick-result-format base power))))))
171 ;;; Four possible return values. NIL if the numbers (rationals or
172 ;;; flonums) are incomparable (either is a NaN). Otherwise: -1, 0, 1
173 ;;; if A is less than, equal to or greater than B.
174 (defun numeric-compare (a b)
175 (cond
176 ((or (and (floatp a) (float-nan-p a))
177 (and (floatp b) (float-nan-p b)))
178 nil)
179 ((and (and (floatp a) (float-infinity-p a))
180 (and (floatp b) (float-infinity-p b)))
181 (let ((sa (float-sign-bit a))
182 (sb (float-sign-bit b)))
183 (if (cl:= sa sb)
185 ;; sign bit is 1 if flonum is negative
186 (if (cl:< sa sb) 1 -1))))
187 ((and (floatp a) (float-infinity-p a))
188 (if (cl:= (float-sign-bit a) 1) -1 1))
189 ((and (floatp b) (float-infinity-p b))
190 (if (cl:= (float-sign-bit b) 1) 1 -1))
191 ((eql a b) 0)
192 (t (let ((ra (rational a))
193 (rb (rational b)))
194 (if (cl:= ra rb)
196 (if (cl:< ra rb) -1 1))))))
198 (defmacro define-flonum-comparator (name form)
199 (let ((clname (intern (string name) "CL")))
200 `(defun ,name (&rest args)
201 (if (every #'rationalp args)
202 (apply #',clname args)
203 (with-memoized-math-op (,clname args)
204 (loop for (a b) on args
205 while b
206 always (let ((c (numeric-compare a b)))
207 ,form)))))))
209 (define-flonum-comparator sb-xc:< (eql c -1))
210 (define-flonum-comparator sb-xc:<= (or (eql c -1) (eql c 0)))
211 (define-flonum-comparator sb-xc:= (eql c 0))
212 (define-flonum-comparator sb-xc:>= (or (eql c 0) (eql c 1)))
213 (define-flonum-comparator sb-xc:> (eql c 1))
215 ;;; what should (/= NaN NaN) return? I'm not convinced that we have a
216 ;;; consistent story. On the other hand it looks like we never call
217 ;;; /= in cross-compilation, let alone /= on NaNs.
218 (defun sb-xc:/= (&rest args)
219 (if (every #'rationalp args)
220 (apply #'cl:/= args)
221 (with-memoized-math-op (/= args)
222 (loop for (a . rest) on args
223 always (loop for b in rest
224 for c = (numeric-compare a b)
225 always (cl:/= c 0))))))
227 (defmacro define-flonum-extremizer (name comparator)
228 (let ((clname (intern (string name) "CL")))
229 `(defun ,name (arg &rest rest &aux (args (cons arg rest)))
230 (if (every #'rationalp args)
231 (apply #',clname args)
232 (with-memoized-math-op (,clname args)
233 (let ((ret arg))
234 (dolist (a rest ret)
235 (when (,comparator a ret)
236 (setf ret a)))))))))
238 (define-flonum-extremizer sb-xc:max sb-xc:>)
239 (define-flonum-extremizer sb-xc:min sb-xc:<)
241 (defun wrap-two-arg-fun (fun value)
242 (lambda (&optional (x nil xp) y)
243 (if xp (funcall fun x y) value)))
245 (defun sb-xc:+ (&rest args)
246 (flet ((two-arg-+ (x y)
247 (let ((format (pick-result-format x y)))
248 (cond
249 ((eql format 'rational) (cl:+ x y))
250 ((and (flonum-minus-zero-p x)
251 (flonum-minus-zero-p y))
252 (coerce -0.0 format))
253 (t (flonum-from-rational (cl:+ (rational x) (rational y)) format))))))
254 (if (every #'rationalp args)
255 (apply #'cl:+ args)
256 (with-memoized-math-op (+ args)
257 (reduce (wrap-two-arg-fun #'two-arg-+ 0) args)))))
259 (defun sb-xc:- (arg &rest rest &aux (args (cons arg rest)))
260 (flet ((one-arg-- (x)
261 (etypecase x
262 (rational (cl:- x))
263 (single-float (make-single-float (logxor (ash -1 31) (single-float-bits x))))
264 (double-float (%make-double-float (logxor (ash -1 63) (double-float-bits x))))))
265 (two-arg-- (x y)
266 (let ((format (pick-result-format x y)))
267 (cond
268 ((eql format 'rational) (cl:- x y))
269 ((and (flonum-minus-zero-p x)
270 (and (zerop y) (not (flonum-minus-zero-p y))))
271 (coerce -0.0 format))
272 (t (flonum-from-rational (cl:- (rational x) (rational y)) format))))))
273 (if (every #'rationalp args)
274 (apply #'cl:- args)
275 (with-memoized-math-op (- args)
276 (if (null rest)
277 (one-arg-- arg)
278 (reduce #'two-arg-- args))))))
280 (defun sb-xc:* (&rest args)
281 (flet ((two-arg-* (x y)
282 (let ((format (pick-result-format x y)))
283 (cond
284 ((eql format 'rational) (cl:* x y))
285 ((or (and (floatp x) (float-infinity-p x))
286 (and (floatp y) (float-infinity-p y)))
287 (when (or (zerop x) (zerop y))
288 (error "Can't multiply infinity with 0."))
289 (coerce (if (cl:= (sgn x) (sgn y))
290 single-float-positive-infinity
291 single-float-negative-infinity)
292 format))
293 ((or (flonum-minus-zero-p x)
294 (flonum-minus-zero-p y))
295 (coerce (if (cl:= (sgn x) (sgn y)) 0 -0.0) format))
296 (t (flonum-from-rational (cl:* (rational x) (rational y)) format))))))
297 (if (every #'rationalp args)
298 (apply #'cl:* args)
299 (with-memoized-math-op (* args)
300 (reduce (wrap-two-arg-fun #'two-arg-* 1) args)))))
302 (defun sb-xc:/ (arg &rest rest &aux (args (cons arg rest)))
303 (flet ((one-arg-/ (x)
304 (cond
305 ((rationalp x) (cl:/ x))
306 ((zerop x)
307 (float-sign x single-float-positive-infinity))
308 (t (flonum-from-rational (cl:/ (rational x)) (type-of x)))))
309 (two-arg-/ (x y)
310 (let ((format (pick-result-format x y)))
311 (cond
312 ((eql format 'rational) (cl:/ x y))
313 ((and (zerop x) (zerop y))
314 (error "can't represent NaN for (/ 0 0)"))
315 ((zerop y)
316 (error "can't represent Inf for (/ x 0)"))
317 ((zerop x)
318 (coerce (if (cl:= (sgn x) (sgn y)) 0 -0.0) format))
319 (t (flonum-from-rational (cl:/ (rational x) (rational y)) format))))))
320 (if (every #'rationalp args)
321 (apply #'cl:/ args)
322 (with-memoized-math-op (/ args)
323 (if (null rest)
324 (one-arg-/ arg)
325 (reduce #'two-arg-/ args))))))
327 (defun %sqrt (rational)
328 (flet ((%%sqrt (rational initial)
329 (let ((current initial))
330 ;; why 7? our initial "guess" has at least ~1 bit of
331 ;; precision (for e.g. RATIONAL = 2), and each iteration
332 ;; gives 2n+1 bits, so 7 gives ~127 bits, which should be
333 ;; enough for everybody.
334 (dotimes (i 7 current)
335 (setf current (cl:/ (cl:+ current (cl:/ rational current)) 2))))))
336 (%%sqrt rational (cl:/ (isqrt (numerator rational)) (isqrt (denominator rational))))))
338 (defun sb-xc:sqrt (arg)
339 (let ((format (if (rationalp arg) 'single-float (type-of arg))))
340 (with-memoized-math-op (sqrt arg)
341 (flonum-from-rational (%sqrt (rational arg)) format))))
343 ;;; There seems to be no portable way to mask float traps, so right
344 ;;; now we ignore them and hardcode special cases.
345 (defmacro sb-vm::with-float-traps-masked (traps &body body)
346 (declare (ignore traps))
347 #+nil
348 (format *error-output*
349 "~&(can't portably mask float traps, proceeding anyway)~%")
350 `(progn ,@body))
352 (defun realpart (x) (if (realp x) x (complexnum-real x)))
353 (defun imagpart (x)
354 (cond ((rationalp x) 0)
355 ((single-float-p x) 0f0)
356 ((double-float-p x) 0d0)
357 (t (complexnum-imag x))))
359 (defun sb-vm::sign-extend (x size)
360 (if (logbitp (1- size) x) (cl:dpb x (cl:byte size 0) -1) x))
362 ;;; PI is needed in order to build the cross-compiler mainly so that vm-fndb
363 ;;; can define bounds on irrational functions.
364 (defconstant pi 3.14159265358979323846264338327950288419716939937511L0)
366 (macrolet ((def (name lambda-list)
367 `(defun ,(intern (string name) "SB-XC") ,lambda-list
368 (declare (ignorable ,@lambda-list))
369 (error "Unimplemented."))))
370 (def acos (number))
371 (def acosh (number))
372 (def asin (number))
373 (def asinh (number))
374 (def atanh (number))
375 (def cis (number))
376 (def conjugate (number))
377 (def cos (number))
378 (def exp (number))
379 (def phase (number))
380 (def sin (number))
381 (def sinh (number))
382 (def tan (number))
383 (def tanh (number)))
385 (defun atan (number1 &optional (number2 nil number2p))
386 (if number2p
387 (with-memoized-math-op (atan (list number1 number2))
388 (error "Unimplemented."))
389 (with-memoized-math-op (atan number1)
390 (if (eql number1 1.4916681462400417d-154)
391 number1
392 (error "Unimplemented.")))))
394 (defun cosh (number)
395 (with-memoized-math-op (cosh number)
396 (case number
397 ((0 0f0) 1f0)
398 (0d0 1d0)
399 (t (error "Unimplemented.")))))
401 (defun natural-log (number)
402 (declare (rational number))
403 (flet ((%log (y)
404 (declare (rational y))
405 (assert (<= 1/2 y 1))
406 ;; Use the Taylor series expansion for log((1-y)/(1+y)),
407 ;; which gives around 4*m bits of precision for m terms
408 ;; when 1/2 <= y <= 1.
409 (let* ((x (/ (- y 1) (+ y 1)))
410 (x^2 (* x x))
411 (sum 0))
412 (do ((k 1 (+ k 2))
413 (x^k x (* x^2 x^k)))
414 ;; 40 * 4 = 160 bits of precision.
415 ((>= k 40) (* 2 sum))
416 (incf sum (/ x^k k))))))
417 ;; Write NUMBER as 2^k * a, so that 1/2 < a <= 1. Then log(NUMBER)
418 ;; is log(a) - k * log(1/2).
419 (let* ((k (1+ (- (integer-length (numerator number))
420 (integer-length (denominator number)))))
421 (a (/ number (expt 2 k))))
422 (- (%log a) (* k (%log 1/2))))))
424 (defun log (number &optional (base nil base-p))
425 (validate-args number base)
426 (when (eql number 0)
427 (error 'division-by-zero :operation 'log :operands `(,number ,@(when base-p base))))
428 (with-memoized-math-op (log (if base-p (list number base) number))
429 (let ((format (pick-float-result-format number (if base-p base 0))))
430 (if (zerop number)
431 (coerce single-float-negative-infinity format)
432 (flonum-from-rational (/ (natural-log (rational number))
433 (if base-p
434 (natural-log (rational base))
436 format)))))
438 ;;; Canonicalize and write out the memoization table.
439 (defun dump-math-memoization-table (table stream)
440 (format stream ";;; This file is machine-generated. DO NOT EDIT~2%")
441 (format stream "~%(~%")
442 (labels ((spelling-of (expr)
443 ;; MUST not write package prefixes !
444 ;; e.g. avoid writing a line like (COERCE (-33619991 SB-XC:DOUBLE-FLOAT) ...)
445 (if (stringp expr)
446 (write-to-string expr :pretty nil :escape t)
447 (let ((hex (write-to-string expr :pretty nil :base 16 :radix t :escape nil))
448 (dec (write-to-string expr :pretty nil :base 10 :escape nil)))
449 (if (<= (length hex) (length dec))
451 dec)))))
452 ;; Record each <fun,args> combination to STREAM
453 ;; Though all symbols we print, such as SINGLE-FLOAT, are accessible
454 ;; in any of the SB- packages, ABCL would buggily output package prefixes
455 ;; if ~S is used here.
456 (let ((*print-pretty* nil))
457 (maphash (lambda (key result)
458 (destructuring-bind (fun . args) key
459 (format stream "(~A ~A~{ ~A~})~%"
461 ;; Why do ABS and RATIONAL write the unary arg as an atom
462 ;; but SQRT writes it as a singleton list?
463 (if (listp args)
464 (mapcar #'spelling-of args)
465 (spelling-of args))
466 ;; Can't use ENSURE-LIST. We need NIL -> (NIL)
467 (if (consp result)
468 result
469 (list result)))))
470 table)))
471 (format stream ")~%"))
473 (defun show-interned-numbers (stream)
474 (flet ((to-native (x)
475 (declare (ignorable x))
476 #+host-quirks-sbcl
477 (flet ((realize (r)
478 (if (rationalp r)
480 (etypecase r
481 (single-float
482 (host-sb-kernel:make-single-float (flonum-bits r)))
483 (double-float
484 (host-sb-kernel:make-double-float
485 (double-float-high-bits r)
486 (double-float-low-bits r)))))))
487 (if (complexp x)
488 (cl:complex (realize (complexnum-real x))
489 (realize (complexnum-imag x)))
490 (realize x)))))
491 (let (values)
492 (format stream "~2&; Interned flonums:~%")
493 (dolist (table (list *interned-single-floats*
494 *interned-double-floats*
495 *interned-complex-numbers*))
496 (maphash (lambda (k v)
497 (let ((actual (to-native v)))
498 (format stream "; ~S -> ~S~@[ = ~D~]~%" k v actual)
499 (when actual
500 (when (member actual values)
501 ;; Duplicates means that the host's EQL
502 ;; would not answer correctly for certain inputs.
503 (error "Duplicate float in interned flonum table"))
504 (push actual values))))
505 table)))))
507 ;;; Perform some simple checks
508 (assert (not (eq -0.0f0 -0.0d0)))
509 (assert (not (eq single-float-negative-infinity 0f0)))
510 (dolist (format '(single-float double-float))
511 (assert (zerop (coerce 0 format)))
512 (assert (zerop (coerce -0.0 format)))
513 (assert (float-infinity-p (coerce single-float-positive-infinity format)))
514 (assert (float-infinity-or-nan-p (coerce single-float-positive-infinity format)))
515 (assert (not (float-nan-p (coerce single-float-positive-infinity format))))
516 (assert (float-infinity-p (coerce single-float-negative-infinity format)))
517 (assert (float-infinity-or-nan-p (coerce single-float-negative-infinity format)))
518 (assert (not (float-nan-p (coerce single-float-negative-infinity format))))
519 (assert (eq (coerce -0.0 format) (coerce -0.0 format)))
520 (assert (eq (coerce single-float-positive-infinity format)
521 (coerce single-float-positive-infinity format)))
522 (assert (eq (coerce single-float-negative-infinity format)
523 (coerce single-float-negative-infinity format)))
524 (assert (eq (sb-xc:+ (coerce -0.0 format) (coerce 0 format)) (coerce 0 format)))
525 (assert (eq (sb-xc:+ (coerce 0 format) (coerce -0.0 format)) (coerce 0 format)))
526 (assert (eq (sb-xc:+ (coerce -0.0 format) (coerce -0.0 format)) (coerce -0.0 format)))
527 (assert (eq (sb-xc:- (coerce 0 format)) (coerce -0.0 format)))
528 (assert (eq (sb-xc:- (coerce -0.0 format)) (coerce 0 format)))
529 (assert (eq (coerce single-float-positive-infinity format)
530 (sb-xc:- (coerce single-float-negative-infinity format))))
531 (assert (eq (coerce single-float-negative-infinity format)
532 (sb-xc:- (coerce single-float-positive-infinity format))))
533 (assert (eq (sb-xc:- (coerce 0 format) (coerce 0 format)) (coerce 0 format)))
534 (assert (eq (sb-xc:- (coerce 0 format) (coerce -0.0 format)) (coerce 0 format)))
535 (assert (eq (sb-xc:- (coerce -0.0 format) (coerce 0 format)) (coerce -0.0 format)))
536 (assert (eq (sb-xc:- (coerce -0.0 format) (coerce -0.0 format)) (coerce 0 format)))
537 (assert (eq (sb-xc:* (coerce 0 format) (coerce 0 format)) (coerce 0 format)))
538 (assert (eq (sb-xc:* (coerce -0.0 format) (coerce 0 format)) (coerce -0.0 format)))
539 (assert (eq (sb-xc:* (coerce 0 format) (coerce -0.0 format)) (coerce -0.0 format)))
540 (assert (eq (sb-xc:* (coerce -0.0 format) (coerce -0.0 format)) (coerce 0 format)))
541 (assert (eq (sb-xc:/ (coerce -0.0 format) (coerce -1 format)) (coerce 0 format)))
542 (assert (eq (sb-xc:/ (coerce -0.0 format) (coerce 1 format)) (coerce -0.0 format)))
543 (assert (eq (sb-xc:/ (coerce 0 format) (coerce -1 format)) (coerce -0.0 format)))
544 (assert (eq (sb-xc:/ (coerce 0 format) (coerce 1 format)) (coerce 0 format)))
545 (assert (eq (sb-xc:fceiling -1/2) -0.0f0))
546 (assert (eq (sb-xc:fceiling (coerce -1/2 format)) (coerce -0.0 format)))
547 (assert (eq (sb-xc:ffloor -1/2) (coerce -1 'single-float)))
548 (assert (eq (sb-xc:ffloor (coerce -1/2 format)) (coerce -1 format)))
549 (assert (eq (sb-xc:ftruncate -1/2) -0.0f0))
550 (assert (eq (sb-xc:ftruncate (coerce -1/2 format)) (coerce -0.0 format)))
551 (assert (eq (sb-xc:fround -1/2) -0.0f0))
552 (assert (eq (sb-xc:fround (coerce -1/2 format)) (coerce -0.0 format)))
553 (assert (equal (multiple-value-list (sb-xc:integer-decode-float 1.0f0))
554 '(8388608 -23 1)))
555 (assert (equal (multiple-value-list (sb-xc:integer-decode-float 1.0d0))
556 '(4503599627370496 -52 1)))
557 (let ((*break-on-signals* nil))
558 (flet ((assert-not-number (x)
559 (handler-case (rational x)
560 (:no-error (x) (error "Expected an error, got ~S" x))
561 (simple-error (x) (declare (ignore x))))))
562 (let ((nan (make-single-float #b01111111101000000000000000000000)))
563 ;; [ exp ]
564 (assert-not-number nan)
565 (assert (float-nan-p nan))
566 (assert (float-infinity-or-nan-p nan))
567 (assert (not (float-infinity-p nan))))
568 (assert-not-number single-float-negative-infinity)
569 (assert-not-number single-float-positive-infinity)
570 (assert-not-number double-float-negative-infinity)
571 (assert-not-number double-float-positive-infinity))))