Don't use "ansify" for self-hosted build.
[sbcl.git] / tests / arith.pure.lisp
blob6ad238de7fb046662ece09eb4bfc8b8ae99ef6a0
1 ;;;; arithmetic tests with no side effects
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; While most of SBCL is derived from the CMU CL system, the test
7 ;;;; files (like this one) were written from scratch after the fork
8 ;;;; from CMU CL.
9 ;;;;
10 ;;;; This software is in the public domain and is provided with
11 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
12 ;;;; more information.
14 (cl:in-package :cl-user)
16 ;;; Once upon a time, in the process of porting CMUCL's SPARC backend
17 ;;; to SBCL, multiplications were excitingly broken. While it's
18 ;;; unlikely that anything with such fundamental arithmetic errors as
19 ;;; these are going to get this far, it's probably worth checking.
20 (with-test (:name (:fundamental-arithmetic :smoke))
21 (macrolet ((test (op res1 res2)
22 `(progn
23 (assert (= (,op 4 2) ,res1))
24 (assert (= (,op 2 4) ,res2))
25 (assert (= (funcall (checked-compile '(lambda (x y) (,op x y)))
26 4 2)
27 ,res1))
28 (assert (= (funcall (checked-compile '(lambda (x y) (,op x y)))
29 2 4)
30 ,res2)))))
31 (test + 6 6)
32 (test - 2 -2)
33 (test * 8 8)
34 (test / 2 1/2)
35 (test expt 16 16)))
37 ;;; In a bug reported by Wolfhard Buss on cmucl-imp 2002-06-18 (BUG
38 ;;; 184), sbcl didn't catch all divisions by zero, notably divisions
39 ;;; of bignums and ratios by 0. Fixed in sbcl-0.7.6.13.
40 (with-test (:name (/ :division-by-zero ratio))
41 (assert-error (funcall (checked-compile
42 `(lambda () (/ 2/3 0))
43 :allow-style-warnings t))
44 division-by-zero))
46 (with-test (:name (/ :division-by-zero bignum))
47 (assert-error (funcall (checked-compile
48 `(lambda () (/ (1+ most-positive-fixnum) 0))
49 :allow-style-warnings t))
50 division-by-zero))
52 ;;; In a bug reported by Raymond Toy on cmucl-imp 2002-07-18, (COERCE
53 ;;; <RATIONAL> '(COMPLEX FLOAT)) was failing to return a complex
54 ;;; float; a patch was given by Wolfhard Buss cmucl-imp 2002-07-19.
55 (assert (= (coerce 1 '(complex float)) #c(1.0 0.0)))
56 (assert (= (coerce 1/2 '(complex float)) #c(0.5 0.0)))
57 (assert (= (coerce 1.0d0 '(complex float)) #c(1.0d0 0.0d0)))
59 ;;; (COERCE #c(<RATIONAL> <RATIONAL>) '(complex float)) resulted in
60 ;;; an error up to 0.8.17.31
61 (assert (= (coerce #c(1 2) '(complex float)) #c(1.0 2.0)))
63 ;;; COERCE also sometimes failed to verify that a particular coercion
64 ;;; was possible (in particular coercing rationals to bounded float
65 ;;; types.
66 (with-test (:name (coerce :to float :outside-bounds))
67 (assert-error (funcall (checked-compile
68 `(lambda () (coerce 1 '(float 2.0 3.0)))
69 :allow-style-warnings t))
70 type-error)
71 (assert-error (funcall (checked-compile
72 `(lambda () (coerce 1 '(single-float -1.0 0.0)))
73 :allow-style-warnings t))
74 type-error)
75 (assert (eql (coerce 1 '(single-float -1.0 2.0)) 1.0)))
77 ;;; ANSI says MIN and MAX should signal TYPE-ERROR if any argument
78 ;;; isn't REAL. SBCL 0.7.7 didn't in the 1-arg case. (reported as a
79 ;;; bug in CMU CL on #lisp IRC by lrasinen 2002-09-01)
80 (with-test (:name (min max type-error))
81 (assert (null (ignore-errors (funcall
82 (checked-compile `(lambda () (min '(1 2 3)))
83 :allow-style-warnings t)))))
84 (assert (= (min -1) -1))
85 (assert (null (ignore-errors (funcall
86 (checked-compile `(lambda () (min 1 #(1 2 3)))
87 :allow-style-warnings t)))))
88 (assert (= (min 10 11) 10))
89 (assert (null (ignore-errors (funcall
90 (checked-compile
91 `(lambda () (min (find-package "CL") -5.0))
92 :allow-style-warnings t)))))
93 (assert (= (min 5.0 -3) -3))
94 (assert (null (ignore-errors (checked-compile `(lambda () (max #c(4 3)))
95 :allow-style-warnings t))))
96 (assert (= (max 0) 0))
97 (assert (null (ignore-errors (funcall
98 (checked-compile `(lambda () (max "MIX" 3))
99 :allow-style-warnings t)))))
100 (assert (= (max -1 10.0) 10.0))
101 (assert (null (ignore-errors (funcall
102 (checked-compile `(lambda () (max 3 #'max))
103 :allow-style-warnings t)))))
104 (assert (= (max -3 0) 0)))
106 (with-test (:name :numeric-inequality-&rest-arguments)
107 (dolist (f '(= < <= > >=))
108 ;; 1 arg
109 (assert-error (funcall f 'feep) type-error)
110 (unless (eq f '=)
111 ;; = accepts complex numbers
112 (assert-error (funcall f #c(0s0 1s0)) type-error))
113 ;; 2 arg
114 (assert-error (funcall f 3 'feep) type-error)
115 (assert-error (funcall f 'feep 3) type-error)
116 ;; 3 arg
117 (assert-error (funcall f 0 0 'feep) type-error)
118 (assert-error (funcall f 0 1 'feep) type-error)
119 (assert-error (funcall f 1 0 'feep) type-error)
120 ;; 4 arg
121 (assert-error (funcall f 0 0 0 'feep) type-error))
122 ;; Also MIN,MAX operate only on REAL
123 (dolist (f '(min max))
124 (assert-error (funcall f #c(1s0 -2s0)) type-error)))
126 ;;; (CEILING x 2^k) was optimized incorrectly
127 (loop for divisor in '(-4 4)
128 for ceiler = (compile nil `(lambda (x)
129 (declare (fixnum x))
130 (declare (optimize (speed 3)))
131 (ceiling x ,divisor)))
132 do (loop for i from -5 to 5
133 for exact-q = (/ i divisor)
134 do (multiple-value-bind (q r)
135 (funcall ceiler i)
136 (assert (= (+ (* q divisor) r) i))
137 (assert (<= exact-q q))
138 (assert (< q (1+ exact-q))))))
140 ;;; (TRUNCATE x 2^k) was optimized incorrectly
141 (loop for divisor in '(-4 4)
142 for truncater = (compile nil `(lambda (x)
143 (declare (fixnum x))
144 (declare (optimize (speed 3)))
145 (truncate x ,divisor)))
146 do (loop for i from -9 to 9
147 for exact-q = (/ i divisor)
148 do (multiple-value-bind (q r)
149 (funcall truncater i)
150 (assert (= (+ (* q divisor) r) i))
151 (assert (<= (abs q) (abs exact-q)))
152 (assert (< (abs exact-q) (1+ (abs q)))))))
154 ;;; CEILING had a corner case, spotted by Paul Dietz
155 (assert (= (ceiling most-negative-fixnum (1+ most-positive-fixnum)) -1))
157 ;;; give any optimizers of constant multiplication a light testing.
158 ;;; 100 may seem low, but (a) it caught CSR's initial errors, and (b)
159 ;;; before checking in, CSR tested with 10000. So one hundred
160 ;;; checkins later, we'll have doubled the coverage.
161 (with-test (:name (* :multiplication :constant :optimization))
162 (dotimes (i 100)
163 (let* ((x (random most-positive-fixnum))
164 (x2 (* x 2))
165 (x3 (* x 3))
166 (fn (checked-compile
167 `(lambda (y)
168 (declare (optimize speed) (type (integer 0 3) y))
169 (* y ,x))
170 :allow-notes (> x3 most-positive-fixnum))))
171 (assert (= (funcall fn 0) 0))
172 (assert (= (funcall fn 1) x))
173 (assert (= (funcall fn 2) x2))
174 (assert (= (funcall fn 3) x3)))))
176 ;;; Bugs reported by Paul Dietz:
178 ;;; (GCD 0 x) must return (abs x)
179 (dolist (x (list -10 (* 3 most-negative-fixnum)))
180 (assert (= (gcd 0 x) (abs x))))
181 ;;; LCM returns a non-negative number
182 (assert (= (lcm 4 -10) 20))
183 (assert (= (lcm 0 0) 0))
185 ;;; PPC bignum arithmetic bug:
186 (multiple-value-bind (quo rem)
187 (truncate 291351647815394962053040658028983955 10000000000000000000000000)
188 (assert (= quo 29135164781))
189 (assert (= rem 5394962053040658028983955)))
191 ;;; x86 LEA bug:
192 (assert (= (funcall
193 (compile nil '(lambda (x) (declare (bit x)) (+ x #xf0000000)))
195 #xf0000001))
197 ;;; LOGBITP on bignums:
198 (dolist (x '(((1+ most-positive-fixnum) 1 nil)
199 ((1+ most-positive-fixnum) -1 t)
200 ((1+ most-positive-fixnum) (1+ most-positive-fixnum) nil)
201 ((1+ most-positive-fixnum) (1- most-negative-fixnum) t)
202 (1 (ash most-negative-fixnum 1) nil)
203 (#.(- sb-vm:n-word-bits sb-vm:n-fixnum-tag-bits 1) most-negative-fixnum t)
204 (#.(1+ (- sb-vm:n-word-bits sb-vm:n-fixnum-tag-bits 1)) (ash most-negative-fixnum 1) t)
205 (#.(+ 2 (- sb-vm:n-word-bits sb-vm:n-fixnum-tag-bits 1)) (ash most-negative-fixnum 1) t)
206 (#.(+ sb-vm:n-word-bits 32) (ash most-negative-fixnum #.(+ 32 sb-vm:n-fixnum-tag-bits 2)) nil)
207 (#.(+ sb-vm:n-word-bits 33) (ash most-negative-fixnum #.(+ 32 sb-vm:n-fixnum-tag-bits 2)) t)))
208 (destructuring-bind (index int result) x
209 (assert (eq (eval `(logbitp ,index ,int)) result))))
211 ;;; off-by-1 type inference error for %DPB and %DEPOSIT-FIELD:
212 (let ((f (compile nil '(lambda (b)
213 (integer-length (dpb b (byte 4 28) -1005))))))
214 (assert (= (funcall f 1230070) 32)))
215 (let ((f (compile nil '(lambda (b)
216 (integer-length (deposit-field b (byte 4 28) -1005))))))
217 (assert (= (funcall f 1230070) 32)))
219 ;;; type inference leading to an internal compiler error:
220 (let ((f (compile nil '(lambda (x)
221 (declare (type fixnum x))
222 (ldb (byte 0 0) x)))))
223 (assert (= (funcall f 1) 0))
224 (assert (= (funcall f most-positive-fixnum) 0))
225 (assert (= (funcall f -1) 0)))
227 ;;; Alpha bignum arithmetic bug:
228 (assert (= (* 966082078641 419216044685) 404997107848943140073085))
230 ;;; Alpha smallnum arithmetic bug:
231 (assert (= (ash -129876 -1026) -1))
233 ;;; Alpha middlenum (yes, really! Affecting numbers between 2^32 and
234 ;;; 2^64 :) arithmetic bug
235 (with-test (:name (truncate :middlenum))
236 (let ((fn (checked-compile
237 `(lambda (a b c d)
238 (declare (type (integer -1621 -513) a)
239 (type (integer -3 34163) b)
240 (type (integer -9485132993 81272960) c)
241 (type (integer -255340814 519943) d)
242 (ignorable a b c d)
243 (optimize (speed 3) (safety 1) (debug 1)))
244 (truncate c (min -100 4149605))))))
245 (assert (= (funcall fn -1332 5864 -6963328729 -43789079) 69633287))))
247 ;;; Here's another fantastic Alpha backend bug: the code to load
248 ;;; immediate 64-bit constants into a register was wrong.
249 (with-test (:name (dpb :constants))
250 (let ((fn (checked-compile `(lambda (a b c d)
251 (declare (type (integer -3563 2733564) a)
252 (type (integer -548947 7159) b)
253 (type (integer -19 0) c)
254 (type (integer -2546009 0) d)
255 (ignorable a b c d)
256 (optimize (speed 3) (safety 1) (debug 1)))
257 (case a
258 ((89 125 16) (ash a (min 18 -706)))
259 (t (dpb -3 (byte 30 30) -1)))))))
260 (assert (= (funcall fn 1227072 -529823 -18 -792831) -2147483649))))
262 ;;; ASH of a negative bignum by a bignum count would erroneously
263 ;;; return 0 prior to sbcl-0.8.4.4
264 (assert (= (ash (1- most-negative-fixnum) (1- most-negative-fixnum)) -1))
266 ;;; Whoops. Too much optimization in division operators for 0
267 ;;; divisor.
268 (with-test (:name (mod truncate rem / floor ceiling :division-by-zero fixnum))
269 (flet ((frob (name)
270 (let ((fn (checked-compile
271 `(lambda (x)
272 (declare (optimize speed) (fixnum x))
273 (,name x 0)))))
274 (assert-error (funcall fn 1) division-by-zero))))
275 (mapc #'frob '(mod truncate rem / floor ceiling))))
277 ;; Check that the logic in SB-KERNEL::BASIC-COMPARE for doing fixnum/float
278 ;; comparisons without rationalizing the floats still gives the right anwers
279 ;; in the edge cases (had a fencepost error).
280 (macrolet ((test (range type sign)
281 `(let (ints
282 floats
283 (start (- ,(find-symbol (format nil
284 "MOST-~A-EXACTLY-~A-FIXNUM"
285 sign type)
286 :sb-kernel)
287 ,range)))
288 (dotimes (i (1+ (* ,range 2)))
289 (let* ((x (+ start i))
290 (y (coerce x ',type)))
291 (push x ints)
292 (push y floats)))
293 (dolist (i ints)
294 (dolist (f floats)
295 (dolist (op '(< <= = >= >))
296 (unless (eq (funcall op i f)
297 (funcall op i (rationalize f)))
298 (error "(not (eq (~a ~a ~f) (~a ~a ~a)))~%"
299 op i f
300 op i (rationalize f)))
301 (unless (eq (funcall op f i)
302 (funcall op (rationalize f) i))
303 (error "(not (eq (~a ~f ~a) (~a ~a ~a)))~%"
304 op f i
305 op (rationalize f) i))))))))
306 (test 32 double-float negative)
307 (test 32 double-float positive)
308 (test 32 single-float negative)
309 (test 32 single-float positive))
311 ;; x86-64 sign-extension bug found using pfdietz's random tester.
312 (assert (= 286142502
313 (funcall (lambda ()
314 (declare (notinline logxor))
315 (min (logxor 0 0 0 286142502))))))
317 ;; Small bugs in LOGCOUNT can still allow SBCL to be built and thus go
318 ;; unnoticed, so check more thoroughly here.
319 (with-test (:name :logcount)
320 (flet ((test (x n)
321 (unless (= (logcount x) n)
322 (error "logcount failure for ~a" x))))
323 ;; Test with some patterns with well known number of ones/zeroes ...
324 (dotimes (i 128)
325 (let ((x (ash 1 i)))
326 (test x 1)
327 (test (- x) i)
328 (test (1- x) i)))
329 ;; ... and with some random integers of varying length.
330 (flet ((test-logcount (x)
331 (declare (type integer x))
332 (do ((result 0 (1+ result))
333 (x (if (minusp x)
334 (lognot x)
336 (logand x (1- x))))
337 ((zerop x) result))))
338 (dotimes (i 200)
339 (let ((x (random (ash 1 i))))
340 (test x (test-logcount x))
341 (test (- x) (test-logcount (- x))))))))
343 ;; 1.0 had a broken ATANH on win32
344 (with-test (:name :atanh)
345 (assert (= (atanh 0.9d0) 1.4722194895832204d0)))
347 ;; Test some cases of integer operations with constant arguments
348 (with-test (:name :constant-integers)
349 (labels ((test-forms (op x y header &rest forms)
350 (let ((val (funcall op x y)))
351 (dolist (form forms)
352 (let ((new-val (funcall (checked-compile (append header form)) x y)))
353 (unless (eql val new-val)
354 (error "~S /= ~S: ~S ~S ~S~%" val new-val (append header form) x y))))))
355 (test-case (op x y type)
356 (test-forms op x y `(lambda (x y &aux z)
357 (declare (type ,type x y)
358 (ignorable x y z)
359 (notinline identity)
360 (optimize speed (safety 0))))
361 `((,op x ,y))
362 `((setf z (,op x ,y))
363 (identity x)
365 `((values (,op x ,y) x))
366 `((,op ,x y))
367 `((setf z (,op ,x y))
368 (identity y)
370 `((values (,op ,x y) y))
372 `((identity x)
373 (,op x ,y))
374 `((identity x)
375 (setf z (,op x ,y))
376 (identity x)
378 `((identity x)
379 (values (,op x ,y) x))
380 `((identity y)
381 (,op ,x y))
382 `((identity y)
383 (setf z (,op ,x y))
384 (identity y)
386 `((identity y)
387 (values (,op ,x y) y))))
388 (test-op (op)
389 (let ((ub `(unsigned-byte ,sb-vm:n-word-bits))
390 (sb `(signed-byte ,sb-vm:n-word-bits)))
391 (loop for (x y type)
392 in `((2 1 fixnum)
393 (2 1 ,ub)
394 (2 1 ,sb)
395 (,(1+ (ash 1 28)) ,(1- (ash 1 28)) fixnum)
396 (,(+ 3 (ash 1 30)) ,(+ 2 (ash 1 30)) ,ub)
397 (,(- -2 (ash 1 29)) ,(- 3 (ash 1 29)) ,sb)
398 ,@(when (> sb-vm:n-word-bits 32)
399 `((,(1+ (ash 1 29)) ,(1- (ash 1 29)) fixnum)
400 (,(1+ (ash 1 31)) ,(1- (ash 1 31)) ,ub)
401 (,(- -2 (ash 1 31)) ,(- 3 (ash 1 30)) ,sb)
402 (,(ash 1 40) ,(ash 1 39) fixnum)
403 (,(ash 1 40) ,(ash 1 39) ,ub)
404 (,(ash 1 40) ,(ash 1 39) ,sb)))
405 ;; fixnums that can be represented as 32-bit
406 ;; sign-extended immediates on x86-64
407 ,@(when (and (> sb-vm:n-word-bits 32)
408 (< sb-vm:n-fixnum-tag-bits 3))
409 `((,(1+ (ash 1 (- 31 sb-vm:n-fixnum-tag-bits)))
410 ,(1- (ash 1 (- 32 sb-vm:n-fixnum-tag-bits)))
411 fixnum))))
413 (test-case op x y type)
414 (test-case op x x type)))))
415 (mapc #'test-op '(+ - * truncate
416 < <= = >= >
418 eq))))
420 ;; GCD used to sometimes return negative values. The following did, on 32 bit
421 ;; builds.
422 (with-test (:name :gcd)
423 ;; from lp#413680
424 (assert (plusp (gcd 20286123923750474264166990598656
425 680564733841876926926749214863536422912)))
426 ;; from lp#516750
427 (assert (plusp (gcd 2596102012663483082521318626691873
428 2596148429267413814265248164610048))))
430 (with-test (:name :expt-zero-zero)
431 ;; Check that (expt 0.0 0.0) and (expt 0 0.0) signal error, but
432 ;; (expt 0.0 0) returns 1.0
433 (flet ((error-case (expr)
434 (assert-error (funcall (checked-compile `(lambda () ,expr)
435 :allow-style-warnings t))
436 sb-int:arguments-out-of-domain-error)))
437 (error-case '(expt 0.0 0.0))
438 (error-case '(expt 0 0.0)))
439 (assert (eql (expt 0.0 0) 1.0)))
441 (with-test (:name :multiple-constant-folding)
442 (let ((*random-state* (make-random-state t)))
443 (flet ((make-args ()
444 (let (args vars)
445 (loop repeat (1+ (random 12))
446 do (if (zerop (random 2))
447 (let ((var (gensym)))
448 (push var args)
449 (push var vars))
450 (push (- (random 21) 10) args)))
451 (values args vars))))
452 (dolist (op '(+ * logior logxor logand logeqv gcd lcm - /))
453 (loop repeat 10
454 do (multiple-value-bind (args vars) (make-args)
455 (let ((fast (checked-compile
456 `(lambda ,vars
457 (,op ,@args))
458 :allow-style-warnings (eq op '/)))
459 (slow (checked-compile
460 `(lambda ,vars
461 (declare (notinline ,op))
462 (,op ,@args))
463 :allow-style-warnings (eq op '/))))
464 (loop repeat 3
465 do (let* ((call-args (loop repeat (length vars)
466 collect (- (random 21) 10)))
467 (fast-result (handler-case
468 (apply fast call-args)
469 (division-by-zero () :div0)))
470 (slow-result (handler-case
471 (apply slow call-args)
472 (division-by-zero () :div0))))
473 (if (not (eql fast-result slow-result))
474 (error "oops: ~S, ~S" args call-args)
475 #+nil (print (list :ok `(,op ,@args) :=> fast-result))
476 ))))))))))
478 ;;; (TRUNCATE <unsigned-word> <constant unsigned-word>) is optimized
479 ;;; to use multiplication instead of division. This propagates to FLOOR,
480 ;;; MOD and REM. Test that the transform is indeed triggered and test
481 ;;; several cases for correct results.
482 (with-test (:name (:integer-division-using-multiplication :used)
483 :skipped-on '(not (or :x86-64 :x86)))
484 (dolist (fun '(truncate floor ceiling mod rem))
485 (let* ((foo (checked-compile
486 `(lambda (x)
487 (declare (optimize (speed 3)
488 (space 1)
489 (compilation-speed 0))
490 (type (unsigned-byte ,sb-vm:n-word-bits) x))
491 (,fun x 9))))
492 (disassembly (with-output-to-string (s)
493 (disassemble foo :stream s))))
494 ;; KLUDGE copied from test :float-division-using-exact-reciprocal
495 ;; in compiler.pure.lisp.
496 (assert (and (not (search "DIV" disassembly))
497 (search "MUL" disassembly))))))
499 (with-test (:name (:integer-division-using-multiplication :correctness))
500 (let ((*random-state* (make-random-state t)))
501 (dolist (dividend-type `((unsigned-byte ,sb-vm:n-word-bits)
502 (and fixnum unsigned-byte)
503 (integer 10000 10100)))
504 (dolist (divisor `(;; Some special cases from the paper
505 7 10 14 641 274177
506 ;; Range extremes
508 ,most-positive-fixnum
509 ,(1- (expt 2 sb-vm:n-word-bits))
510 ;; Some random values
511 ,@(loop for i from 8 to sb-vm:n-word-bits
512 for r = (random (expt 2 i))
513 ;; We don't want 0, 1 and powers of 2.
514 when (not (zerop (logand r (1- r))))
515 collect r)))
516 (dolist (fun '(truncate ceiling floor mod rem))
517 (let ((foo (checked-compile
518 `(lambda (x)
519 (declare (optimize (speed 3)
520 (space 1)
521 (compilation-speed 0))
522 (type ,dividend-type x))
523 (,fun x ,divisor)))))
524 (dolist (dividend `(0 1 ,most-positive-fixnum
525 ,(1- divisor) ,divisor
526 ,(1- (* divisor 2)) ,(* divisor 2)
527 ,@(loop repeat 4
528 collect (+ 10000 (random 101)))
529 ,@(loop for i from 4 to sb-vm:n-word-bits
530 for pow = (expt 2 (1- i))
531 for r = (+ pow (random pow))
532 collect r)))
533 (when (typep dividend dividend-type)
534 (multiple-value-bind (q1 r1)
535 (funcall foo dividend)
536 (multiple-value-bind (q2 r2)
537 (funcall fun dividend divisor)
538 (unless (and (= q1 q2)
539 (eql r1 r2))
540 (error "bad results for ~s with dividend type ~s"
541 (list fun dividend divisor)
542 dividend-type))))))))))))
544 ;; The fast path for logbitp underestimated sb!vm:n-positive-fixnum-bits
545 ;; for > 61 bit fixnums.
546 (with-test (:name :logbitp-wide-fixnum)
547 (assert (not (logbitp (1- (integer-length most-positive-fixnum))
548 most-negative-fixnum))))
550 ;; EXPT dispatches in a complicated way on the types of its arguments.
551 ;; Check that all possible combinations are covered.
552 (with-test (:name (:expt :argument-type-combinations))
553 (let ((numbers '(2 ; fixnum
554 3/5 ; ratio
555 1.2f0 ; single-float
556 2.0d0 ; double-float
557 #c(3/5 1/7) ; complex rational
558 #c(1.2f0 1.3f0) ; complex single-float
559 #c(2.0d0 3.0d0))) ; complex double-float
560 (bignum (expt 2 64))
561 results)
562 (dolist (base (cons bignum numbers))
563 (dolist (power numbers)
564 #+nil (format t "(expt ~s ~s) => " base power)
565 (let ((result (expt base power)))
566 #+nil (format t "~s~%" result)
567 (push result results))))
568 (assert (every #'numberp results))))
570 (with-test (:name :bug-741564)
571 ;; The bug was that in (expt <fixnum> <(complex double-float)>) the
572 ;; calculation was partially done only to single-float precision,
573 ;; making the complex double-float result too unprecise. Some other
574 ;; combinations of argument types were affected, too; test that all
575 ;; of them are good to double-float precision.
576 (labels ((nearly-equal-p (x y)
577 "Are the arguments equal to nearly double-float precision?"
578 (declare (type double-float x y))
579 (< (/ (abs (- x y)) (abs y))
580 (* double-float-epsilon 4))) ; Differences in the two least
581 ; significant mantissa bits
582 ; are OK.
583 (test-complex (x y)
584 (and (nearly-equal-p (realpart x) (realpart y))
585 (nearly-equal-p (imagpart x) (imagpart y))))
586 (print-result (msg base power got expected)
587 (declare (ignorable msg base power got expected))
588 #+nil
589 (format t "~a (expt ~s ~s)~%got ~s~%expected ~s~%"
590 msg base power got expected)))
591 (let ((n-broken 0))
592 (flet ((test (base power coerce-to-type)
593 (let* ((got (expt base power))
594 (expected (expt (coerce base coerce-to-type) power))
595 (result (test-complex got expected)))
596 (print-result (if result "Good:" "Bad:")
597 base power got expected)
598 (unless result
599 (incf n-broken)))))
600 (dolist (base (list 2 ; fixnum
601 (expt 2 64) ; bignum
602 3/5 ; ratio
603 2.0f0)) ; single-float
604 (let ((power #c(-2.5d0 -4.5d0))) ; complex double-float
605 (test base power 'double-float)))
606 (dolist (base (list #c(2.0f0 3.0f0) ; complex single-float
607 #c(2 3) ; complex fixnum
608 (complex (expt 2 64) (expt 2 65))
609 ; complex bignum
610 #c(3/5 1/7))) ; complex ratio
611 (dolist (power (list #c(-2.5d0 -4.5d0) ; complex double-float
612 -2.5d0)) ; double-float
613 (test base power '(complex double-float)))))
614 (when (> n-broken 0)
615 (error "Number of broken combinations: ~a" n-broken)))))
617 (with-test (:name (:ldb :rlwinm :ppc))
618 (let ((one (checked-compile `(lambda (a) (ldb (byte 9 27) a))))
619 (two (checked-compile `(lambda (a)
620 (declare (type (integer -3 57216651) a))
621 (ldb (byte 9 27) a)))))
622 (assert (= 0 (- (funcall one 10) (funcall two 10))))))
624 ;; The ISQRT implementation is sufficiently complicated that it should
625 ;; be tested.
626 (with-test (:name :isqrt)
627 (labels ((test (x)
628 (let* ((r (isqrt x))
629 (r2 (expt r 2))
630 (s2 (expt (1+ r) 2)))
631 (unless (and (<= r2 x)
632 (> s2 x))
633 (error "isqrt failure for ~a" x))))
634 (tests (x)
635 (test x)
636 (let ((x2 (expt x 2)))
637 (test x2)
638 (test (1+ x2))
639 (test (1- x2)))))
640 (test most-positive-fixnum)
641 (test (1+ most-positive-fixnum))
642 (loop for i from 1 to 200
643 for pow = (expt 2 (1- i))
644 for j = (+ pow (random pow))
646 (tests i)
647 (tests j))
648 (dotimes (i 10)
649 (tests (random (expt 2 (+ 1000 (random 10000))))))))
651 ;; bug 1026634 (reported by Eric Marsden on sbcl-devel)
652 (with-test (:name :recursive-cut-to-width)
653 (assert (eql (funcall
654 (checked-compile
655 `(lambda (x)
656 (declare (optimize (space 3))
657 (type (integer 12417236377505266230
658 12417274239874990070)
660 (logand 8459622733968096971 x)))
661 12417237222845306758)
662 2612793697039849090)))
664 ;; Also reported by Eric Marsden on sbcl-devel (2013-06-06)
665 (with-test (:name :more-recursive-cut-to-width)
666 (assert (eql (funcall
667 (checked-compile
668 `(lambda (a b)
669 (declare (optimize (speed 2) (safety 0)))
670 (logand (the (eql 16779072918521075607) a)
671 (the (integer 21371810342718833225 21371810343571293860) b))))
672 16779072918521075607 21371810342718833263)
673 2923729245085762055)))
675 (with-test (:name :complicated-logand-identity)
676 (loop for k from -8 upto 8 do
677 (loop for min from -16 upto 16 do
678 (loop for max from min upto 16 do
679 (let ((f (checked-compile `(lambda (x)
680 (declare (type (integer ,min ,max) x))
681 (logand x ,k)))))
682 (loop for x from min upto max do
683 (assert (eql (logand x k) (funcall f x)))))))))
685 (with-test (:name :complicated-logior-identity)
686 (loop for k from -8 upto 8 do
687 (loop for min from -16 upto 16 do
688 (loop for max from min upto 16 do
689 (let ((f (checked-compile `(lambda (x)
690 (declare (type (integer ,min ,max) x))
691 (logior x ,k)))))
692 (loop for x from min upto max do
693 (assert (eql (logior x k) (funcall f x)))))))))
695 (with-test (:name :ldb-negative-index-no-error)
696 (assert-error
697 (funcall (checked-compile `(lambda (x y)
698 (ldb (byte x y) 100)))
699 -1 -2))
700 (assert-error
701 (funcall (checked-compile `(lambda (x y)
702 (mask-field (byte x y) 100)))
703 -1 -2))
704 (assert-error
705 (funcall (checked-compile `(lambda (x y)
706 (dpb 0 (byte x y) 100)))
707 -1 -2))
708 (assert-error
709 (funcall (checked-compile `(lambda (x y)
710 (deposit-field 0 (byte x y) 100)))
711 -1 -2)))
713 (with-test (:name :setf-mask-field)
714 (assert (= (funcall
715 (checked-compile `(lambda (a)
716 (setf (mask-field (byte 2 0) a) 1) a))
717 15))))
719 (with-test (:name :complex-multiply)
720 (assert (= (funcall
721 (checked-compile
722 `(lambda ()
723 (declare (optimize speed))
724 (let (z)
725 (expt (setf z (complex -0.123 -0.789)) 2)))))
726 #C(-0.60739195 0.194094))))
728 (with-test (:name :complex-sqrt)
729 (assert (= (expt (sqrt least-negative-double-float) 2)
730 least-negative-double-float)))
732 (with-test (:name :ldb-sign)
733 (assert (= (funcall (checked-compile
734 `(lambda (x)
735 (ldb (byte ,(1- sb-vm:n-word-bits) 0) x)))
737 12)))
739 (with-test (:name :mod-arith-large-constant)
740 (assert (= (funcall (checked-compile
741 '(lambda (x)
742 (declare (sb-ext:word x))
743 (logand sb-ext:most-positive-word
744 (+ x 2312423423))))
746 2312423435)))
748 (with-test (:name :bignum-ashift-left-fixnum)
749 (assert (= (eval '(ash most-negative-fixnum (1- sb-vm:n-word-bits)))
750 (eval '(* most-negative-fixnum (expt 2 (1- sb-vm:n-word-bits)))))))
752 (with-test (:name :fixnum-ldb-sign-bits)
753 (let ((fun (checked-compile `(lambda (x)
754 (declare (fixnum x))
755 (ldb (byte (/ sb-vm:n-word-bits 2)
756 (/ sb-vm:n-word-bits 2)) x)))))
757 (assert (= (funcall fun
758 most-positive-fixnum)
759 (ash most-positive-fixnum (- (/ sb-vm:n-word-bits 2)))))
760 (assert (= (funcall fun -1)
761 (1- (expt 2 (/ sb-vm:n-word-bits 2)))))))
763 (with-test (:name :dpb-sign-bits)
764 (let ((fun (checked-compile `(lambda (x)
765 (declare (fixnum x))
766 (dpb 1 (byte (/ sb-vm:n-word-bits 2)
767 (/ sb-vm:n-word-bits 2)) x)))))
768 (assert (= (funcall fun -1)
769 (logior (ash 1 (/ sb-vm:n-word-bits 2))
770 (logandc2 -1
771 (mask-field (byte (/ sb-vm:n-word-bits 2)
772 (/ sb-vm:n-word-bits 2))
773 -1)))))
774 (assert (= (funcall fun most-positive-fixnum)
775 (logior (ash 1 (/ sb-vm:n-word-bits 2))
776 (logandc2 most-positive-fixnum
777 (mask-field (byte (/ sb-vm:n-word-bits 2)
778 (/ sb-vm:n-word-bits 2))
779 -1)))))))
781 (with-test (:name :dpb-position-zero)
782 (let ((fun (checked-compile `(lambda (x)
783 (declare (sb-vm:word x))
784 (dpb 0 (byte (/ sb-vm:n-word-bits 2) 0) x)))))
785 (assert (= (funcall fun 1) 0))
786 (assert (= (funcall fun sb-ext:most-positive-word)
787 (logxor sb-ext:most-positive-word
788 (1- (expt 2 (/ sb-vm:n-word-bits 2))))))))
790 (with-test (:name :logand-mask-word)
791 (let ((fun (checked-compile `(lambda (x)
792 (logand x (ash sb-ext:most-positive-word -1))))))
793 (assert (= (funcall fun -1)
794 (ash most-positive-word -1)))))
796 (with-test (:name ://complex-real-single-float)
797 (assert (= (funcall (checked-compile `(lambda (b)
798 (declare (type single-float b))
799 (/ #c(1.0 2.0) b)))
800 1.0)
801 #c(1.0 2.0))))
803 (with-test (:name :unsigned-ash)
804 (let ((fun (checked-compile
805 `(lambda (x)
806 (declare (sb-vm:signed-word x))
807 (ash x -64)))))
808 (assert (zerop (funcall fun 123)))
809 (assert (= (funcall fun -321) -1))))