1 ;;; -*- Mode: Lisp; Package: C; Log: code.log -*-
3 ;;; **********************************************************************
4 ;;; This code was written as part of the CMU Common Lisp project at
5 ;;; Carnegie Mellon University, and has been placed in the public domain.
8 "$Header: src/compiler/float-tran.lisp $")
10 ;;; **********************************************************************
12 ;;; This file contains floating-point specific transforms, and may be somewhat
13 ;;; implementation dependent in its assumptions of what the formats are.
15 ;;; Author: Rob MacLachlan
18 (intl:textdomain "cmucl")
23 (defknown %single-float (real) single-float (movable foldable flushable))
24 (defknown %double-float (real) double-float (movable foldable flushable))
26 (deftransform float ((n prototype) (* single-float) * :when :both)
29 (deftransform float ((n prototype) (* double-float) * :when :both)
32 (deftransform float ((n) *)
33 `(if (floatp n) n (%single-float n)))
35 (deftransform %single-float ((n) (single-float) * :when :both)
38 (deftransform %double-float ((n) (double-float) * :when :both)
43 (defknown %double-double-float (real)
45 (movable foldable flushable))
47 (deftransform float ((n prototype) (* double-double-float) * :when :both)
48 '(%double-double-float n))
50 (deftransform %double-float ((n) (double-double-float) * :when :both)
51 '(double-double-hi n))
53 (deftransform %single-float ((n) (double-double-float) * :when :both)
54 '(float (double-double-hi n) 1f0))
56 (deftransform %double-double-float ((n) (double-double-float) * :when :both)
60 (defun %double-double-float (n)
61 (make-double-double-float (float n 1d0) 0d0))
63 ;; Moved to code/float.lisp, because we need this relatively early in
64 ;; the build process to handle float and real types.
66 (defun %double-double-float (n)
69 (%make-double-double-float (float n 1d0) 0d0))
71 (%make-double-double-float (float n 1d0) 0d0))
73 (%make-double-double-float (float n 1d0) 0d0))
77 (bignum:bignum-to-float n 'double-double-float))
79 (kernel::float-ratio n 'double-double-float))))
82 (defknown %complex-single-float (number) (complex single-float)
83 (movable foldable flushable))
84 (defknown %complex-double-float (number) (complex double-float)
85 (movable foldable flushable))
86 (defknown %complex-double-double-float (number) (complex double-double-float)
87 (movable foldable flushable))
91 (let ((name (symbolicate "%COMPLEX-" type "-FLOAT"))
92 (convert (symbolicate "%" type "-FLOAT")))
98 (complex (,convert n)))
100 (complex (,convert (realpart n))
101 (,convert (imagpart n))))))
102 (deftransform ,name ((n) ((complex ,(symbolicate type "-FLOAT"))) * :when :both)
107 (frob double-double))
110 (deftransform coerce ((n type) (* *) * :when :both)
111 (unless (constant-continuation-p type)
113 `(the ,(continuation-value type)
114 ,(let ( (tspec (specifier-type (continuation-value type))) )
115 (cond #+double-double
116 ((csubtypep tspec (specifier-type 'double-double-float))
117 '(%double-double-float n))
118 ((csubtypep tspec (specifier-type 'double-float))
120 ((csubtypep tspec (specifier-type 'float))
123 ((csubtypep tspec (specifier-type '(complex double-double-float)))
124 '(%complex-double-double-float n))
125 ((csubtypep tspec (specifier-type '(complex double-float)))
126 '(%complex-double-float n))
127 ((csubtypep tspec (specifier-type '(complex single-float)))
128 '(%complex-single-float n))
132 ;;; Not strictly float functions, but primarily useful on floats:
134 (macrolet ((frob (fun ufun)
136 (defknown ,ufun (real) integer (movable foldable flushable))
137 (deftransform ,fun ((x &optional by)
139 (constant-argument (member 1))))
140 '(let ((res (,ufun x)))
141 (values res (- x res)))))))
142 (frob round %unary-round))
144 (defknown %unary-truncate (real) integer
145 (movable foldable flushable))
147 ;; Convert (truncate x y) to the obvious implementation. We only want
148 ;; this when under certain conditions and let the generic truncate
149 ;; handle the rest. (Note: if y = 1, the divide and multiply by y
150 ;; should be removed by other deftransforms.)
152 (deftransform truncate ((x &optional y)
153 (float &optional (or float integer)))
154 '(let ((res (%unary-truncate (/ x y))))
155 (values res (- x (* y res)))))
157 (deftransform floor ((number &optional divisor)
158 (float &optional (or integer float)))
159 '(multiple-value-bind (tru rem) (truncate number divisor)
160 (if (and (not (zerop rem))
164 (values (1- tru) (+ rem divisor))
167 (deftransform ceiling ((number &optional divisor)
168 (float &optional (or integer float)))
169 '(multiple-value-bind (tru rem) (truncate number divisor)
170 (if (and (not (zerop rem))
174 (values (1+ tru) (- rem divisor))
177 (defknown %unary-ftruncate/single-float (single-float) single-float
178 (movable foldable flushable))
179 (defknown %unary-ftruncate/double-float (double-float) double-float
180 (movable foldable flushable))
182 (defknown %unary-ftruncate (real) float
183 (movable foldable flushable))
185 ;; Convert (ftruncate x y) to the obvious implementation. We only
186 ;; want this under certain conditions and let the generic ftruncate
187 ;; handle the rest. (Note: if y = 1, the divide and multiply by y
188 ;; should be removed by other deftransforms.)
190 (deftransform ftruncate ((x &optional (y 1))
191 (float &optional (or float integer)))
192 '(let ((res (%unary-ftruncate (/ x y))))
193 (values res (- x (* y res)))))
196 (defknown fast-unary-ftruncate ((or single-float double-float))
197 (or single-float double-float)
198 (movable foldable flushable))
201 (defoptimizer (fast-unary-ftruncate derive-type) ((f))
202 (one-arg-derive-type f
204 (ftruncate-derive-type-quot-aux n
205 (specifier-type '(integer 1 1))
209 ;; Convert %unary-ftruncate to unary-ftruncate/{single,double}-float
210 ;; if x is known to be of the right type. Also, if the result is
211 ;; known to fit in the same range as a (signed-byte 32), convert this
212 ;; to %unary-truncate, which might be a single instruction, and float
213 ;; the result. However, for sparc, we have a vop to do this so call
214 ;; that, and for Sparc V9, we can actually handle a 64-bit integer
217 (macrolet ((frob (ftype func)
218 `(deftransform %unary-ftruncate ((x) (,ftype))
219 (let* ((x-type (continuation-type x))
220 (lo (bound-value (numeric-type-low x-type)))
221 (hi (bound-value (numeric-type-high x-type)))
222 (limit-lo (- (ash 1 #-sparc-v9 31 #+sparc-v9 63)))
223 (limit-hi (ash 1 #-sparc-v9 31 #+sparc-v9 63)))
224 (if (and (numberp lo) (numberp hi)
227 #-sparc '(let ((result (coerce (%unary-truncate x) ',ftype)))
231 #+sparc '(let ((result (fast-unary-ftruncate x)))
236 (frob single-float %unary-ftruncate/single-float)
237 (frob double-float %unary-ftruncate/double-float))
242 (deftransform fround ((x &optional (y 1))
243 ((or single-float double-float)
244 &optional (or single-float double-float integer)))
245 '(let ((res (%unary-fround (/ x y))))
246 (values res (- x (* y res)))))
248 (defknown %unary-fround (real) float
249 (movable foldable flushable))
251 (defknown %unary-fround/single-float (single-float) single-float
252 (movable foldable flushable))
254 (defknown %unary-fround/double-float (double-float) double-float
255 (movable foldable flushable))
257 (deftransform %unary-fround ((x) (single-float))
258 '(%unary-fround/single-float x))
260 (deftransform %unary-fround ((x) (double-float))
261 '(%unary-fround/double-float x))
267 (macrolet ((frob (fun type)
268 `(deftransform random ((num &optional state)
269 (,type &optional *) *
271 "use inline float operations"
272 '(,fun num (or state *random-state*)))))
273 (frob %random-single-float single-float)
274 (frob %random-double-float double-float))
276 #-(or new-random random-mt19937)
277 (deftransform random ((num &optional state)
278 ((integer 1 #.random-fixnum-max) &optional *))
279 _N"use inline fixnum operations"
280 '(rem (random-chunk (or state *random-state*)) num))
282 ;;; With the latest propagate-float-type code the compiler can inline
283 ;;; truncate (signed-byte 32) allowing 31 bits, and (unsigned-byte 32)
284 ;;; 32 bits on the x86. When not using the propagate-float-type
285 ;;; feature the best size that can be inlined is 29 bits. The choice
286 ;;; shouldn't cause bootstrap problems just slow code.
288 (deftransform random ((num &optional state)
294 #+x86 (intl:gettext "use inline (unsigned-byte 32) operations")
295 #-x86 (intl:gettext "use inline (signed-byte 32) operations")
296 '(values (truncate (%random-double-float (coerce num 'double-float)
297 (or state *random-state*)))))
300 (deftransform random ((num &optional state)
301 ((integer 1 #.(expt 2 32)) &optional *))
302 _N"use inline (unsigned-byte 32) operations"
303 (let* ((num-type (continuation-type num))
304 (num-high (cond ((numeric-type-p num-type)
305 (numeric-type-high num-type))
306 ((union-type-p num-type)
307 ;; Find the maximum of the union type. We
308 ;; know this works because if we're in this
309 ;; routine, NUM must be a subtype of
310 ;; (INTEGER 1 2^32), so each member of the
311 ;; union must be a subtype too.
312 (reduce #'max (union-type-types num-type)
313 :key #'numeric-type-high))
316 ;; Rather than doing (rem (random-chunk) num-high), we do,
317 ;; essentially, (rem (* num-high (random-chunk)) #x100000000). I
318 ;; (rtoy) believe this approach doesn't have the bias issue with
319 ;; doing rem. This method works by treating (random-chunk) as if
320 ;; it were a 32-bit fraction between 0 and 1, exclusive. Multiply
321 ;; this by num-high to get a random number between 0 and num-high,
322 ;; This should have no bias.
323 (cond ((constant-continuation-p num)
324 (if (= num-high (expt 2 32))
325 '(random-chunk (or state *random-state*))
326 '(values (bignum::%multiply
327 (random-chunk (or state *random-state*))
329 ((< num-high (expt 2 32))
330 '(values (bignum::%multiply (random-chunk (or state *random-state*))
332 ((= num-high (expt 2 32))
333 '(if (= num (expt 2 32))
334 (random-chunk (or state *random-state*))
335 (values (bignum::%multiply (random-chunk (or state *random-state*))
338 (error (intl:gettext "Shouldn't happen"))))))
341 ;;;; Float accessors:
343 (defknown make-single-float ((signed-byte 32)) single-float
344 (movable foldable flushable))
346 (defknown make-double-float ((signed-byte 32) (unsigned-byte 32)) double-float
347 (movable foldable flushable))
349 (defknown single-float-bits (single-float) (signed-byte 32)
350 (movable foldable flushable))
352 (defknown double-float-high-bits (double-float) (signed-byte 32)
353 (movable foldable flushable))
355 (defknown double-float-low-bits (double-float) (unsigned-byte 32)
356 (movable foldable flushable))
359 (defknown double-float-bits (double-float)
360 (values (signed-byte 32) (unsigned-byte 32))
361 (movable foldable flushable))
365 (defknown double-double-float-p (t)
367 (movable foldable flushable))
369 (defknown %make-double-double-float (double-float double-float)
371 (movable foldable flushable))
374 (defknown double-double-hi (double-double-float)
376 (movable foldable flushable))
378 (defknown double-double-lo (double-double-float)
380 (movable foldable flushable))
384 (deftransform float-sign ((float &optional float2)
385 (single-float &optional single-float) *)
387 (let ((temp (gensym)))
388 `(let ((,temp (abs float2)))
389 (if (minusp (single-float-bits float)) (- ,temp) ,temp)))
390 '(if (minusp (single-float-bits float)) -1f0 1f0)))
392 (deftransform float-sign ((float &optional float2)
393 (double-float &optional double-float) *)
395 (let ((temp (gensym)))
396 `(let ((,temp (abs float2)))
397 (if (minusp (double-float-high-bits float)) (- ,temp) ,temp)))
398 '(if (minusp (double-float-high-bits float)) -1d0 1d0)))
401 (deftransform float-sign ((float &optional float2)
402 (double-double-float &optional double-double-float) *)
404 (let ((temp (gensym)))
405 `(let ((,temp (abs float2)))
406 (if (minusp (float-sign (double-double-hi float)))
409 '(if (minusp (float-sign (double-double-hi float))) -1w0 1w0)))
413 ;;;; DECODE-FLOAT, INTEGER-DECODE-FLOAT, SCALE-FLOAT:
415 ;;; Convert these operations to format specific versions when the format is
419 (deftype single-float-exponent ()
420 `(integer ,(- vm:single-float-normal-exponent-min vm:single-float-bias
421 vm:single-float-digits)
422 ,(- vm:single-float-normal-exponent-max vm:single-float-bias)))
424 (deftype double-float-exponent ()
425 `(integer ,(- vm:double-float-normal-exponent-min vm:double-float-bias
426 vm:double-float-digits)
427 ,(- vm:double-float-normal-exponent-max vm:double-float-bias)))
430 (deftype single-float-int-exponent ()
431 `(integer ,(- vm:single-float-normal-exponent-min vm:single-float-bias
432 (* vm:single-float-digits 2))
433 ,(- vm:single-float-normal-exponent-max vm:single-float-bias
434 vm:single-float-digits)))
436 (deftype double-float-int-exponent ()
437 `(integer ,(- vm:double-float-normal-exponent-min vm:double-float-bias
438 (* vm:double-float-digits 2))
439 ,(- vm:double-float-normal-exponent-max vm:double-float-bias
440 vm:double-float-digits)))
442 (deftype single-float-significand ()
443 `(integer 0 (,(ash 1 vm:single-float-digits))))
445 (deftype double-float-significand ()
446 `(integer 0 (,(ash 1 vm:double-float-digits))))
448 (defknown decode-single-float (single-float)
449 (values (single-float 0.5f0 (1f0))
450 single-float-exponent
452 (movable foldable flushable))
454 (defknown decode-double-float (double-float)
455 (values (double-float 0.5d0 (1d0))
456 double-float-exponent
458 (movable foldable flushable))
460 (defknown integer-decode-single-float (single-float)
461 (values single-float-significand single-float-int-exponent (integer -1 1))
462 (movable foldable flushable))
464 (defknown integer-decode-double-float (double-float)
465 (values double-float-significand double-float-int-exponent (integer -1 1))
466 (movable foldable flushable))
468 (defknown scale-single-float (single-float fixnum) single-float
469 (movable foldable flushable))
471 (defknown scale-double-float (double-float fixnum) double-float
472 (movable foldable flushable))
474 (deftransform decode-float ((x) (single-float) * :when :both)
475 '(decode-single-float x))
477 (deftransform decode-float ((x) (double-float) * :when :both)
478 '(decode-double-float x))
480 (deftransform integer-decode-float ((x) (single-float) * :when :both)
481 '(integer-decode-single-float x))
483 (deftransform integer-decode-float ((x) (double-float) * :when :both)
484 '(integer-decode-double-float x))
486 (deftransform scale-float ((f ex) (single-float *) * :when :both)
487 (if (and (backend-featurep :x86)
488 (not (backend-featurep :sse2))
489 (csubtypep (continuation-type ex)
490 (specifier-type '(signed-byte 32)))
491 (not (byte-compiling)))
492 '(coerce (%scalbn (coerce f 'double-float) ex) 'single-float)
493 '(scale-single-float f ex)))
495 (deftransform scale-float ((f ex) (double-float *) * :when :both)
496 (if (and (backend-featurep :x86)
497 (not (backend-featurep :sse2))
498 (csubtypep (continuation-type ex)
499 (specifier-type '(signed-byte 32))))
501 '(scale-double-float f ex)))
503 ;;; toy@rtp.ericsson.se:
505 ;;; Optimizers for scale-float. If the float has bounds, new bounds
506 ;;; are computed for the result, if possible.
508 (defun scale-float-derive-type-aux (f ex same-arg)
509 (declare (ignore same-arg))
510 (flet ((scale-bound (x n)
511 ;; We need to be a bit careful here and catch any overflows
512 ;; that might occur. We can ignore underflows which become
515 (let ((value (handler-case
516 (scale-float (bound-value x) n)
517 (floating-point-overflow ()
519 ;; This check is necessary for ppc because the current
520 ;; implementation on ppc doesn't signal floating-point
521 ;; overflow. (How many other places do we need to check
523 (if (and (floatp value) (float-infinity-p value))
527 (when (and (numeric-type-p f) (numeric-type-p ex))
528 (let ((f-lo (numeric-type-low f))
529 (f-hi (numeric-type-high f))
530 (ex-lo (numeric-type-low ex))
531 (ex-hi (numeric-type-high ex))
534 (when (and f-hi ex-hi)
535 (setf new-hi (scale-bound f-hi ex-hi)))
536 (when (and f-lo ex-lo)
537 (setf new-lo (scale-bound f-lo ex-lo)))
538 ;; We're computing bounds for scale-float. Assume the bounds
539 ;; on f are fl and fh, and the bounds on ex are nl and nh.
540 ;; The resulting bound should be fl*2^nl and fh*2^nh.
541 ;; However, if fh is negative, and we get an underflow, we
542 ;; might get bounds like 0 and fh*2^nh < 0. Our bounds are
543 ;; backwards. Thus, swap the bounds to get the correct
545 (when (and new-lo new-hi (< (bound-value new-hi)
546 (bound-value new-lo)))
547 (rotatef new-lo new-hi))
548 (make-numeric-type :class (numeric-type-class f)
549 :format (numeric-type-format f)
554 (defoptimizer (scale-float derive-type) ((f ex))
555 (two-arg-derive-type f ex #'scale-float-derive-type-aux
558 ;;; toy@rtp.ericsson.se:
560 ;;; Defoptimizers for %single-float and %double-float. This makes the
561 ;;; FLOAT function return the correct ranges if the input has some
562 ;;; defined range. Quite useful if we want to convert some type of
563 ;;; bounded integer into a float.
567 (let ((aux-name (symbolicate fun "-DERIVE-TYPE-AUX")))
569 (defun ,aux-name (num)
570 ;; When converting a number to a float, the limits are
572 (let* ((lo (bound-func #'(lambda (x)
573 ;; If we can't coerce it, we
574 ;; return a NIL for the bound.
575 ;; (Is IGNORE-ERRORS too
576 ;; heavy-handed? Should we
577 ;; try to do something more
579 (ignore-errors (coerce x ',type)))
580 (numeric-type-low num)))
581 (hi (bound-func #'(lambda (x)
582 (ignore-errors (coerce x ',type)))
583 (numeric-type-high num))))
584 (specifier-type `(,',type ,(or lo '*) ,(or hi '*)))))
586 (defoptimizer (,fun derive-type) ((num))
587 (one-arg-derive-type num #',aux-name #',fun))))))
588 (frob %single-float single-float)
589 (frob %double-float double-float))
592 ;;;; Float contagion:
594 ;;; FLOAT-CONTAGION-ARG1, ARG2 -- Internal
596 ;;; Do some stuff to recognize when the loser is doing mixed float and
597 ;;; rational arithmetic, or different float types, and fix it up. If we don't,
598 ;;; he won't even get so much as an efficency note.
600 (deftransform float-contagion-arg1 ((x y) * * :defun-only t :node node)
601 `(,(continuation-function-name (basic-combination-fun node))
604 (deftransform float-contagion-arg2 ((x y) * * :defun-only t :node node)
605 `(,(continuation-function-name (basic-combination-fun node))
608 (dolist (x '(+ * / -))
609 (%deftransform x '(function (rational float) *) #'float-contagion-arg1)
610 (%deftransform x '(function (float rational) *) #'float-contagion-arg2))
612 (dolist (x '(= < > + * / -))
613 (%deftransform x '(function (single-float double-float) *)
614 #'float-contagion-arg1)
615 (%deftransform x '(function (double-float single-float) *)
616 #'float-contagion-arg2))
619 ;;; Prevent zerop, plusp, minusp from losing horribly. We can't in general
620 ;;; float rational args to comparison, since Common Lisp semantics says we are
621 ;;; supposed to compare as rationals, but we can do it for any rational that
622 ;;; has a precise representation as a float (such as 0).
624 (macrolet ((frob (op)
625 `(deftransform ,op ((x y) (float rational) * :when :both)
626 (unless (constant-continuation-p y)
627 (give-up (intl:gettext "Can't open-code float to rational comparison.")))
628 (let ((val (continuation-value y)))
629 (unless (eql (rational (float val)) val)
630 (give-up (intl:gettext "~S doesn't have a precise float representation.")
632 `(,',op x (float y x)))))
638 ;;;; Irrational transforms:
640 (defknown (%tan %sinh %asinh %atanh %log %logb %log10 #+x87 %tan-quick)
641 (double-float) double-float
642 (movable foldable flushable))
644 (defknown (%sin %cos %tanh #+x87 %sin-quick #+x87 %cos-quick)
645 (double-float) (double-float -1.0d0 1.0d0)
646 (movable foldable flushable))
648 (defknown (%asin %atan)
649 (double-float) (double-float #.(- (/ pi 2)) #.(/ pi 2))
650 (movable foldable flushable))
653 (double-float) (double-float 0.0d0 #.pi)
654 (movable foldable flushable))
657 (double-float) (double-float 1.0d0)
658 (movable foldable flushable))
660 (defknown (%acosh %exp %sqrt)
661 (double-float) (double-float 0.0d0)
662 (movable foldable flushable))
665 (double-float) (double-float -1d0)
666 (movable foldable flushable))
669 (double-float double-float) (double-float 0d0)
670 (movable foldable flushable))
673 (double-float double-float) double-float
674 (movable foldable flushable))
677 (double-float double-float) (double-float #.(- pi) #.pi)
678 (movable foldable flushable))
681 (double-float double-float) double-float
682 (movable foldable flushable))
685 (double-float (signed-byte 32)) double-float
686 (movable foldable flushable))
689 (double-float) double-float
690 (movable foldable flushable))
692 (dolist (stuff '((exp %exp *)
703 (atanh %atanh float)))
704 (destructuring-bind (name prim rtype) stuff
705 (deftransform name ((x) '(single-float) rtype :eval-name t)
706 `(coerce (,prim (coerce x 'double-float)) 'single-float))
707 (deftransform name ((x) '(double-float) rtype :eval-name t :when :both)
710 ;;; The argument range is limited on the x86 FP trig. functions. A
711 ;;; post-test can detect a failure (and load a suitable result), but
712 ;;; this test is avoided if possible.
714 ;;; Simple tests show that sin/cos produce numbers greater than 1 when
715 ;;; the arg >= 2^63. tan produces floating-point invalid exceptions
716 ;;; for arg >= 2^62. So limit these to that range.
718 (dolist (stuff '((sin %sin %sin-quick 63)
719 (cos %cos %cos-quick 63)
720 (tan %tan %tan-quick 62)))
721 (destructuring-bind (name prim prim-quick limit)
723 (deftransform name ((x) '(single-float) '* :eval-name t)
724 (if (and (backend-featurep :x86)
725 (not (backend-featurep :sse2)))
726 (cond ((csubtypep (continuation-type x)
727 (specifier-type `(single-float
728 (,(- (expt 2f0 limit)))
729 (,(expt 2f0 limit)))))
730 `(coerce (,prim-quick (coerce x 'double-float))
734 _N"Unable to avoid inline argument range check~@
735 because the argument range (~s) was not within 2^~D"
736 (type-specifier (continuation-type x))
738 `(coerce (,prim (coerce x 'double-float)) 'single-float)))
739 `(coerce (,prim (coerce x 'double-float)) 'single-float)))
740 (deftransform name ((x) '(double-float) '* :eval-name t :when :both)
741 (if (and (backend-featurep :x86)
742 (not (backend-featurep :sse2)))
743 (cond ((csubtypep (continuation-type x)
744 (specifier-type `(double-float
745 (,(- (expt 2d0 limit)))
746 (,(expt 2d0 limit)))))
750 _N"Unable to avoid inline argument range check~@
751 because the argument range (~s) was not within 2^~D"
752 (type-specifier (continuation-type x))
757 (deftransform atan ((x y) (single-float single-float) *)
758 `(coerce (%atan2 (coerce x 'double-float) (coerce y 'double-float))
760 (deftransform atan ((x y) (double-float double-float) * :when :both)
763 (deftransform expt ((x y) ((single-float 0f0) single-float) *)
764 `(coerce (%pow (coerce x 'double-float) (coerce y 'double-float))
766 (deftransform expt ((x y) ((double-float 0d0) double-float) * :when :both)
768 (deftransform expt ((x y) ((single-float 0f0) (signed-byte 32)) *)
769 `(coerce (%pow (coerce x 'double-float) (coerce y 'double-float))
771 (deftransform expt ((x y) ((double-float 0d0) (signed-byte 32)) * :when :both)
772 `(%pow x (coerce y 'double-float)))
774 ;;; ANSI says log with base zero returns zero.
775 (deftransform log ((x y) (float float) float)
776 '(if (zerop y) y (/ (log x) (log y))))
779 ;;; Handle some simple transformations
781 (deftransform abs ((x) ((complex double-float)) double-float :when :both)
782 '(%hypot (realpart x) (imagpart x)))
784 (deftransform abs ((x) ((complex single-float)) single-float)
785 '(coerce (%hypot (coerce (realpart x) 'double-float)
786 (coerce (imagpart x) 'double-float))
789 (deftransform abs ((x) (real) real)
790 (let ((x-type (continuation-type x)))
791 ;; If the arg is known to non-negative, we can just return the
792 ;; arg. However, (abs -0.0) is 0.0, so this transform only works
793 ;; on floats that are known not to include negative zero.
794 (if (csubtypep x-type (specifier-type '(or (rational 0) (float (0d0)) (member 0f0 0d0))))
798 (deftransform phase ((x) ((complex double-float)) double-float :when :both)
799 '(%atan2 (imagpart x) (realpart x)))
801 (deftransform phase ((x) ((complex single-float)) single-float)
802 '(coerce (%atan2 (coerce (imagpart x) 'double-float)
803 (coerce (realpart x) 'double-float))
806 (deftransform phase ((x) ((float)) float :when :both)
807 '(if (minusp (float-sign x))
811 ;;; The number is of type REAL.
812 (declaim (inline numeric-type-real-p))
813 (defun numeric-type-real-p (type)
814 (and (numeric-type-p type)
815 (eq (numeric-type-complexp type) :real)))
817 ;;; Coerce a numeric type bound to the given type while handling
818 ;;; exclusive bounds.
819 (defun coerce-numeric-bound (bound type)
822 (list (coerce (car bound) type))
823 (coerce bound type))))
826 ;;;; Optimizers for elementary functions
828 ;;;; These optimizers compute the output range of the elementary
829 ;;;; function, based on the domain of the input.
832 ;;; Generate a specifier for a complex type specialized to the same
833 ;;; type as the argument.
834 (defun complex-float-type (arg)
835 (declare (type numeric-type arg))
836 (let* ((format (case (numeric-type-class arg)
837 ((integer rational) 'single-float)
838 (t (numeric-type-format arg))))
839 (float-type (or format 'float)))
840 (specifier-type `(complex ,float-type))))
842 ;;; Compute a specifier like '(or float (complex float)), except float
843 ;;; should be the right kind of float. Allow bounds for the float
845 (defun float-or-complex-float-type (arg &optional lo hi)
846 (declare (type numeric-type arg))
847 (let* ((format (case (numeric-type-class arg)
848 ((integer rational) 'single-float)
849 (t (numeric-type-format arg))))
850 (float-type (or format 'float))
851 (lo (coerce-numeric-bound lo float-type))
852 (hi (coerce-numeric-bound hi float-type)))
853 (specifier-type `(or (,float-type ,(or lo '*) ,(or hi '*))
854 (complex ,float-type)))))
858 ;;; Test if the numeric-type ARG is within in domain specified by
859 ;;; DOMAIN-LOW and DOMAIN-HIGH, consider negative and positive zero to
860 ;;; be distinct as for the :negative-zero-is-not-zero feature. Note
861 ;;; that only inclusive and open domain limits are handled as these
862 ;;; are the only types of limits currently used. With the
863 ;;; :negative-zero-is-not-zero feature this could be handled by the
864 ;;; numeric subtype code in type.lisp.
866 (defun domain-subtypep (arg domain-low domain-high)
867 (declare (type numeric-type arg)
868 (type (or real null) domain-low domain-high))
869 (let* ((arg-lo (numeric-type-low arg))
870 (arg-lo-val (bound-value arg-lo))
871 (arg-hi (numeric-type-high arg))
872 (arg-hi-val (bound-value arg-hi)))
873 ;; Check that the ARG bounds are correctly canonicalised.
874 (when (and arg-lo (floatp arg-lo-val) (zerop arg-lo-val) (consp arg-lo)
875 (minusp (float-sign arg-lo-val)))
876 (compiler-note _N"Float zero bound ~s not correctly canonicalised?" arg-lo)
877 (setq arg-lo 0l0 arg-lo-val 0l0))
878 (when (and arg-hi (zerop arg-hi-val) (floatp arg-hi-val) (consp arg-hi)
879 (plusp (float-sign arg-hi-val)))
880 (compiler-note _N"Float zero bound ~s not correctly canonicalised?" arg-hi)
881 (setq arg-hi -0l0 arg-hi-val -0l0))
882 (flet ((fp-neg-zero-p (f) ; Is F -0.0?
883 (and (floatp f) (zerop f) (minusp (float-sign f))))
884 (fp-pos-zero-p (f) ; Is F +0.0?
885 (and (floatp f) (zerop f) (plusp (float-sign f)))))
886 (and (or (null domain-low)
887 (and arg-lo (>= arg-lo-val domain-low)
888 (not (and (fp-pos-zero-p domain-low)
889 (fp-neg-zero-p arg-lo)))))
890 (or (null domain-high)
891 (and arg-hi (<= arg-hi-val domain-high)
892 (not (and (fp-neg-zero-p domain-high)
893 (fp-pos-zero-p arg-hi)))))))))
895 ;;; Elfun-Derive-Type-Simple
897 ;;; Handle monotonic functions of a single variable whose domain is
898 ;;; possibly part of the real line. ARG is the variable, FCN is the
899 ;;; function, and DOMAIN is a specifier that gives the (real) domain
900 ;;; of the function. If ARG is a subset of the DOMAIN, we compute the
901 ;;; bounds directly. Otherwise, we compute the bounds for the
902 ;;; intersection between ARG and DOMAIN, and then append a complex
903 ;;; result, which occurs for the parts of ARG not in the DOMAIN.
905 ;;; Negative and positive zero are considered distinct within
906 ;;; DOMAIN-LOW and DOMAIN-HIGH, as for the :negative-zero-is-not-zero
909 ;;; DEFAULT-LOW and DEFAULT-HIGH are the lower and upper bounds if we
910 ;;; can't compute the bounds using FCN.
912 (defun elfun-derive-type-simple (arg fcn domain-low domain-high
913 default-low default-high
914 &optional (increasingp t))
915 (declare (type (or null real) domain-low domain-high))
918 (cond ((eq (numeric-type-complexp arg) :complex)
919 (complex-float-type arg))
920 ((numeric-type-real-p arg)
921 ;; The argument is real, so let's find the intersection
922 ;; between the argument and the domain of the function.
923 ;; We compute the bounds on the intersection, and for
924 ;; everything else, we return a complex number of the
926 (multiple-value-bind (intersection difference)
927 (interval-intersection/difference
928 (numeric-type->interval arg)
929 (make-interval :low domain-low :high domain-high))
932 ;; Process the intersection.
933 (let* ((low (interval-low intersection))
934 (high (interval-high intersection))
935 (res-lo (or (bound-func fcn (if increasingp low high))
937 (res-hi (or (bound-func fcn (if increasingp high low))
939 ;; Result specifier type.
940 (format (case (numeric-type-class arg)
941 ((integer rational) 'single-float)
942 (t (numeric-type-format arg))))
943 (bound-type (or format 'float))
948 :low (coerce-numeric-bound res-lo bound-type)
949 :high (coerce-numeric-bound res-hi bound-type))))
950 ;; If the ARG is a subset of the domain, we don't
951 ;; have to worry about the difference, because that
953 (if (or (null difference)
954 ;; Check if the arg is within the domain.
955 (domain-subtypep arg domain-low domain-high))
958 (specifier-type `(complex ,bound-type))))))
960 ;; No intersection so the result must be purely complex.
961 (complex-float-type arg)))))
963 (float-or-complex-float-type arg default-low default-high))))))
966 ((frob (name domain-low domain-high def-low-bnd def-high-bnd
967 &key (increasingp t))
968 (let ((num (gensym)))
969 `(defoptimizer (,name derive-type) ((,num))
973 (elfun-derive-type-simple arg #',name
974 ,domain-low ,domain-high
975 ,def-low-bnd ,def-high-bnd
978 ;; These functions are easy because they are defined for the whole
980 (frob exp nil nil 0 nil)
981 (frob sinh nil nil nil nil)
982 (frob tanh nil nil -1 1)
983 (frob asinh nil nil nil nil)
985 ;; These functions are only defined for part of the real line. The
986 ;; condition selects the desired part of the line.
987 (frob asin -1d0 1d0 (- (/ pi 2)) (/ pi 2))
988 ;; Acos is monotonic decreasing, so we need to swap the function
989 ;; values at the lower and upper bounds of the input domain.
990 (frob acos -1d0 1d0 0 pi :increasingp nil)
991 (frob acosh 1d0 nil nil nil)
992 (frob atanh -1d0 1d0 -1 1)
993 ;; Kahan says that (sqrt -0.0) is -0.0, so use a specifier that
995 (frob sqrt -0d0 nil 0 nil))
997 ;;; Compute bounds for (expt x y). This should be easy since (expt x
998 ;;; y) = (exp (* y (log x))). However, computations done this way
999 ;;; have too much roundoff. Thus we have to do it the hard way.
1001 (defun safe-expt (x y)
1007 ;;; Handle the case when x >= 1
1008 (defun interval-expt-> (x y)
1009 (case (c::interval-range-info y 0d0)
1011 ;; Y is positive and log X >= 0. The range of exp(y * log(x)) is
1012 ;; obviously non-negative. We just have to be careful for
1013 ;; infinite bounds (given by nil).
1014 (let ((lo (safe-expt (c::bound-value (c::interval-low x))
1015 (c::bound-value (c::interval-low y))))
1016 (hi (safe-expt (c::bound-value (c::interval-high x))
1017 (c::bound-value (c::interval-high y)))))
1018 (list (c::make-interval :low (or lo 1) :high hi))))
1020 ;; Y is negative and log x >= 0. The range of exp(y * log(x)) is
1021 ;; obviously [0, 1]. However, underflow (nil) means 0 is the
1023 (let ((lo (safe-expt (c::bound-value (c::interval-high x))
1024 (c::bound-value (c::interval-low y))))
1025 (hi (safe-expt (c::bound-value (c::interval-low x))
1026 (c::bound-value (c::interval-high y)))))
1027 (list (c::make-interval :low (or lo 0) :high (or hi 1)))))
1029 ;; Split the interval in half
1030 (destructuring-bind (y- y+)
1031 (c::interval-split 0 y t)
1032 (list (interval-expt-> x y-)
1033 (interval-expt-> x y+))))))
1035 ;;; Handle the case when x < 0, and when y is known to be an integer.
1036 ;;; In this case, we can do something useful because the x^y is still
1037 ;;; a real number if x and y are.
1038 (defun interval-expt-<-0 (x y)
1041 (format t "x = ~A~%" x)
1042 (format t "range-info y (~A) = ~A~%" y (interval-range-info y)))
1043 (flet ((handle-positive-power-0 (x y)
1044 ;; -1 <= X <= 0 and Y is positive. We need to consider if
1045 ;; Y contains an odd integer or not. Find the smallest
1046 ;; even and odd integer (if possible) contained in Y.
1047 (let* ((y-lo (bound-value (interval-low y)))
1048 (min-odd (if (oddp y-lo)
1050 (let ((y-odd (1+ y-lo)))
1051 (if (interval-contains-p y-odd y)
1054 (min-even (if (evenp y-lo)
1056 (let ((y-even (1+ y-lo)))
1057 (if (interval-contains-p y-even y)
1060 (cond ((and min-odd min-even)
1061 ;; The Y interval contains both even and odd
1062 ;; integers. Then the lower bound is (least
1063 ;; x)^(least positive odd), because this
1064 ;; creates the most negative value. The upper
1065 ;; is (most x)^(least positive even), because
1066 ;; this is the most positive number.
1068 ;; (Recall that if |x|<1, |x|^y gets smaller as y
1070 (let ((lo (safe-expt (bound-value (interval-low x))
1072 (hi (safe-expt (bound-value (interval-high x))
1074 (list (make-interval :low lo :high hi))))
1076 ;; Y consists of just one odd integer.
1077 (assert (oddp min-odd))
1078 (let ((lo (safe-expt (bound-value (interval-low x))
1080 (hi (safe-expt (bound-value (interval-high x))
1082 (list (make-interval :low lo :high hi))))
1084 ;; Y consists of just one even integer.
1085 (assert (evenp min-even))
1086 (let ((lo (safe-expt (bound-value (interval-high x))
1088 (hi (safe-expt (bound-value (interval-low x))
1090 (list (make-interval :low lo :high hi))))
1092 ;; No mininum even or odd integer, so Y has no
1094 (list (make-interval :low nil :high nil))))))
1095 (handle-positive-power-1 (x y)
1096 ;; X <= -1, Y is a positive integer. Find the largest even
1097 ;; and odd integer contained in Y, if possible.
1098 (let* ((y-hi (bound-value (interval-high y)))
1102 (let ((y-odd (1- y-hi)))
1103 (if (interval-contains-p y-odd y)
1110 (let ((y-even (1- y-hi)))
1111 (if (interval-contains-p y-even y)
1115 ;; At least one of max-odd and max-even must be non-NIL!
1116 (cond ((and max-odd max-even)
1117 ;; The Y interval contains both even and odd
1118 ;; integers. Then the lower bound is (least
1119 ;; x)^(most positive odd), because this
1120 ;; creates the most negative value. The upper
1121 ;; is (least x)^(most positive even), because
1122 ;; this is the most positive number.
1124 (let ((lo (safe-expt (bound-value (interval-low x))
1126 (hi (safe-expt (bound-value (interval-low x))
1128 (list (make-interval :low lo :high hi))))
1130 ;; Y consists of just one odd integer.
1131 (assert (oddp max-odd))
1132 (let ((lo (safe-expt (bound-value (interval-low x))
1134 (hi (safe-expt (bound-value (interval-high x))
1136 (list (make-interval :low lo :high hi))))
1138 ;; Y consists of just one even integer.
1139 (assert (evenp max-even))
1140 (let ((lo (safe-expt (bound-value (interval-high x))
1142 (hi (safe-expt (bound-value (interval-low x))
1144 (list (make-interval :low lo :high hi))))
1146 ;; No maximum even or odd integer, which means y
1147 ;; is no upper bound.
1148 (list (make-interval :low nil :high nil)))))))
1149 ;; We need to split into x < -1 and -1 <= x <= 0, first.
1150 (case (interval-range-info x -1)
1154 (format t "x range +~%")
1155 (case (interval-range-info y 0)
1157 (handle-positive-power-0 x y))
1159 ;; Y is negative. We should do something better
1160 ;; than this because there's an extra rounding which
1163 (format t "Handle y neg~%")
1164 (let ((unit (make-interval :low 1 :high 1))
1165 (result (handle-positive-power-0 x (interval-neg y))))
1167 (format t "result = ~A~%" result)
1168 (mapcar #'(lambda (r)
1169 (interval-div unit r))
1172 ;; Split the interval and try again. Since we know y is an
1173 ;; integer, we don't need interval-split. Also we want to
1174 ;; handle an exponent of 0 ourselves as a special case.
1175 (multiple-value-bind (y- y+)
1176 (values (make-interval :low (interval-low y)
1178 (make-interval :low 1
1179 :high (interval-high y)))
1180 (append (list (make-interval :low 1 :high 1))
1181 (interval-expt-<-0 x y-)
1182 (interval-expt-<-0 x y+))))))
1185 (case (c::interval-range-info y)
1187 ;; Y is positive. We need to consider if Y contains an
1188 ;; odd integer or not.
1190 (handle-positive-power-1 x y))
1192 ;; Y is negative. Do this in a better way
1193 (let ((unit (make-interval :low 1 :high 1))
1194 (result (handle-positive-power-1 x (interval-neg y))))
1195 (mapcar #'(lambda (r)
1196 (interval-div unit r))
1199 ;; Split the interval and try again.
1201 (format t "split y ~A~%" y)
1202 (multiple-value-bind (y- y+)
1203 (values (make-interval :low (interval-low y) :high -1)
1204 (make-interval :low 1 :high (interval-high y)))
1205 (append (list (make-interval :low 1 :high 1))
1206 (interval-expt-<-0 x y-)
1207 (interval-expt-<-0 x y+))))))
1210 (format t "splitting x ~A~%" x)
1211 (destructuring-bind (neg pos)
1212 (interval-split -1 x t t)
1213 (append (interval-expt-<-0 neg y)
1214 (interval-expt-<-0 pos y)))))))
1216 ;;; Handle the case when x <= 1
1217 (defun interval-expt-< (x y &optional integer-power-p)
1218 (case (c::interval-range-info x 0d0)
1220 ;; The case of 0 <= x <= 1 is easy
1221 (case (c::interval-range-info y)
1223 ;; Y is positive and log X <= 0. The range of exp(y * log(x)) is
1224 ;; obviously [0, 1]. We just have to be careful for infinite bounds
1226 (let ((lo (safe-expt (c::bound-value (c::interval-low x))
1227 (c::bound-value (c::interval-high y))))
1228 (hi (safe-expt (c::bound-value (c::interval-high x))
1229 (c::bound-value (c::interval-low y)))))
1230 ;; If the low bound, LO, is NIL, that means the we have
1231 ;; +0.0^inf, which is +0.0, but NIL is returned by
1232 ;; SAFE-EXPT. That means the result is includes +0.0. Make
1233 ;; it so by returning a member type and an exclusive
1236 (list (c::make-interval :low lo :high (or hi 1)))
1237 (list (c::make-interval :low (list 0) :high (or hi 1))
1238 (c::make-member-type :members (list 0))))))
1240 ;; Y is negative and log x <= 0. The range of exp(y * log(x)) is
1241 ;; obviously [1, inf].
1242 (let ((hi (safe-expt (c::bound-value (c::interval-low x))
1243 (c::bound-value (c::interval-low y))))
1244 (lo (safe-expt (c::bound-value (c::interval-high x))
1245 (c::bound-value (c::interval-high y)))))
1246 (list (c::make-interval :low (or lo 1) :high hi))))
1248 ;; Split the interval in half
1249 (destructuring-bind (y- y+)
1250 (c::interval-split 0 y t)
1251 (list (interval-expt-< x y- integer-power-p)
1252 (interval-expt-< x y+ integer-power-p))))))
1254 ;; The case where x <= 0.
1255 (cond (integer-power-p
1256 (interval-expt-<-0 x y))
1258 ;; Y is not an integer. Just give up and return an
1259 ;; unbounded interval.
1260 (list (c::make-interval :low nil :high nil)))))
1262 (destructuring-bind (neg pos)
1263 (interval-split 0 x t t)
1264 (append (interval-expt-< neg y integer-power-p)
1265 (interval-expt-< pos y integer-power-p))))))
1267 ;;; Compute bounds for (expt x y)
1269 (defun interval-expt (x y &optional integer-power-p)
1270 (case (interval-range-info x 1)
1273 (interval-expt-> x y))
1276 (interval-expt-< x y integer-power-p))
1278 (destructuring-bind (left right)
1279 (interval-split 1 x t t)
1280 (append (interval-expt left y integer-power-p)
1281 (interval-expt right y integer-power-p))))))
1283 (defun fixup-interval-expt (bnd x-int y-int x-type y-type)
1284 (declare (ignore x-int))
1285 ;; Figure out what the return type should be, given the argument
1286 ;; types and bounds and the result type and bounds.
1290 (reduce #'min (member-type-members b)))
1296 (reduce #'max (member-type-members b)))
1298 (interval-high b)))))
1299 (cond ((csubtypep x-type (specifier-type 'integer))
1300 ;; An integer to some power. Cases to consider:
1301 (case (numeric-type-class y-type)
1303 ;; Positive integer to an integer power is either an
1304 ;; integer or a rational.
1305 (let ((lo (or (low-bnd bnd) '*))
1306 (hi (or (hi-bnd bnd) '*)))
1307 (if (and (interval-low y-int)
1308 (>= (bound-value (interval-low y-int)) 0))
1309 (specifier-type `(integer ,lo ,hi))
1310 (specifier-type `(rational ,lo ,hi)))))
1312 ;; Positive integer to rational power is either a rational
1313 ;; or a single-float.
1314 (let* ((lo (low-bnd bnd))
1317 (floor (bound-value lo))
1320 (ceiling (bound-value hi))
1323 (bound-func #'float lo)
1326 (bound-func #'float hi)
1328 (specifier-type `(or (rational ,int-lo ,int-hi)
1329 (single-float ,f-lo, f-hi)))))
1331 ;; Positive integer to a float power is a float of the
1333 (let* ((res (copy-numeric-type y-type))
1337 (coerce lo (numeric-type-format res))
1340 (coerce hi (numeric-type-format res))
1342 (setf (numeric-type-low res) f-lo)
1343 (setf (numeric-type-high res) f-hi)
1346 ;; Positive integer to a number is a number (for now)
1347 (specifier-type 'number))))
1348 ((csubtypep x-type (specifier-type 'rational))
1349 ;; A rational to some power
1350 (case (numeric-type-class y-type)
1352 ;; Positive rational to an integer power is always a rational
1353 (specifier-type `(rational ,(or (low-bnd bnd) '*)
1354 ,(or (hi-bnd bnd) '*))))
1356 ;; Positive rational to rational power is either a rational
1357 ;; or a single-float.
1358 (let* ((lo (low-bnd bnd))
1361 (floor (bound-value lo))
1364 (ceiling (bound-value hi))
1367 (bound-func #'float lo)
1370 (bound-func #'float hi)
1372 (specifier-type `(or (rational ,int-lo ,int-hi)
1373 (single-float ,f-lo, f-hi)))))
1375 ;; Positive rational to a float power is a float
1376 (let ((res (copy-numeric-type y-type)))
1377 (setf (numeric-type-low res) (low-bnd bnd))
1378 (setf (numeric-type-high res) (hi-bnd bnd))
1381 ;; Positive rational to a number is a number (for now)
1382 (specifier-type 'number))))
1383 ((csubtypep x-type (specifier-type 'float))
1384 ;; A float to some power
1385 (flet ((make-result (type)
1386 (let ((res-type (or type 'float)))
1389 ;; Coerce all elements to the appropriate float
1391 (make-member-type :members (mapcar #'(lambda (x)
1392 (coerce x res-type))
1393 (member-type-members bnd))))
1398 :low (coerce-numeric-bound (low-bnd bnd) res-type)
1399 :high (coerce-numeric-bound (hi-bnd bnd) res-type)))))))
1400 (case (numeric-type-class y-type)
1401 ((or integer rational)
1402 ;; Positive float to an integer or rational power is always a float
1403 (make-result (numeric-type-format x-type)))
1405 ;; Positive float to a float power is a float of the higher type
1406 (make-result (float-format-max (numeric-type-format x-type)
1407 (numeric-type-format y-type))))
1409 ;; Positive float to a number is a number (for now)
1410 (specifier-type 'number)))))
1412 ;; A number to some power is a number.
1413 (specifier-type 'number)))))
1415 (defun merged-interval-expt (x y &optional integer-power-p)
1416 (let* ((x-int (numeric-type->interval x))
1417 (y-int (numeric-type->interval y)))
1418 (mapcar #'(lambda (type)
1419 (fixup-interval-expt type x-int y-int x y))
1420 (flatten-list (interval-expt x-int y-int integer-power-p)))))
1422 (defun expt-derive-type-aux (x y same-arg)
1423 (declare (ignore same-arg))
1424 (cond ((or (not (numeric-type-real-p x))
1425 (not (numeric-type-real-p y)))
1426 ;; Use numeric contagion if either is not real
1427 (numeric-contagion x y))
1428 ((csubtypep y (specifier-type 'integer))
1429 ;; A real raised to an integer power is well-defined
1430 (merged-interval-expt x y t))
1432 ;; A real raised to a non-integral power is complicated....
1433 (cond ((or (csubtypep x (specifier-type '(rational 0)))
1434 (csubtypep x (specifier-type '(float (0d0)))))
1435 ;; A positive real to any power is well-defined.
1436 (merged-interval-expt x y))
1437 ((and (csubtypep x (specifier-type 'rational))
1438 (csubtypep x (specifier-type 'rational)))
1439 ;; A rational to a rational power can be a rational or
1440 ;; a single-float or a complex single-float.
1441 (specifier-type '(or rational single-float (complex single-float))))
1443 ;; A real to some power. The result could be a real
1445 (float-or-complex-float-type (numeric-contagion x y)))))))
1447 (defoptimizer (expt derive-type) ((x y))
1448 (two-arg-derive-type x y #'expt-derive-type-aux #'expt))
1451 ;;; Note must assume that a type including 0.0 may also include -0.0
1452 ;;; and thus the result may be complex -infinity + i*pi.
1454 (defun log-derive-type-aux-1 (x)
1455 (elfun-derive-type-simple x #'log 0d0 nil nil nil))
1457 (defun log-derive-type-aux-2 (x y same-arg)
1458 (let ((log-x (log-derive-type-aux-1 x))
1459 (log-y (log-derive-type-aux-1 y))
1461 ;; log-x or log-y might be union types. We need to run through
1462 ;; the union types ourselves because /-derive-type-aux doesn't.
1463 (dolist (x-type (prepare-arg-for-derive-type log-x))
1464 (dolist (y-type (prepare-arg-for-derive-type log-y))
1465 (push (/-derive-type-aux x-type y-type same-arg) result)))
1466 (setf result (flatten-list result))
1468 (make-union-type result)
1471 (defoptimizer (log derive-type) ((x &optional y))
1473 (two-arg-derive-type x y #'log-derive-type-aux-2 #'log)
1474 (one-arg-derive-type x #'log-derive-type-aux-1 #'log)))
1477 (defun atan-derive-type-aux-1 (y)
1478 (elfun-derive-type-simple y #'atan nil nil (- (/ pi 2)) (/ pi 2)))
1480 (defun atan-derive-type-aux-2 (y x same-arg)
1481 (declare (ignore same-arg))
1482 ;; The hard case with two args. We just return the max bounds.
1483 (let ((result-type (numeric-contagion y x)))
1484 (cond ((and (numeric-type-real-p x)
1485 (numeric-type-real-p y))
1486 (let* ((format (case (numeric-type-class result-type)
1487 ((integer rational) 'single-float)
1488 (t (numeric-type-format result-type))))
1489 (bound-format (or format 'float)))
1490 (make-numeric-type :class 'float
1493 :low (coerce (- pi) bound-format)
1494 :high (coerce pi bound-format))))
1496 ;; The result is a float or a complex number
1497 (float-or-complex-float-type result-type)))))
1499 (defoptimizer (atan derive-type) ((y &optional x))
1501 (two-arg-derive-type y x #'atan-derive-type-aux-2 #'atan)
1502 (one-arg-derive-type y #'atan-derive-type-aux-1 #'atan)))
1505 (defun cosh-derive-type-aux (x)
1506 ;; We note that cosh x = cosh |x| for all real x.
1507 (elfun-derive-type-simple
1508 (if (numeric-type-real-p x)
1509 (abs-derive-type-aux x)
1511 #'cosh nil nil 0 nil))
1513 (defoptimizer (cosh derive-type) ((num))
1514 (one-arg-derive-type num #'cosh-derive-type-aux #'cosh))
1517 (defun phase-derive-type-aux (arg)
1518 (let* ((format (case (numeric-type-class arg)
1519 ((integer rational) 'single-float)
1520 (t (numeric-type-format arg))))
1521 (bound-type (or format 'float)))
1522 (cond ((numeric-type-real-p arg)
1523 (case (interval-range-info (numeric-type->interval arg) 0.0)
1525 ;; The number is positive, so the phase is 0.
1526 (make-numeric-type :class 'float
1529 :low (coerce 0 bound-type)
1530 :high (coerce 0 bound-type)))
1532 ;; The number is always negative, so the phase is pi
1533 (make-numeric-type :class 'float
1536 :low (coerce pi bound-type)
1537 :high (coerce pi bound-type)))
1539 ;; We can't tell. The result is 0 or pi. Use a union
1542 (make-numeric-type :class 'float
1545 :low (coerce 0 bound-type)
1546 :high (coerce 0 bound-type))
1547 (make-numeric-type :class 'float
1550 :low (coerce pi bound-type)
1551 :high (coerce pi bound-type))))))
1553 ;; We have a complex number. The answer is the range -pi
1554 ;; to pi. (-pi is included because we have -0.)
1555 (make-numeric-type :class 'float
1558 :low (coerce (- pi) bound-type)
1559 :high (coerce pi bound-type))))))
1561 (defoptimizer (phase derive-type) ((num))
1562 (one-arg-derive-type num #'phase-derive-type-aux #'phase))
1565 (deftransform realpart ((x) ((complex rational)) *)
1566 '(kernel:%realpart x))
1567 (deftransform imagpart ((x) ((complex rational)) *)
1568 '(kernel:%imagpart x))
1570 ;;; Make REALPART and IMAGPART return the appropriate types. This
1571 ;;; should help a lot in optimized code.
1573 (defun realpart-derive-type-aux (type)
1574 (let ((class (numeric-type-class type))
1575 (format (numeric-type-format type)))
1576 (cond ((numeric-type-real-p type)
1577 ;; The realpart of a real has the same type and range as
1579 (make-numeric-type :class class
1582 :low (numeric-type-low type)
1583 :high (numeric-type-high type)))
1585 ;; We have a complex number. The result has the same type
1586 ;; as the real part, except that it's real, not complex,
1588 (make-numeric-type :class class
1591 :low (numeric-type-low type)
1592 :high (numeric-type-high type))))))
1594 (defoptimizer (realpart derive-type) ((num))
1595 (one-arg-derive-type num #'realpart-derive-type-aux #'realpart))
1597 (defun imagpart-derive-type-aux (type)
1598 (let ((class (numeric-type-class type))
1599 (format (numeric-type-format type)))
1600 (cond ((numeric-type-real-p type)
1601 ;; The imagpart of a real has the same type as the input,
1602 ;; except that it's zero
1603 (let ((bound-format (or format class 'real)))
1604 (make-numeric-type :class class
1607 :low (coerce 0 bound-format)
1608 :high (coerce 0 bound-format))))
1610 ;; We have a complex number. The result has the same type as
1611 ;; the imaginary part, except that it's real, not complex,
1613 (make-numeric-type :class class
1616 :low (numeric-type-low type)
1617 :high (numeric-type-high type))))))
1619 (defoptimizer (imagpart derive-type) ((num))
1620 (one-arg-derive-type num #'imagpart-derive-type-aux #'imagpart))
1622 (defun complex-derive-type-aux-1 (re-type)
1623 (if (numeric-type-p re-type)
1624 (make-numeric-type :class (numeric-type-class re-type)
1625 :format (numeric-type-format re-type)
1626 :complexp (if (csubtypep re-type
1627 (specifier-type 'rational))
1630 :low (numeric-type-low re-type)
1631 :high (numeric-type-high re-type))
1632 (specifier-type 'complex)))
1634 (defun complex-derive-type-aux-2 (re-type im-type same-arg)
1635 (declare (ignore same-arg))
1636 (if (and (numeric-type-p re-type)
1637 (numeric-type-p im-type))
1638 ;; Need to check to make sure numeric-contagion returns the
1639 ;; right type for what we want here.
1641 ;; Also, what about rational canonicalization, like (complex 5 0)
1642 ;; is 5? So, if the result must be complex, we make it so.
1643 ;; If the result might be complex, which happens only if the
1644 ;; arguments are rational, we make it a union type of (or
1645 ;; rational (complex rational)).
1646 (let* ((element-type (numeric-contagion re-type im-type))
1647 (rat-result-p (csubtypep element-type
1648 (specifier-type 'rational))))
1653 `(complex ,(numeric-type-class element-type)))))
1654 (make-numeric-type :class (numeric-type-class element-type)
1655 :format (numeric-type-format element-type)
1656 :complexp (if rat-result-p
1659 (specifier-type 'complex)))
1661 (defoptimizer (complex derive-type) ((re &optional im))
1663 (two-arg-derive-type re im #'complex-derive-type-aux-2 #'complex)
1664 (one-arg-derive-type re #'complex-derive-type-aux-1 #'complex)))
1667 ;;; Define some transforms for complex operations. We do this in lieu
1668 ;;; of complex operation VOPs. Some architectures have vops, though.
1671 ((frob (type &optional (real-type type))
1672 ;; These are functions for which we normally would want to
1675 (deftransform %negate ((z) ((complex ,type)) *)
1677 '(complex (%negate (realpart z)) (%negate (imagpart z))))
1678 (deftransform + ((w z) ((complex ,type) (complex ,type)) *)
1679 ;; Complex + complex
1680 '(complex (+ (realpart w) (realpart z))
1681 (+ (imagpart w) (imagpart z))))
1682 (deftransform - ((w z) ((complex ,type) (complex ,type)) *)
1683 ;; Complex - complex
1684 '(complex (- (realpart w) (realpart z))
1685 (- (imagpart w) (imagpart z))))
1686 (deftransform + ((w z) ((complex ,type) ,real-type) *)
1688 '(complex (+ (realpart w) z) (+ 0 (imagpart w))))
1689 (deftransform - ((w z) ((complex ,type) ,real-type) *)
1691 '(complex (- (realpart w) z) (- (imagpart w) 0)))
1692 (deftransform * ((x y) ((complex ,type) (complex ,type)) *)
1693 ;; Complex * complex
1694 '(let* ((rx (realpart x))
1698 (complex (- (* rx ry) (* ix iy))
1699 (+ (* rx iy) (* ix ry)))))
1700 ;; SSE2 can use a special transform
1701 #-(and sse2 complex-fp-vops)
1702 (deftransform / ((x y) ((complex ,type) (complex ,type)) *
1703 :policy (> speed space))
1704 ;; Complex / complex
1705 '(let* ((rx (realpart x))
1709 (if (> (abs ry) (abs iy))
1710 (let* ((r (/ iy ry))
1711 (dn (+ ry (* r iy))))
1712 (complex (/ (+ rx (* ix r)) dn)
1713 (/ (- ix (* rx r)) dn)))
1714 (let* ((r (/ ry iy))
1715 (dn (+ iy (* r ry))))
1716 (complex (/ (+ (* rx r) ix) dn)
1717 (/ (- (* ix r) rx) dn))))))
1718 (deftransform * ((w z) ((complex ,type) ,real-type) *)
1720 '(complex (* (realpart w) z) (* (imagpart w) z)))
1721 (deftransform / ((w z) ((complex ,type) ,real-type) *)
1723 '(complex (/ (realpart w) z) (/ (imagpart w) z)))
1731 (frob double-double-float real))
1734 ((frob (type &optional (real-type type))
1735 ;; These are functions for which we probably wouldn't want to
1739 (deftransform conjugate ((z) ((complex ,type)) *)
1740 ;; Conjugate of complex number
1741 '(complex (realpart z) (- (imagpart z))))
1743 (deftransform - ((z w) (,real-type (complex ,type)) *)
1744 ;; Real - complex. The 0 for the imaginary part is
1745 ;; needed so we get the correct signed zero.
1746 '(- (complex z (coerce 0 ',real-type)) w))
1748 (deftransform + ((z w) (,real-type (complex ,type)) *)
1749 ;; Real + complex. The 0 for the imaginary part is
1750 ;; needed so we get the correct signed zero.
1751 '(+ (complex z (coerce 0 ',real-type)) w))
1753 (deftransform * ((z w) (,real-type (complex ,type)) *)
1755 '(complex (* z (realpart w)) (* z (imagpart w))))
1756 (deftransform cis ((z) ((,type)) *)
1758 '(complex (cos z) (sin z)))
1759 (deftransform / ((rx y) (,real-type (complex ,type)) *)
1761 '(let* ((ry (realpart y))
1763 (if (> (abs ry) (abs iy))
1764 (let* ((r (/ iy ry))
1765 (dn (+ ry (* r iy))))
1767 (/ (- (* rx r)) dn)))
1768 (let* ((r (/ ry iy))
1769 (dn (+ iy (* r ry))))
1770 (complex (/ (* rx r) dn)
1773 (deftransform = ((w z) ((complex ,type) (complex ,type)) *)
1774 '(and (= (realpart w) (realpart z))
1775 (= (imagpart w) (imagpart z))))
1776 (deftransform = ((w z) ((complex ,type) ,type) *)
1777 '(and (= (realpart w) z) (zerop (imagpart w))))
1778 (deftransform = ((w z) (,type (complex ,type)) *)
1779 '(and (= (realpart z) w) (zerop (imagpart z))))
1784 (frob double-double-float))
1786 #+(and sse2 complex-fp-vops)
1789 `(deftransform / ((x y) (,type ,type) *
1790 :policy (> speed space))
1791 ;; Divide a complex by a complex
1793 ;; Here's how we do a complex division
1795 ;; Compute (xr + i*xi)/(yr + i*yi)
1797 ;; Assume |yi| < |yr|. Then
1799 ;; (xr + i*xi) (xr + i*xi)
1800 ;; ----------- = -----------------
1801 ;; (yr + i*yi) yr*(1 + i*(yi/yr))
1803 ;; (xr + i*xi)*(1 - i*(yi/yr))
1804 ;; = ---------------------------
1805 ;; yr*(1 + (yi/yr)^2)
1807 ;; (xr + i*xi)*(1 - i*(yi/yr))
1808 ;; = ---------------------------
1811 ;; This allows us to use a fast complex multiply followed by
1813 '(let* ((ry (realpart y))
1815 (if (> (abs ry) (abs iy))
1816 (let* ((r (/ iy ry))
1817 (dn (+ ry (* r iy))))
1818 (/ (* x (complex ,one r))
1820 (let* ((r (/ ry iy))
1821 (dn (+ iy (* r ry))))
1822 (/ (* x (complex r ,(- one)))
1824 (frob (complex single-float) 1f0)
1825 (frob (complex double-float) 1d0))
1827 ;;;; Complex contagion:
1830 ;;; COMPLEX-CONTAGION-ARG1, ARG2
1832 ;;; Handles complex contagion of two complex numbers of different types.
1833 (deftransform complex-contagion-arg1 ((x y) * * :defun-only t :node node)
1834 ;;(format t "complex-contagion arg1~%")
1835 `(,(continuation-function-name (basic-combination-fun node))
1836 (coerce x ',(type-specifier (continuation-type y))) y))
1838 (deftransform complex-contagion-arg2 ((x y) * * :defun-only t :node node)
1839 ;;(format t "complex-contagion arg2~%")
1840 `(,(continuation-function-name (basic-combination-fun node))
1841 x (coerce y ',(type-specifier (continuation-type x)))))
1843 (dolist (x '(= + * / -))
1844 (%deftransform x '(function ((complex single-float) (complex double-float)) *)
1845 #'complex-contagion-arg1)
1846 (%deftransform x '(function ((complex double-float) (complex single-float)) *)
1847 #'complex-contagion-arg2))
1849 ;;; COMPLEX-REAL-CONTAGION-ARG1, ARG2
1851 ;;; Handles the case of mixed complex and real numbers. We assume
1852 ;;; the real number doesn't cause complex number to increase in
1854 (deftransform complex-real-contagion-arg1 ((x y) * * :defun-only t :node node)
1855 ;;(format t "complex-real-contagion-arg1~%")
1856 `(,(continuation-function-name (basic-combination-fun node))
1857 (coerce x ',(numeric-type-format (continuation-type y)))
1860 (deftransform complex-real-contagion-arg2 ((x y) * * :defun-only t :node node)
1861 ;;(format t "complex-real-contagion-arg2~%")
1862 `(,(continuation-function-name (basic-combination-fun node))
1864 (coerce y ',(numeric-type-format (continuation-type x)))))
1867 (dolist (x '(= + * / -))
1868 (%deftransform x '(function ((or rational single-float) (complex double-float)) *)
1869 #'complex-real-contagion-arg1)
1870 (%deftransform x '(function ((complex double-float) (or rational single-float)) *)
1871 #'complex-real-contagion-arg2)
1872 (%deftransform x '(function (rational (complex single-float)) *)
1873 #'complex-real-contagion-arg1)
1874 (%deftransform x '(function ((complex single-float) rational) *)
1875 #'complex-real-contagion-arg2))
1877 ;;; UPGRADED-COMPLEX-REAL-CONTAGION-ARG1, ARG2
1879 ;;; Handles the case of mixed complex and real numbers. We assume
1880 ;;; the real number is more precise than the complex, so that the
1881 ;;; complex number needs to be coerced to a more precise complex.
1882 (deftransform upgraded-complex-real-contagion-arg1 ((x y) * * :defun-only t :node node)
1883 ;;(format t "upgraded-complex-real-contagion-arg1~%")
1884 `(,(continuation-function-name (basic-combination-fun node))
1885 (coerce x '(complex ,(type-specifier (continuation-type y))))
1888 (deftransform upgraded-complex-real-contagion-arg2 ((x y) * * :defun-only t :node node)
1890 (format t "upgraded-complex-real-contagion-arg2: ~A ~A~%"
1891 (continuation-type x) (continuation-type y))
1892 `(,(continuation-function-name (basic-combination-fun node))
1894 (coerce y '(complex ,(type-specifier (continuation-type x))))))
1897 (dolist (x '(= + * / -))
1898 (%deftransform x '(function ((or (complex single-float) (complex rational))
1900 #'upgraded-complex-real-contagion-arg1)
1901 (%deftransform x '(function (double-float
1902 (or (complex single-float) (complex rational))) *)
1903 #'upgraded-complex-real-contagion-arg2))
1906 ;;; Here are simple optimizers for sin, cos, and tan. They do not
1907 ;;; produce a minimal range for the result; the result is the widest
1908 ;;; possible answer. This gets around the problem of doing range
1909 ;;; reduction correctly but still provides useful results when the
1910 ;;; inputs are union types.
1912 (defun trig-derive-type-aux (arg domain fcn
1913 &optional def-lo def-hi (increasingp t))
1916 (cond ((eq (numeric-type-complexp arg) :complex)
1917 (complex-float-type arg))
1918 ((numeric-type-real-p arg)
1919 (let* ((format (case (numeric-type-class arg)
1920 ((integer rational) 'single-float)
1921 (t (numeric-type-format arg))))
1922 (bound-type (or format 'float)))
1923 ;; If the argument is a subset of the "principal" domain
1924 ;; of the function, we can compute the bounds because
1925 ;; the function is monotonic. We can't do this in
1926 ;; general for these periodic functions because we can't
1927 ;; (and don't want to) do the argument reduction in
1928 ;; exactly the same way as the functions themselves do
1930 (if (csubtypep arg domain)
1931 (let ((res-lo (bound-func fcn (numeric-type-low arg)))
1932 (res-hi (bound-func fcn (numeric-type-high arg))))
1934 (rotatef res-lo res-hi))
1938 :low (coerce-numeric-bound res-lo bound-type)
1939 :high (coerce-numeric-bound res-hi bound-type)))
1943 :low (and def-lo (coerce def-lo bound-type))
1944 :high (and def-hi (coerce def-hi bound-type))))))
1946 (float-or-complex-float-type arg def-lo def-hi))))))
1948 (defoptimizer (sin derive-type) ((num))
1949 (one-arg-derive-type
1952 ;; Derive the bounds if the arg is in [-pi/2, pi/2]
1953 (trig-derive-type-aux
1955 (specifier-type `(float ,(- (/ pi 2)) ,(/ pi 2)))
1960 (defoptimizer (cos derive-type) ((num))
1961 (one-arg-derive-type
1964 ;; Derive the bounds if the arg is in [0, pi]
1965 (trig-derive-type-aux arg
1966 (specifier-type `(float 0d0 ,pi))
1972 (defoptimizer (tan derive-type) ((num))
1973 (one-arg-derive-type
1976 ;; Derive the bounds if the arg is in [-pi/2, pi/2]
1977 (trig-derive-type-aux arg
1978 (specifier-type `(float ,(- (/ pi 2)) ,(/ pi 2)))
1983 ;;; conjugate always returns the same type as the input type
1984 (defoptimizer (conjugate derive-type) ((num))
1985 (continuation-type num))
1987 (defoptimizer (cis derive-type) ((num))
1988 (one-arg-derive-type num
1990 (specifier-type `(complex ,(or (numeric-type-format arg) 'float))))
1994 ;;; Support for double-double floats
1996 ;;; The algorithms contained herein are based on the code written by
1997 ;;; Yozo Hida. See http://www.cs.berkeley.edu/~yozo/ for more
2003 (declaim (inline quick-two-sum))
2004 (defun quick-two-sum (a b)
2005 "Computes fl(a+b) and err(a+b), assuming |a| >= |b|"
2006 (declare (double-float a b))
2011 (declaim (inline two-sum))
2012 (defun two-sum (a b)
2013 "Computes fl(a+b) and err(a+b)"
2014 (declare (double-float a b))
2020 (declare (optimize (inhibit-warnings 3)))
2023 (declaim (maybe-inline add-dd))
2024 (defun add-dd (a0 a1 b0 b1)
2025 "Add the double-double A0,A1 to the double-double B0,B1"
2026 (declare (double-float a0 a1 b0 b1)
2028 (inhibit-warnings 3)))
2029 (multiple-value-bind (s1 s2)
2031 (declare (double-float s1 s2))
2032 (when (float-infinity-p s1)
2033 (return-from add-dd (values s1 0d0)))
2034 (multiple-value-bind (t1 t2)
2036 (declare (double-float t1 t2))
2038 (multiple-value-bind (s1 s2)
2039 (quick-two-sum s1 s2)
2040 (declare (double-float s1 s2))
2042 (multiple-value-bind (r1 r2)
2043 (quick-two-sum s1 s2)
2044 (if (and (zerop a0) (zerop b0))
2045 ;; Handle sum of signed zeroes here.
2046 (values (float-sign (+ a0 b0) 0d0)
2048 (values r1 r2)))))))
2050 (deftransform + ((a b) (vm::double-double-float vm::double-double-float)
2052 `(multiple-value-bind (hi lo)
2053 (add-dd (kernel:double-double-hi a) (kernel:double-double-lo a)
2054 (kernel:double-double-hi b) (kernel:double-double-lo b))
2055 (truly-the ,(type-specifier (node-derived-type node))
2056 (kernel:%make-double-double-float hi lo))))
2058 (declaim (inline quick-two-diff))
2059 (defun quick-two-diff (a b)
2060 "Compute fl(a-b) and err(a-b), assuming |a| >= |b|"
2061 (declare (double-float a b))
2063 (values s (- (- a s) b))))
2065 (declaim (inline two-diff))
2066 (defun two-diff (a b)
2067 "Compute fl(a-b) and err(a-b)"
2068 (declare (double-float a b))
2074 (declare (optimize (inhibit-warnings 3)))
2077 (declaim (maybe-inline sub-dd))
2078 (defun sub-dd (a0 a1 b0 b1)
2079 "Subtract the double-double B0,B1 from A0,A1"
2080 (declare (double-float a0 a1 b0 b1)
2082 (inhibit-warnings 3)))
2083 (multiple-value-bind (s1 s2)
2085 (declare (double-float s2))
2086 (when (float-infinity-p s1)
2087 (return-from sub-dd (values s1 0d0)))
2088 (multiple-value-bind (t1 t2)
2091 (multiple-value-bind (s1 s2)
2092 (quick-two-sum s1 s2)
2093 (declare (double-float s2))
2095 (multiple-value-bind (r1 r2)
2096 (quick-two-sum s1 s2)
2097 (if (and (zerop a0) (zerop b0))
2098 (values (float-sign (- a0 b0) 0d0)
2100 (values r1 r2)))))))
2102 (declaim (maybe-inline sub-d-dd))
2103 (defun sub-d-dd (a b0 b1)
2104 "Compute double-double = double - double-double"
2105 (declare (double-float a b0 b1)
2106 (optimize (speed 3) (safety 0)
2107 (inhibit-warnings 3)))
2108 (multiple-value-bind (s1 s2)
2110 (declare (double-float s2))
2111 (when (float-infinity-p s1)
2112 (return-from sub-d-dd (values s1 0d0)))
2114 (multiple-value-bind (r1 r2)
2115 (quick-two-sum s1 s2)
2116 (if (and (zerop a) (zerop b0))
2117 (values (float-sign (- a b0) 0d0) 0d0)
2120 (declaim (maybe-inline sub-dd-d))
2121 (defun sub-dd-d (a0 a1 b)
2122 "Subtract the double B from the double-double A0,A1"
2123 (declare (double-float a0 a1 b)
2124 (optimize (speed 3) (safety 0)
2125 (inhibit-warnings 3)))
2126 (multiple-value-bind (s1 s2)
2128 (declare (double-float s2))
2129 (when (float-infinity-p s1)
2130 (return-from sub-dd-d (values s1 0d0)))
2132 (multiple-value-bind (r1 r2)
2133 (quick-two-sum s1 s2)
2134 (if (and (zerop a0) (zerop b))
2135 (values (float-sign (- a0 b) 0d0) 0d0)
2138 (deftransform - ((a b) (vm::double-double-float vm::double-double-float)
2140 `(multiple-value-bind (hi lo)
2141 (sub-dd (kernel:double-double-hi a) (kernel:double-double-lo a)
2142 (kernel:double-double-hi b) (kernel:double-double-lo b))
2143 (truly-the ,(type-specifier (node-derived-type node))
2144 (kernel:%make-double-double-float hi lo))))
2146 (deftransform - ((a b) (double-float vm::double-double-float)
2148 `(multiple-value-bind (hi lo)
2150 (kernel:double-double-hi b) (kernel:double-double-lo b))
2151 (truly-the ,(type-specifier (node-derived-type node))
2152 (kernel:%make-double-double-float hi lo))))
2154 (deftransform - ((a b) (vm::double-double-float double-float)
2156 `(multiple-value-bind (hi lo)
2157 (sub-dd-d (kernel:double-double-hi a) (kernel:double-double-lo a)
2159 (truly-the ,(type-specifier (node-derived-type node))
2160 (kernel:%make-double-double-float hi lo))))
2162 (declaim (maybe-inline split))
2163 ;; This algorithm is the version given by Yozo Hida. It has problems
2164 ;; with overflow because we multiply by 1+2^27.
2166 ;; But be very careful about replacing this with a new algorithm. The
2167 ;; values computed here are very important to get the rounding right.
2168 ;; If you change this, the rounding may be different, which will
2169 ;; affect other parts of the algorithm.
2171 ;; I (rtoy) tried a different algorithm that split the number in two
2172 ;; as described, but without overflow. However, that caused
2173 ;; -9.4294948327242751340284975915175w0/1w14 to return a value that
2174 ;; wasn't really close to -9.4294948327242751340284975915175w-14.
2176 ;; This also means we can't print numbers like 1w308 with the current
2177 ;; printing algorithm, or even divide 1w308 by 10.
2180 "Split the double-float number a into a-hi and a-lo such that a =
2181 a-hi + a-lo and a-hi contains the upper 26 significant bits of a and
2182 a-lo contains the lower 26 bits."
2183 (declare (double-float a))
2184 (let* ((tmp (* a (+ 1 (expt 2 27))))
2185 (a-hi (- tmp (- tmp a)))
2187 (values a-hi a-lo)))
2189 ;; +split-limit+ is the largest number for which Yozo's algorithm
2190 ;; still works. Basically we want a*(1+2^27) <=
2191 ;; most-positive-double-float < 2^1024. Therefore, a < 2^1024/(1+2^27)
2192 ;; If we calculate that, we get a = 1.3393857490036326d300. A quick
2193 ;; test shows that this would cause overflow, but previous float would
2194 ;; not. This is the value we want.
2195 (defconstant +split-limit+
2196 (scale-float (/ (float (1+ (expt 2 27)) 1d0)) 1024))
2199 "Split the double-float number a into a-hi and a-lo such that a =
2200 a-hi + a-lo and a-hi contains the upper 26 significant bits of a and
2201 a-lo contains the lower 26 bits."
2202 (declare (double-float a)
2204 (inhibit-warnings 3)))
2205 ;; This splits the number a into 2 parts of 27 and 26 bits each, but
2206 ;; the parts are, I think, supposed to be properly rounded in an
2209 ;; For numbers that are very large, we use a different algorithm.
2210 ;; For smaller numbers, we can use the original algorithm of Yozo
2212 (if (>= (abs a) +split-limit+)
2213 ;; I've tested this algorithm against Yozo's method for 1
2214 ;; billion randomly generated double-floats between 2^(-995) and
2215 ;; 2^996, and identical results are obtained. For numbers that
2216 ;; are very small, this algorithm produces different numbers
2217 ;; because of underflow. For very large numbers, we, of course
2218 ;; produce different results because Yozo's method causes
2220 (let* ((tmp (* a (+ 1 (scale-float 1d0 -27))))
2221 (as (* a (scale-float 1d0 -27)))
2222 (a-hi (* (- tmp (- tmp as)) (expt 2 27)))
2225 ;; Yozo's algorithm.
2226 (let* ((tmp (* a (+ 1 (expt 2 27))))
2227 (a-hi (- tmp (- tmp a)))
2229 (values a-hi a-lo))))
2232 (declaim (inline two-prod))
2234 (defun two-prod (a b)
2235 _N"Compute fl(a*b) and err(a*b)"
2236 (declare (double-float a b))
2238 (multiple-value-bind (a-hi a-lo)
2240 ;;(format t "a-hi, a-lo = ~S ~S~%" a-hi a-lo)
2241 (multiple-value-bind (b-hi b-lo)
2243 ;;(format t "b-hi, b-lo = ~S ~S~%" b-hi b-lo)
2244 (let ((e (+ (+ (- (* a-hi b-hi) p)
2249 (declare (optimize (inhibit-warnings 3)))
2253 (defun two-prod (a b)
2254 _N"Compute fl(a*b) and err(a*b)"
2255 (declare (double-float a b))
2256 ;; PPC has a fused multiply-subtract instruction that can be used
2259 (err (vm::fused-multiply-subtract a b p)))
2262 (declaim (inline two-sqr))
2265 _N"Compute fl(a*a) and err(a*b). This is a more efficient
2266 implementation of two-prod"
2267 (declare (double-float a))
2269 (multiple-value-bind (a-hi a-lo)
2272 (declare (optimize (inhibit-warnings 3)))
2273 (values q (+ (+ (- (* a-hi a-hi) q)
2279 _N"Compute fl(a*a) and err(a*b). This is a more efficient
2280 implementation of two-prod"
2281 (declare (double-float a))
2283 (values q (vm::fused-multiply-subtract a a q))))
2285 (declaim (maybe-inline mul-dd-d))
2286 (defun mul-dd-d (a0 a1 b)
2287 (declare (double-float a0 a1 b)
2289 (inhibit-warnings 3)))
2290 (multiple-value-bind (p1 p2)
2292 (declare (double-float p2))
2293 (when (float-infinity-p p1)
2294 (return-from mul-dd-d (values p1 0d0)))
2295 ;;(format t "mul-dd-d p1,p2 = ~A ~A~%" p1 p2)
2297 ;;(format t "mul-dd-d p2 = ~A~%" p2)
2298 (multiple-value-bind (r1 r2)
2299 (quick-two-sum p1 p2)
2301 (setf r1 (float-sign p1 0d0))
2305 (declaim (maybe-inline mul-dd))
2306 (defun mul-dd (a0 a1 b0 b1)
2307 "Multiply the double-double A0,A1 with B0,B1"
2308 (declare (double-float a0 a1 b0 b1)
2310 (inhibit-warnings 3)))
2311 (multiple-value-bind (p1 p2)
2313 (declare (double-float p1 p2))
2314 (when (float-infinity-p p1)
2315 (return-from mul-dd (values p1 0d0)))
2318 (multiple-value-bind (r1 r2)
2319 (quick-two-sum p1 p2)
2321 (values (float-sign p1 0d0) 0d0)
2324 (declaim (maybe-inline add-dd-d))
2325 (defun add-dd-d (a0 a1 b)
2326 "Add the double-double A0,A1 to the double B"
2327 (declare (double-float a0 a1 b)
2329 (inhibit-warnings 3)))
2330 (multiple-value-bind (s1 s2)
2332 (declare (double-float s1 s2))
2333 (when (float-infinity-p s1)
2334 (return-from add-dd-d (values s1 0d0)))
2336 (multiple-value-bind (r1 r2)
2337 (quick-two-sum s1 s2)
2338 (if (and (zerop a0) (zerop b))
2339 (values (float-sign (+ a0 b) 0d0) 0d0)
2342 (declaim (maybe-inline sqr-dd))
2343 (defun sqr-dd (a0 a1)
2344 (declare (double-float a0 a1)
2346 (inhibit-warnings 3)))
2347 (multiple-value-bind (p1 p2)
2349 (declare (double-float p1 p2))
2350 (incf p2 (* 2 a0 a1))
2351 ;; Hida's version of sqr (qd-2.1.210) has the following line for
2352 ;; the sqr function. But if you compare this with mul-dd, this
2353 ;; doesn't exist there, and if you leave it in, it produces
2354 ;; results that are different from using mul-dd to square a value.
2357 (quick-two-sum p1 p2)))
2359 (deftransform + ((a b) (vm::double-double-float (or integer single-float double-float))
2361 `(multiple-value-bind (hi lo)
2362 (add-dd-d (kernel:double-double-hi a) (kernel:double-double-lo a)
2364 (truly-the ,(type-specifier (node-derived-type node))
2365 (kernel:%make-double-double-float hi lo))))
2367 (deftransform + ((a b) ((or integer single-float double-float) vm::double-double-float)
2369 `(multiple-value-bind (hi lo)
2370 (add-dd-d (kernel:double-double-hi b) (kernel:double-double-lo b)
2372 (truly-the ,(type-specifier (node-derived-type node))
2373 (kernel:%make-double-double-float hi lo))))
2375 (deftransform * ((a b) (vm::double-double-float vm::double-double-float)
2377 ;; non-const-same-leaf-ref-p is stolen from two-arg-derive-type.
2378 (flet ((non-const-same-leaf-ref-p (x y)
2379 ;; Just like same-leaf-ref-p, but we don't care if the
2380 ;; value of the leaf is constant or not.
2381 (declare (type continuation x y))
2382 (let ((x-use (continuation-use x))
2383 (y-use (continuation-use y)))
2386 (eq (ref-leaf x-use) (ref-leaf y-use))))))
2387 (destructuring-bind (arg1 arg2)
2388 (combination-args node)
2389 ;; If the two args to * are the same, we square the number
2390 ;; instead of multiply. Squaring is simpler than a full
2392 (if (non-const-same-leaf-ref-p arg1 arg2)
2393 `(multiple-value-bind (hi lo)
2394 (sqr-dd (kernel:double-double-hi a) (kernel:double-double-lo a))
2395 (truly-the ,(type-specifier (node-derived-type node))
2396 (kernel:%make-double-double-float hi lo)))
2397 `(multiple-value-bind (hi lo)
2398 (mul-dd (kernel:double-double-hi a) (kernel:double-double-lo a)
2399 (kernel:double-double-hi b) (kernel:double-double-lo b))
2400 (truly-the ,(type-specifier (node-derived-type node))
2401 (kernel:%make-double-double-float hi lo)))))))
2403 (deftransform * ((a b) (vm::double-double-float (or integer single-float double-float))
2405 `(multiple-value-bind (hi lo)
2406 (mul-dd-d (kernel:double-double-hi a) (kernel:double-double-lo a)
2408 (truly-the ,(type-specifier (node-derived-type node))
2409 (kernel:%make-double-double-float hi lo))))
2411 (deftransform * ((a b) ((or integer single-float double-float) vm::double-double-float)
2413 `(multiple-value-bind (hi lo)
2414 (mul-dd-d (kernel:double-double-hi b) (kernel:double-double-lo b)
2416 (truly-the ,(type-specifier (node-derived-type node))
2417 (kernel:%make-double-double-float hi lo))))
2419 (declaim (maybe-inline div-dd))
2420 (defun div-dd (a0 a1 b0 b1)
2421 "Divide the double-double A0,A1 by B0,B1"
2422 (declare (double-float a0 a1 b0 b1)
2424 (inhibit-warnings 3))
2426 (let ((q1 (/ a0 b0)))
2427 (when (float-infinity-p q1)
2428 (return-from div-dd (values q1 0d0)))
2429 ;; (q1b0, q1b1) = q1*(b0,b1)
2430 ;;(format t "q1 = ~A~%" q1)
2431 (multiple-value-bind (q1b0 q1b1)
2433 ;;(format t "q1*b = ~A ~A~%" q1b0 q1b1)
2434 (multiple-value-bind (r0 r1)
2436 (sub-dd a0 a1 q1b0 q1b1)
2437 ;;(format t "r = ~A ~A~%" r0 r1)
2438 (let ((q2 (/ r0 b0)))
2439 (multiple-value-bind (q2b0 q2b1)
2441 (multiple-value-bind (r0 r1)
2443 (sub-dd r0 r1 q2b0 q2b1)
2444 (declare (ignore r1))
2445 (let ((q3 (/ r0 b0)))
2446 (multiple-value-bind (q1 q2)
2447 (quick-two-sum q1 q2)
2448 (add-dd-d q1 q2 q3))))))))))
2450 (declaim (maybe-inline div-dd-d))
2451 (defun div-dd-d (a0 a1 b)
2452 (declare (double-float a0 a1 b)
2454 (inhibit-warnings 3)))
2455 (let ((q1 (/ a0 b)))
2456 ;; q1 = approx quotient
2457 ;; Now compute a - q1 * b
2458 (multiple-value-bind (p1 p2)
2460 (multiple-value-bind (s e)
2462 (declare (double-float e))
2466 (let ((q2 (/ (+ s e) b)))
2467 (quick-two-sum q1 q2))))))
2469 (deftransform / ((a b) (vm::double-double-float vm::double-double-float)
2471 `(multiple-value-bind (hi lo)
2472 (div-dd (kernel:double-double-hi a) (kernel:double-double-lo a)
2473 (kernel:double-double-hi b) (kernel:double-double-lo b))
2474 (truly-the ,(type-specifier (node-derived-type node))
2475 (kernel:%make-double-double-float hi lo))))
2477 (deftransform / ((a b) (vm::double-double-float (or integer single-float double-float))
2479 `(multiple-value-bind (hi lo)
2480 (div-dd-d (kernel:double-double-hi a) (kernel:double-double-lo a)
2482 (truly-the ,(type-specifier (node-derived-type node))
2483 (kernel:%make-double-double-float hi lo))))
2485 (declaim (inline sqr-d))
2488 (declare (double-float a)
2490 (inhibit-warnings 3)))
2493 (declaim (inline mul-d-d))
2494 (defun mul-d-d (a b)
2497 (declaim (maybe-inline sqrt-dd))
2498 (defun sqrt-dd (a0 a1)
2499 (declare (type (double-float 0d0) a0)
2502 (inhibit-warnings 3)))
2503 ;; Strategy: Use Karp's trick: if x is an approximation to sqrt(a),
2506 ;; y = a*x + (a-(a*x)^2)*x/2
2508 ;; is an approximation that is accurate to twice the accuracy of x.
2509 ;; Also, the multiplication (a*x) and [-]*x can be done with only
2510 ;; half the precision.
2511 (if (and (zerop a0) (zerop a1))
2513 (let* ((x (/ (sqrt a0)))
2515 (multiple-value-bind (s0 s1)
2517 (multiple-value-bind (s2)
2518 (sub-dd a0 a1 s0 s1)
2519 (multiple-value-bind (p0 p1)
2520 (mul-d-d s2 (* x 0.5d0))
2521 (add-dd-d p0 p1 ax)))))))
2523 (deftransform sqrt ((a) ((vm::double-double-float 0w0))
2525 `(multiple-value-bind (hi lo)
2526 (sqrt-dd (kernel:double-double-hi a) (kernel:double-double-lo a))
2527 (truly-the ,(type-specifier (node-derived-type node))
2528 (kernel:%make-double-double-float hi lo))))
2530 (declaim (inline neg-dd))
2531 (defun neg-dd (a0 a1)
2532 (declare (double-float a0 a1)
2534 (inhibit-warnings 3)))
2535 (values (- a0) (- a1)))
2537 (declaim (inline abs-dd))
2538 (defun abs-dd (a0 a1)
2539 (declare (double-float a0 a1)
2541 (inhibit-warnings 3)))
2546 (deftransform abs ((a) (vm::double-double-float)
2548 `(multiple-value-bind (hi lo)
2549 (abs-dd (kernel:double-double-hi a) (kernel:double-double-lo a))
2550 (truly-the ,(type-specifier (node-derived-type node))
2551 (kernel:%make-double-double-float hi lo))))
2553 (deftransform %negate ((a) (vm::double-double-float)
2555 `(multiple-value-bind (hi lo)
2556 (neg-dd (kernel:double-double-hi a) (kernel:double-double-lo a))
2557 (truly-the ,(type-specifier (node-derived-type node))
2558 (kernel:%make-double-double-float hi lo))))
2560 (declaim (inline dd=))
2561 (defun dd= (a0 a1 b0 b1)
2565 (declaim (inline dd<))
2566 (defun dd< (a0 a1 b0 b1)
2571 (declaim (inline dd>))
2572 (defun dd> (a0 a1 b0 b1)
2577 (deftransform = ((a b) (vm::double-double-float vm::double-double-float) *)
2578 `(dd= (kernel:double-double-hi a)
2579 (kernel:double-double-lo a)
2580 (kernel:double-double-hi b)
2581 (kernel:double-double-lo b)))
2584 (deftransform < ((a b) (vm::double-double-float vm::double-double-float) *)
2585 `(dd< (kernel:double-double-hi a)
2586 (kernel:double-double-lo a)
2587 (kernel:double-double-hi b)
2588 (kernel:double-double-lo b)))
2591 (deftransform > ((a b) (vm::double-double-float vm::double-double-float) *)
2592 `(dd> (kernel:double-double-hi a)
2593 (kernel:double-double-lo a)
2594 (kernel:double-double-hi b)
2595 (kernel:double-double-lo b)))
2597 ) ; progn double-double