1 ;;;; -*- Mode: lisp -*-
3 ;;;; Copyright (c) 2007 Raymond Toy
5 ;;;; Permission is hereby granted, free of charge, to any person
6 ;;;; obtaining a copy of this software and associated documentation
7 ;;;; files (the "Software"), to deal in the Software without
8 ;;;; restriction, including without limitation the rights to use,
9 ;;;; copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ;;;; copies of the Software, and to permit persons to whom the
11 ;;;; Software is furnished to do so, subject to the following
14 ;;;; The above copyright notice and this permission notice shall be
15 ;;;; included in all copies or substantial portions of the Software.
17 ;;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 ;;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 ;;;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 ;;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 ;;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 ;;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 ;;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 ;;;; OTHER DEALINGS IN THE SOFTWARE.
29 (make-instance 'qd-real
:value qdi
:+qd-pi
+))
32 (defconstant +quad-double-float-positive-infinity
+
33 (make-instance 'qd-real
:value
(make-qd-d ext
:double-float-positive-infinity
))
34 "Positive infinity for qd-real")
37 (defconstant +quad-double-float-negative-infinity
+
38 (make-instance 'qd-real
:value
(make-qd-d ext
:double-float-negative-infinity
))
39 "Negative infinity for qd-real")
41 (defconstant +most-positive-quad-double-float
+
42 (make-instance 'qd-real
43 :value
(qdi::%make-qd-d most-positive-double-float
44 (cl:scale-float most-positive-double-float
(cl:* 1 -
53))
45 (cl:scale-float most-positive-double-float
(cl:* 2 -
53))
46 (cl:scale-float most-positive-double-float
(cl:* 3 -
53)))))
48 (defconstant +least-positive-quad-double-float
+
49 (make-instance 'qd-real
50 :value
(make-qd-d least-positive-double-float
)))
52 ;; Not sure this is 100% correct, but I think if the first component
53 ;; is any smaller than this, the last component would no longer be a
54 ;; normalized double-float.
55 (defconstant +least-positive-normalized-quad-double-float
+
56 (make-instance 'qd-real
57 :value
(make-qd-d (cl:scale-float least-positive-normalized-double-float
(cl:* 3 53)))))
59 (defconstant +qd-real-one
+
60 (make-instance 'qd-real
:value
(make-qd-d 1d0
)))
62 (defmethod add1 ((a number
))
65 (defmethod add1 ((a qd-real
))
66 (make-instance 'qd-real
:value
(add-qd-d (qd-value a
) 1d0
)))
68 (defmethod sub1 ((a number
))
71 (defmethod sub1 ((a qd-real
))
72 (make-instance 'qd-real
:value
(sub-qd-d (qd-value a
) 1d0
)))
74 (declaim (inline 1+ 1-
))
82 (defmethod two-arg-+ ((a qd-real
) (b qd-real
))
83 (make-instance 'qd-real
:value
(add-qd (qd-value a
) (qd-value b
))))
85 (defmethod two-arg-+ ((a qd-real
) (b cl
:float
))
86 (make-instance 'qd-real
:value
(add-qd-d (qd-value a
) (cl:float b
1d0
))))
89 (defmethod two-arg-+ ((a qd-real
) (b ext
:double-double-float
))
90 (make-instance 'qd-real
:value
(add-qd-dd (qd-value a
) b
)))
92 (defmethod two-arg-+ ((a real
) (b qd-real
))
95 (defmethod two-arg-+ ((a number
) (b number
))
101 (do ((args (cdr args
) (cdr args
))
103 (two-arg-+ res
(car args
))))
106 (defmethod two-arg-- ((a qd-real
) (b qd-real
))
107 (make-instance 'qd-real
:value
(sub-qd (qd-value a
) (qd-value b
))))
109 (defmethod two-arg-- ((a qd-real
) (b cl
:float
))
110 (make-instance 'qd-real
:value
(sub-qd-d (qd-value a
) (cl:float b
1d0
))))
113 (defmethod two-arg-- ((a qd-real
) (b ext
:double-double-float
))
114 (make-instance 'qd-real
:value
(sub-qd-dd (qd-value a
) b
)))
116 (defmethod two-arg-- ((a cl
:float
) (b qd-real
))
117 (make-instance 'qd-real
:value
(sub-d-qd (cl:float a
1d0
) (qd-value b
))))
119 (defmethod two-arg-- ((a number
) (b number
))
122 (defmethod unary-minus ((a number
))
125 (defmethod unary-minus ((a qd-real
))
126 (make-instance 'qd-real
:value
(neg-qd (qd-value a
))))
128 (defun - (number &rest more-numbers
)
130 (do ((nlist more-numbers
(cdr nlist
))
132 ((atom nlist
) result
)
133 (declare (list nlist
))
134 (setq result
(two-arg-- result
(car nlist
))))
135 (unary-minus number
)))
138 (defmethod two-arg-* ((a qd-real
) (b qd-real
))
139 (make-instance 'qd-real
:value
(mul-qd (qd-value a
) (qd-value b
))))
141 (defmethod two-arg-* ((a qd-real
) (b cl
:float
))
142 (make-instance 'qd-real
:value
(mul-qd-d (qd-value a
) (cl:float b
1d0
))))
145 (defmethod two-arg-* ((a qd-real
) (b ext
:double-double-float
))
146 ;; We'd normally want to use mul-qd-dd, but mul-qd-dd is broken.
147 (make-instance 'qd-real
:value
(mul-qd (qd-value a
)
148 (make-qd-dd b
0w0
))))
150 (defmethod two-arg-* ((a real
) (b qd-real
))
153 (defmethod two-arg-* ((a number
) (b number
))
156 (defun * (&rest args
)
159 (do ((args (cdr args
) (cdr args
))
161 (two-arg-* res
(car args
))))
164 (defmethod two-arg-/ ((a qd-real
) (b qd-real
))
165 (make-instance 'qd-real
:value
(div-qd (qd-value a
) (qd-value b
))))
167 (defmethod two-arg-/ ((a qd-real
) (b cl
:float
))
168 (make-instance 'qd-real
:value
(div-qd-d (qd-value a
) (cl:float b
1d0
))))
171 (defmethod two-arg-/ ((a qd-real
) (b ext
:double-double-float
))
172 (make-instance 'qd-real
:value
(div-qd-dd (qd-value a
)
175 (defmethod two-arg-/ ((a cl
:float
) (b qd-real
))
176 (make-instance 'qd-real
:value
(div-qd (make-qd-d (cl:float a
1d0
))
180 (defmethod two-arg-/ ((a ext
:double-double-float
) (b qd-real
))
181 (make-instance 'qd-real
:value
(div-qd (make-qd-dd a
0w0
)
184 (defmethod two-arg-/ ((a number
) (b number
))
187 (defmethod unary-divide ((a number
))
190 (defmethod unary-divide ((a qd-real
))
191 (make-instance 'qd-real
:value
(div-qd +qd-one
+ (qd-value a
))))
193 (defun / (number &rest more-numbers
)
195 (do ((nlist more-numbers
(cdr nlist
))
197 ((atom nlist
) result
)
198 (declare (list nlist
))
199 (setq result
(two-arg-/ result
(car nlist
))))
200 (unary-divide number
)))
202 (macrolet ((frob (name &optional
(type 'real
))
203 (let ((method-name (intern (concatenate 'string
"Q" (symbol-name name
))))
204 (cl-name (intern (symbol-name name
) :cl
))
205 (qd-name (intern (concatenate 'string
(symbol-name name
) "-QD"))))
207 (defmethod ,method-name
((x ,type
))
209 (defmethod ,method-name
((x qd-real
))
210 (,qd-name
(qd-value x
)))
211 (declaim (inline ,name
))
213 (,method-name x
))))))
218 (defun bignum-to-qd (bignum)
219 (make-instance 'qd-real
220 :value
(qdi::make-float
(if (minusp bignum
) -
1 1)
226 (defmethod qfloat ((x real
) (num-type cl
:float
))
227 (cl:float x num-type
))
229 (defmethod qfloat ((x cl
:float
) (num-type qd-real
))
230 (make-instance 'qd-real
:value
(make-qd-d (cl:float x
1d0
))))
232 (defmethod qfloat ((x integer
) (num-type qd-real
))
233 (cond ((typep x
'fixnum
)
234 (make-instance 'qd-real
:value
(make-qd-d (cl:float x
1d0
))))
240 (defmethod qfloat ((x ratio
) (num-type qd-real
))
241 ;; This probably has some issues with roundoff
242 (two-arg-/ (qfloat (numerator x
) num-type
)
243 (qfloat (denominator x
) num-type
)))
245 (defmethod qfloat ((x ratio
) (num-type qd-real
))
246 ;; This probably has some issues with roundoff
247 (let ((top (qd-value (qfloat (numerator x
) num-type
)))
248 (bot (qd-value (qfloat (denominator x
) num-type
))))
249 (make-instance 'qd-real
:value
(div-qd top bot
))))
252 (defmethod qfloat ((x ext
:double-double-float
) (num-type qd-real
))
253 (make-instance 'qd-real
:value
(make-qd-dd x
0w0
)))
255 (defmethod qfloat ((x qd-real
) (num-type cl
:float
))
256 (multiple-value-bind (q0 q1 q2 q3
)
257 (qd-parts (qd-value x
))
258 (cl:float
(cl:+ q0 q1 q2 q3
) num-type
)))
261 (defmethod qfloat ((x qd-real
) (num-type ext
:double-double-float
))
262 (multiple-value-bind (q0 q1 q2 q3
)
263 (qd-parts (qd-value x
))
264 (cl:+ (cl:float q0
1w0
)
269 (defmethod qfloat ((x qd-real
) (num-type qd-real
))
272 (declaim (inline float
))
273 (defun float (x num-type
)
276 (defmethod qrealpart ((x number
))
278 (defmethod qrealpart ((x qd-real
))
280 (defmethod qrealpart ((x qd-complex
))
281 (make-instance 'qd-real
:value
(qd-real x
)))
285 (defmethod qimagpart ((x number
))
287 (defmethod qimagpart ((x qd-real
))
289 (defmethod qimagpart ((x qd-complex
))
290 (make-instance 'qd-real
:value
(qd-imag x
)))
295 (defmethod qconjugate ((a number
))
298 (defmethod qconjugate ((a qd-real
))
299 (make-instance 'qd-real
:value
(qd-value a
)))
301 (defmethod qconjugate ((a qd-complex
))
302 (make-instance 'qd-complex
304 :imag
(neg-qd (qd-imag a
))))
309 (defmethod qscale-float ((f cl
:float
) (n integer
))
310 (cl:scale-float f n
))
312 (defmethod qscale-float ((f qd-real
) (n integer
))
313 (make-instance 'qd-real
:value
(scale-float-qd (qd-value f
) n
)))
315 (declaim (inline scale-float
))
316 (defun scale-float (f n
)
321 (let ((method (intern (concatenate 'string
"TWO-ARG-" (symbol-name op
))))
322 (cl-fun (find-symbol (symbol-name op
) :cl
))
323 (qd-fun (intern (concatenate 'string
"QD-" (symbol-name op
))
324 (find-package :qdi
))))
326 (defmethod ,method
((a real
) (b real
))
328 (defmethod ,method
((a qd-real
) (b real
))
329 (,qd-fun
(qd-value a
) (make-qd-d (cl:float b
1d0
))))
330 (defmethod ,method
((a real
) (b qd-real
))
331 (,qd-fun
(make-qd-d (cl:float a
1d0
)) (qd-value b
)))
332 (defmethod ,method
((a qd-real
) (b qd-real
))
333 (,qd-fun
(qd-value a
) (qd-value b
)))
334 (defun ,op
(number &rest more-numbers
)
335 "Returns T if its arguments are in strictly increasing order, NIL otherwise."
336 (declare (optimize (safety 2))
337 (dynamic-extent more-numbers
))
338 (do* ((n number
(car nlist
))
339 (nlist more-numbers
(cdr nlist
)))
341 (declare (list nlist
))
342 (if (not (,method n
(car nlist
))) (return nil
))))))))
348 (macrolet ((frob (name)
349 (let ((method-name (intern (concatenate 'string
"Q" (symbol-name name
))))
350 (cl-name (intern (symbol-name name
) :cl
))
351 (qd-name (intern (concatenate 'string
(symbol-name name
) "-QD"))))
353 (defmethod ,method-name
((x number
))
355 (defmethod ,method-name
((x qd-real
))
356 (make-instance 'qd-real
:value
(,qd-name
(qd-value x
))))
357 (declaim (inline ,name
))
359 (,method-name x
))))))
375 (defmethod qsqrt ((x number
))
378 (defmethod qsqrt ((x qd-real
))
380 (make-instance 'qd-complex
382 :imag
(sqrt-qd (neg-qd (qd-value x
))))
383 (make-instance 'qd-real
:value
(sqrt-qd (qd-value x
)))))
389 "Compute 2^N * X without compute 2^N first (use properties of the
390 underlying floating-point format"
391 (declare (type qd-real x
))
394 (declaim (inline qd-cssqs
))
396 (multiple-value-bind (rho k
)
397 (qdi::hypot-aux-qd
(qd-value (realpart z
))
398 (qd-value (imagpart z
)))
399 (values (make-instance 'qd-real
:value rho
)
403 (defmethod qabs ((z qd-complex
))
405 ;; If |x| > |y| then sqrt(x^2+y^2) = |x|*sqrt(1+(y/x)^2)
406 (multiple-value-bind (abs^
2 rho
)
407 (hypot-qd (qd-value (realpart z
))
408 (qd-value (imagpart z
)))
409 (scale-float (make-instance 'qd-real
:value
(sqrt abs^
2))
412 (defmethod qabs ((z qd-complex
))
414 ;; If |x| > |y| then sqrt(x^2+y^2) = |x|*sqrt(1+(y/x)^2)
415 (make-instance 'qd-real
416 :value
(hypot-qd (qd-value (realpart z
))
417 (qd-value (imagpart z
)))))
419 (defmethod qlog ((a number
) &optional b
)
424 (defmethod qlog ((a qd-real
) &optional b
)
426 (/ (qlog a
) (qlog b
))
427 (if (minusp (float-sign a
))
428 (make-instance 'qd-complex
429 :real
(log-qd (abs-qd (qd-value a
)))
431 (make-instance 'qd-real
:value
(log-qd (qd-value a
))))))
433 (declaim (inline log
))
434 (defun log (a &optional b
)
438 (defmethod log1p ((a qd-real
))
439 (make-instance 'qd-real
:value
(log1p-qd (qd-value a
))))
441 (defmethod qatan ((y real
) &optional x
)
443 (cond ((typep x
'qd-real
)
444 (make-instance 'qd-real
445 :value
(atan2-qd (qd-value y
) (qd-value x
))))
451 (defmethod qatan ((y qd-real
) &optional x
)
452 (make-instance 'qd-real
455 (atan2-qd (qd-value y
) (qd-value x
))
456 (atan-qd (qd-value y
)))))
458 (defun atan (y &optional x
)
462 (defmethod qexpt ((x number
) (y number
))
465 (defmethod qexpt ((x qd-real
) (y real
))
468 (defmethod qexpt ((x real
) (y qd-real
))
471 (defmethod qexpt ((x qd-real
) (y cl
:complex
))
472 (exp (* (make-instance 'qd-complex
473 :real
(qd-value (realpart y
))
474 :imag
(qd-value (imagpart y
)))
477 (defmethod qexpt ((x cl
:complex
) (y qd-real
))
479 (log (make-instance 'qd-complex
480 :real
(qd-value (realpart x
))
481 :imag
(qd-value (imagpart x
)))))))
483 (defmethod qexpt ((x qd-real
) (y qd-real
))
484 ;; x^y = exp(y*log(x))
487 (defmethod qexpt ((x qd-real
) (y integer
))
488 (make-instance 'qd-real
489 :value
(npow (qd-value x
) y
)))
491 (declaim (inline expt
))
497 (defmethod two-arg-= ((a number
) (b number
))
499 (defmethod two-arg-= ((a qd-real
) (b number
))
501 (qd-= (qd-value a
) (make-qd-d (cl:float b
1d0
)))
503 (defmethod two-arg-= ((a number
) (b qd-real
))
505 (qd-= (make-qd-d (cl:float a
1d0
)) (qd-value b
))
508 (defmethod two-arg-= ((a qd-real
) (b qd-real
))
509 (qd-= (qd-value a
) (qd-value b
)))
511 (defun = (number &rest more-numbers
)
512 "Returns T if all of its arguments are numerically equal, NIL otherwise."
513 (declare (optimize (safety 2))
514 (dynamic-extent more-numbers
))
515 (do ((nlist more-numbers
(cdr nlist
)))
517 (declare (list nlist
))
518 (if (not (two-arg-= (car nlist
) number
))
521 (defun /= (number &rest more-numbers
)
522 "Returns T if no two of its arguments are numerically equal, NIL otherwise."
523 (declare (optimize (safety 2))
524 (dynamic-extent more-numbers
))
525 (do* ((head number
(car nlist
))
526 (nlist more-numbers
(cdr nlist
)))
528 (declare (list nlist
))
529 (unless (do* ((nl nlist
(cdr nl
)))
532 (if (two-arg-= head
(car nl
))
536 (defmethod qcomplex ((x real
) &optional y
)
537 (cl:complex x
(if y y
0)))
539 (defmethod qcomplex ((x qd-real
) &optional y
)
540 (make-instance 'qd-complex
542 :imag
(if y
(qd-value y
) +qd-zero
+)))
544 (defun complex (x &optional
(y 0))
547 (defmethod qinteger-decode-float ((f cl
:float
))
548 (cl:integer-decode-float f
))
550 (defmethod qinteger-decode-float ((f qd-real
))
551 (integer-decode-qd (qd-value f
)))
553 (declaim (inline integer-decode-float
))
554 (defun integer-decode-float (f)
555 (qinteger-decode-float f
))
557 (defmethod qdecode-float ((f cl
:float
))
560 (defmethod qdecode-float ((f qd-real
))
561 (multiple-value-bind (frac exp s
)
562 (decode-float-qd (qd-value f
))
563 (values (make-instance 'qd-real
:value frac
)
565 (make-instance 'qd-real
:value s
))))
567 (declaim (inline decode-float
))
568 (defun decode-float (f)
571 (defmethod qfloor ((x real
) &optional y
)
576 (defmethod qfloor ((x qd-real
) &optional y
)
578 (let ((f (qfloor (/ x y
))))
581 (let ((f (ffloor-qd (qd-value x
))))
582 (multiple-value-bind (int exp sign
)
583 (integer-decode-qd f
)
584 (values (ash (* sign int
) exp
)
585 (make-instance 'qd-real
587 (- x
(make-instance 'qd-real
590 (defun floor (x &optional y
)
593 (defmethod qffloor ((x real
) &optional y
)
598 (defmethod qffloor ((x qd-real
) &optional y
)
600 (let ((f (qffloor (/ x y
))))
603 (let ((f (make-instance 'qd-real
:value
(ffloor-qd (qd-value x
)))))
607 (defun ffloor (x &optional y
)
610 (defun ceiling (x &optional y
)
611 (multiple-value-bind (f rem
)
619 (defun fceiling (x &optional y
)
620 (multiple-value-bind (f rem
)
628 (defun truncate (x &optional
(y 1))
633 (defun ftruncate (x &optional
(y 1))
638 (defmethod %unary-round
((x real
))
641 (defmethod %unary-round
((number qd-real
))
642 (multiple-value-bind (bits exp
)
643 (integer-decode-float number
)
644 (let* ((shifted (ash bits exp
))
645 (rounded (if (and (minusp exp
)
647 (not (zerop (logand bits
648 (ash 1 (- -
1 exp
))))))
655 (defun round (number &optional
(divisor 1))
657 (let ((r (%unary-round number
)))
660 (multiple-value-bind (tru rem
)
661 (truncate number divisor
)
664 (let ((thresh (/ (abs divisor
) 2)))
665 (cond ((or (> rem thresh
)
666 (and (= rem thresh
) (oddp tru
)))
668 (values (- tru
1) (+ rem divisor
))
669 (values (+ tru
1) (- rem divisor
))))
670 ((let ((-thresh (- thresh
)))
672 (and (= rem -thresh
) (oddp tru
))))
674 (values (+ tru
1) (- rem divisor
))
675 (values (- tru
1) (+ rem divisor
))))
676 (t (values tru rem
))))))))
678 (defun fround (number &optional
(divisor 1))
679 "Same as ROUND, but returns first value as a float."
680 (multiple-value-bind (res rem
)
681 (round number divisor
)
682 (values (float res
(if (floatp rem
) rem
1.0)) rem
)))
684 (defmethod qfloat-sign ((a real
) &optional
(f (float 1 a
)))
687 (defmethod qfloat-sign ((a qd-real
) &optional f
)
689 (make-instance 'qd-real
690 :value
(mul-qd-d (abs-qd (qd-value f
))
691 (cl:float-sign
(qd-0 (qd-value a
)))))
692 (make-instance 'qd-real
:value
(make-qd-d (cl:float-sign
(qd-0 (qd-value a
)))))))
694 (declaim (inline float-sign
))
695 (defun float-sign (n &optional float2
)
696 (qfloat-sign n float2
))
698 (defun max (number &rest more-numbers
)
699 "Returns the greatest of its arguments."
700 (declare (optimize (safety 2)) (type (or real qd-real
) number
)
701 (dynamic-extent more-numbers
))
702 (dolist (real more-numbers
)
703 (when (> real number
)
707 (defun min (number &rest more-numbers
)
708 "Returns the least of its arguments."
709 (declare (optimize (safety 2)) (type (or real qd-real
) number
)
710 (dynamic-extent more-numbers
))
711 (do ((nlist more-numbers
(cdr nlist
))
712 (result (the (or real qd-real
) number
)))
713 ((null nlist
) (return result
))
714 (declare (list nlist
))
715 (if (< (car nlist
) result
)
716 (setq result
(car nlist
)))))
718 (defmethod qasin ((x number
))
721 (defmethod qasin ((x qd-real
))
723 (make-instance 'qd-real
:value
(asin-qd (qd-value x
)))
724 (qd-complex-asin x
)))
726 (declaim (inline asin
))
730 (defmethod qacos ((x number
))
733 (defmethod qacos ((x qd-real
))
737 (make-instance 'qd-real
:value
(acos-qd (qd-value x
))))))
739 (declaim (inline acos
))
743 (defmethod qacosh ((x number
))
746 (defmethod qacosh ((x qd-real
))
749 (make-instance 'qd-real
:value
(acosh-qd (qd-value x
)))))
752 (declaim (inline acosh
))
756 (defmethod qatanh ((x number
))
759 (defmethod qatanh ((x qd-real
))
762 (make-instance 'qd-real
:value
(atanh-qd (qd-value x
)))))
765 (declaim (inline atanh
))
769 (defmethod qcis ((x real
))
772 (defmethod qcis ((x qd-real
))
773 (multiple-value-bind (s c
)
774 (sincos-qd (qd-value x
))
775 (make-instance 'qd-complex
779 (declaim (inline cis
))
783 (defmethod qphase ((x number
))
786 (defmethod qphase ((x qd-real
))
789 (make-instance 'qd-real
:value
(make-qd-d 0d0
))))
791 (declaim (inline phase
))
795 (defun signum (number)
796 "If NUMBER is zero, return NUMBER, else return (/ NUMBER (ABS NUMBER))."
799 (if (rationalp number
)
800 (if (plusp number
) 1 -
1)
801 (/ number
(abs number
)))))
803 (defmethod random ((x cl
:real
) &optional
(state *random-state
*))
806 (defmethod random ((x qd-real
) &optional
(state *random-state
*))
807 (* x
(make-instance 'qd-real
808 :value
(qdi:random-qd state
))))
810 (define-compiler-macro + (&whole form
&rest args
)
813 (do ((args (cdr args
) (cdr args
))
815 `(two-arg-+ ,res
,(car args
))))
818 (define-compiler-macro -
(&whole form number
&rest more-numbers
)
820 (do ((nlist more-numbers
(cdr nlist
))
822 ((atom nlist
) result
)
823 (declare (list nlist
))
824 (setq result
`(two-arg-- ,result
,(car nlist
))))
825 `(unary-minus ,number
)))
827 (define-compiler-macro * (&whole form
&rest args
)
830 (do ((args (cdr args
) (cdr args
))
832 `(two-arg-* ,res
,(car args
))))
835 (define-compiler-macro / (number &rest more-numbers
)
837 (do ((nlist more-numbers
(cdr nlist
))
839 ((atom nlist
) result
)
840 (declare (list nlist
))
841 (setq result
`(two-arg-/ ,result
,(car nlist
))))
842 `(unary-divide ,number
)))
844 ;; Compiler macros to convert <, >, <=, and >= into multiple calls of
845 ;; the corresponding two-arg-<foo> function.
848 (let ((method (intern (concatenate 'string
"TWO-ARG-" (symbol-name op
)))))
849 `(define-compiler-macro ,op
(number &rest more-numbers
)
850 (do* ((n number
(car nlist
))
851 (nlist more-numbers
(cdr nlist
))
854 `(and ,@(nreverse res
)))
855 (push `(,',method
,n
,(car nlist
)) res
))))))
861 (define-compiler-macro /= (&whole form number
&rest more-numbers
)
862 ;; Convert (/= x y) to (not (two-arg-= x y)). Should we try to
863 ;; handle a few more cases?
864 (if (cdr more-numbers
)
866 `(not (two-arg-= ,number
,(car more-numbers
)))))
869 (defun read-qd-real-or-complex (stream)
870 (let ((c (peek-char t stream
)))
873 (read-char stream
) ; Skip the paren
874 (let ((real (read stream t nil t
))
875 (imag (read stream t nil t
)))
876 (unless (char= (peek-char t stream
) #\
))
877 (error "Illegal QD-COMPLEX number format"))
878 ;; Read closing paren
880 (make-instance 'qd-complex
881 :real
(qd-value (float real
+qd-real-one
+))
882 :imag
(qd-value (float imag
+qd-real-one
+)))))
884 (make-instance 'qd-real
:value
(read-qd stream
))))))
886 (defun qd-class-reader (stream subchar arg
)
887 (declare (ignore subchar
))
889 (warn "Numeric argument ignored in #~DQ" arg
))
890 (read-qd-real-or-complex stream
))
892 ;; Yow! We redefine the #q reader that is in qd-io.lisp to read in
893 ;; and make a real qd-real float, instead of the hackish
895 (set-dispatch-macro-character #\
# #\Q
#'qd-class-reader
)