~ chicken-core (chicken-5) 92433dcf7ba701520ad7cd5a1e1365837107562e
commit 92433dcf7ba701520ad7cd5a1e1365837107562e Author: Peter Bex <peter@more-magic.net> AuthorDate: Sat Jan 31 22:31:21 2015 +0100 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sun May 31 14:15:51 2015 +0200 Add some tests from the numbers egg, they all pass in interpreted mode. To run the test suite we still need to do quite a bit of work on the compiler. diff --git a/LICENSE b/LICENSE index 095b9ac0..ba9c71f9 100644 --- a/LICENSE +++ b/LICENSE @@ -188,3 +188,34 @@ tests/r4rstest.scm: Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA; or view http://swissnet.ai.mit.edu/~jaffer/GPL.html + +tests/numbers-test-gauche.scm: + + Copyright (c) 2000-2010 Shiro Kawai <shiro@acm.org> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the authors nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/distribution/manifest b/distribution/manifest index 1493bda4..a6323df7 100644 --- a/distribution/manifest +++ b/distribution/manifest @@ -123,6 +123,9 @@ tests/embedded4.scm tests/condition-tests.scm tests/fixnum-tests.scm tests/numbers-string-conversion-tests.scm +tests/numbers-tests.scm +tests/numbers-tests-ashinn.scm +tests/numbers-tests-gauche.scm tests/path-tests.scm tests/posix-tests.scm tests/r4rstest.out diff --git a/tests/numbers-test-ashinn.scm b/tests/numbers-test-ashinn.scm new file mode 100644 index 00000000..bbedff1c --- /dev/null +++ b/tests/numbers-test-ashinn.scm @@ -0,0 +1,144 @@ +(include "test.scm") + +(current-test-epsilon 0) ;; We want exact comparisons by default + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; run tests + +(test-begin "numbers (Alex Shinn's tests)") + +(test-group "basic cases, fixnum base" + (test-equal (expt 0 0) 1) + (test-equal (expt 2 0) 1) + (test-equal (expt 2 1) 2) + (test-equal (expt 2 2) 4) + (test-equal (expt 3 2) 9) + (test-equal (expt 3 2.0) 9.0) + (parameterize ((current-test-epsilon 0.001)) + (test-equal (expt 3 2.1) 10.0451) + (test-equal (expt 3 0.1) 1.1161) + (test-equal (expt 3 -1) (/ 1 3)) + (test-equal (expt 3 -2) (/ 1 9)) + (test-equal (expt 3 -2.1) 0.09955))) + +(test-group "basic cases, flonum base" + (test-equal (expt 0.0 0) 1.0) + (test-equal (expt 3.14 0) 1.0) + (test-equal (expt 3.14 1) 3.14) + (test-equal (expt 3.14 2) 9.8596) + (test-equal (expt 3.14 2.0) 9.8596) + (parameterize ((current-test-epsilon 0.001)) + (test-equal (expt 3.14 2.1) 11.0548) + (test-equal (expt 3.14 0.1) 1.1212) + (test-equal (expt 3.14 -1) 0.31847) + (test-equal (expt 3.14 -2) 0.10142) + (test-equal (expt 3.14 -2.1) 0.090458))) + +(test-group "overflows into bignums" + (test-equal (expt 2 30) 1073741824) + (test-equal (expt 2 31) 2147483648) + (test-equal (expt 2 32) 4294967296) + (test-equal (expt 2 62) 4611686018427387904) + (test-equal (expt 2 63) 9223372036854775808) + (test-equal (expt 2 64) 18446744073709551616)) + +(define (one-followed-by-n-zeros n) + (string->number (string-append "1" (make-string n #\0)))) + +(test-group "bug reported on the chicken list" + (test-equal (expt 10 100) (one-followed-by-n-zeros 100))) + +(test-group "bignum base" + (test-equal (expt (one-followed-by-n-zeros 100) 0) 1) + (parameterize ((current-test-epsilon 0.001)) + (test-equal (expt (one-followed-by-n-zeros 100) 1) (one-followed-by-n-zeros 100)) + (test-equal (expt (one-followed-by-n-zeros 100) 2) (one-followed-by-n-zeros 200)) + (test-equal (expt (one-followed-by-n-zeros 100) 0.1) 10000000000.0))) + +(define (real-approx= expected result) + (cond ((zero? result) (< (abs expected) (current-test-epsilon))) + ((zero? expected) (< (abs result) (current-test-epsilon))) + (else (< (min (abs (- 1 (/ expected result))) + (abs (- 1 (/ result expected)))) + (current-test-epsilon))))) + +;; test-equal? doesn't work on compnums +(define (test-equal/comp? a b) + (and (real-approx= (real-part a) (real-part b)) + (real-approx= (imag-part a) (imag-part b)))) + +(test-group "e^(pi*i) = -1" + (parameterize ((current-test-epsilon 0.001) + (current-test-comparator test-equal/comp?)) + (test-equal (expt (exp 1) (* (acos -1) (sqrt -1))) -1.0))) + +(test-group "rational rounding" + (test-equal (round (/ 9 10)) 1) + (test-equal (round (/ 6 10)) 1) + (test-equal (round (/ 5 10)) 0) + (test-equal (round (/ 1 10)) 0) + (test-equal (round (/ 0 10)) 0) + (test-equal (round (/ -1 10)) 0) + (test-equal (round (/ -5 10)) 0) + (test-equal (round (/ -6 10)) -1) + (test-equal (round (/ -9 10)) -1) + (test-equal (round (/ (expt 10 10000) (+ (expt 10 10000) 1))) 1) + (test-equal (round (/ (+ 1 (expt 10 10000)) (expt 10 100))) (expt 10 9900))) + +(test-group "srfi-33" + (test-equal (bitwise-and #b0 #b1) 0) + (test-equal (bitwise-and #b1 #b1) 1) + (test-equal (bitwise-and #b1 #b10) 0) + (test-equal (bitwise-and #b11 #b10) #b10) + (test-equal (bitwise-and #b101 #b111) #b101) + (test-equal (bitwise-and -1 #b111) #b111) + (test-equal (bitwise-and -2 #b111) #b110) + (test-equal (bitwise-and -4290775858 1694076839) 3769478) + (test-equal (bitwise-and -193073517 1689392892) 1680869008) + ;; (test-equal (bitwise-ior 1694076839 -4290775858) -2600468497) + ;; (test-equal (bitwise-ior -193073517 1689392892) -184549633) + ;; (test-equal (bitwise-xor 1694076839 -4290775858) -2604237975) + ;; (test-equal (bitwise-xor -193073517 1689392892) -1865418641) + + (test-equal (arithmetic-shift 1 0) 1) + (test-equal (arithmetic-shift 1 1) 2) + (test-equal (arithmetic-shift 1 2) 4) + (test-equal (arithmetic-shift 1 3) 8) + (test-equal (arithmetic-shift 1 4) 16) + (test-equal (arithmetic-shift 1 31) (expt 2 31)) + (test-equal (arithmetic-shift 1 32) (expt 2 32)) + (test-equal (arithmetic-shift 1 33) (expt 2 33)) + (test-equal (arithmetic-shift 1 63) (expt 2 63)) + (test-equal (arithmetic-shift 1 64) (expt 2 64)) + (test-equal (arithmetic-shift 1 65) (expt 2 65)) + (test-equal (arithmetic-shift 1 127) (expt 2 127)) + (test-equal (arithmetic-shift 1 128) (expt 2 128)) + (test-equal (arithmetic-shift 1 129) (expt 2 129)) + (test-equal (arithmetic-shift 11829675785914119 8) 3028397001194014464) + + (test-equal (arithmetic-shift -1 0) -1) + (test-equal (arithmetic-shift -1 1) -2) + (test-equal (arithmetic-shift -1 2) -4) + (test-equal (arithmetic-shift -1 3) -8) + (test-equal (arithmetic-shift -1 4) -16) + (test-equal (arithmetic-shift -1 31) (- (expt 2 31))) + (test-equal (arithmetic-shift -1 32) (- (expt 2 32))) + (test-equal (arithmetic-shift -1 33) (- (expt 2 33))) + (test-equal (arithmetic-shift -1 63) (- (expt 2 63))) + (test-equal (arithmetic-shift -1 64) (- (expt 2 64))) + (test-equal (arithmetic-shift -1 65) (- (expt 2 65))) + (test-equal (arithmetic-shift -1 127) (- (expt 2 127))) + (test-equal (arithmetic-shift -1 128) (- (expt 2 128))) + (test-equal (arithmetic-shift -1 129) (- (expt 2 129))) + + (test-equal (arithmetic-shift 1 -63) 0) + (test-equal (arithmetic-shift 1 -64) 0) + (test-equal (arithmetic-shift 1 -65) 0) + + (test-equal (arithmetic-shift #x100000000000000010000000000000000 64) + #x1000000000000000100000000000000000000000000000000) + + (test-assert (not (bit-set? 1 64))) + (test-assert (bit-set? #x10000000000000000 64))) + +(test-end) diff --git a/tests/numbers-test-gauche.scm b/tests/numbers-test-gauche.scm new file mode 100644 index 00000000..2d4b5f15 --- /dev/null +++ b/tests/numbers-test-gauche.scm @@ -0,0 +1,2118 @@ +;; +;; test numeric system implementation +;; +;; These tests are from Gauche Scheme (v0.9.1), which can be found at +;; http://practical-scheme.net/gauche/index.html +;; Some modifications were made to allow it to be used with the "test" +;; egg for Chicken +;; +;; Copyright (c) 2000-2010 Shiro Kawai <shiro@acm.org> +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; +;; 3. Neither the name of the authors nor the names of its contributors +;; may be used to endorse or promote products derived from this +;; software without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;; + +(include "test.scm") + +(define (exp2 pow) + (do ((i 0 (+ i 1)) + (m 1 (+ m m))) + ((>= i pow) m))) + +(define (fermat n) ;Fermat's number + (+ (expt 2 (expt 2 n)) 1)) + +;; Gauche compat +(define (greatest-fixnum) most-positive-fixnum) +(define (least-fixnum) most-negative-fixnum) +(define (fixnum-width) fixnum-precision) + +(define ash arithmetic-shift) +(define logior bitwise-ior) +(define logand bitwise-and) +(define lognot bitwise-not) +(define (logtest a b) (= (bitwise-and a b) b)) + +(define-syntax let1 + (syntax-rules () + ((_ var val forms ...) + (let ((var val)) forms ...)))) + +(define (integer->digit i r) + (and (< i r) + (if (< i 10) + (integer->char (+ (char->integer #\0) i)) + (integer->char (+ (char->integer #\a) (- i 10)))))) + +(define (read-from-string s) (with-input-from-string s read)) + +(define (truncate->exact x) (inexact->exact (truncate x))) +(define (round->exact x) (inexact->exact (round x))) +(define (floor->exact x) (inexact->exact (floor x))) +(define (ceiling->exact x) (inexact->exact (ceiling x))) + +;; This is probably a bit silly +(define (+. . args) (if (null? args) 0.0 (apply + (map exact->inexact args)))) +(define (-. . args) (apply - (map exact->inexact args))) +(define (*. . args) (if (null? args) 1.0 (apply * (map exact->inexact args)))) +(define (/. . args) (apply / (map exact->inexact args))) + +(test-begin "Gauche numbers test") + +;;================================================================== +;; Reader/writer +;; + +;;------------------------------------------------------------------ +(test-begin "integer addition & reader") + +(define (i-tester x) + (list x (+ x -1 x) (+ x x) (- x) (- (+ x -1 x)) (- 0 x x) (- 0 x x 1))) + +(test-equal "around 2^28" + (i-tester (exp2 28)) + '(268435456 536870911 536870912 + -268435456 -536870911 -536870912 -536870913)) + +(test-equal "around 2^31" + (i-tester (exp2 31)) + '(2147483648 4294967295 4294967296 + -2147483648 -4294967295 -4294967296 -4294967297)) + +(test-equal "around 2^60" + (i-tester (exp2 60)) + '(1152921504606846976 2305843009213693951 2305843009213693952 + -1152921504606846976 -2305843009213693951 -2305843009213693952 + -2305843009213693953)) + +(test-equal "around 2^63" + (i-tester (exp2 63)) + '(9223372036854775808 18446744073709551615 18446744073709551616 + -9223372036854775808 -18446744073709551615 -18446744073709551616 + -18446744073709551617)) + +(test-equal "around 2^127" + (i-tester (exp2 127)) + '(170141183460469231731687303715884105728 + 340282366920938463463374607431768211455 + 340282366920938463463374607431768211456 + -170141183460469231731687303715884105728 + -340282366920938463463374607431768211455 + -340282366920938463463374607431768211456 + -340282366920938463463374607431768211457)) + +;; test for reader's overflow detection code +(test-equal "peculiarity around 2^32" + (* 477226729 10) 4772267290) + +(test-equal "radix" (list #b1010101001010101 + #o1234567 + #o12345677654321 + #d123456789 + #d123456789987654321 + #x123456 + #xdeadbeef + #xDeadBeef) + '(43605 342391 718048024785 + 123456789 123456789987654321 + 1193046 3735928559 3735928559)) + +(test-equal "exactness" (exact? #e10) #t) +(test-equal "exactness" (exact? #e10.0) #t) +(test-equal "exactness" (exact? #e10e10) #t) +(test-equal "exactness" (exact? #e12.34) #t) +(test-equal "inexactness" (exact? #i10) #f) +(test-equal "inexactness" (exact? #i10.0) #f) +(test-equal "inexactness" (exact? #i12.34) #f) + +(test-equal "exactness & radix" (list (exact? #e#xdeadbeef) + #e#xdeadbeef + (exact? #x#edeadbeef) + #x#edeadbeef) + '(#t 3735928559 #t 3735928559)) +(test-equal "inexactness & radix" (list (exact? #i#xdeadbeef) + #i#xdeadbeef + (exact? #x#ideadbeef) + #x#ideadbeef) + '(#f 3735928559.0 #f 3735928559.0)) + +(test-equal "invalid exactness/radix spec" (or (string->number "#e") + (string->number "#i") + (string->number "#e#i3") + (string->number "#i#e5") + (string->number "#x#o13") + (string->number "#e#b#i00101")) + #f) + +(define (radix-tester radix) + (list + (let loop ((digits 0) + (input "1") + (value 1)) + (cond ((> digits 64) #t) + ((eqv? (string->number input radix) value) + (loop (+ digits 1) (string-append input "0") (* value radix))) + (else #f))) + (let loop ((digits 0) + (input (string (integer->digit (- radix 1) radix))) + (value (- radix 1))) + (cond ((> digits 64) #t) + ((eqv? (string->number input radix) value) + (loop (+ digits 1) + (string-append input (string (integer->digit (- radix 1) radix))) + (+ (* value radix) (- radix 1)))) + (else #f))))) + +(test-equal "base-2 reader" (radix-tester 2) '(#t #t)) +(test-equal "base-3 reader" (radix-tester 3) '(#t #t)) +(test-equal "base-4 reader" (radix-tester 4) '(#t #t)) +(test-equal "base-5 reader" (radix-tester 5) '(#t #t)) +(test-equal "base-6 reader" (radix-tester 6) '(#t #t)) +(test-equal "base-7 reader" (radix-tester 7) '(#t #t)) +(test-equal "base-8 reader" (radix-tester 8) '(#t #t)) +(test-equal "base-9 reader" (radix-tester 9) '(#t #t)) +(test-equal "base-10 reader" (radix-tester 10) '(#t #t)) +(test-equal "base-11 reader" (radix-tester 11) '(#t #t)) +(test-equal "base-12 reader" (radix-tester 12) '(#t #t)) +(test-equal "base-13 reader" (radix-tester 13) '(#t #t)) +(test-equal "base-14 reader" (radix-tester 14) '(#t #t)) +(test-equal "base-15 reader" (radix-tester 15) '(#t #t)) +(test-equal "base-16 reader" (radix-tester 16) '(#t #t)) +(test-equal "base-17 reader" (radix-tester 17) '(#t #t)) +(test-equal "base-18 reader" (radix-tester 18) '(#t #t)) +(test-equal "base-19 reader" (radix-tester 19) '(#t #t)) +(test-equal "base-20 reader" (radix-tester 20) '(#t #t)) +(test-equal "base-21 reader" (radix-tester 21) '(#t #t)) +(test-equal "base-22 reader" (radix-tester 22) '(#t #t)) +(test-equal "base-23 reader" (radix-tester 23) '(#t #t)) +(test-equal "base-24 reader" (radix-tester 24) '(#t #t)) +(test-equal "base-25 reader" (radix-tester 25) '(#t #t)) +(test-equal "base-26 reader" (radix-tester 26) '(#t #t)) +(test-equal "base-27 reader" (radix-tester 27) '(#t #t)) +(test-equal "base-28 reader" (radix-tester 28) '(#t #t)) +(test-equal "base-29 reader" (radix-tester 29) '(#t #t)) +(test-equal "base-30 reader" (radix-tester 30) '(#t #t)) +(test-equal "base-31 reader" (radix-tester 31) '(#t #t)) +(test-equal "base-32 reader" (radix-tester 32) '(#t #t)) +(test-equal "base-33 reader" (radix-tester 33) '(#t #t)) +(test-equal "base-34 reader" (radix-tester 34) '(#t #t)) +(test-equal "base-35 reader" (radix-tester 35) '(#t #t)) +(test-equal "base-36 reader" (radix-tester 36) '(#t #t)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "rational reader") + +(define (rational-test v) + (if (number? v) (list v (exact? v)) v)) + +(test-equal "rational reader" (rational-test '1234/1) '(1234 #t)) +(test-equal "rational reader" (rational-test '-1234/1) '(-1234 #t)) +(test-equal "rational reader" (rational-test '+1234/1) '(1234 #t)) +;; The following is invalid R5RS syntax, so it's commented out (it fails, too) +#;(test-equal "rational reader" (rational-test '1234/-1) '|1234/-1|) +(test-equal "rational reader" (rational-test '2468/2) '(1234 #t)) +(test-equal "rational reader" (rational-test '1/2) '(1/2 #t)) +(test-equal "rational reader" (rational-test '-1/2) '(-1/2 #t)) +(test-equal "rational reader" (rational-test '+1/2) '(1/2 #t)) +(test-equal "rational reader" (rational-test '751/1502) '(1/2 #t)) + +(test-equal "rational reader" (rational-test (string->number "3/03")) + '(1 #t)) +(test-equal "rational reader" (rational-test (string->number "3/0")) #;'(+inf.0 #f) ; <- I think that's wrong in Gauche + #f) +(test-equal "rational reader" (rational-test (string->number "-3/0")) #;'(-inf.0 #f) ; same as above + #f) +(test-equal "rational reader" (rational-test (string->number "3/3/4")) + #f) +(test-equal "rational reader" (rational-test (string->number "1/2.")) + #f) +(test-equal "rational reader" (rational-test (string->number "1.3/2")) + #f) + +(test-error "rational reader" (rational-test (read-from-string "#e3/0"))) +(test-error "rational reader" (rational-test (read-from-string "#e-3/0"))) + +(test-equal "rational reader w/#e" (rational-test '#e1234/1) + '(1234 #t)) +(test-equal "rational reader w/#e" (rational-test '#e-1234/1) + '(-1234 #t)) +(test-equal "rational reader w/#e" (rational-test '#e32/7) + '(32/7 #t)) +(test-equal "rational reader w/#e" (rational-test '#e-32/7) + '(-32/7 #t)) +(test-equal "rational reader w/#i" (rational-test '#i1234/1) + '(1234.0 #f)) +(test-equal "rational reader w/#i" (rational-test '#i-1234/1) + '(-1234.0 #f)) +(test-equal "rational reader w/#i" (rational-test '#i-4/32) + '(-0.125 #f)) + +(test-equal "rational reader w/radix" (rational-test '#e#xff/11) + '(15 #t)) +(test-equal "rational reader w/radix" (rational-test '#o770/11) + '(56 #t)) +(test-equal "rational reader w/radix" (rational-test '#x#iff/11) + '(15.0 #f)) + +(test-equal "rational reader edge case" (symbol? (read-from-string "/1")) #t) +(test-equal "rational reader edge case" (symbol? (read-from-string "-/1")) #t) +(test-equal "rational reader edge case" (symbol? (read-from-string "+/1")) #t) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "flonum reader") + +(define (flonum-test v) + (if (number? v) (list v (inexact? v)) v)) + +(test-equal "flonum reader" (flonum-test 3.14) '(3.14 #t)) +(test-equal "flonum reader" (flonum-test 0.14) '(0.14 #t)) +(test-equal "flonum reader" (flonum-test .14) '(0.14 #t)) +(test-equal "flonum reader" (flonum-test 3.) '(3.0 #t)) +(test-equal "flonum reader" (flonum-test -3.14) '(-3.14 #t)) +(test-equal "flonum reader" (flonum-test -0.14) '(-0.14 #t)) +(test-equal "flonum reader" (flonum-test -.14) '(-0.14 #t)) +(test-equal "flonum reader" (flonum-test -3.) '(-3.0 #t)) +(test-equal "flonum reader" (flonum-test +3.14) '(3.14 #t)) +(test-equal "flonum reader" (flonum-test +0.14) '(0.14 #t)) +(test-equal "flonum reader" (flonum-test +.14) '(0.14 #t)) +(test-equal "flonum reader" (flonum-test +3.) '(3.0 #t)) +(test-equal "flonum reader" (flonum-test .0) '(0.0 #t)) +(test-equal "flonum reader" (flonum-test 0.) '(0.0 #t)) +(test-equal "flonum reader" (string->number ".") #f) +(test-equal "flonum reader" (string->number "-.") #f) +(test-equal "flonum reader" (string->number "+.") #f) + +(test-equal "flonum reader (exp)" (flonum-test 3.14e2) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314e3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test 314e0) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test 314e-0) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test 3140000e-4) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test -3.14e2) '(-314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test -.314e3) '(-314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test -314e0) '(-314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test -314.e-0) '(-314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test -3140000e-4) '(-314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test +3.14e2) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test +.314e3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test +314.e0) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test +314e-0) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test +3140000.000e-4) '(314.0 #t)) + +(test-equal "flonum reader (exp)" (flonum-test .314E3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314s3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314S3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314l3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314L3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314f3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314F3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314d3) '(314.0 #t)) +(test-equal "flonum reader (exp)" (flonum-test .314D3) '(314.0 #t)) + +(test-equal "flonum reader (minimum denormalized number 5.0e-324)" (let1 x (expt 2.0 -1074) + (= x (string->number (number->string x)))) + #t) +(test-equal "flonum reader (minimum denormalized number -5.0e-324)" (let1 x (- (expt 2.0 -1074)) + (= x (string->number (number->string x)))) + #t) + + +(test-equal "padding" (flonum-test '1#) '(10.0 #t)) +(test-equal "padding" (flonum-test '1#.) '(10.0 #t)) +(test-equal "padding" (flonum-test '1#.#) '(10.0 #t)) +(test-equal "padding" (flonum-test '10#.#) '(100.0 #t)) +(test-equal "padding" (flonum-test '1##.#) '(100.0 #t)) +(test-equal "padding" (flonum-test '100.0#) '(100.0 #t)) +(test-equal "padding" (flonum-test '1.#) '(1.0 #t)) + +(test-equal "padding" (flonum-test '1#1) '|1#1|) +(test-equal "padding" (flonum-test '1##1) '|1##1|) +(test-equal "padding" (flonum-test '1#.1) '|1#.1|) +(test-equal "padding" (flonum-test '1.#1) '|1.#1|) + +(test-equal "padding" (flonum-test '.#) '|.#|) +(test-equal "padding" (flonum-test '0.#) '(0.0 #t)) +(test-equal "padding" (flonum-test '.0#) '(0.0 #t)) +(test-equal "padding" (flonum-test '0#) '(0.0 #t)) +(test-equal "padding" (flonum-test '0#.#) '(0.0 #t)) +(test-equal "padding" (flonum-test '0#.0) '|0#.0|) + +(test-equal "padding" (flonum-test '1#e2) '(1000.0 #t)) +(test-equal "padding" (flonum-test '1##e1) '(1000.0 #t)) +(test-equal "padding" (flonum-test '1#.##e2) '(1000.0 #t)) +(test-equal "padding" (flonum-test '0.#e2) '(0.0 #t)) +(test-equal "padding" (flonum-test '.0#e2) '(0.0 #t)) +(test-equal "padding" (flonum-test '.##e2) '|.##e2|) + +(test-equal "padding (exactness)" (flonum-test '#e1##) '(100 #f)) +(test-equal "padding (exactness)" (flonum-test '#e12#) '(120 #f)) +(test-equal "padding (exactness)" (flonum-test '#e12#.#) '(120 #f)) +(test-equal "padding (exactness)" (flonum-test '#i1##) '(100.0 #t)) +(test-equal "padding (exactness)" (flonum-test '#i12#) '(120.0 #t)) +(test-equal "padding (exactness)" (flonum-test '#i12#.#) '(120.0 #t)) + +(test-equal "exponent out-of-range 1" (flonum-test '1e309) '(+inf.0 #t)) +(test-equal "exponent out-of-range 2" (flonum-test '1e10000) '(+inf.0 #t)) +;; TODO: Figure out what goes wrong here +;(test-equal "exponent out-of-range 3" (flonum-test '1e1000000000000000000000000000000000000000000000000000000000000000) '(+inf.0 #t)) +(test-equal "exponent out-of-range 4" (flonum-test '-1e309) '(-inf.0 #t)) +(test-equal "exponent out-of-range 5" (flonum-test '-1e10000) '(-inf.0 #t)) +;(test-equal "exponent out-of-range 6" (flonum-test '-1e1000000000000000000000000000000000000000000000000000000000000000) '(-inf.0 #t)) +(test-equal "exponent out-of-range 7" (flonum-test '1e-324) '(0.0 #t)) +(test-equal "exponent out-of-range 8" (flonum-test '1e-1000) '(0.0 #t)) +;(test-equal "exponent out-of-range 9" (flonum-test '1e-1000000000000000000000000000000000000000000000000000000000000000000) '(0.0 #t)) + +(test-equal "no integral part" (read-from-string ".5") 0.5) +(test-equal "no integral part" (read-from-string "-.5") -0.5) +(test-equal "no integral part" (read-from-string "+.5") 0.5) +(test-end) + +;;------------------------------------------------------------------ +(test-begin "exact fractional number") + +(test-equal "exact fractonal number" (string->number "#e1.2345e4") + 12345) +(test-equal "exact fractonal number" (string->number "#e1.2345e14") + 123450000000000) +(test-equal "exact fractonal number" (string->number "#e1.2345e2") + 12345/100) +(test-equal "exact fractonal number" (string->number "#e1.2345e-2") + 12345/1000000) +(test-equal "exact fractonal number" (string->number "#e-1.2345e4") + -12345) +(test-equal "exact fractonal number" (string->number "#e-1.2345e14") + -123450000000000) +(test-equal "exact fractonal number" (string->number "#e-1.2345e2") + -12345/100) +(test-equal "exact fractonal number" (string->number "#e-1.2345e-2") + -12345/1000000) + +(test-equal "exact fractonal number" (string->number "#e0.0001e300") + (expt 10 296)) +(test-equal "exact fractonal number" (string->number "#e-0.0001e300") + (- (expt 10 296))) + +(test-equal "exact fractonal number" (read-from-string "#e1e330") + (expt 10 330)) +(test-equal "exact fractonal number" (read-from-string "#e1e-330") + (expt 10 -330)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "complex reader") + +(define (decompose-complex z) + (cond ((real? z) z) + ((complex? z) + (list (real-part z) (imag-part z))) + (else z))) + +;; Fixed for exactness (Gauche's complex numbers are always inexact) +(test-equal "complex reader" (decompose-complex '1+i) '(1 1)) +(test-equal "complex reader" (decompose-complex '1+1i) '(1 1)) +(test-equal "complex reader" (decompose-complex '1-i) '(1 -1)) +(test-equal "complex reader" (decompose-complex '1-1i) '(1 -1)) +(test-equal "complex reader" (decompose-complex '1.0+1i) '(1.0 1.0)) +(test-equal "complex reader" (decompose-complex '1.0+1.0i) '(1.0 1.0)) +(test-equal "complex reader" (decompose-complex '1e-5+1i) '(1e-5 1.0)) +(test-equal "complex reader" (decompose-complex '1e+5+1i) '(1e+5 1.0)) +(test-equal "complex reader" (decompose-complex '1+1e-5i) '(1.0 1e-5)) +(test-equal "complex reader" (decompose-complex '1+1e+5i) '(1.0 1e+5)) +(test-equal "complex reader" (decompose-complex '0.1+0.1e+5i) '(0.1 1e+4)) +(test-equal "complex reader" (decompose-complex '+i) '(0 1)) +(test-equal "complex reader" (decompose-complex '-i) '(0 -1)) +(test-equal "complex reader" (decompose-complex '+1i) '(0 1)) +(test-equal "complex reader" (decompose-complex '-1i) '(0 -1)) +(test-equal "complex reader" (decompose-complex '+1.i) '(0.0 1.0)) +(test-equal "complex reader" (decompose-complex '-1.i) '(0.0 -1.0)) +(test-equal "complex reader" (decompose-complex '+1.0i) '(0.0 1.0)) +(test-equal "complex reader" (decompose-complex '-1.0i) '(0.0 -1.0)) +(test-equal "complex reader" (decompose-complex '1+0.0i) 1.0) +(test-equal "complex reader" (decompose-complex '1+.0i) 1.0) +(test-equal "complex reader" (decompose-complex '1+0.i) 1.0) +(test-equal "complex reader" (decompose-complex '1+0.0e-43i) 1.0) +(test-equal "complex reader" (decompose-complex '1e2+0.0e-43i) 100.0) + +(test-equal "complex reader" (decompose-complex 'i) 'i) +(test-equal "complex reader" (decompose-complex (string->number ".i")) #f) +(test-equal "complex reader" (decompose-complex (string->number "+.i")) #f) +(test-equal "complex reader" (decompose-complex (string->number "-.i")) #f) +(test-equal "complex reader" (decompose-complex '33i) '33i) +(test-equal "complex reader" (decompose-complex 'i+1) 'i+1) +(test-equal "complex reader" (decompose-complex '++i) '|++i|) +(test-equal "complex reader" (decompose-complex '--i) '|--i|) + +(test-equal "complex reader" (decompose-complex 1/2+1/2i) '(1/2 1/2)) +(test-equal "complex reader" (decompose-complex 0+1/2i) '(0 1/2)) +(test-equal "complex reader" (decompose-complex -1/2i) '(0 -1/2)) +(test-equal "complex reader" (decompose-complex 1/2-0/2i) 1/2) +;; The following is also invalid R5RS syntax, so it's commented out +#;(test-equal "complex reader" (decompose-complex (string->number "1/2-1/0i")) '(0.5 -inf.0)) + +(test-equal "complex reader (polar)" (make-polar 1.0 1.0) 1.0@1.0) +(test-equal "complex reader (polar)" (make-polar 1.0 -1.0) 1.0@-1.0) +(test-equal "complex reader (polar)" (make-polar 1.0 1.0) 1.0@+1.0) +(test-equal "complex reader (polar)" (make-polar -7.0 -3.0) -7@-3.0) +(test-equal "complex reader (polar)" (make-polar 3.5 -3.0) 7/2@-3.0) +(test-equal "complex reader (polar)" (string->number "7/2@-3.14i") #f) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "integer writer syntax") + +(define (i-tester2 x) + (map number->string (i-tester x))) + +(test-equal "around 2^28" + (i-tester2 (exp2 28)) + '("268435456" "536870911" "536870912" + "-268435456" "-536870911" "-536870912" "-536870913")) + +(test-equal "around 2^31" + (i-tester2 (exp2 31)) + '("2147483648" "4294967295" "4294967296" + "-2147483648" "-4294967295" "-4294967296" "-4294967297")) + +(test-equal "around 2^60" + (i-tester2 (exp2 60)) + '("1152921504606846976" "2305843009213693951" "2305843009213693952" + "-1152921504606846976" "-2305843009213693951" "-2305843009213693952" + "-2305843009213693953")) + +(test-equal "around 2^63" + (i-tester2 (exp2 63)) + '("9223372036854775808" "18446744073709551615" "18446744073709551616" + "-9223372036854775808" "-18446744073709551615" "-18446744073709551616" + "-18446744073709551617")) + +(test-equal "around 2^127" + (i-tester2 (exp2 127)) + '("170141183460469231731687303715884105728" + "340282366920938463463374607431768211455" + "340282366920938463463374607431768211456" + "-170141183460469231731687303715884105728" + "-340282366920938463463374607431768211455" + "-340282366920938463463374607431768211456" + "-340282366920938463463374607431768211457")) + +(test-end) + +;;================================================================== +;; Conversions +;; + +;; We first test expt, for we need to use it to test exact<->inexact +;; conversion stuff. +(test-begin "expt") + +(test-equal "exact expt" (expt 5 0) 1) +(test-equal "exact expt" (expt 5 10) 9765625) +(test-equal "exact expt" (expt 5 13) 1220703125) +(test-equal "exact expt" (expt 5 123) 94039548065783000637498922977779654225493244541767001720700136502273380756378173828125) +(test-equal "exact expt" (expt 5 -123) 1/94039548065783000637498922977779654225493244541767001720700136502273380756378173828125) +(test-equal "exact expt" (expt -5 0) 1) +(test-equal "exact expt" (expt -5 10) 9765625) +(test-equal "exact expt" (expt -5 13) -1220703125) +(test-equal "exact expt" (expt -5 123) -94039548065783000637498922977779654225493244541767001720700136502273380756378173828125) +(test-equal "exact expt" (expt -5 -123) -1/94039548065783000637498922977779654225493244541767001720700136502273380756378173828125) +(test-equal "exact expt" (expt 1 720000) 1) +(test-equal "exact expt" (expt -1 720000) 1) +(test-equal "exact expt" (expt -1 720001) -1) + +(test-equal "exact expt (ratinoal)" (expt 2/3 33) + 8589934592/5559060566555523) +(test-equal "exact expt (rational)" (expt -2/3 33) + -8589934592/5559060566555523) +(test-equal "exact expt (ratinoal)" (expt 2/3 -33) + 5559060566555523/8589934592) + +(test-end) + +(parameterize ((current-test-epsilon 10e7)) + (test-equal "expt (coercion to inexact)" (expt 2 1/2) + 1.4142135623730951)) ;; NB: pa$ will be tested later + +(test-begin "exact<->inexact") + +(for-each + (lambda (e&i) + (let ((e (car e&i)) + (i (cdr e&i))) + (test-equal (format "exact->inexact ~s" i) (exact->inexact e) i) + (test-equal (format "exact->inexact ~s" (- i)) (exact->inexact (- e)) (- i)) + (test-equal (format "inexact->exact ~s" e) (inexact->exact i) e) + (test-equal (format "inexact->exact ~s" (- e)) (inexact->exact (- i)) (- e)) + )) + `((0 . 0.0) + (1 . 1.0) + (-1 . -1.0) + (,(expt 2 52) . ,(expt 2.0 52)) + (,(expt 2 53) . ,(expt 2.0 53)) + (,(expt 2 54) . ,(expt 2.0 54)) + )) + +;; Rounding bignum to flonum, edge cases. +;; Test patterns: +;; +;; <------53bits-------> +;;a) 100000000...000000000100000....0000 round down (r0) +;;b) 100000000...000000000100000....0001 round up (r1) +;;c) 100000000...000000001100000....0000 round up (r2) +;;d) 100000000...000000001011111....1111 round down (r1) +;;e) 111111111...111111111100000....0000 round up, carry over (* r0 2) +;;f) 101111111...111111111100000....0000 round up, no carry over (r3) +;; <--32bits--> +;;g) 100..0000111.....1111100000....0000 round up; boundary on ILP32 (r4) + +(let loop ((n 0) + (a (+ (expt 2 53) 1)) + (c (+ (expt 2 53) 3)) + (e (- (expt 2 54) 1)) + (f (+ (expt 2 53) (expt 2 52) -1)) + (g (+ (expt 2 53) (expt 2 33) -1)) + (r0 (expt 2.0 53)) + (r1 (+ (expt 2.0 53) 2.0)) + (r2 (+ (expt 2.0 53) 4.0)) + (r3 (+ (expt 2.0 53) (expt 2.0 52))) + (r4 (+ (expt 2.0 53) (expt 2.0 33)))) + (when (< n 32) + (test-equal (format "exact->inexact, pattern a: round down (~a)" n) + (exact->inexact a) r0) + (test-equal (format "exact->inexact, pattern b: round up (~a)" n) + (exact->inexact (+ a 1)) r1) + (test-equal (format "exact->inexact, pattern c: round up (~a)" n) + (exact->inexact c) r2) + (test-equal (format "exact->inexact, pattern d: round down (~a)" n) + (exact->inexact (- c 1)) r1) + (test-equal (format "exact->inexact, pattern e: round up (~a)" n) + (exact->inexact e) (* r0 2.0)) + (test-equal (format "exact->inexact, pattern f: round up (~a)" n) + (exact->inexact f) r3) + (test-equal (format "exact->inexact, pattern g: round up (~a)" n) + (exact->inexact g) r4) + (loop (+ n 1) (ash a 1) (ash c 1) (ash e 1) (ash f 1) (ash g 1) + (* r0 2.0) (* r1 2.0) (* r2 2.0) (* r3 2.0) (* r4 2.0)))) + + +(parameterize ((current-test-epsilon 10e12)) + (test-equal "expt (ratnum with large denom and numer) with inexact conversion 1" + (exact->inexact (expt 8/9 342)) + (expt 8/9 342.0)) + + (test-equal "expt (ratnum with large denom and numer) with inexact conversion 2" + (exact->inexact (expt -8/9 343)) + (expt -8/9 343.0))) + +;; The following few tests covers RATNUM paths in Scm_GetDouble +(test-equal "expt (ratnum with large denom and numer) with inexact conversion 3" + (exact->inexact (/ (expt 10 20) (expt 10 328))) 1.0e-308) +;; In the original Gauche test this checked for a return value of 0.0, but +;; that's quite Gauche-specific. We return 1.0e-309. +;; It's probably wrong to test this kind of behaviour in the first place... +(test-equal "expt (ratnum with large denom and numer) with inexact conversion 4" + (exact->inexact (/ (expt 10 20) (expt 10 329))) 1.0e-309) +(test-equal "expt (ratnum with large denom and numer) with inexact conversion 5" + (exact->inexact (/ (expt 10 328) (expt 10 20))) 1.0e308) +(test-equal "expt (ratnum with large denom and numer) with inexact conversion 6" + (exact->inexact (/ (expt 10 329) (expt 10 20))) +inf.0) +(test-equal "expt (ratnum with large denom and numer) with inexact conversion 7" + (exact->inexact (/ (expt -10 329) (expt 10 20))) -inf.0) + +(test-end) + +;;================================================================== +;; Predicates +;; + +(test-begin "predicates") + +(test-equal "integer?" (integer? 0) #t) +(test-equal "integer?" (integer? 85736847562938475634534245) #t) +(test-equal "integer?" (integer? 85736.534245) #f) +(test-equal "integer?" (integer? 3.14) #f) +(test-equal "integer?" (integer? 3+4i) #f) +(test-equal "integer?" (integer? 3+0i) #t) +(test-equal "integer?" (integer? #f) #f) + +(test-equal "rational?" (rational? 0) #t) +(test-equal "rational?" (rational? 85736847562938475634534245) #t) +(test-equal "rational?" (rational? 1/2) #t) +(test-equal "rational?" (rational? 85736.534245) #t) +(test-equal "rational?" (rational? 3.14) #t) +(test-equal "rational?" (rational? 3+4i) #f) +(test-equal "rational?" (rational? 3+0i) #t) +(test-equal "rational?" (rational? #f) #f) +(test-equal "rational?" (rational? +inf.0) #f) +(test-equal "rational?" (rational? -inf.0) #f) +(test-equal "rational?" (rational? +nan.0) #f) + +(test-equal "real?" (real? 0) #t) +(test-equal "real?" (real? 85736847562938475634534245) #t) +(test-equal "real?" (real? 857368.4756293847) #t) +(test-equal "real?" (real? 3+0i) #t) +(test-equal "real?" (real? 3+4i) #f) +(test-equal "real?" (real? +4.3i) #f) +(test-equal "real?" (real? '()) #f) +(test-equal "real?" (real? +inf.0) #t) +(test-equal "real?" (real? -inf.0) #t) +(test-equal "real?" (real? +nan.0) #t) + +(test-equal "complex?" (complex? 0) #t) +(test-equal "complex?" (complex? 85736847562938475634534245) #t) +(test-equal "complex?" (complex? 857368.4756293847) #t) +(test-equal "complex?" (complex? 3+0i) #t) +(test-equal "complex?" (complex? 3+4i) #t) +(test-equal "complex?" (complex? +4.3i) #t) +(test-equal "complex?" (complex? '()) #f) + +(test-equal "number?" (number? 0) #t) +(test-equal "number?" (number? 85736847562938475634534245) #t) +(test-equal "number?" (number? 857368.4756293847) #t) +(test-equal "number?" (number? 3+0i) #t) +(test-equal "number?" (number? 3+4i) #t) +(test-equal "number?" (number? +4.3i) #t) +(test-equal "number?" (number? '()) #f) + +(test-equal "exact?" (exact? 1) #t) +(test-equal "exact?" (exact? 4304953480349304983049304953804) #t) +(test-equal "exact?" (exact? 430495348034930/4983049304953804) #t) +(test-equal "exact?" (exact? 1.0) #f) +(test-equal "exact?" (exact? 4304953480349304983.049304953804) #f) +(test-equal "exact?" (exact? 1.0+0i) #f) +(test-equal "exact?" (exact? 1.0+5i) #f) +(test-equal "inexact?" (inexact? 1) #f) +(test-equal "inexact?" (inexact? 4304953480349304983049304953804) #f) +(test-equal "inexact?" (inexact? 430495348034930/4983049304953804) #f) +(test-equal "inexact?" (inexact? 1.0) #t) +(test-equal "inexact?" (inexact? 4304953480349304983.049304953804) #t) +(test-equal "inexact?" (inexact? 1.0+0i) #t) +(test-equal "inexact?" (inexact? 1.0+5i) #t) + +(test-equal "odd?" (odd? 1) #t) +(test-equal "odd?" (odd? 2) #f) +(test-equal "even?" (even? 1) #f) +(test-equal "even?" (even? 2) #t) +(test-equal "odd?" (odd? 1.0) #t) +(test-equal "odd?" (odd? 2.0) #f) +(test-equal "even?" (even? 1.0) #f) +(test-equal "even?" (even? 2.0) #t) +(test-equal "odd?" (odd? 10000000000000000000000000000000000001) #t) +(test-equal "odd?" (odd? 10000000000000000000000000000000000002) #f) +(test-equal "even?" (even? 10000000000000000000000000000000000001) #f) +(test-equal "even?" (even? 10000000000000000000000000000000000002) #t) + +(test-equal "zero?" (zero? 0) #t) +(test-equal "zero?" (zero? 0.0) #t) +(test-equal "zero?" (zero? (- 10 10.0)) #t) +(test-equal "zero?" (zero? 0+0i) #t) +(test-equal "zero?" (zero? 1.0) #f) +(test-equal "zero?" (zero? +5i) #f) +(test-equal "positive?" (positive? 1) #t) +(test-equal "positive?" (positive? -1) #f) +(test-equal "positive?" (positive? 1/7) #t) +(test-equal "positive?" (positive? -1/7) #f) +(test-equal "positive?" (positive? 3.1416) #t) +(test-equal "positive?" (positive? -3.1416) #f) +(test-equal "positive?" (positive? 134539485343498539458394) #t) +(test-equal "positive?" (positive? -134539485343498539458394) #f) +(test-equal "negative?" (negative? 1) #f) +(test-equal "negative?" (negative? -1) #t) +(test-equal "negative?" (negative? 1/7) #f) +(test-equal "negative?" (negative? -1/7) #t) +(test-equal "negative?" (negative? 3.1416) #f) +(test-equal "negative?" (negative? -3.1416) #t) +(test-equal "negative?" (negative? 134539485343498539458394) #f) +(test-equal "negative?" (negative? -134539485343498539458394) #t) + +(let-syntax ((tester (syntax-rules () + ((_ name proc result) + (begin (test-error name (proc #t)) + (test-equal name (list (proc 1) + (proc +inf.0) + (proc -inf.0) + (proc +nan.0)) result)))))) + (tester "finite?" finite? `(#t #f #f #f)) + (tester "infinite?" infinite? `(#f #t #t #f)) + (tester "nan?" nan? `(#f #f #f #t)) + ) + + +(test-equal "eqv?" (eqv? 20 20) #t) +(test-equal "eqv?" (eqv? 20.0 20.00000) #t) +(test-equal "eqv?" (eqv? 4/5 0.8) #f) +(test-equal "eqv?" (eqv? (exact->inexact 4/5) 0.8) #t) +(test-equal "eqv?" (eqv? 4/5 (inexact->exact 0.8)) #f) +(test-equal "eqv?" (eqv? 20 (inexact->exact 20.0)) #t) +(test-equal "eqv?" (eqv? 20 20.0) #f) + +;; numeric comparison involving nan. we should test both +;; inlined case and applied case +(define-syntax test-nan-cmp + (ir-macro-transformer + (lambda (e r c) + (let ((op (cadr e))) + `(begin + (test-equal (format "NaN ~a (inlined)" ',op) (list (,op +nan.0 +nan.0) (,op +nan.0 0) (,op 0 +nan.0)) + '(#f #f #f)) + (test-equal (format "NaN ~a (applied)" ',op) (list (apply ,op '(+nan.0 +nan.0)) + (apply ,op '(+nan.0 0)) + (apply ,op '(0 +nan.0))) + '(#f #f #f))))))) +(test-nan-cmp =) +(test-nan-cmp <) +(test-nan-cmp <=) +(test-nan-cmp >) +(test-nan-cmp >=) + +;; the following tests combine instructions for comparison. +(let ((zz #f)) + (set! zz 3.14) ;; prevent the compiler from optimizing constants + + (test-equal "NUMEQF" (list (= 3.14 zz) (= zz 3.14) (= 3.15 zz) (= zz 3.15)) + '(#t #t #f #f)) + (test-equal "NLTF" (list (< 3.14 zz) (< zz 3.14) + (< 3.15 zz) (< zz 3.15) + (< 3.13 zz) (< zz 3.13)) + '(#f #f #f #t #t #f)) + (test-equal "NLEF" (list (<= 3.14 zz) (<= zz 3.14) + (<= 3.15 zz) (<= zz 3.15) + (<= 3.13 zz) (<= zz 3.13)) + '(#t #t #f #t #t #f)) + (test-equal "NGTF" (list (> 3.14 zz) (> zz 3.14) + (> 3.15 zz) (> zz 3.15) + (> 3.13 zz) (> zz 3.13)) + '(#f #f #t #f #f #t)) + (test-equal "NGEF" (list (>= 3.14 zz) (>= zz 3.14) + (>= 3.15 zz) (>= zz 3.15) + (>= 3.13 zz) (>= zz 3.13)) + '(#t #t #t #f #f #t)) + ) + +;; Go through number comparison routines. +;; assumes a >= b, a > 0, b > 0 +;; we use apply to prevent inlining. +(define (numcmp-test msg eq a b) + (let ((pp (list a b)) + (pm (list a (- b))) + (mp (list (- a) b)) + (mm (list (- a) (- b)))) + (define (test4 op opname rev results) + (for-each (lambda (result comb args) + (let ((m (conc msg " " (if rev 'rev "") opname "(" comb ")"))) + (test-equal m (apply op (if rev (reverse args) args)) result))) + results '(++ +- -+ --) (list pp pm mp mm))) + (test4 = '= #f (list eq #f #f eq)) + (test4 = '= #t (list eq #f #f eq)) + (test4 >= '>= #f (list #t #t #f eq)) + (test4 >= '>= #t (list eq #f #t #t)) + (test4 > '> #f (list (not eq) #t #f #f)) + (test4 > '> #t (list #f #f #t (not eq))) + (test4 <= '<= #f (list eq #f #t #t)) + (test4 <= '<= #t (list #t #t #f eq)) + (test4 < '< #f (list #f #f #t (not eq))) + (test4 < '< #t (list (not eq) #t #f #f)) + )) + +(numcmp-test "fixnum vs fixnum eq" #t 156 156) +(numcmp-test "fixnum vs fixnum ne" #f 878252 73224) +(numcmp-test "bignum vs fixnum ne" #f (expt 3 50) 9982425) +(numcmp-test "bignum vs bignum eq" #t (expt 3 50) (expt 3 50)) +(numcmp-test "bignum vs bignum ne" #f (expt 3 50) (expt 3 49)) +(numcmp-test "flonum vs fixnum eq" #t 314.0 314) +(numcmp-test "flonum vs fixnum ne" #f 3140.0 314) +(numcmp-test "flonum vs bignum eq" #t (expt 2.0 64) (expt 2 64)) +(numcmp-test "flonum vs bignum ne" #f (expt 2.0 64) (expt 2 63)) +(numcmp-test "ratnum vs fixnum ne" #f 13/2 6) +(numcmp-test "ratnum vs ratnum eq" #t 3/5 3/5) +(numcmp-test "ratnum vs ratnum 1 ne" #f 3/5 4/7) +(numcmp-test "ratnum vs ratnum 2 ne" #f 4/5 3/7) +(numcmp-test "ratnum vs ratnum 3 ne" #f 4/7 2/5) +(numcmp-test "ratnum vs ratnum 4 ne" #f 4/7 3/7) +(numcmp-test "ratnum vs flonum eq" #t 3/8 0.375) +(numcmp-test "ratnum vs flonum ne" #f 8/9 0.6) +(numcmp-test "ratnum vs bignum ne" #f (/ (+ (expt 2 64) 1) 2) (expt 2 63)) + +;; This is from the bug report from Bill Schottsteadt. Before 0.8.10 +;; this yielded #t because of the precision loss in fixnum vs ratnum +;; comparison. + +(test-equal "fixnum/ratnum comparison" (= -98781233389595723930250385525631360344437602649022271391716773162526352115087074898920261954897888235939429993829738630297052776667061779065100945771127020439712527398509771853491319737304616607041615012797134365574007368603232768089410097730646360760856052946465578073788924743642391638455649511108051053789425902013657106523269224045822294981391380222050223141347787674321888089837786284947870569165079491411110074602544203383038299901291952931113248943344436935596614205784436844912243069019367149526328612664067719765890897558075277707055756274228634652905751880612235340874976952880431555921814590049070979276358637989837532124647692152520447680373275200239544449293834424643702763974403094033892112967196087310232853165951285609426599617479356206218697586025251765476179158153123631158173662488102357611674821528467825910806391548770908013608889792001203039243914696463472490444573930050190716726220002151679336252008777326482398042427845860796285369622627679324605214987983884122808994422164327311297556122943400093231935477754959547620500784989043704825777186301417894825200797719289692636286337716705491307686644214213732116277102140558505945554566856673724837541141206267647285222293953181717113434757149921850120377706206012113994795124049471433490016083401216757825264766474891405185591236321448744678896448941259668731597494947127423662646933419809756274038044752395708014998820826196523041220918922611359697502638594907608648168849193813197790291360087857093790119162389573209640804111261616771827989939551840471235079945175327536638365874717775169210186608268924244639016270610098894971732892267642318266405837012482726627199088381027028630711279130575230815976484191675172279903609489448225149181063260231957171204855841611039996959582465138269247794842445177715476581512709861409446684911276158067098438009067149531119008707418601627426255891/2063950098473886055933596136103014753954685977787179797499441692283103642150668140884348149132839387663291870239435604463778573480782766958396423322880804442523056530013282118705429274303746421980903580754656364533869319744640130831962767797772323836293079599182477171562218297208495122660799328579852852969560730744211066545295945803939271680397511478811389399527913043145952054883289558914237172406636283114284363301999238526952309439259354223729114988806937903509692118585280437646676248013406270664905997291670857985754768850507766359973207600149782819306010561088246502918148146264806947375101624011387317921439210509902170092173796154464078297852707797984007992277904626058467143192149921546030028316990855470478894515952884526783686210401408859364838148201339959570732480920969000913791571631154267939054105878236201498477027265774680071188764947522112650857013491135901945605796776829525789886482760578142306057177990048751864852763036720112071475134369179525117161001517868525821398753039187062869247457336940152614866298628205010037695017885878296140891234142925514925051385440766473260338168038302226808098439763889250948602137806546736025439919604390464712793474019469457135856879584745805794574609707742445431851999335443724488636749987837445626810087003490329257105472274738811579817454656532496370562155449815456374456838912258383282154811001588175608617475540639254689723629881619252699580383612847920348111900440075645703960104081690968807839189109040568288972353424306876947127635585164905071821419089229871978994388197349499565628906992171901547121903117815637249359328193980583892566359962066242217169190169986105579733710057404319381685578470983838597020624234209884597110721892707818651210378187525863009879314177842634871978427592746452643603586344401223449546482306838947819060455178762434166799996220143825677025686435609179225302671777326568324855229172912876656233006785717920665743720753617646617017219230313226844735567400507490772935145894670445831971526014183234960075574401616682479457962912905141754252265169682318523572680657053374002911007741991220001444440319448034755483178790032581428679303588017268970 0) + #f) + + +;;================================================================== +;; Fixnum stuff +;; + +(test-equal "fixnum? fixnum" (fixnum? 0) #t) +(test-equal "fixnum? ratnum" (fixnum? 1/2) #f) +(test-equal "fixnum? bignum" (fixnum? (expt 2 256)) #f) +(test-equal "fixnum? flonum" (fixnum? 3.14) #f) +(test-equal "fixnum? compnum" (fixnum? 1+3i) #f) + +(test-equal "fixnum? greatest" (fixnum? (greatest-fixnum)) #t) +(test-equal "fixnum? greatest+1" (fixnum? (+ (greatest-fixnum) 1)) #f) +(test-equal "fixnum? least" (fixnum? (least-fixnum)) #t) +(test-equal "fixnum? least-1" (fixnum? (- (least-fixnum) 1)) #f) + +(test-equal "greatest fixnum & width" (- (ash 1 (fixnum-width)) 1) + (greatest-fixnum)) +(test-equal "least fixnum & width" (- (ash 1 (fixnum-width))) + (least-fixnum)) + +(test-end) + +;;================================================================== +;; Arithmetics +;; + +;;------------------------------------------------------------------ +(test-begin "integer addition") + +(define x #xffffffff00000000ffffffff00000000) +(define xx (- x)) +(define y #x00000002000000000000000200000000) +(define yy (- y)) +(define z #x00000000000000010000000000000001) +(test-equal "bignum + bignum" (+ x y) + #x100000001000000010000000100000000) +(test-equal "bignum + -bignum" (+ x yy) + #xfffffffd00000000fffffffd00000000) +(test-equal "bignum - bignum" (- x z) + #xfffffffefffffffffffffffeffffffff) +(test-equal "bignum - bignum" (- (+ x y) y) + x) +(test-equal "-bignum + bignum" (+ xx y) + #x-fffffffd00000000fffffffd00000000) +(test-equal "-bignum + -bignum" (+ xx yy) + #x-100000001000000010000000100000000) +(test-equal "-bignum - bignum" (- xx y) + #x-100000001000000010000000100000000) +(test-equal "-bignum - -bignum" (- xx yy) + #x-fffffffd00000000fffffffd00000000) + +;; This test a possible shortcut in Scm_Add etc. We use apply +;; to avoid operators from being inlined. +(test-equal "0 + bignum" (list (apply + (list 0 x)) (apply + (list x 0))) + (list x x)) +(test-equal "0 - bignum" (list (apply - (list 0 x)) (apply - (list x 0))) + (list (- x) x)) +(test-equal "0 * bignum" (list (apply * (list 0 x)) (apply * (list x 0))) + (list 0 0)) +(test-equal "1 * bignum" (list (apply * (list 1 x)) (apply * (list x 1))) + (list x x)) +(test-equal "bignum / 1" (apply / (list x 1)) + x) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "small immediate integer constants") + +;; pushing small literal integer on the stack may be done +;; by combined instruction PUSHI. These test if it works. + +(define (foo a b c d e) (list a b c d e)) + +;; 2^19-1 +(test-equal "PUSHI" (foo 0 524287 524288 -524287 -524288) + '(0 524287 524288 -524287 -524288)) +;; 2^51-1 +(test-equal "PUSHI" (foo 0 2251799813685247 2251799813685248 + -2251799813685247 -2251799813685248) + '(0 2251799813685247 2251799813685248 + -2251799813685247 -2251799813685248 )) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "small immediate integer additions") + +;; small literal integer x (-2^19 <= x < 2^19 on 32bit architecture) +;; in binary addition/subtraction is compiled in special instructuions, +;; NUMADDI and NUMSUBI. + +(define x 2) +(test-equal "NUMADDI" (+ 3 x) 5) +(test-equal "NUMADDI" (+ x 3) 5) +(test-equal "NUMADDI" (+ -1 x) 1) +(test-equal "NUMADDI" (+ x -1) 1) +(test-equal "NUMSUBI" (- 3 x) 1) +(test-equal "NUMSUBI" (- x 3) -1) +(test-equal "NUMSUBI" (- -3 x) -5) +(test-equal "NUMSUBI" (- x -3) 5) +(define x 2.0) +(test-equal "NUMADDI" (+ 3 x) 5.0) +(test-equal "NUMADDI" (+ x 3) 5.0) +(test-equal "NUMADDI" (+ -1 x) 1.0) +(test-equal "NUMADDI" (+ x -1) 1.0) +(test-equal "NUMSUBI" (- 3 x) 1.0) +(test-equal "NUMSUBI" (- x 3) -1.0) +(test-equal "NUMSUBI" (- -3 x) -5.0) +(test-equal "NUMSUBI" (- x -3) 5.0) +(define x #x100000000) +(test-equal "NUMADDI" (+ 3 x) #x100000003) +(test-equal "NUMADDI" (+ x 3) #x100000003) +(test-equal "NUMADDI" (+ -1 x) #xffffffff) +(test-equal "NUMADDI" (+ x -1) #xffffffff) +(test-equal "NUMSUBI" (- 3 x) #x-fffffffd) +(test-equal "NUMSUBI" (- x 3) #xfffffffd) +(test-equal "NUMSUBI" (- -3 x) #x-100000003) +(test-equal "NUMSUBI" (- x -3) #x100000003) +(define x 33/7) +(test-equal "NUMADDI" (+ 3 x) 54/7) +(test-equal "NUMADDI" (+ x 3) 54/7) +(test-equal "NUMADDI" (+ -1 x) 26/7) +(test-equal "NUMADDI" (+ x -1) 26/7) +(test-equal "NUMADDI" (- 3 x) -12/7) +(test-equal "NUMADDI" (- x 3) 12/7) +(test-equal "NUMADDI" (- -3 x) -54/7) +(test-equal "NUMADDI" (- x -3) 54/7) + +(test-equal "NUMADDI" (+ 10 (if #t 20 25)) 30) +(test-equal "NUMADDI" (+ (if #t 20 25) 10) 30) +(test-equal "NUMADDI" (+ 10 (if #f 20 25)) 35) +(test-equal "NUMADDI" (+ (if #f 20 25) 10) 35) +(test-equal "NUMADDI" (let ((x #t)) (+ 10 (if x 20 25))) 30) +(test-equal "NUMADDI" (let ((x #t)) (+ (if x 20 25) 10)) 30) +(test-equal "NUMADDI" (let ((x #f)) (+ 10 (if x 20 25))) 35) +(test-equal "NUMADDI" (let ((x #f)) (+ (if x 20 25) 10)) 35) +(test-equal "NUMADDI" (+ 10 (do ((x 0 (+ x 1))) ((> x 10) x))) 21) +(test-equal "NUMADDI" (+ (do ((x 0 (+ x 1))) ((> x 10) x)) 10) 21) +(test-equal "NUMSUBI" (- 10 (if #t 20 25)) -10) +(test-equal "NUMSUBI" (- (if #t 20 25) 10) 10) +(test-equal "NUMSUBI" (- 10 (if #f 20 25)) -15) +(test-equal "NUMSUBI" (- (if #f 20 25) 10) 15) +(test-equal "NUMSUBI" (let ((x #t)) (- 10 (if x 20 25))) -10) +(test-equal "NUMSUBI" (let ((x #t)) (- (if x 20 25) 10)) 10) +(test-equal "NUMSUBI" (let ((x #f)) (- 10 (if x 20 25))) -15) +(test-equal "NUMSUBI" (let ((x #f)) (- (if x 20 25) 10)) 15) +(test-equal "NUMSUBI" (- 10 (do ((x 0 (+ x 1))) ((> x 10) x))) -1) +(test-equal "NUMSUBI" (- (do ((x 0 (+ x 1))) ((> x 10) x)) 10) 1) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "immediate flonum integer arith") + +;; tests special instructions for immediate flonum integer arithmetic + + +(define x 2.0) +(test-equal "NUMADDF" (+ 3 x) 5.0) +(test-equal "NUMADDF" (+ x 3) 5.0) +(test-equal "NUMADDF" (+ -1 x) 1.0) +(test-equal "NUMADDF" (+ x -1) 1.0) +(test-equal "NUMADDF" (+ +i x) 2.0+1.0i) +(test-equal "NUMADDF" (+ x +i) 2.0+1.0i) + +(test-equal "NUMSUBF" (- 3 x) 1.0) +(test-equal "NUMSUBF" (- x 3) -1.0) +(test-equal "NUMSUBF" (- -3 x) -5.0) +(test-equal "NUMSUBF" (- x -3) 5.0) +(test-equal "NUMSUBF" (- +i x) -2.0+1.0i) +(test-equal "NUMSUBF" (- x +i) 2.0-1.0i) + +(test-equal "NUMMULF" (* x 2) 4.0) +(test-equal "NUMMULF" (* 2 x) 4.0) +(test-equal "NUMMULF" (* x 1.5) 3.0) +(test-equal "NUMMULF" (* 1.5 x) 3.0) +(test-equal "NUMMULF" (* x +i) 0+2.0i) +(test-equal "NUMMULF" (* +i x) 0+2.0i) + +(test-equal "NUMDIVF" (/ x 4) 0.5) +(test-equal "NUMDIVF" (/ 4 x) 2.0) +(test-equal "NUMDIVF" (/ x 4.0) 0.5) +(test-equal "NUMDIVF" (/ 4.0 x) 2.0) +(test-equal "NUMDIVF" (/ x +4i) 0.0-0.5i) +(test-equal "NUMDIVF" (/ +4i x) 0.0+2.0i) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "rational number addition") + +(test-equal "ratnum +" (+ 11/13 21/19) 482/247) +(test-equal "ratnum -" (- 11/13 21/19) -64/247) + +;; tests possible shortcut in Scm_Add etc. +(test-equal "ratnum + 0" (list (apply + '(0 11/13)) (apply + '(11/13 0))) + (list 11/13 11/13)) +(test-equal "ratnum - 0" (list (apply - '(0 11/13)) (apply - '(11/13 0))) + (list -11/13 11/13)) +(test-equal "ratnum * 0" (list (apply * '(0 11/13)) (apply * '(11/13 0))) + (list 0 0)) +(test-equal "ratnum * 1" (list (apply * '(1 11/13)) (apply * '(11/13 1))) + (list 11/13 11/13)) +(test-equal "ratnum / 1" (apply / '(11/13 1)) + 11/13) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "promotions in addition") + +(define-syntax +-tester + (syntax-rules () + ((_ (+ args ...)) + (let ((inline (+ args ...)) + (other (apply + `(,args ...)))) + (and (= inline other) + (list inline (exact? inline))))))) + +(test-equal "+" (+-tester (+)) '(0 #t)) +(test-equal "+" (+-tester (+ 1)) '(1 #t)) +(test-equal "+" (+-tester (+ 1 2)) '(3 #t)) +(test-equal "+" (+-tester (+ 1 2 3)) '(6 #t)) +(test-equal "+" (+-tester (+ 1/6 1/3 1/2)) '(1 #t)) +(test-equal "+" (+-tester (+ 1.0)) '(1.0 #f)) +(test-equal "+" (+-tester (+ 1.0 2)) '(3.0 #f)) +(test-equal "+" (+-tester (+ 1 2.0)) '(3.0 #f)) +(test-equal "+" (+-tester (+ 1 2 3.0)) '(6.0 #f)) +(test-equal "+" (+-tester (+ 1/6 1/3 0.5)) '(1.0 #f)) +(test-equal "+" (+-tester (+ 1 +i)) '(1+i #t)) +(test-equal "+" (+-tester (+ 1 2 +i)) '(3+i #t)) +(test-equal "+" (+-tester (+ +i 1 2)) '(3+i #t)) +(test-equal "+" (+-tester (+ 1.0 2 +i)) '(3.0+i #f)) +(test-equal "+" (+-tester (+ +i 1.0 2)) '(3.0+i #f)) +(test-equal "+" (+-tester (+ 4294967297 1.0)) '(4294967298.0 #f)) +(test-equal "+" (+-tester (+ 4294967297 1 1.0)) '(4294967299.0 #f)) +(test-equal "+" (+-tester (+ 4294967297 1.0 -i)) '(4294967298.0-i #f)) +(test-equal "+" (+-tester (+ -i 4294967297 1.0)) '(4294967298.0-i #f)) +(test-equal "+" (+-tester (+ 1.0 4294967297 -i)) '(4294967298.0-i #f)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "integer multiplication") + +(define (m-result x) (list x (- x) (- x) x x (- x) (- x) x)) +(define (m-tester x y) + (list (* x y) (* (- x) y) (* x (- y)) (* (- x) (- y)) + (apply * (list x y)) (apply * (list (- x) y)) + (apply * (list x (- y))) (apply * (list (- x) (- y))))) + +(test-equal "fix*fix->big[1]" (m-tester 41943 17353) + (m-result 727836879)) +(test-equal "fix*fix->big[1]" (m-tester 41943 87353) + (m-result 3663846879)) +(test-equal "fix*fix->big[2]" (m-tester 65536 65536) + (m-result 4294967296)) +(test-equal "fix*fix->big[2]" (m-tester 4194303 87353) + (m-result 366384949959)) +(test-equal "fix*big[1]->big[1]" (m-tester 3 1126270821) + (m-result 3378812463)) +(test-equal "fix*big[1]->big[2]" (m-tester 85746 4294967296) + (m-result 368276265762816)) +(test-equal "big[1]*fix->big[1]" (m-tester 1126270821 3) + (m-result 3378812463)) +(test-equal "big[1]*fix->big[2]" (m-tester 4294967296 85746) + (m-result 368276265762816)) +(test-equal "big[2]*fix->big[2]" (m-tester 535341266467 23) + (m-result 12312849128741)) +(test-equal "big[1]*big[1]->big[2]" (m-tester 1194726677 1126270821) + (m-result 1345585795375391817)) + +;; Large number multiplication test using Fermat's number +;; The decomposition of Fermat's number is taken from +;; http://www.dd.iij4u.or.jp/~okuyamak/Information/Fermat.html +(test-equal "fermat(7)" (* 59649589127497217 5704689200685129054721) + (fermat 7)) +(test-equal "fermat(8)" (* 1238926361552897 + 93461639715357977769163558199606896584051237541638188580280321) + (fermat 8)) +(test-equal "fermat(9)" (* 2424833 + 7455602825647884208337395736200454918783366342657 + 741640062627530801524787141901937474059940781097519023905821316144415759504705008092818711693940737) + (fermat 9)) +(test-equal "fermat(10)" (* 45592577 + 6487031809 + 4659775785220018543264560743076778192897 + 130439874405488189727484768796509903946608530841611892186895295776832416251471863574140227977573104895898783928842923844831149032913798729088601617946094119449010595906710130531906171018354491609619193912488538116080712299672322806217820753127014424577 + ) + (fermat 10)) +(test-equal "fermat(11)" (* 319489 + 974849 + 167988556341760475137 + 3560841906445833920513 + 173462447179147555430258970864309778377421844723664084649347019061363579192879108857591038330408837177983810868451546421940712978306134189864280826014542758708589243873685563973118948869399158545506611147420216132557017260564139394366945793220968665108959685482705388072645828554151936401912464931182546092879815733057795573358504982279280090942872567591518912118622751714319229788100979251036035496917279912663527358783236647193154777091427745377038294584918917590325110939381322486044298573971650711059244462177542540706913047034664643603491382441723306598834177 + ) + (fermat 11)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "multiplication short cuts") + +(parameterize ((current-test-comparator eqv?)) +;; these test shortcut in Scm_Mul +;; note the difference of 0 and 0.0 + (let1 big (read-from-string "100000000000000000000") + (test-equal "bignum * 0" (apply * `(,big 0)) 0) + (test-equal "0 * bignum" (apply * `(0 ,big)) 0) + (test-equal "bignum * 1" (apply * `(,big 1)) big) + (test-equal "1 * bignum" (apply * `(1 ,big)) big) + + (test-equal "bignum * 0.0" (apply * `(,big 0.0)) 0.0) + (test-equal "0.0 * bignum" (apply * `(0.0 ,big)) 0.0) + (test-equal "bignum * 1.0" (apply * `(,big 1.0)) 1.0e20) + (test-equal "1.0 * bignum" (apply * `(1.0 ,big)) 1.0e20) + ) + +(test-equal "ratnum * 0" (apply * '(1/2 0)) 0) +(test-equal "0 * ratnum" (apply * '(0 1/2)) 0) +(test-equal "ratnum * 1" (apply * '(1/2 1)) 1/2) +(test-equal "1 * ratnum" (apply * '(1 1/2)) 1/2) + +(test-equal "ratnum * 0.0" (apply * '(1/2 0.0)) 0.0) +(test-equal "0.0 * ratnum" (apply * '(0.0 1/2)) 0.0) +(test-equal "ratnum * 1.0" (apply * '(1/2 1.0)) 0.5) +(test-equal "1.0 * ratnum" (apply * '(1.0 1/2)) 0.5) + +;; Fixed for exactness (Gauche represents zero always exactly?) +(test-equal "flonum * 0" (apply * '(3.0 0)) 0.0) +(test-equal "0 * flonum" (apply * '(0 3.0)) 0.0) +(test-equal "flonum * 1" (apply * '(3.0 1)) 3.0) +(test-equal "1 * flonum" (apply * '(1 3.0)) 3.0) + +(test-equal "flonum * 0.0" (apply * '(3.0 0.0)) 0.0) +(test-equal "0.0 * flonum" (apply * '(0.0 3.0)) 0.0) +(test-equal "flonum * 1.0" (apply * '(3.0 1.0)) 3.0) +(test-equal "1.0 * flonum" (apply * '(1.0 3.0)) 3.0) + +(test-equal "compnum * 0" (* 0 +i) 0) +(test-equal "0 * compnum" (* +i 0) 0) +(test-equal "compnum * 1" (* 1 +i) +i) +(test-equal "1 * compnum" (* +i 1) +i) + +(test-equal "compnum * 0.0" (* 0.0 +i) 0.0) +(test-equal "0.0 * compnum" (* +i 0.0) 0.0) +(test-equal "compnum * 1.0" (* 1.0 +i) +1.0i) +(test-equal "1.0 * compnum" (* +i 1.0) +1.0i)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "division") + +(test-equal "exact division" (/ 3 4 5) 3/20) +(test-equal "exact division" (/ 9223372036854775808 18446744073709551616) 1/2) +(test-equal "exact division" (/ 28153784189046 42) + 4692297364841/7) +(test-equal "exact division" (/ 42 28153784189046) + 7/4692297364841) +(test-equal "exact division" (/ 42 -28153784189046) + -7/4692297364841) +(test-equal "exact division" (/ -42 -28153784189046) + 7/4692297364841) +(test-equal "exact reciprocal" (/ 3) 1/3) +(test-equal "exact reciprocal" (/ -3) -1/3) +(test-equal "exact reciprocal" (/ 6/5) 5/6) +(test-equal "exact reciprocal" (/ -6/5) -5/6) +(test-equal "exact reciprocal" (/ 4692297364841/7) 7/4692297364841) + +(define (almost=? x y) + (define (flonum=? x y) + (let ((ax (abs x)) (ay (abs y))) + (< (abs (- x y)) (* (max ax ay) 0.0000000000001)))) + (and (flonum=? (car x) (car y)) + (flonum=? (cadr x) (cadr y)) + (flonum=? (caddr x) (caddr y)) + (flonum=? (cadddr x) (cadddr y)) + (eq? (list-ref x 4) (list-ref y 4)))) + +(define (d-result x exact?) (list x (- x) (- x) x exact?)) +(define (d-tester x y) + (list (/ x y) (/ (- x) y) (/ x (- y)) (/ (- x) (- y)) + (exact? (/ x y)))) + +;; inexact division +(test-equal "exact/inexact -> inexact" (d-tester 13 4.0) + (d-result 3.25 #f)) +(test-equal "exact/inexact -> inexact" (d-tester 13/2 4.0) + (d-result 1.625 #f)) +(test-equal "inexact/exact -> inexact" (d-tester 13.0 4) + (d-result 3.25 #f)) +(test-equal "inexact/exact -> inexact" (d-tester 13.0 4/3) + (d-result 9.75 #f)) +(test-equal "inexact/inexact -> inexact" (d-tester 13.0 4.0) + (d-result 3.25 #f)) + +;; complex division +(test-equal "complex division" (let ((a 3) + (b 4+3i) + (c 7.3)) + (- (/ a b c) + (/ (/ a b) c))) + 0.0) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "quotient") + +(define (q-result x exact?) (list x (- x) (- x) x exact?)) +(define (q-tester x y) + (list (quotient x y) (quotient (- x) y) + (quotient x (- y)) (quotient (- x) (- y)) + (exact? (quotient x y)))) + + +;; these uses BignumDivSI -> bignum_sdiv +(test-equal "big[1]/fix->fix" (q-tester 727836879 41943) + (q-result 17353 #t)) +(test-equal "big[1]/fix->fix" (q-tester 3735928559 27353) + (q-result 136582 #t)) +(test-equal "big[2]/fix->big[1]" (q-tester 12312849128741 23) + (q-result 535341266467 #t)) +(test-equal "big[2]/fix->big[2]" (q-tester 12312849128741 1) + (q-result 12312849128741 #t)) + +;; these uses BignumDivSI -> bignum_gdiv +(test-equal "big[1]/fix->fix" (q-tester 3663846879 87353) + (q-result 41943 #t)) +(test-equal "big[2]/fix->fix" (q-tester 705986470884353 36984440) + (q-result 19088743 #t)) +(test-equal "big[2]/fix->fix" (q-tester 12312849128741 132546) + (q-result 92894912 #t)) +(test-equal "big[2]/fix->big[1]" (q-tester 425897458766735 164900) + (q-result 2582762030 #t)) + +;; these uses BignumDivRem +(test-equal "big[1]/big[1]->fix" (q-tester 4020957098 1952679221) + (q-result 2 #t)) +(test-equal "big[1]/big[1] -> fix" (q-tester 1952679221 4020957098) + (q-result 0 #t)) +;; this tests loop in estimation phase +(test-equal "big[3]/big[2] -> big[1]" (q-tester #x10000000000000000 #x10000ffff) + (q-result #xffff0001 #t)) +;; this test goes through a rare case handling code ("add back") in +;; the algorithm. +(test-equal "big[3]/big[2] -> fix" (q-tester #x7800000000000000 #x80008889ffff) + (q-result #xeffe #t)) + +;; inexact quotient +(test-equal "exact/inexact -> inexact" (q-tester 13 4.0) + (q-result 3.0 #f)) +(test-equal "inexact/exact -> inexact" (q-tester 13.0 4) + (q-result 3.0 #f)) +(test-equal "inexact/inexact -> inexact" (q-tester 13.0 4.0) + (q-result 3.0 #f)) +(test-equal "exact/inexact -> inexact" (q-tester 727836879 41943.0) + (q-result 17353.0 #f)) +(test-equal "inexact/exact -> inexact" (q-tester 727836879.0 41943) + (q-result 17353.0 #f)) +(test-equal "inexact/inexact -> inexact" (q-tester 727836879.0 41943.0) + (q-result 17353.0 #f)) + +;; Test by fermat numbers +(test-equal "fermat(7)" (quotient (fermat 7) 5704689200685129054721) + 59649589127497217) +(test-equal "fermat(8)" (quotient (fermat 8) 93461639715357977769163558199606896584051237541638188580280321) + 1238926361552897) +(test-equal "fermat(9)" (quotient (quotient (fermat 9) 7455602825647884208337395736200454918783366342657) + 741640062627530801524787141901937474059940781097519023905821316144415759504705008092818711693940737) + 2424833) +(test-equal "fermat(10)" (quotient (quotient (quotient (fermat 10) + 130439874405488189727484768796509903946608530841611892186895295776832416251471863574140227977573104895898783928842923844831149032913798729088601617946094119449010595906710130531906171018354491609619193912488538116080712299672322806217820753127014424577) + 6487031809) + 45592577) + 4659775785220018543264560743076778192897) +(test-equal "fermat(11)" (quotient (quotient (quotient (quotient (fermat 11) + 167988556341760475137) + 173462447179147555430258970864309778377421844723664084649347019061363579192879108857591038330408837177983810868451546421940712978306134189864280826014542758708589243873685563973118948869399158545506611147420216132557017260564139394366945793220968665108959685482705388072645828554151936401912464931182546092879815733057795573358504982279280090942872567591518912118622751714319229788100979251036035496917279912663527358783236647193154777091427745377038294584918917590325110939381322486044298573971650711059244462177542540706913047034664643603491382441723306598834177 + ) + 974849) + 319489) + 3560841906445833920513) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "remainder") + +(define (r-result x exact?) (list x (- x) x (- x) exact?)) +(define (r-tester x y) + (list (remainder x y) (remainder (- x) y) + (remainder x (- y)) (remainder (- x) (- y)) + (exact? (remainder x y)))) + +;; small int +(test-equal "fix rem fix -> fix" (r-tester 13 4) + (r-result 1 #t)) +(test-equal "fix rem fix -> fix" (r-tester 1234 87935) + (r-result 1234 #t)) +(test-equal "fix rem big[1] -> fix" (r-tester 12345 3735928559) + (r-result 12345 #t)) + +;; these uses BignumDivSI -> bignum_sdiv +(test-equal "big[1] rem fix -> fix" (r-tester 727836879 41943) + (r-result 0 #t)) +(test-equal "big[1] rem fix -> fix" (r-tester 3735928559 27353) + (r-result 1113 #t)) +(test-equal "big[2] rem fix -> fix" (r-tester 12312849128756 23) + (r-result 15 #t)) +(test-equal "big[2] rem fix -> fix" (r-tester 12312849128756 1) + (r-result 0 #t)) + +;; these uses BignumDivSI -> bignum_gdiv +(test-equal "big[1] rem fix -> fix" (r-tester 3663846879 87353) + (r-result 0 #t)) +(test-equal "big[2] rem fix -> fix" (r-tester 705986470884353 36984440) + (r-result 725433 #t)) +(test-equal "big[2] rem fix -> fix" (r-tester 12312849128741 132546) + (r-result 122789 #t)) +(test-equal "big[2] rem fix -> fix" (r-tester 425897458766735 164900) + (r-result 19735 #t)) + +;; these uses BignumDivRem +(test-equal "big[1] rem big[1] -> fix" (r-tester 4020957098 1952679221) + (r-result 115598656 #t)) +(test-equal "big[1] rem big[1] -> fix" (r-tester 1952679221 4020957098) + (r-result 1952679221 #t)) +;; this tests loop in estimation phase +(test-equal "big[3] rem big[2] -> big[1]" (r-tester #x10000000000000000 #x10000ffff) + (r-result #xfffe0001 #t)) +;; this tests "add back" code +(test-equal "big[3] rem big[2] -> big[2]" (r-tester #x7800000000000000 #x80008889ffff) + (r-result #x7fffb114effe #t)) + +;; inexact remainder +(test-equal "exact rem inexact -> inexact" (r-tester 13 4.0) + (r-result 1.0 #f)) +(test-equal "inexact rem exact -> inexact" (r-tester 13.0 4) + (r-result 1.0 #f)) +(test-equal "inexact rem inexact -> inexact" (r-tester 13.0 4.0) + (r-result 1.0 #f)) +(test-equal "exact rem inexact -> inexact" (r-tester 3735928559 27353.0) + (r-result 1113.0 #f)) +(test-equal "inexact rem exact -> inexact" (r-tester 3735928559.0 27353) + (r-result 1113.0 #f)) +(test-equal "inexact rem inexact -> inexact" (r-tester 3735928559.0 27353.0) + (r-result 1113.0 #f)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "modulo") + +(define (m-result a b exact?) (list a b (- b) (- a) exact?)) +(define (m-tester x y) + (list (modulo x y) (modulo (- x) y) + (modulo x (- y)) (modulo (- x) (- y)) + (exact? (modulo x y)))) + +;; small int +(test-equal "fix mod fix -> fix" (m-tester 13 4) + (m-result 1 3 #t)) +(test-equal "fix mod fix -> fix" (m-tester 1234 87935) + (m-result 1234 86701 #t)) +(test-equal "fix mod big[1] -> fix/big" (m-tester 12345 3735928559) + (m-result 12345 3735916214 #t)) + +;; these uses BignumDivSI -> bignum_sdiv +(test-equal "big[1] mod fix -> fix" (m-tester 727836879 41943) + (m-result 0 0 #t)) +(test-equal "big[1] mod fix -> fix" (m-tester 3735928559 27353) + (m-result 1113 26240 #t)) +(test-equal "big[2] mod fix -> fix" (m-tester 12312849128756 23) + (m-result 15 8 #t)) +(test-equal "big[2] mod fix -> fix" (m-tester 12312849128756 1) + (m-result 0 0 #t)) + +;; these uses BignumDivSI -> bignum_gdiv +(test-equal "big[1] mod fix -> fix" (m-tester 3663846879 87353) + (m-result 0 0 #t)) +(test-equal "big[2] mod fix -> fix" (m-tester 705986470884353 36984440) + (m-result 725433 36259007 #t)) +(test-equal "big[2] mod fix -> fix" (m-tester 12312849128741 132546) + (m-result 122789 9757 #t)) +(test-equal "big[2] mod fix -> fix" (m-tester 425897458766735 164900) + (m-result 19735 145165 #t)) + +;; these uses BignumDivRem +(test-equal "big[1] mod big[1] -> fix" (m-tester 4020957098 1952679221) + (m-result 115598656 1837080565 #t)) +(test-equal "big[1] mod big[1] -> fix" (m-tester 1952679221 4020957098) + (m-result 1952679221 2068277877 #t)) +;; this tests loop in estimation phase +(test-equal "big[3] mod big[2] -> big[1]" (m-tester #x10000000000000000 #x10000ffff) + (m-result #xfffe0001 #x2fffe #t)) +;; this tests "add back" code +(test-equal "big[3] mod big[2] -> big[2]" (m-tester #x7800000000000000 #x80008889ffff) + (m-result #x7fffb114effe #xd7751001 #t)) + +;; inexact modulo +(test-equal "exact mod inexact -> inexact" (m-tester 13 4.0) + (m-result 1.0 3.0 #f)) +(test-equal "inexact mod exact -> inexact" (m-tester 13.0 4) + (m-result 1.0 3.0 #f)) +(test-equal "inexact mod inexact -> inexact" (m-tester 13.0 4.0) + (m-result 1.0 3.0 #f)) +(test-equal "exact mod inexact -> inexact" (m-tester 3735928559 27353.0) + (m-result 1113.0 26240.0 #f)) +(test-equal "inexact mod exact -> inexact" (m-tester 3735928559.0 27353) + (m-result 1113.0 26240.0 #f)) +(test-equal "inexact mod inexact -> inexact" (m-tester 3735928559.0 27353.0) + (m-result 1113.0 26240.0 #f)) + +;; test by mersenne prime? - code by 'hipster' + +(define (mersenne-prime? p) + (let ((m (- (expt 2 p) 1))) + (do ((i 3 (+ i 1)) + (s 4 (modulo (- (* s s) 2) m))) + ((= i (+ p 1)) (= s 0))))) + +(test-equal "mersenne prime" + (map mersenne-prime? '(3 5 7 13 17 19 31 61 89 107 127 521 607 1279)) + '(#t #t #t #t #t #t #t #t #t #t #t #t #t #t)) + +(test-end) + +;;------------------------------------------------------------------ +;; R6RS +#| +(test-begin "div and mod") + +(let () + (define (do-quadrants proc) + (lambda (x y =) + (proc x y =) + (proc (- x) y =) + (proc x (- y) =) + (proc (- x) (- y) =))) + + (define (test-div x y =) + (test-equal (format "~a div ~a" x y) (receive (d m) (div-and-mod x y) + (let1 z (+ (* d y) m) + (list (or (= x z) z) + (or (and (<= 0 m) (< m (abs y))) m)))) + '(#t #t))) + + (define (test-div0 x y =) + (test-equal (format "~a div0 ~a" x y) (receive (d m) (div0-and-mod0 x y) + (let1 z (+ (* d y) m) + (list (or (= x z) z) + (or (and (<= (- (abs y)) (* m 2)) + (< (* m 2) (abs y))) + m)))) + '(#t #t))) + + ((do-quadrants test-div) 123 10 =) + (parameterize ((current-test-epsilon 1e-10)) + ((do-quadrants test-div) 123.0 10.0 =)) + ((do-quadrants test-div) (read-from-string "123/7") (read-from-string "10/7") =) + ((do-quadrants test-div) (read-from-string "123/7") 5 =) + ((do-quadrants test-div) 123 (read-from-string "5/7") =) + ((do-quadrants test-div) 130.75 10.5 =) + + ((do-quadrants test-div0) 123 10 =) + ((do-quadrants test-div0) 129 10 =) + (parameterize ((current-test-epsilon 1e-10)) + ((do-quadrants test-div0) 123.0 10.0 =) + ((do-quadrants test-div0) 129.0 10.0 =)) + ((do-quadrants test-div0) (read-from-string "123/7") (read-from-string "10/7") =) + ((do-quadrants test-div0) (read-from-string "129/7") (read-from-string "10/7") =) + ((do-quadrants test-div0) (read-from-string "121/7") 5 =) + ((do-quadrants test-div0) (read-from-string "124/7") 5 =) + ((do-quadrants test-div0) 121 (read-from-string "5/7") =) + ((do-quadrants test-div0) 124 (read-from-string "5/7") =) + ((do-quadrants test-div0) 130.75 10.5 =) + ((do-quadrants test-div0) 129.75 10.5 =) + ) + +(test-end) +|# +;;------------------------------------------------------------------ +(test-begin "rounding") + +(define (round-tester value exactness cei flo tru rou) + (test-equal (string-append "rounding " (number->string value)) + (let ((c (ceiling value)) + (f (floor value)) + (t (truncate value)) + (r (round value))) + (list (and (exact? c) (exact? f) (exact? t) (exact? r)) + c f t r)) + (list exactness cei flo tru rou))) + +(round-tester 0 #t 0 0 0 0) +(round-tester 3 #t 3 3 3 3) +(round-tester -3 #t -3 -3 -3 -3) +(round-tester (expt 2 99) #t (expt 2 99) (expt 2 99) (expt 2 99) (expt 2 99)) +(round-tester (- (expt 2 99)) #t + (- (expt 2 99)) (- (expt 2 99)) (- (expt 2 99)) (- (expt 2 99))) + +(round-tester 9/4 #t 3 2 2 2) +(round-tester -9/4 #t -2 -3 -2 -2) +(round-tester 34985495387484938453495/17 #t + 2057970316910878732559 + 2057970316910878732558 + 2057970316910878732558 + 2057970316910878732559) +(round-tester -34985495387484938453495/17 #t + -2057970316910878732558 + -2057970316910878732559 + -2057970316910878732558 + -2057970316910878732559) + +(round-tester 35565/2 #t 17783 17782 17782 17782) +(round-tester -35565/2 #t -17782 -17783 -17782 -17782) +(round-tester 35567/2 #t 17784 17783 17783 17784) +(round-tester -35567/2 #t -17783 -17784 -17783 -17784) + +(test-equal "round->exact" (round->exact 3.4) 3) +(test-equal "round->exact" (round->exact 3.5) 4) +(test-equal "floor->exact" (floor->exact 3.4) 3) +(test-equal "floor->exact" (floor->exact -3.5) -4) +(test-equal "ceiling->exact" (ceiling->exact 3.4) 4) +(test-equal "ceiling->exact" (ceiling->exact -3.5) -3) +(test-equal "truncate->exact" (truncate->exact 3.4) 3) +(test-equal "truncate->exact" (truncate->exact -3.5) -3) + +(test-end) + +;;------------------------------------------------------------------ + +#| +;; Nonstandard and Gauche-specific +(test-begin "clamping") + +(parameterize ((current-test-comparator eqv?)) + (test-equal "clamp (1)" (clamp 1) 1) + (test-equal "clamp (1 #f)" (clamp 1 #f) 1) + (test-equal "clamp (1 #f #f)" (clamp 1 #f #f) 1) + (test-equal "clamp (1.0)" (clamp 1.0) 1.0) + (test-equal "clamp (1.0 #f)" (clamp 1.0 #f) 1.0) + (test-equal "clamp (1.0 #f #f)" (clamp 1.0 #f #f) 1.0) + + (test-equal "clamp (1 0)" (clamp 1 0) 1) + (test-equal "clamp (1 0 #f)" (clamp 1 0 #f) 1) + (test-equal "clamp (1 0 2)" (clamp 1 0 2) 1) + (test-equal "clamp (1 5/4)" (clamp 1 5/4) 5/4) + (test-equal "clamp (1 5/4 #f)" (clamp 1 5/4 #f) 5/4) + (test-equal "clamp (1 #f 5/4)" (clamp 1 #f 5/4) 1) + (test-equal "clamp (1 0 3/4)" (clamp 1 0 3/4) 3/4) + (test-equal "clamp (1 #f 3/4)" (clamp 1 #f 3/4) 3/4) + + (test-equal "clamp (1.0 0)" (clamp 1.0 0) 1.0) + (test-equal "clamp (1.0 0 #f)" (clamp 1.0 0 #f) 1.0) + (test-equal "clamp (1.0 0 2)" (clamp 1.0 0 2) 1.0) + (test-equal "clamp (1.0 5/4)" (clamp 1.0 5/4) 1.25) + (test-equal "clamp (1.0 5/4 #f)" (clamp 1.0 5/4 #f) 1.25) + (test-equal "clamp (1.0 #f 5/4)" (clamp 1.0 #f 5/4) 1.0) + (test-equal "clamp (1.0 0 3/4)" (clamp 1.0 0 3/4) 0.75) + (test-equal "clamp (1.0 #f 3/4)" (clamp 1.0 #f 3/4) 0.75) + + (test-equal "clamp (1 0.0)" (clamp 1 0.0) 1.0) + (test-equal "clamp (1 0.0 #f)" (clamp 1 0.0 #f) 1.0) + (test-equal "clamp (1 0.0 2)" (clamp 1 0.0 2) 1.0) + (test-equal "clamp (1 0 2.0)" (clamp 1 0 2.0) 1.0) + (test-equal "clamp (1 1.25)" (clamp 1 1.25) 1.25) + (test-equal "clamp (1 #f 1.25)" (clamp 1 #f 1.25) 1.0) + (test-equal "clamp (1 1.25 #f)" (clamp 1 1.25 #f) 1.25) + (test-equal "clamp (1 0.0 3/4)" (clamp 1 0.0 3/4) 0.75) + (test-equal "clamp (1 0 0.75)" (clamp 1 0 0.75) 0.75) + + (test-equal "clamp (1 -inf.0 +inf.0)" (clamp 1 -inf.0 +inf.0) 1.0)) + +(test-end) +|# + +;;------------------------------------------------------------------ +(test-begin "logical operations") + +(test-equal "ash (fixnum)" (ash #x81 15) ;fixnum + #x408000) +(test-equal "ash (fixnum)" (ash #x408000 -15) + #x81) +(test-equal "ash (fixnum)" (ash #x408000 -22) + #x01) +(test-equal "ash (fixnum)" (ash #x408000 -23) + 0) +(test-equal "ash (fixnum)" (ash #x408000 -24) + 0) +(test-equal "ash (fixnum)" (ash #x408000 -100) + 0) +(test-equal "ash (fixnum)" (ash #x81 0) + #x81) +(test-equal "ash (neg. fixnum)" (ash #x-81 15) ;negative fixnum + #x-408000) +(test-equal "ash (neg. fixnum)" (ash #x-408000 -15) ;nagative fixnum + #x-81) +(test-equal "ash (fixnum)" (ash #x-408000 -22) + -2) +(test-equal "ash (fixnum)" (ash #x-408000 -23) + -1) +(test-equal "ash (fixnum)" (ash #x-408000 -24) + -1) +(test-equal "ash (fixnum)" (ash #x-408000 -100) + -1) +(test-equal "ash (fixnum)" (ash #x-408000 0) + #x-408000) + + +(test-equal "ash (fixnum->bignum)" (ash #x81 24) + #x81000000) +(test-equal "ash (fixnum->bignum)" (ash #x81 31) + #x4080000000) +(test-equal "ash (fixnum->bignum)" (ash #x81 32) + #x8100000000) +(test-equal "ash (fixnum->bignum)" (ash #x81 56) + #x8100000000000000) +(test-equal "ash (fixnum->bignum)" (ash #x81 63) + #x408000000000000000) +(test-equal "ash (fixnum->bignum)" (ash #x81 64) + #x810000000000000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 24) + #x-81000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 31) + #x-4080000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 32) + #x-8100000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 56) + #x-8100000000000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 63) + #x-408000000000000000) +(test-equal "ash (neg.fixnum->bignum)" (ash #x-81 64) + #x-810000000000000000) + +(test-equal "ash (bignum->fixnum)" (ash #x81000000 -24) + #x81) +(test-equal "ash (bignum->fixnum)" (ash #x81000000 -25) + #x40) +(test-equal "ash (bignum->fixnum)" (ash #x81000000 -31) + 1) +(test-equal "ash (bignum->fixnum)" (ash #x81000000 -32) + 0) +(test-equal "ash (bignum->fixnum)" (ash #x81000000 -100) + 0) +(test-equal "ash (bignum->fixnum)" (ash #x4080000000 -31) + #x81) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000 -32) + #x81) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000 -33) + #x40) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000 -39) + 1) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000 -40) + 0) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000 -100) + 0) +(test-equal "ash (bignum->fixnum)" (ash #x8100000000000000 -56) + #x81) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -63) + #x81) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -64) + #x40) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -65) + #x20) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -70) + 1) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -71) + 0) +(test-equal "ash (bignum->fixnum)" (ash #x408000000000000000 -100) + 0) + +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -24) + #x-81) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -25) + #x-41) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -26) + #x-21) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -31) + -2) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -32) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -33) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-81000000 -100) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -31) + #x-81) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -32) + #x-41) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -33) + #x-21) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -38) + -2) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -39) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-4080000000 -100) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -63) + #x-81) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -64) + #x-41) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -65) + #x-21) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -70) + -2) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -71) + -1) +(test-equal "ash (neg.bignum->fixnum)" (ash #x-408000000000000000 -72) + -1) + +(test-equal "ash (bignum->bignum)" (ash #x1234567812345678 4) + #x12345678123456780) +(test-equal "ash (bignum->bignum)" (ash #x1234567812345678 60) + #x1234567812345678000000000000000) +(test-equal "ash (bignum->bignum)" (ash #x1234567812345678 64) + #x12345678123456780000000000000000) +(test-equal "ash (bignum->bignum)" (ash #x1234567812345678 -4) + #x123456781234567) +(test-equal "ash (bignum->bignum)" (ash #x1234567812345678 -32) + #x12345678) +(test-equal "ash (neg.bignum->bignum)" (ash #x-1234567812345678 -4) + #x-123456781234568) +(test-equal "ash (bignum->bignum)" (ash #x-1234567812345678 -32) + #x-12345679) + +(test-equal "lognot (fixnum)" (lognot 0) -1) +(test-equal "lognot (fixnum)" (lognot -1) 0) +(test-equal "lognot (fixnum)" (lognot 65535) -65536) +(test-equal "lognot (fixnum)" (lognot -65536) 65535) +(test-equal "lognot (bignum)" (lognot #x1000000000000000000) + #x-1000000000000000001) +(test-equal "lognot (bignum)" (lognot #x-1000000000000000001) + #x1000000000000000000) + +(test-equal "logand (+fix & 0)" (logand #x123456 0) + 0) +(test-equal "logand (+big & 0)" (logand #x1234567812345678 0) + 0) +(test-equal "logand (+fix & -1)" (logand #x123456 -1) + #x123456) +(test-equal "logand (+big & -1)" (logand #x1234567812345678 -1) + #x1234567812345678) +(test-equal "logand (+fix & +fix)" (logand #xaa55 #x6666) + #x2244) +(test-equal "logand (+fix & +big)" (logand #xaa55 #x6666666666) + #x2244) +(test-equal "logand (+big & +fix)" (logand #xaa55aa55aa #x6666) + #x4422) +(test-equal "logand (+big & +big)" (logand #xaa55aa55aa #x6666666666) + #x2244224422) +(test-equal "logand (+big & +big)" (logand #x123456789abcdef #xfedcba987654321fedcba987654321fedcba) + #x103454301aaccaa) +(test-equal "logand (+big & +big)" (logand #xaa55ea55aa #x55aa55aa55) + #x400000) +(test-equal "logand (+fix & -fix)" (logand #xaa55 #x-6666) + #x8810) +(test-equal "logand (+fix & -big)" (logand #xaa55 #x-6666666666) + #x8810) +(test-equal "logand (+big & -fix)" (logand #xaa55aa55aa #x-6666) + #xaa55aa118a) +(test-equal "logand (+big & -big)" (logand #xaa55aa55aa #x-6666666666) + #x881188118a) +(test-equal "logand (+big & -big)" (logand #x123456789abcdef #x-fedcba987654321fedcba987654321fedcba) + #x20002488010146) +(test-equal "logand (-fix & +fix)" (logand #x-aa55 #x6666) + #x4422) +(test-equal "logand (-fix & +big)" (logand #x-aa55 #x6666666666) + #x6666664422) +(test-equal "logand (-big & +fix)" (logand #x-aa55aa55aa #x6666) + #x2246) +(test-equal "logand (-big & +big)" (logand #x-aa55aa55aa #x6666666666) + #x4422442246) +(test-equal "logand (-big & +big)" (logand #x-123456789abcdef #xfedcba987654321fedcba987654321fedcba) + #xfedcba987654321fedcba884200020541010) +(test-equal "logand (-fix & -fix)" (logand #x-aa55 #x-6666) + #x-ee76) +(test-equal "logand (-fix & -big)" (logand #x-aa55 #x-6666666666) + #x-666666ee76) +(test-equal "logand (-big & -fix)" (logand #x-aa55aa55aa #x-6666) + #x-aa55aa77ee) +(test-equal "logand (-big & -big)" (logand #x-aa55aa55aa #x-6666666666) + #x-ee77ee77ee) +(test-equal "logand (-big & -big)" (logand #x-123456789abcdef #x-fedcba987654321fedcba987654321fedcba) + #x-fedcba987654321fedcba9a76567a9ffde00) + +(test-equal "logior (+fix | 0)" (logior #x123456 0) + #x123456) +(test-equal "logior (+big | 0)" (logior #x1234567812345678 0) + #x1234567812345678) +(test-equal "logior (+fix | -1)" (logior #x123456 -1) + -1) +(test-equal "logior (+big | -1)" (logior #x1234567812345678 -1) + -1) +(test-equal "logior (+fix | +fix)" (logior #xaa55 #x6666) + #xee77) +(test-equal "logior (+fix | +big)" (logior #xaa55 #x6666666666) + #x666666ee77) +(test-equal "logior (+big | +fix)" (logior #xaa55aa55aa #x6666) + #xaa55aa77ee) +(test-equal "logior (+big | +big)" (logior #xaa55aa55aa #x6666666666) + #xee77ee77ee) +(test-equal "logior (+big | +big)" (logior #x123456789abcdef #xfedcba987654321fedcba987654321fedcba) + #xfedcba987654321fedcba9a76567a9ffddff) +(test-equal "logior (+fix | -fix)" (logior #xaa55 #x-6666) + #x-4421) +(test-equal "logior (+fix | -big)" (logior #xaa55 #x-6666666666) + #x-6666664421) +(test-equal "logior (+big | -fix)" (logior #xaa55aa55aa #x-6666) + #x-2246) +(test-equal "logior (+big | -big)" (logior #xaa55aa55aa #x-6666666666) + #x-4422442246) +(test-equal "logior (+big | -big)" (logior #x123456789abcdef #x-fedcba987654321fedcba987654321fedcba) + #x-fedcba987654321fedcba884200020541011) +(test-equal "logior (-fix | +fix)" (logior #x-aa55 #x6666) + #x-8811) +(test-equal "logior (-fix | +big)" (logior #x-aa55 #x6666666666) + #x-8811) +(test-equal "logior (-big | +fix)" (logior #x-aa55aa55aa #x6666) + #x-aa55aa118a) +(test-equal "logior (-big | +big)" (logior #x-aa55aa55aa #x6666666666) + #x-881188118a) +(test-equal "logior (-big | +big)" (logior #x-123456789abcdef #xfedcba987654321fedcba987654321fedcba) + #x-20002488010145) +(test-equal "logior (-fix | -fix)" (logior #x-aa55 #x-6666) + #x-2245) +(test-equal "logior (-fix | -big)" (logior #x-aa55 #x-6666666666) + #x-2245) +(test-equal "logior (-big | -fix)" (logior #x-aa55aa55aa #x-6666) + #x-4422) +(test-equal "logior (-big | -big)" (logior #x-aa55aa55aa #x-6666666666) + #x-2244224422) +(test-equal "logior (-big | -big)" (logior #x-123456789abcdef #x-fedcba987654321fedcba987654321fedcba) + #x-103454301aacca9) + +(test-equal "logtest" (logtest #xfeedbabe #x10000000) + #t) +(test-equal "logtest" (logtest #xfeedbabe #x01100101) + #f) + +#| + +;; TODO: We don't have these procedures (yet?). Should there be compat +;; versions at the top? +(let loop ((a 1) ; 1, 10, 100, ... + (b 1) ; 1, 11, 111, ... + (c 2) ; 10, 101, 1001, ... + (n 1)) ; counter + (when (< n 69) + (test-equal (format "logcount (positive, 100...) ~a" n) (logcount a) 1) + (test-equal (format "logcount (positive, 111...) ~a" n) (logcount b) n) + (test-equal (format "logcount (negative, 100...) ~a" n) (logcount (- a)) (- n 1)) + (test-equal (format "logcount (negative, 100..1) ~a" n) (logcount (- c)) 1) + (loop (+ b 1) (+ b b 1) (+ b b 3) (+ n 1)))) + +(test-equal "logbit?" (map (lambda (i) (logbit? i #b10110)) '(0 1 2 3 4 5 6)) + '(#f #t #t #f #t #f #f)) +(test-equal "logbit?" (map (lambda (i) (logbit? i #b-10110)) '(0 1 2 3 4 5 6)) + '(#f #t #f #t #f #t #t)) + +(test-equal "copy-bit" (copy-bit 4 #b11000110 #t) + #b11010110) +(test-equal "copy-bit" (copy-bit 4 #b11000110 #f) + #b11000110) +(test-equal "copy-bit" (copy-bit 6 #b11000110 #f) + #b10000110) + +(test-equal "bit-field" (bit-field #b1101101010 0 4) + #b1010) +(test-equal "bit-field" (bit-field #b1101101010 4 9) + #b10110) + +(test-equal "copy-bit-field" (copy-bit-field #b1101101010 0 4 0) + #b1101100000) +(test-equal "copy-bit-field" (copy-bit-field #b1101101010 0 4 -1) + #b1101101111) +(test-equal "copy-bit-field" (copy-bit-field #b1101101010 5 16 -1) + #b1111111111101010) +|# + +(test-equal "integer-length" (integer-length #b10101010) + 8) +(test-equal "integer-length" (integer-length #b1111) + 4) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "inexact arithmetics") + +(test-equal "+. (0)" (+.) 0.0) +(test-equal "+. (1)" (+. 1) 1.0) +(test-equal "+. (1big)" (+. 100000000000000000000) 1.0e20) +(test-equal "+. (1rat)" (+. 3/2) 1.5) +(test-equal "+. (1cmp)" (+. 1+i) 1.0+i) +(test-equal "+. (2)" (+. 0 1) 1.0) +(test-equal "+. (2big)" (+. 1 100000000000000000000) 1.0e20) +(test-equal "+. (2rat)" (+. 1 1/2) 1.5) +(test-equal "+. (many)" (+. 1 2 3 4 5) 15.0) + +(test-equal "-. (1)" (-. 1) -1.0) +(test-equal "-. (1big)" (-. 100000000000000000000) -1.0e20) +(test-equal "-. (1rat)" (-. 3/2) -1.5) +(test-equal "-. (1cmp)" (-. 1+i) -1.0-i) +(test-equal "-. (2)" (-. 0 1) -1.0) +(test-equal "-. (2big)" (-. 1 100000000000000000000) -1.0e20) +(test-equal "-. (2rat)" (-. 1 1/2) 0.5) +(test-equal "-. (many)" (-. 1 2 3 4 5) -13.0) + +(test-equal "*. (0)" (*.) 1.0) +(test-equal "*. (1)" (*. 1) 1.0) +(test-equal "*. (1big)" (*. 100000000000000000000) 1.0e20) +(test-equal "*. (1rat)" (*. 3/2) 1.5) +(test-equal "*. (1cmp)" (*. 1+i) 1.0+i) +(test-equal "*. (2)" (*. 0 1) 0.0) +(test-equal "*. (2big)" (*. 1 100000000000000000000) 1.0e20) +(test-equal "*. (2rat)" (*. 1 1/2) 0.5) +(test-equal "*. (many)" (*. 1 2 3 4 5) 120.0) + +(test-equal "/. (1)" (/. 1) 1.0) +(test-equal "/. (1big)" (/. 100000000000000000000) 1.0e-20) +(test-equal "/. (1rat)" (/. 3/2) 0.6666666666666666) +(test-equal "/. (1cmp)" (/. 1+i) 0.5-0.5i) +(test-equal "/. (2)" (/. 0 1) 0.0) +(test-equal "/. (2big)" (/. 1 100000000000000000000) 1.0e-20) +(test-equal "/. (2rat)" (/. 1 1/2) 2.0) +(test-equal "/. (many)" (/. 1 2 5) 0.1) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "sqrt") + +;; R6RS and R7RS +(define (integer-sqrt-tester k) + (test-equal (format "exact-integer-sqrt ~a" k) (receive (s r) (exact-integer-sqrt k) + (list (= k (+ (* s s) r)) + (< k (* (+ s 1) (+ s 1))))) + '(#t #t))) + +(integer-sqrt-tester 0) +(integer-sqrt-tester 1) +(integer-sqrt-tester 2) +(integer-sqrt-tester 3) +(integer-sqrt-tester 4) +(integer-sqrt-tester 10) +(integer-sqrt-tester (expt 2 32)) +(integer-sqrt-tester (- (expt 2 53) 1)) +(integer-sqrt-tester (expt 2 53)) +(integer-sqrt-tester (+ (expt 2 53) 1)) +(integer-sqrt-tester 9999999999999999999999999999999999999999999999999999) +(integer-sqrt-tester (+ (expt 10 400) 3141592653589)) ; double range overflow + +(test-error "exact-integer-sqrt -1" (exact-integer-sqrt -1)) +(test-error "exact-integer-sqrt 1.0" (exact-integer-sqrt 1.0)) +(test-error "exact-integer-sqrt 1/4" (exact-integer-sqrt (read-from-string "1/4"))) + +(parameterize ((current-test-comparator eqv?)) + (test-equal "sqrt, exact" (sqrt 0) 0) + (test-equal "sqrt, exact" (sqrt 16) 4) + (test-equal "sqrt, inexact" (sqrt 16.0) 4.0) + (test-equal "sqrt, inexact" (sqrt -16.0) (read-from-string "+4.0i")) + (test-equal "sqrt, exact" (sqrt (read-from-string "1/16")) (read-from-string "1/4")) + (test-equal "sqrt, inexact" (sqrt (exact->inexact (read-from-string "1/16"))) 0.25)) + +(test-end) + +;;------------------------------------------------------------------ +(test-begin "ffx optimization") + +;; This code is provided by naoya_t to reproduce the FFX bug +;; existed until r6714. The bug was that the ARGP words of +;; in-stack continuations were not scanned when flonum register +;; bank was cleared. This code exhibits the case by putting +;; the result of (sqrt 2) as an unfinished argument, then calling +;; inverse-erf which caused flushing flonum regs (see "NG" line). + +;; (use math.const) +(define-constant pi 3.141592653589793) + + +(let () + (define *epsilon* 1e-12) + + ;; + ;; normal quantile function (probit function) + ;; + (define (probit p) + (define (probit>0 p) + (* (inverse-erf (- (* p 2) 1)) (sqrt 2))) ;; OK + (if (< p 0) + (- 1 (probit>0 (- p))) + (probit>0 p) )) + + (define (probit p) + (define (probit>0 p) + (* (sqrt 2) (inverse-erf (- (* p 2) 1)))) ;; NG + (if (< p 0) + (- 1 (probit>0 (- p))) + (probit>0 p) )) + + ;; + ;; inverse error function (erf-1) + ;; + (define (inverse-erf z) + (define (calc-next-ck k c) + (let loop ((m 0) (sum 0) (ca c) (cz (reverse c))) + (if (= m k) sum + (loop (+ m 1) + (+ sum (/. (* (car ca) (car cz)) (+ m 1) (+ m m 1))) + (cdr ca) (cdr cz))))) + (define (calc-cks k) + (let loop ((i 0) (cks '(1))) + (if (= i k) cks + (loop (+ i 1) (cons (calc-next-ck (+ i 1) cks) cks))))) + (define (calc-ck k) (car (calc-cks k))) + + (define (inverse-erf>0 z) + (let1 r (* pi z z 1/4) ; (pi*z^2)/4 + (let loop ((k 0) (cks '(1)) (sum 0) (a 1)) + (let1 delta (* a (/ (car cks) (+ k k 1))) + (if (< delta (* sum *epsilon*)) + (* 1/2 z (sqrt pi) sum) + (loop (+ k 1) + (cons (calc-next-ck (+ k 1) cks) cks) + (+ sum delta) + (* a r))))))) + + (cond [(< z 0) (- (inverse-erf>0 (- z)))] + [(= z 0) 0] + [else (inverse-erf>0 z)]) ) + + (define ~= (lambda (x y) (< (abs (- x y)) 1e-7))) + ;; + ;; TEST + ;; + (parameterize ((current-test-comparator ~=)) + (test-equal "probit(0.025)" (probit 0.025) -1.959964) + (test-equal "probit(0.975)" (probit 0.975) 1.959964)) + ) + +(test-end) + +(test-end) diff --git a/tests/numbers-test.scm b/tests/numbers-test.scm new file mode 100644 index 00000000..6eadd867 --- /dev/null +++ b/tests/numbers-test.scm @@ -0,0 +1,1651 @@ +;;;; numbers-test.scm + +(include "test.scm") +(use posix) + +;; The default "comparator" doesn't know how to deal with extended number types +(current-test-comparator + (lambda (exp act) + (or (equal? exp act) + (if (or (and (cplxnum? exp) (number? act)) + (and (cplxnum? act) (number? exp))) + (and (< (abs (real-part (- exp act))) + (current-test-epsilon)) + (< (abs (imag-part (- exp act))) + (current-test-epsilon))) + (and (number? exp) + (inexact? exp) + (< (abs (- 1 (abs (if (zero? act) (+ 1 exp) (/ exp act))))) + (current-test-epsilon))))))) + +(test-begin "numbers") + +(current-test-epsilon 0) ;; We want exact comparisons + +(define max-fix most-positive-fixnum) +(define min-fix most-negative-fixnum) +;; The minimal bignum in the sense that any smaller makes it a fixnum +(define min-big (+ most-positive-fixnum 1)) + +(define 64-bits? (##sys#fudge 3)) + +(define (show x) + (print (and x (number->string x))) + x) + +;(set-gc-report! #t) + +(define max2 (+ max-fix max-fix)) + +(define b1 (+ 22 max2)) ; 2147483668 or 4611686018427387928 + +(define c1 (make-rectangular 33 44)) +(define c2 (make-rectangular -1.2 44)) + +(define b2 (- min-fix 22)) +(define r1 (/ 33 44)) +(define r2 (/ 1000 44)) + +;; Found with the pi-ratios benchmark (find-pi 10 20 50) +(define pi 3.14159265358979323881089001960817518141234854964894) +(define ratpi 314159265358979323881089001960817518141234854964894/100000000000000000000000000000000000000000000000000) + +(test-group "basic constructors" + (test-assert "some bignum (twice maxint)" (show max2)) + (test-assert "some other bignum (2147483668 or 9223372036854775828)" (show b1)) + (test-assert "negative bignum" (show b2)) + (test-assert "exact complex" (show c1)) + (test-assert "inexact complex" (show c2)) + (test-assert "rational" (show r1)) +) + +(test-group "addition" + (test-equal "+: no arguments" (+) 0) + (test-equal "+: single argument" (+ 33) 33) + (test-equal "+: adding fixnums" (+ 33 44) 77) + (test-equal "+: adding fixnums (2nd negative)" (+ 33 -44) -11) + (test-equal "+: adding fix/flo" (+ 33 44.5) 77.5) + (test-assert "+: adding fix/big" (show (+ 22 max2))) + (test-assert "+: adding fix/rat" (show (+ 22 r1))) + (test-equal "+: adding fix/complex" (+ 99 c1) (make-rectangular 132 44)) + (test-equal "+: adding complex/fix (inexact)" (+ c2 99) (make-rectangular 97.8 44)) + (test-equal "+: flo/flo" (+ 3.4 5.6) 9.0) + (test-equal "+: flo/big" + (+ 3.4 b1) + (if 64-bits? 9223372036854775809.4 2147483671.4)) + (test-assert "+: flo/rat" (show (+ 33.4 r1))) + (test-equal "+: flo/comp" (+ 3.4 c1) (make-rectangular 36.4 44)) + (test-assert "+: big/rat" (show (+ b1 r1))) + (test-equal "+: comp+comp" (+ c1 c1) (make-rectangular 66 88)) + (test-equal "+: comp+comp (inexact)" (+ c1 c2) (make-rectangular 31.8 88)) + (test-equal "+: multiarg" (+ 33 44 55) 132) +) + +(test-group "subtraction" + + (test-equal "-: negate fix" (- 33) -33) + (test-equal "-: negate most negative fix" (- min-fix) min-big) + (test-equal "abs: most negative fix" (abs most-negative-fixnum) min-big) + (test-equal "-: negate flo" (- 33.2) -33.2) + (test-assert "-: negate rat" (show (- r1))) + (test-equal "-: double-negate big" (- (- b1)) b1) + (test-equal "-: negate comp" (- c1) (make-rectangular -33 -44)) + (test-equal "-: fixnums" (- 33 44) -11) + (test-equal "-: fixnums (2nd negative)" (- 33 -44) 77) + (test-assert "-: fixnums (overflow)" (show (- min-fix min-fix))) + (test-equal "-: fix/flo" (- 33 44.5) -11.5) + (test-equal "-: flo/fix" (- 44.5 33) 11.5) + (test-assert "-: fix/big" (show (- 22 b2))) + (test-assert "-: big/fix" (show (- b2 22))) + (test-equal "-: big/fix (normalizing to fix)" (- min-big 1) max-fix) + (test-assert "-: fix/rat" (show (- 22 r1))) + (test-assert "-: rat/fix" (show (- r1 22))) + (test-equal "-: fix/complex" (- 99 c1) (make-rectangular 66 -44)) + (test-equal "-: complex/fix" (- c1 99) (make-rectangular -66 44)) + (test-equal "-: complex/fix (inexact)" (- c2 99) (make-rectangular -100.2 44)) + (test-equal "-: fix/complex (inexact)" (- 99 c2) (make-rectangular 100.2 -44)) + (test-equal "-: fix/complex (negative im)" (- 99 1+2i) 98-2i) + (test-equal "-: fix/complex (negative im, inexact)" (- 99 1.0+2.0i) 98.0-2.0i) + (test-equal "-: fix/complex (negative real, inexact)" (- 99 -1.0+2.0i) 100.0-2.0i) + (test-equal "-: rat/complex (negative real)" (- 3/2 -1+2i) 5/2-2i) + + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "-: flo/flo" (- 5.6 3.4) 2.2)) + + (test-assert "-: flo/big" (show (- 3.4 b1))) + (test-assert "-: big/flo" (show (- b1 3.4))) + (test-assert "-: flo/rat" (show (- 3.4 r1))) + (test-assert "-: rat/flo" (show (- r1 3.4))) + (test-assert "-: big/rat" (show (- b1 r1))) + (test-assert "-: rat/big" (show (- r1 b1))) + (test-equal "-: flo/comp" (- 3.4 c1) (make-rectangular -29.6 -44)) + (test-equal "-: comp/flo" (- c1 3.4) (make-rectangular 29.6 44)) + (test-equal "-: comp-comp" (- c1 c1) 0) + (test-equal "-: comp-comp (inexact)" (- c1 c2) 34.2) + (test-equal "-: multiarg" (- 33 44 55) -66) +) + + +(test-group "multiplication" + + (test-equal "*: no arguments" (*) 1) + (test-equal "*: single argument" (* 33) 33) + (test-equal "*: multiplying fixnums" (* 33 44) 1452) + (test-equal "*: multiplying fixnums (2nd negative)" (* 33 -44) -1452) + (test-equal "*: multiplying fix/flo" (* 33 44.5) 1468.5) + (test-assert "*: multiplying fix/big (-> 47244640212)" (show (* 22 max2))) + (test-assert "*: multiplying fix/rat" (show (* 33 r1))) + (test-equal "*: multiplying fix/complex" (* 99 c1) (make-rectangular 3267 4356)) + (test-equal "*: multiplying complex/fix (inexact)" (* c2 99) (make-rectangular -118.8 4356.0)) + (test-equal "*: multiplying most negative fixnum by one (edge case)" + (list (* most-negative-fixnum 1) (fixnum? (* most-negative-fixnum 1))) + (list most-negative-fixnum #t)) + (test-equal "*: flo/flo" (* 3.4 5.6) 19.04) + (test-equal "*: flo/big" + (* 0.001 b1) + (if 64-bits? 9223372036854775.806 2147483.668)) + (test-assert "*: flo/rat" (show (* 3.4 r1))) + (test-assert "*: big/rat" (show (* b1 r1))) + (test-equal "*: flo/comp" (* 3.4 c1) (make-rectangular 112.2 149.6)) + (test-equal "*: comp*comp" (* c1 c1) (make-rectangular -847 2904)) + (test-equal "*: comp*comp (inexact)" (* c1 c2) (make-rectangular -1975.6 1399.2)) + (test-equal "*: multiarg" (* 33 44 55) 79860) +) + +(test-group "division" + + (test-assert "/: rec. fix" (show (/ 33))) + (test-assert "/: rec. flo" (show (/ 33.2))) + (test-assert "/: rec. rat" (show (/ r1))) + (test-assert "/: rec. big" (show (/ b1))) + (test-assert "/: rec. comp" (/ c1)) + (test-assert "/: fixnums" (show (/ 33 44))) + (test-equal "/: fixnums (both negative, fixnum result)" (show (/ -2 -2)) 1) + (test-assert "/: fixnums (2nd negative)" (show (/ 33 -44))) + (test-assert "/: fixnums" (show (/ min-fix min-fix))) + (test-equal "/: fix/flo" (/ 33 44.5) (fp/ 33.0 44.5)) + (test-equal "/: flo/fix" (/ 44.5 33) (fp/ 44.5 33.0)) + (test-assert "/: fix/big" (show (/ 22 b2))) + (test-assert "/: big/fix" (show (/ b2 22))) + (test-assert "/: fix/rat" (show (/ 22 r1))) + (test-assert "/: rat/fix" (show (/ r1 22))) + (test-assert "/: fix/complex" (show (/ 99 c1))) + (test-assert "/: complex/fix" (show (/ c1 99))) + (test-assert "/: complex/fix (inexact)" (show (- c2 99))) + (test-assert "/: fix/complex (inexact)" (show (- 99 c2))) + (test-equal "/: flo/flo" (/ 5.6 3.4) (fp/ 5.6 3.4)) + (test-assert "/: flo/big" (show (/ 3.4 b1))) + (test-assert "/: big/flo" (show (/ b1 3.4))) + (test-assert "/: flo/rat" (show (/ 3.4 r1))) + (test-assert "/: rat/flo" (show (/ r1 3.4))) + (test-assert "/: big/rat" (show (/ b1 r1))) + (test-assert "/: rat/big" (show (/ r1 b1))) + (test-assert "/: rat/rat" (show (/ r1 r1))) + (test-assert "/: flo/comp" (show (/ 3.4 c1))) + (test-assert "/: comp/flo" (show (/ c1 3.4))) + (test-assert "/: comp/comp" (show (/ c1 c1))) + (test-assert "/: comp/comp (inexact)" (show (/ c1 c2))) + (test-equal "/: rat/complex" (/ 1/2 1+2i) 1/10-1/5i) + (test-equal "/: rat/complex (negative im)" (/ 1/2 1-2i) 1/10+1/5i) + (test-equal "/: rat/complex (negative real)" (/ 1/2 -1+2i) -1/10-1/5i) + (test-equal "/: rat/complex (negative real&im)" (/ 1/2 -1-2i) -1/10+1/5i) + + (test-assert "/: multiarg" (show (/ 66 2 44))) + (test-error "/: div fixnum by 0" (/ 33 0)) + ;; R7RS says it is an error if any but the first argument is an exact + ;; zero. R5RS doesn't say anything at all (??). + (test-error "/: div flonum by 0" (/ 33.0 0)) + (test-equal "/: div fixnum by 0.0" (/ 33 0.0) +inf.0) + (test-equal "/: div flonum by 0.0" (/ 33.0 0.0) +inf.0) + (test-equal "/: div by 0 (inexact)" (/ 33 0.0) +inf.0) + (test-assert "/: big result" (show (/ b1 2))) +) + +(test-group "quotient" + (test-equal "quotient: fix/fix" (quotient 22 11) 2) + (test-equal "quotient: fix/big" (quotient 22 b1) 0) + (test-equal "quotient: fix/big (most negative)" (quotient min-fix (- min-fix)) -1) + (test-equal "quotient: big/fix (most negative)" (quotient (- min-fix) min-fix) -1) + (test-equal "quotient: fix/fix (most negative)" (quotient min-fix -1) (* min-fix -1)) + (test-equal "quotient: flo/flo" (quotient 22.0 11.0) 2.0) + (test-equal "quotient: fix/flo" (quotient 22 11.0) 2.0) + (test-equal "quotient: flo/fix" (quotient 22.0 11) 2.0) + (test-equal "quotient: flo/big" (quotient 22.0 b1) 0.0) + (test-equal "quotient: big/flo" (quotient b1 (/ b1 2.0)) 2.0) + (test-equal "quotient: big/big" (quotient (- min-fix) (- min-fix)) 1) + (test-equal "quotient: big/big" (quotient (+ (- min-fix) 5) (- min-fix)) 1) + + (test-error "quotient: flo/flo (fractional)" (quotient 23.0 11.5)) + (test-error "quotient: fix/flo (fractional)" (quotient 23 11.5)) + (test-error "quotient: flo/fix (fractional)" (quotient 13.5 6)) +) + +(test-group "remainder" + (test-equal "remainder: fix/fix" (remainder 22 11) 0) + (test-equal "remainder: fix/big" (remainder 22 b1) 22) + (test-equal "remainder: fix/big (most negative)" (remainder min-fix (- min-fix)) 0) + (test-equal "remainder: big/fix (most negative)" (remainder (- min-fix) min-fix) 0) + (test-equal "remainder: big/big" (remainder (- min-fix) (- min-fix)) 0) + (test-equal "remainder: big/big" (remainder (+ (- min-fix) 5) (- min-fix)) 5) + + (test-equal "remainder: flo/flo" (remainder 22.0 11.0) 0.0) + (test-equal "remainder: fix/flo" (remainder 22 11.0) 0.0) + (test-equal "remainder: flo/fix" (remainder 22.0 11) 0.0) + (unless 64-bits? ;; We lose so much precision when converting to double this makes no sense + (test-equal "remainder: flo/big" (remainder 22.0 b1) 22.0)) + + (test-error "remainder: flo/flo (fractional)" (remainder 22.5 2.25)) + (test-error "remainder: fix/flo (fractional)" (remainder 6 12.5)) + (test-error "remainder: flo/fix (fractional)" (remainder 13.5 6)) + (unless 64-bits? + (test-error "remainder: flo/big (fractional)" (remainder (+ b1 0.5) b1))) +) + +(test-group "quotient&remainder" + (test-equal "quotient&remainder: fix/fix" + (receive (quotient&remainder 22 11)) '(2 0)) + (test-equal "quotient&remainder: fix/big" + (receive (quotient&remainder 22 b1)) '(0 22)) + (test-equal "quotient&remainder: fix/big (most negative)" + (receive (quotient&remainder min-fix (- min-fix))) '(-1 0)) + (test-equal "quotient&remainder: big/fix (most negative)" + (receive (quotient&remainder (- min-fix) min-fix)) '(-1 0)) + (test-equal "quotient&remainder: fix/fix (most negative)" + (receive (quotient&remainder min-fix -1)) `(,(* min-fix -1) 0)) + (test-equal "quotient&remainder: big/big" (receive (quotient&remainder (- min-fix) (- min-fix))) + '(1 0)) + (test-equal "quotient&remainder: big/big" (receive (quotient&remainder (+ (- min-fix) 5) (- min-fix))) + '(1 5)) + + (test-equal "quotient&remainder: flo/flo" + (receive (quotient&remainder 22.0 4.0)) '(5.0 2.0)) + (test-equal "quotient&remainder: flo/fix" + (receive (quotient&remainder 22.0 4)) '(5.0 2.0)) + (test-equal "quotient&remainder: fix/flo" + (receive (quotient&remainder 22 4.0)) '(5.0 2.0)) + (test-error "quotient&remainder: flo/fix (fractional)" + (receive (quotient&remainder 0.1 2))) + (test-error "quotient&remainder: flo/big (fractional)" + (receive (quotient&remainder 0.5 b1))) + (test-error "quotient&remainder: big/flo (fractional)" + (receive (quotient&remainder b1 0.5))) +) + +(test-group "gcd" + (test-equal "gcd: fix (64-bit)/big" (gcd 907947775416515 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111) 1) + (test-equal "gcd: big/big" (gcd 234897235923342343242 234790237101762305340234) 6) + (test-equal (gcd) 0) + (test-equal (gcd 6) 6) + (test-equal (gcd -2) 2) + (test-equal (gcd 6 8) 2) + (test-equal (gcd 6 8 5) 1) + (test-equal (gcd 6 -8 5) 1) + (test-equal (gcd 6.0) 6.0) + (test-equal (gcd 6.0 8.0) 2.0) + (test-error (gcd 6.1)) + (test-error (gcd 6.1 8.0)) + (test-error (gcd 6.0 8.1)) + (test-error (gcd +inf.0)) + (test-error (gcd +nan.0)) + (test-error (gcd 6.0 +inf.0)) + (test-error (gcd +inf.0 6.0)) + (test-error (gcd +nan.0 6.0)) + (test-error (gcd 6.0 +nan.0)) + (test-error (gcd 1+2i 3+4i)) + (test-error (gcd 1/2 3/4))) + +(test-group "lcm" + (test-equal (lcm) 1) + (test-equal (lcm 5) 5) + (test-equal (lcm -8) 8) + (test-equal (lcm 6 8) 24) + (test-equal (lcm 6 8 5) 120) + (test-equal (lcm 6.0 8.0) 24.0) + (test-error (lcm 6.1 8.0)) + (test-error (lcm 6.0 8.1)) + (test-error (lcm +inf.0)) + (test-error (lcm +nan.0)) + (test-error (lcm 6.0 +inf.0)) + (test-error (lcm +inf.0 6.0)) + (test-error (lcm +nan.0 6.0)) + (test-error (lcm 6.0 +nan.0)) + (test-error (lcm 1+2i 3+4i)) + (test-error (lcm 1/2 3/4))) + + +(test-group "equality" + + (test-equal "=: fix/fix" (= 33 33) #t) + (test-equal "=: fix/flo" (= 33 33.0) #t) + (test-equal "=: !fix/fix" (= 33 34) #f) + (test-equal "=: !fix/flo" (= 33 33.1) #f) + (test-equal "=: !fix/flo (overflow)" (= 9007199254740993 9007199254740992.0) #f) + (test-equal "=: !fix/flo (inf)" (= 0 +inf.0) #f) + (test-equal "=: !fix/flo (-inf)" (= 0 -inf.0) #f) + (test-equal "=: !fix/flo (+nan)" (= 0 -nan.0) #f) + (test-equal "=: flo/fix" (= 33.0 33) #t) + (test-equal "=: !flo/fix (overflow)" (= 9007199254740992.0 9007199254740993) #f) + (test-equal "=: !flo/fix (inf)" (= +inf.0 0) #f) + (test-equal "=: !flo/fix (-inf)" (= -inf.0 0) #f) + (test-equal "=: !flo/fix (+nan)" (= -nan.0 0) #f) + (test-equal "=: flo/flo" (= 33.1 33.1) #t) + (test-equal "=: !flo/flo" (= 33.1 -33.1) #f) + ;; Flonums are only 53 bits of precision, so it will drop data. + ;; Comparison is exact + (unless 64-bits? + (test-equal "=: big/flo" (= b1 (+ 0.0 b1)) #t)) + (test-equal "=: big/big" (= b1 b1) #t) + (test-equal "=: !big/big" (= b2 b1) #f) + (test-equal "=: rat/flo" (= r1 (+ r1 0.0)) #t) + (test-equal "=: rat/rat" (= r1 r1) #t) + (test-equal "=: !rat/rat" (= r1 r2) #f) + (test-equal "=: comp/comp" (= c1 c1) #t) + (test-equal "=: !comp/comp" (= c1 c2) #f) +) + +(test-group "generic equality" + (test-equal "equal?: fix/fix" (equal? 33 33) #t) + (test-equal "equal?: fix/flo" (equal? 33 33.0) #f) + (test-equal "equal?: !fix/fix" (equal? 33 34) #f) + (test-equal "equal?: !fix/flo" (equal? 33 33.1) #f) + (test-equal "equal?: flo/fix" (equal? 33.0 33) #f) + (test-equal "equal?: flo/flo" (equal? 33.1 33.1) #t) + (test-equal "equal?: !flo/flo" (equal? 33.1 -33.1) #f) + (test-equal "equal?: big/flo" (equal? b1 (+ 0.0 b1)) #f) + (test-equal "equal?: big/big" (equal? b1 b1) #t) + (test-equal "equal?: big/big2" (equal? b1 (+ 1 b1 -1)) #t) + (test-equal "equal?: !big/big" (equal? b2 b1) #f) + (test-equal "equal?: rat/flo" (equal? r1 (+ r1 0.0)) #f) + (test-equal "equal?: rat/rat" (equal? r1 r1) #t) + (test-equal "equal?: !rat/rat" (equal? r1 r2) #f) + (test-equal "equal?: comp/comp" (equal? c1 c1) #t) + (test-equal "equal?: !comp/comp" (equal? c1 c2) #f) + (test-equal "equal?: nan/nan" (equal? (/ 0.0 0.0) (/ 0.0 0.0)) #f) + (test-equal "equal?: nan+nan/nan+nan" (equal? (make-rectangular (/ 0.0 0.0) + (/ 0.0 0.0)) + (make-rectangular (/ 0.0 0.0) + (/ 0.0 0.0))) #f) +) + + +(test-group "greater & greater/equal" + + (test-equal ">: fix/fix" (> 44 33) #t) + (test-equal ">=: fix/fix" (>= 44 33) #t) + (test-equal ">: fix/fix/fix" (> 44 33 22) #t) + (test-equal ">=: fix/fix/fix" (>= 44 33 22) #t) + (test-equal ">: !fix/fix" (> 33 44) #f) + (test-equal ">=: !fix/fix" (>= 33 44) #f) + (test-equal ">: !fix/fix/fix" (> 22 33 44) #f) + (test-equal ">=: !fix/fix/fix" (>= 22 33 44) #f) + (test-equal ">: fix/fix" (> 33 33) #f) + (test-equal ">=: !fix/fix" (>= 33 33) #t) + (test-equal ">: fix/flo" (> 44 33.0) #t) + (test-equal ">=: fix/flo" (>= 44 33.0) #t) + (test-equal ">: !fix/flo" (> 33 44.0) #f) + (test-equal ">=: !fix/flo" (>= 33 44.0) #f) + (test-equal ">: !fix/flo" (> 33 33.0) #f) + (test-equal ">=: !fix/flo" (>= 33 33.0) #t) + (test-equal ">: fix/flo (flo overflow), on 64 bits" + (> 9007199254740993 9007199254740992.0) #t) ; 2^53 + (test-equal ">=: fix/flo (flo overflow), on 64 bits" + (>= 9007199254740993 9007199254740992.0) #t) + (test-equal ">: fix/flo (flo underflow), on 64 bits" + (> -9007199254740992 -9007199254740991.0) #f) + (test-equal ">=: fix/flo (flo underflow), on 64 bits" + (>= -9007199254740992 -9007199254740991.0) #f) + (test-equal ">: fix/big" (> 44 b2) #t) + (test-equal ">=: fix/big" (>= 44 b2) #t) + (test-equal ">: !fix/big" (> 33 b1) #f) + (test-equal ">=: !fix/big" (>= 33 b1) #f) + (test-equal ">: fix/rat" (> 44 r1) #t) + (test-equal ">=: fix/rat" (>= 44 r1) #t) + (test-equal ">: !fix/rat" (> 0 r1) #f) + (test-equal ">=: !fix/rat" (>= 0 r1) #f) + + (test-equal ">: flo/fix" (> 44.0 33) #t) + (test-equal ">=: flo/fix" (>= 44.0 33) #t) + (test-equal ">: !flo/fix" (> 33.0 44) #f) + (test-equal ">=: !flo/fix" (>= 33.0 44) #f) + (test-equal ">: !flo/fix" (> 33.0 33) #f) + (test-equal ">=: flo/fix" (>= 33.0 33) #t) + (test-equal ">: flo/flo" (> 44.0 33.0) #t) + (test-equal ">=: flo/flo" (>= 44.0 33.0) #t) + (test-equal ">: !flo/flo" (> 33.0 44.0) #f) + (test-equal ">=: !flo/flo" (>= 33.0 44.0) #f) + (test-equal ">: flo/big" (> 44.0 b2) #t) + (test-equal ">=: flo/big" (>= 44.0 b2) #t) + (test-equal ">: flo/fix (flo overflow), on 64 bits" + (> 9007199254740992.0 9007199254740993) #f) ; 2^53 + (test-equal ">=: flo/fix (flo overflow), on 64 bits" + (>= 9007199254740992.0 9007199254740993) #f) + (test-equal ">: fix/flo (flo underflow), on 64 bits" + (> -9007199254740991.0 -9007199254740992) #t) + (test-equal ">=: fix/flo (flo underflow), on 64 bits" + (>= -9007199254740991.0 -9007199254740992) #t) + (test-equal ">: flo/big (flo overflow)" + (> 1237940039285380274899124224.0 1237940039285380274899124225) #f) + (test-equal ">=: flo/big (flo overflow)" + (>= 1237940039285380274899124224.0 1237940039285380274899124225) #f) + (test-equal ">: !flo/big" (> 33.0 b1) #f) + (test-equal ">=: !flo/big" (>= 33.0 b1) #f) + (test-equal ">: flo/rat" (> 44.0 r1) #t) + (test-equal ">=: flo/rat" (>= 44.0 r1) #t) + (test-equal ">: !flo/rat" (> 0.0 r1) #f) + (test-equal ">=: !flo/rat" (>= 0.0 r1) #f) + (test-equal ">: !rat/rat" (> r1 r1) #f) + (test-equal ">=: rat/rat" (>= r1 r1) #t) + (test-equal ">: flo/nan" (> 0.0 +nan.0) #f) + (test-equal ">=: flo/nan" (>= 0.0 +nan.0) #f) + (test-equal ">: nan/flo" (> +nan.0 0.0) #f) + (test-equal ">=: nan/flo" (>= +nan.0 0.0) #f) + (test-equal ">: flo/flo/nan" (> 1.0 0.0 +nan.0) #f) + (test-equal ">=: flo/flo/nan" (>= 1.0 0.0 +nan.0) #f) + + (test-equal ">: big/fix" (> b1 33) #t) + (test-equal ">=: big/fix" (>= b1 33) #t) + (test-equal ">: !big/fix" (> b2 44) #f) + (test-equal ">=: !big/fix" (>= b2 44) #f) + (test-equal ">: big/flo" (> b1 33.0) #t) + (test-equal ">=: big/flo" (>= b1 33.0) #t) + (test-equal ">: big/flo (flo overflow)" + (> 1237940039285380274899124225 1237940039285380274899124224.0) #t) + (test-equal ">=: big/flo (flo overflow)" + (>= 1237940039285380274899124225 1237940039285380274899124224.0) #t) + (test-equal ">: !big/flo" (> b2 44.0) #f) + (test-equal ">=: !big/flo" (>= b2 44.0) #f) + (test-equal ">: big/big" (> b1 b2) #t) + (test-equal ">=: big/big" (>= b1 b2) #t) + (test-equal ">: !big/big" (> b2 b1) #f) + (test-equal ">=: !big/big" (>= b2 b1) #f) + (test-equal ">: big/rat" (> b1 r1) #t) + (test-equal ">=: big/rat" (>= b1 r1) #t) + (test-equal ">: !big/rat" (> b2 r1) #f) + (test-equal ">=: !big/rat" (>= b2 r1) #f) + + (test-equal ">: rat/fix" (> r1 2) #f) + (test-equal ">=: rat/fix" (>= r1 2) #f) + (test-equal ">: !rat/fix" (> r1 44) #f) + (test-equal ">=: !rat/fix" (>= r1 44) #f) + (test-equal ">: rat/flo" (> r2 2.0) #t) + (test-equal ">=: rat/flo" (>= r2 2.0) #t) + (test-equal ">: !rat/flo" (> b2 44.0) #f) + (test-equal ">=: !rat/flo" (>= b2 44.0) #f) + (test-equal ">: !rat/big" (> r1 b1) #f) + (test-equal ">=: !rat/big" (>= r1 b1) #f) + (test-equal ">: rat/rat" (> r2 r1) #t) + (test-equal ">=: rat/rat" (>= r2 r1) #t) + (test-equal ">: !rat/rat" (> r1 r2) #f) + (test-equal ">=: !rat/rat" (>= r1 r2) #f) + (test-equal ">: rat/flo (flo overflow)" + (> 1237940039285380274899124224/1237940039285380274899124223 1.0) #t) + (test-equal ">: rat/flo (flo overflow)" + (> 1237940039285380274899124224/1237940039285380274899124223 1.5) #f) + (test-equal ">=: rat/flo (flo overflow)" + (>= 1237940039285380274899124224/1237940039285380274899124223 1.0) #t) + (test-equal ">=: rat/flo (flo overflow)" + (>= 1237940039285380274899124224/1237940039285380274899124223 1.5) #f) + (test-equal ">: rat/flo (flo underflow)" + (> -1237940039285380274899124224/1237940039285380274899124223 -1.0) #f) + (test-equal ">: rat/flo (flo underflow)" + (> -1237940039285380274899124224/1237940039285380274899124223 -1.5) #t) + (test-equal ">=: rat/flo (flo underflow)" + (>= -1237940039285380274899124224/1237940039285380274899124223 -1.0) #f) + (test-equal ">=: rat/flo (flo underflow)" + (>= -1237940039285380274899124224/1237940039285380274899124223 -1.5) #t) +) + + +(test-group "less & less/equal" + + (test-equal "<: !fix/fix" (< 44 33) #f) + (test-equal "<=: !fix/fix" (<= 44 33) #f) + (test-equal "<: fix/fix/fix" (< 33 44 55) #t) + (test-equal "<=: fix/fix/fix" (<= 33 44 55) #t) + (test-equal "<: !fix/fix/fix" (< 33 55 44) #f) + (test-equal "<=: !fix/fix/fix" (<= 33 55 44) #f) + (test-equal "<: !fix/fix/fix" (< 44 33 55) #f) + (test-equal "<=: !fix/fix/fix" (<= 44 33 55) #f) + (test-equal "<: !fix/fix/fix" (< 44 44 44) #f) + (test-equal "<=: fix/fix/fix" (<= 44 44 44) #t) + (test-equal "<: fix/fix" (< 33 44) #t) + (test-equal "<=: fix/fix" (<= 33 44) #t) + (test-equal "<: !fix/fix" (< 33 33) #f) + (test-equal "<=: fix/fix" (<= 33 33) #t) + (test-equal "<: !fix/flo" (< 44 33.0) #f) + (test-equal "<=: !fix/flo" (<= 44 33.0) #f) + (test-equal "<: fix/flo" (< 33 44.0) #t) + (test-equal "<=: fix/flo" (<= 33 44.0) #t) + (test-equal "<: fix/flo (flo overflow), on 64 bits" + (< 9007199254740993 9007199254740992.0) #f) ; 2^53 + (test-equal "<=: fix/flo (flo overflow), on 64 bits" + (< 9007199254740993 9007199254740992.0) #f) + (test-equal "<: fix/flo (flo underflow), on 64 bits" + (< -9007199254740993 -9007199254740992.0) #t) + (test-equal "<=: fix/flo (flo underflow), on 64 bits" + (<= -9007199254740993 -9007199254740992.0) #t) + (test-equal "<: !fix/flo" (< 33.0 33.0) #f) + (test-equal "<=: fix/flo" (<= 33.0 33.0) #t) + (test-equal "<: !fix/big" (< 44 b2) #f) + (test-equal "<=: !fix/big" (<= 44 b2) #f) + (test-equal "<: fix/big" (< 33 b1) #t) + (test-equal "<=: fix/big" (<= 33 b1) #t) + (test-equal "<: !big/big" (< b1 b1) #f) + (test-equal "<=: big/big" (<= b1 b1) #t) + (test-equal "<: !fix/rat" (< 44 r1) #f) + (test-equal "<=: !fix/rat" (<= 44 r1) #f) + (test-equal "<: fix/rat" (< 0 r1) #t) + (test-equal "<=: fix/rat" (<= 0 r1) #t) + + (test-equal "<: !flo/fix" (< 44.0 33) #f) + (test-equal "<=: !flo/fix" (<= 44.0 33) #f) + (test-equal "<: flo/fix" (< 33.0 44) #t) + (test-equal "<=: flo/fix" (<= 33.0 44) #t) + (test-equal "<: !flo/flo" (< 44.0 33.0) #f) + (test-equal "<=: !flo/flo" (<= 44.0 33.0) #f) + (test-equal "<: flo/flo" (< 33.0 44.0) #t) + (test-equal "<=: flo/flo" (<= 33.0 44.0) #t) + (test-equal "<: !flo/big" (< 44.0 b2) #f) + (test-equal "<=: !flo/big" (<= 44.0 b2) #f) + (test-equal "<: flo/big" (< 33.0 b1) #t) + (test-equal "<=: flo/big" (<= 33.0 b1) #t) + (test-equal "<: flo/fix (flo overflow), on 64 bits" + (< 9007199254740992.0 9007199254740993) #t) ; 2^53 + (test-equal "<=: flo/fix (flo overflow), on 64 bits" + (< 9007199254740992.0 9007199254740993) #t) + (test-equal "<: flo/fix (flo underflow), on 64 bits" + (< -9007199254740992.0 -9007199254740993) #f) + (test-equal "<=: flo/fix (flo underflow), on 64 bits" + (<= -9007199254740992.0 -9007199254740993) #f) + (test-equal "<: flo/big (flo overflow)" + (< 1237940039285380274899124224.0 1237940039285380274899124225) #t) + (test-equal "<=: flo/big (flo overflow)" + (<= 1237940039285380274899124224.0 1237940039285380274899124225) #t) + (test-equal "<: !flo/rat" (< 44.0 r1) #f) + (test-equal "<=: !flo/rat" (<= 44.0 r1) #f) + (test-equal "<: flo/rat" (< 0.0 r1) #t) + (test-equal "<=: flo/rat" (<= 0.0 r1) #t) + (test-equal "<: flo/nan" (< 0.0 +nan.0) #f) + (test-equal "<=: flo/nan" (<= 0.0 +nan.0) #f) + (test-equal "<: nan/flo" (< +nan.0 0.0) #f) + (test-equal "<=: nan/flo" (<= +nan.0 0.0) #f) + (test-equal "<: flo/flo/nan" (< 0.0 1.0 +nan.0) #f) + (test-equal "<=: flo/flo/nan" (<= 0.0 1.0 +nan.0) #f) + + (test-equal "<: !big/fix" (< b1 33) #f) + (test-equal "<=: !big/fix" (<= b1 33) #f) + (test-equal "<: big/fix" (< b2 44) #t) + (test-equal "<=: big/fix" (<= b2 44) #t) + (test-equal "<: !big/flo" (< b1 33.0) #f) + (test-equal "<=: !big/flo" (<= b1 33.0) #f) + (test-equal "<: big/flo" (< b2 44.0) #t) + (test-equal "<=: big/flo" (<= b2 44.0) #t) + (test-equal "<: big/flo (max flo)" + (< 1237940039285380274899124224 1237940039285380274899124224.0) #f) + (test-equal "<=: big/flo (max flo)" + (<= 1237940039285380274899124224 1237940039285380274899124224.0) #t) + (test-equal "<: big/flo (max flo, smaller bignum)" + (< 1237940039285380274899124223 1237940039285380274899124224.0) #t) + (test-equal "<: big/flo (max flo, smaller bignum)" + (<= 1237940039285380274899124223 1237940039285380274899124224.0) #t) + (test-equal "<: !big/big" (< b1 b2) #f) + (test-equal "<=: !big/big" (<= b1 b2) #f) + (test-equal "<: big/big" (< b2 b1) #t) + (test-equal "<=: big/big" (<= b2 b1) #t) + (test-equal "<: !big/rat" (< b1 r1) #f) + (test-equal "<=: !big/rat" (<= b1 r1) #f) + (test-equal "<: big/rat" (< b2 r1) #t) + (test-equal "<=: big/rat" (<= b2 r1) #t) + + (test-equal "<: !rat/fix" (< r2 2) #f) + (test-equal "<=: !rat/fix" (<= r2 2) #f) + (test-equal "<: rat/fix" (< r1 44) #t) + (test-equal "<=: rat/fix" (<= r1 44) #t) + (test-equal "<: !rat/flo" (< r2 2.0) #f) + (test-equal "<=: !rat/flo" (<= r2 2.0) #f) + (test-equal "<: rat/flo" (< b2 44.0) #t) + (test-equal "<=: rat/flo" (<= b2 44.0) #t) + (test-equal "<: rat/big" (< r1 b1) #t) + (test-equal "<=: rat/big" (<= r1 b1) #t) + (test-equal "<: !rat/rat" (< r2 r1) #f) + (test-equal "<=: !rat/rat" (<= r2 r1) #f) + (test-equal "<: rat/rat" (< r1 r2) #t) + (test-equal "<=: rat/rat" (<= r1 r2) #t) + (test-equal "<: rat/flo (flo overflow)" + (< 1237940039285380274899124224/1237940039285380274899124223 1.0) #f) + (test-equal "<: rat/flo (flo overflow)" + (< 1237940039285380274899124224/1237940039285380274899124223 1.5) #t) + (test-equal "<=: rat/flo (flo overflow)" + (<= 1237940039285380274899124224/1237940039285380274899124223 1.0) #f) + (test-equal "<=: rat/flo (flo overflow)" + (<= 1237940039285380274899124224/1237940039285380274899124223 1.5) #t) + (test-equal "<: rat/flo (flo underflow)" + (< -1237940039285380274899124224/1237940039285380274899124223 -1.0) #t) + (test-equal "<: rat/flo (flo underflow)" + (< -1237940039285380274899124224/1237940039285380274899124223 -1.5) #f) + (test-equal "<=: rat/flo (flo underflow)" + (<= -1237940039285380274899124224/1237940039285380274899124223 -1.0) #t) + (test-equal "<=: rat/flo (flo underflow)" + (<= -1237940039285380274899124224/1237940039285380274899124223 -1.5) #f) +) + +(test-group "complex" + + (test-equal "real-part" (real-part c1) 33) + (test-equal "real-part of flonum" (real-part 1.23) 1.23) + (test-equal "real-part of fixnum" (real-part 123) 123) + (test-equal "real-part of ratnum" (real-part 1/2) 1/2) + (test-equal "real-part of bignum" (real-part b1) b1) + (test-equal "real-part of negative flonum" (real-part -1.23) -1.23) + (test-equal "real-part of negative fixnum" (real-part -123) -123) + (test-equal "real-part of negative ratnum" (real-part -1/2) -1/2) + (test-equal "real-part of negative bignum" (real-part (- b1)) (- b1)) + (test-equal "imag-part" (imag-part c1) 44) + (test-equal "imag-part of flonum" (imag-part 1.23) 0.0) + (test-equal "imag-part of fixnum" (imag-part 123) 0) + (test-equal "imag-part of ratnum" (imag-part 1/2) 0) + (test-equal "imag-part of bignum" (imag-part b1) 0) + (test-assert "make-polar" (show (make-polar 33 44))) + (test-equal "magnitude" (magnitude 0+8i) 8) + (test-equal "magnitude" (magnitude 0+1/2i) 1/2) + (test-equal "magnitude of flonum" (magnitude 1.23) 1.23) + (test-equal "magnitude of fixnum" (magnitude 123) 123) + (test-equal "magnitude of ratnum" (magnitude 1/2) 1/2) + (test-equal "magnitude of bignum" (magnitude b1) b1) + (test-equal "magnitude of negative flonum" (magnitude -1.23) 1.23) + (test-equal "magnitude of negative fixnum" (magnitude -123) 123) + (test-equal "magnitude of negative ratnum" (magnitude -1/2) 1/2) + (test-equal "magnitude of negative bignum" (magnitude (- b1)) b1) + (test-assert "angle" (show (angle c1))) + (test-equal "angle of flonum" (angle 1.23) 0.0) + (test-equal "angle of fixnum" (angle 123) 0.0) + (test-equal "angle of ratnum" (angle 1/2) 0.0) + (test-equal "angle of bignum" (angle b1) 0.0) + (test-equal "angle of negative flonum" (angle -1.23) pi) + (test-equal "angle of negative fixnum" (angle -123) pi) + (test-equal "angle of negative ratnum" (angle -1/2) pi) + (test-equal "angle of negative bignum" (angle (- b1)) pi) +) + +(test-group "rational" + + ;; Use equal? instead of = to check equality and exactness in one go + (parameterize ((current-test-comparator equal?)) + (test-assert (show (numerator b1))) + (test-equal (numerator r1) 3) + (test-equal (numerator 33) 33) + (test-equal (denominator r1) 4) + (test-equal (denominator b1) 1) + (test-equal (denominator 33) 1) + (test-equal (numerator 0) 0) + (test-equal (denominator 0) 1) + (test-equal (numerator 3) 3) + (test-equal (denominator 3) 1) + (test-equal (numerator -3) -3) + (test-equal (denominator -3) 1) + (test-equal (numerator 0.5) 1.0) + (test-equal (denominator 0.5) 2.0) + (test-equal (numerator 1.25) 5.0) + (test-equal (denominator 1.25) 4.0) + (test-equal (numerator -1.25) -5.0) + (test-equal (denominator -1.25) 4.0) + (test-equal (numerator 1e10) 1e10) + (test-equal (denominator 1e10) 1.0)) + (test-error (numerator +inf.0)) + (test-error (numerator +nan.0)) + (test-error (denominator +inf.0)) + (test-error (denominator +nan.0)) + +) + +(test-group "misc" + + (test-equal "inexact->exact" (inexact->exact 2.3) 2589569785738035/1125899906842624) + (test-error "inexact->exact +inf" (inexact->exact +inf.0)) + (test-error "inexact->exact -inf" (inexact->exact -inf.0)) + (test-error "inexact->exact -NaN" (inexact->exact +nan.0)) + (test-equal "sqrt (integer result)" (sqrt 16) 4) + (test-equal "sqrt (exact result)" (sqrt 1/4) 1/2) + (test-equal "sqrt (inexact result)" (sqrt 2) 1.4142135623730951) + (test-equal "sqrt (inexact input)" (sqrt 4.0) 2.0) + (test-equal "sqrt (exact large number)" (sqrt (* max-fix max-fix)) max-fix) + (test-error "exact-integer-sqrt (nonint flonum)" (exact-integer-sqrt 1.5)) + (test-error "exact-integer-sqrt (ratnum)" (exact-integer-sqrt 1/2)) + (test-error "exact-integer-sqrt (int flonum)" (exact-integer-sqrt 4.0)) + (test-equal "exact-integer-sqrt (w/o rest)" + (receive x (exact-integer-sqrt (* max-fix max-fix)) x) + (list max-fix 0)) + (test-equal "exact-integer-sqrt (with rest)" + (receive x (exact-integer-sqrt (+ (* max-fix max-fix) 5)) x) + (list max-fix 5)) + (test-equal "exact-integer-nth-root without rest" + (receive x (exact-integer-nth-root 243 5) x) + (list 3 0)) + (test-equal "exact-integer-nth-root with rest" + (receive x (exact-integer-nth-root 128 4) x) + (list 3 47)) + (test-equal "exact-integer-nth-root with insanely large base" + (receive x (exact-integer-nth-root 5 (if 64-bits? 10000000000 100000000)) x) + (list 1 4)) + (test-equal "expt" (expt 2 4) 16) + (test-assert "expt" (show (expt 2 100))) + ;; The next three according to R7RS + (test-equal "expt 0.0^0.0)" (expt 0.0 0.0) 1.0) + (test-equal "expt 0.0^{pos}" (expt 0.0 1.0) 0.0) + ;; An error is not mandatory: + ;; "[...] either an error is signalled or an unspecified number is returned." + ;(test-error "expt 0.0^{neg}" (expt 0.0 -1.0)) + ;; R7 doesn't say anything specific about fixnums, so I guess this should behave the same + (test-equal "expt 0^0" (expt 0 0) 1) + (test-equal "expt 0^{pos}" (expt 0 1) 0) + (test-error "expt 0^{neg}" (expt 0 -1)) + (test-equal "expt (rat base)" (expt 1/2 2) 1/4) + (test-equal "expt (rat exponent)" (expt 16 1/4) 2) + (test-equal "expt (negative rat exponent)" (expt 16 -1/4) 1/2) + (test-equal "expt (inexact from rat exponent)" (expt 2 1/7) 1.1040895136738123) + (test-equal "expt (> 1 rat exponent)" (expt 1/64 3/2) 1/512) + (test-equal "expt (rat base & exponent)" (expt 1/4 1/2) 1/2) + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "expt (negative w/ rat exponent)" (expt -16 1/4) 1.4142135623731+1.41421356237309i)) + (test-assert "expt" (show (expt 2 2.0))) + (test-assert "expt" (show (expt 2 -1))) + (test-equal "expt between double and 64-bit integer value" + (expt 999 6) 994014980014994001) + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "expt with complex result" (expt -1 1.5) -1.836909530733566e-16-1.0i)) + (test-equal "exact expt with complex number" (expt 0+1i 5) 0+1i) + (test-equal "exact expt with complex number, real result" (expt 0+1i 6) -1) + (test-equal "inexact expt with complex number" (expt 0.0+1.0i 5.0) 0.0+1.0i) + (test-equal "inexact expt with complex number, real result" (expt 0.0+1.0i 6.0) -1.0) + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "inexact noninteger expt with complex number" + (expt 0.0+4.0i 0.5) 1.4142135623731+1.41421356237309i) + (test-equal "exp with complex numbers" (exp 1+i) 1.4686939399158851+2.2873552871788423i)) + + (test-equal "log of exp = 1" (log (exp 1)) 1.0) + (test-assert "log(-x) = compnum" (cplxnum? (log -2.0))) + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "log of -1" (log -1) 0.0+3.141592653589793i)) + ;; XXX We should probably attempt to make this return an exact number + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "log(expt(2,x),2) = x" (log (expt 2 500) 2) 500.0) + (test-equal "log with complex number" (log +i) 0.0+1.5707963267948966i) + + (test-equal "exp(log(x)) = x" (exp (log 2.0-3.0i)) 2.0-3.0i) + (test-equal "log(exp(x)) = x" (log (exp 2.0-3.0i)) 2.0-3.0i) + (test-equal "log(expt(2,x),2) = x" (log (expt 2 2.0-3.0i) 2) 2.0-3.0i)) + + (letrec ((fac (lambda (n) + (if (zero? n) + 1 + (* n (fac (- n 1))) ) ) ) ) + (test-assert "bigfac" (show (fac 100))) + (test-equal "zero signum fixnum" (signum 0) 0) + (test-equal "zero signum flonum" (signum .0) 0.0) + (test-equal "positive signum fixnum" (signum 2) 1) + (test-equal "positive signum ratnum" (signum 1/2) 1) + (test-equal "positive signum flonum" (signum 2.0) 1.0) + (test-equal "positive signum bignum" (signum b1) 1) + (test-equal "negative signum fixnum" (signum -2) -1) + (test-equal "negative signum ratnum" (signum -1/2) -1) + (test-equal "negative signum flonum" (signum -2) -1) + (test-equal "negative signum bignum" (signum (- b1)) -1) + ;; From CLHS + (parameterize ((current-test-epsilon 1e-10)) + (test-equal "positive signum compnum(1)" (signum 0+33i) 0+1i) + (test-equal "positive signum compnum(2)" (signum 7.5+10.0i) 0.6+0.8i) + (test-equal "negative signum compnum " (signum 0.0-14.7i) 0.0-1.0i))) + (test-equal "most-negative-fixnum + most-negative-fixnum = 2 * most-negative-fixnum" + (+ most-negative-fixnum most-negative-fixnum) (* 2 most-negative-fixnum)) + (test-equal "most-negative-fixnum - most-negative-fixnum = 0" + (- most-negative-fixnum most-negative-fixnum) 0) + (test-equal "most-positive-fixnum + most-positive-fixnum = 2 * most-positive-fixnum" + (+ most-positive-fixnum most-positive-fixnum) (* 2 most-positive-fixnum)) + (test-equal "most-positive-fixnum - most-positive-fixnum = 0" + (- most-positive-fixnum most-positive-fixnum) 0) +) + + +(test-group "R5RS" + + (test-equal "+" (+ 3 4) 7) + (test-equal "+" (+ 3) 3) + (test-equal "+" (+) 0) + (test-equal "*" (* 4) 4) + (test-equal "*" (*) 1) + + (test-equal "-" (- 3 4) -1) + (test-equal "-" (- 3 4 5) -6) + (test-equal "-" (- 3) -3) + (test-assert "/ (3/20)" (show (/ 3 4 5))) + (test-assert "/ (1/3)" (show (/ 3))) + + (test-equal "numerator" (numerator (/ 6 4)) 3) + (test-equal "denominator" (denominator (/ 6 4)) 2) + + (test-equal "complex?" (complex? c1) #t) + (test-equal "complex?" (complex? 3) #t) + (test-equal "real?" (real? 3) #t) + (test-equal "real?" (real? (make-rectangular -2.5 0.0)) #t) + (test-equal "real?" (real? -2+1i) #f) + (test-equal "real?" (real? 1e0) #t) + (test-equal "rational?" (rational? (/ 6 10)) #t) + (test-assert "check rational" (show (/ 6 3))) + (test-equal "rational?" (rational? (/ 6 3)) #t) + (test-equal "integer?" (integer? (make-rectangular 3 0)) #t) + (test-equal "integer?" (integer? 1+3i) #f) + (test-equal "integer?" (integer? 3.0) #t) + (test-equal "integer?" (integer? (/ 8 4)) #t) + (test-equal "integer?" (integer? 1/2) #f) + (test-equal "exact-integer?" (exact-integer? (make-rectangular 3 0)) #t) + (test-equal "exact-integer?" (exact-integer? 1+3i) #f) + (test-equal "exact-integer?" (exact-integer? 3.0) #f) + (test-equal "exact-integer?" (exact-integer? (/ 8 4)) #t) + (test-equal "exact-integer?" (exact-integer? 1/2) #f) + + (test-equal "max" (max 3 4) 4) + (test-equal "max" (max 3.9 4) 4.0) + + (test-equal "modulo" (modulo 13 4) 1) + (test-equal "modulo" (modulo 13.0 4) 1.0) + (test-equal "modulo" (modulo 13 4.0) 1.0) + (test-error "modulo" (modulo 13.1 4.0)) + (test-error "modulo" (modulo 13.0 4.1)) + (test-equal "remainder" (remainder 13 4) 1) + (test-error "remainder" (remainder 13.1 4.0)) + (test-error "remainder" (remainder 13.0 4.1)) + (test-equal "modulo" (modulo -13 4) 3) + (test-equal "remainder" (remainder -13 4) -1) + (test-equal "modulo" (modulo 13 -4) -3) + (test-equal "remainder" (remainder 13 -4) 1) + (test-equal "modulo" (modulo -13 -4) -1) + (test-equal "remainder" (remainder -13 -4) -1) + (test-equal "remainder" (remainder -13 -4.0) -1.0) + + (test-assert (even? 2)) + (test-assert (not (even? 1))) + (test-assert (even? -2)) + (test-assert (not (even? -1))) + (test-assert (even? 2.0)) + (test-assert (not (even? 1.0))) + (test-assert (even? -2.0)) + (test-assert (not (even? -1.0))) + (test-error (even? 2.1)) + (test-error (even? -2.3)) + (test-error (even? +inf.0)) + (test-error (even? +nan.0)) + (test-assert (even? (* most-positive-fixnum 2))) + (test-assert (not (even? (+ (* most-positive-fixnum 2) 1)))) + (test-assert (odd? (+ (* most-positive-fixnum 2) 1))) + (test-assert (not (odd? (* most-positive-fixnum 2)))) + (test-error (even? 2.0+3.0i)) + (test-error (even? 2+3i)) + (test-error (odd? 2.0+3.0i)) + (test-error (odd? 2+3i)) + + (test-equal "floor" (floor -4.3) -5.0) + (test-equal "ceiling" (ceiling -4.3) -4.0) + (test-equal "truncate" (truncate -4.3) -4.0) + (test-equal "round" (round -4.3) -4.0) + (test-equal "floor" (floor 3.5) 3.0) + (test-equal "ceiling" (ceiling 3.5) 4.0) + (test-equal "truncate" (truncate 3.5) 3.0) + (test-equal "round" (round 3.5) 4.0) + (test-equal "round" (round 4.5) 4.0) + (test-equal "round" (round (/ 7 2)) 4) + (test-equal "round" (round 7) 7) + + (test-equal "rationalize (1/3)" (rationalize (inexact->exact .3) (/ 1 10)) 1/3) + (test-equal "rationalize (#i1/3)" (rationalize .3 (/ 1 10)) #i1/3) +) + +(test-group "bitwise ops" + + (test-equal "and" (bitwise-and #xff #x1) 1) + (test-equal "zero-arg and" (bitwise-and) -1) ; Arbitrary, but specified by srfi-33 + (test-equal "ior" (bitwise-ior #x0f #x1) #xf) + (test-equal "zero-arg ior" (bitwise-ior) 0) ; Same + (test-equal "xor" (bitwise-xor #x0f #x1) 14) + (test-equal "zero-arg xor" (bitwise-xor) 0) ; Same + (test-assert "not" (show (bitwise-not #x0f))) + (test-error (bitwise-and 'x)) + (test-error (bitwise-xor 'x)) + (test-error (bitwise-ior 'x)) + (test-error (bitwise-and 1 'x)) + (test-error (bitwise-xor 1 'x)) + (test-error (bitwise-ior 1 'x)) + (test-error (bit-set? 1 -1)) + (test-error (bit-set? b1 -1)) + (test-error (bit-set? 1 1.0)) + (test-error (bit-set? 1.0 1)) + (test-equal (bit-set? -1 b1) #t) + (test-equal (bit-set? 0 b1) #f) + (test-equal (bit-set? 5 2) #t) + (test-equal (bit-set? 5 0) #t) + (test-equal (bit-set? 5 1) #f) + (test-equal (bit-set? -2 0) #f) + (test-equal (bit-set? -2 1) #t) + (test-equal (bit-set? (expt -2 63) 256) #t) + (test-equal (bit-set? (expt 2 63) 256) #f) + (test-equal (arithmetic-shift 15 2) 60) + (test-equal (arithmetic-shift 15 -2) 3) + (test-equal (arithmetic-shift -15 2) -60) + (test-equal (arithmetic-shift -15 -2) -4) ; 2's complement + (test-equal (arithmetic-shift -31 most-negative-fixnum) -1) + (test-equal (arithmetic-shift 31 most-negative-fixnum) 0) + (test-equal (arithmetic-shift b1 0) b1) + (test-equal (arithmetic-shift (arithmetic-shift b1 -1) 1) b1) + (test-error (arithmetic-shift 0.1 2)) + ;; XXX Do the following two need to fail? Might as well use the integral value + (test-error (arithmetic-shift #xf 2.0)) + (test-error (arithmetic-shift #xf -2.0)) + (test-error (arithmetic-shift #xf 2.1)) + (test-error (arithmetic-shift #xf -2.1)) + (test-error (arithmetic-shift +inf.0 2)) + (test-error (arithmetic-shift +nan.0 2)) + (when 64-bits? + (test-equal (arithmetic-shift (expt 2 31) (- (expt 2 31))) 0)) + + ;; by Jeremy Sydik + (let ((leftrot32 + (lambda (value amount) + (let ((shifted (arithmetic-shift value amount))) + (let ((anded (bitwise-and #xFFFFFFFF shifted))) + (bitwise-ior anded + (arithmetic-shift shifted -32)))) ))) + (test-equal "leftrot32 28" (leftrot32 1 28) 268435456) + (test-equal "leftrot32 29" (leftrot32 1 29) 536870912) + (test-equal "leftrot32 30" (leftrot32 1 30) 1073741824)) +) + +(test-group "string conversion" + + (test-assert "fix" (number->string 123)) + (test-assert "fix/base" (number->string 123 16)) + (test-assert "flo" (number->string 99.2)) + (test-assert "big" (number->string b1)) + (test-assert "big/base" (number->string b1 2)) + (test-assert "rat" (number->string r1)) + (test-assert "comp" (number->string c1)) + + (test-equal "edge case printing" + (number->string (expt 2 256) 16) + "10000000000000000000000000000000000000000000000000000000000000000") + (test-equal "positive hexdigit invariance" + (number->string + (string->number "123456789abcdef123456789abcdef123456789abcdef" 16) + 16) + "123456789abcdef123456789abcdef123456789abcdef") + (test-equal "negative hexdigit invariance" + (number->string + (string->number "-123456789abcdef123456789abcdef123456789abcdef" 16) + 16) + "-123456789abcdef123456789abcdef123456789abcdef") + + (test-equal "fix" (string->number "123") 123) + (test-equal "fix/base" (string->number "ff" 16) 255) + (test-equal "fix/base-o" (string->number "16" 8) 14) + (test-equal "fix/unusual-base" (string->number "1234" 5) 194) + (test-equal "fix/wrong-base" (string->number "1234" 4) #f) + (test-error "fix/invalid-base" (string->number "1234" 0)) + (test-error "fix/invalid-base" (string->number "1234" 1)) + (test-equal "embedded base overrides supplied base" (string->number "#x10" 10) 16) + (test-equal "flo" (string->number "123.23") 123.23) + (test-equal "flo2" (string->number "1e2") 100.0) + (test-assert "big" (show (string->number "123873487384737447"))) + (test-assert "big/neg" (show (string->number "-123873487384737447"))) + (test-assert "big/pos" (show (string->number "+123873487384737447"))) + (test-assert "rat" (show (string->number "123/456"))) + (test-assert "rat/neg" (show (string->number "-123/456"))) + (test-assert "rat/pos" (show (string->number "+123/456"))) + (test-assert "rat2" (show (string->number "#o123/456"))) + (test-equal "rat/inexact" (show (string->number "#i123/456")) (/ 123.0 456)) + (test-equal "invalid rat" (string->number "123/0") #f) + (test-assert "comp" (show (string->number "+12i"))) + (test-assert "comp" (show (string->number "12+34i"))) + (test-assert "comp" (show (string->number "-i"))) + (test-assert "comp" (show (string->number "99@55"))) + (test-assert "comp" (show (string->number "1/2@3/4"))) + (test-assert "comp2" (show (string->number "#x99+55i"))) + ;; This is to check for a silly problem cause by representing numbers exactly + ;; all the way until the end, then converting to inexact. This "silly problem" + ;; could probably be exploited in a resource consumption attack. + (let* ((t1 (current-seconds)) + (i1 (string->number "1e1000000")) + (i2 (string->number "1.0e1000000")) + (e1 (string->number "#e1e1000000")) + (e2 (string->number "#e1.0e1000000")) + (t2 (current-seconds))) + (test-assert "read time for inexacts with large positive exp isn't insanely high" (< (- t2 t1) 2)) + (test-equal "inexact read back are equal" i2 i1) + (test-equal "inexact are inf" +inf.0 i1) + (test-equal "exact are equal" e2 e1) + (test-equal "exact are false" #f e1)) + (let* ((t1 (current-seconds)) + (i1 (string->number "-1e1000000")) + (i2 (string->number "-1.0e1000000")) + (e1 (string->number "#e-1e1000000")) + (e2 (string->number "#e-1.0e1000000")) + (t2 (current-seconds))) + (test-assert "read time for inexacts with large positive exp isn't insanely high" (< (- t2 t1) 2)) + (test-equal "negative inexact read back are equal" i2 i1) + (test-equal "negative inexact are negative inf" -inf.0 i1) + (test-equal "negative exact are equal" e2 e1) + (test-equal "negative exact are false" #f e1)) + (let* ((t1 (current-seconds)) + (i1 (string->number "1e-1000000")) + (i2 (string->number "1.0e-1000000")) + (e1 (string->number "#e1e-1000000")) + (e2 (string->number "#e1.0e-1000000")) + (t2 (current-seconds))) + (test-assert "read time for inexacts with large negative exp isn't insanely high" (< (- t2 t1) 2)) + (test-equal "inexact read back are equal" i2 i1) + (test-equal "inexact are 0" +0.0 i1) + (test-equal "exact are equal" e2 e1) + (test-equal "exact are false" #f e1)) + + (test-group "read/write invariance of simple integers for different radices" + (let lp ((radix 2) + (digit 0)) + (cond ((= digit radix) (lp (add1 radix) 0)) + ((<= radix 36) + (let* ((char (string-ref (number->string digit radix) 0)) + (str (make-string 10 char))) + (test-equal (sprintf "radix ~A digits ~S" radix digit) + (number->string (string->number str) radix) + (if (char=? char #\0) "0" str))))))) +) + +(test-group "non-standard type procedures" + + (test-equal "fixnum" (fixnum? max-fix) #t) + + (test-equal "bignum" (bignum? b1) #t) + (test-equal "bignum" (bignum? min-big) #t) + + (test-equal "ratnum" (ratnum? r1) #t) + + (test-equal "nan: fix" (nan? 1) #f) + (test-equal "nan: flo" (nan? 1.0) #f) + (test-equal "nan: +inf" (nan? (/ 1.0 0.0)) #f) + (test-equal "nan: -inf" (nan? (/ -1.0 0.0)) #f) + (test-equal "nan: nan" (nan? (/ 0.0 0.0)) #t) + (test-equal "nan: nan+nani" (nan? (make-rectangular (/ 0.0 0.0) (/ 0.0 0.0))) #t) + (test-equal "nan: flo+nani" (nan? (make-rectangular 1.0 (/ 0.0 0.0))) #t) + (test-equal "nan: nan+floi" (nan? (make-rectangular (/ 0.0 0.0) 1.0)) #t) + (test-error "nan: no number" (nan? 'x)) + + (test-equal "finite: fix" (finite? 1) #t) + (test-equal "finite: flo" (finite? 1.0) #t) + (test-equal "finite: +inf" (finite? (/ 1.0 0.0)) #f) + (test-equal "finite: -inf" (finite? (/ 1.0 0.0)) #f) + (test-equal "finite: nan" (finite? (/ 0.0 0.0)) #f) + (test-equal "finite: nan+floi" (finite? (make-rectangular (/ 0.0 0.0) 1.0)) #f) + (test-equal "finite: inf+infi" (finite? (make-rectangular (/ 1.0 0.0) (/ 1.0 0.0))) #f) + (test-equal "finite: flo+infi" (finite? (make-rectangular 1.0 (/ 1.0 0.0))) #f) + (test-equal "finite: inf+floi" (finite? (make-rectangular (/ 1.0 0.0) 1.0)) #f) + (test-error "finite: no number" (finite? 'x)) + + (test-equal "infinite: fix" (infinite? 1) #f) + (test-equal "infinite: flo" (infinite? 1.0) #f) + (test-equal "infinite: +inf" (infinite? (/ 1.0 0.0)) #t) + (test-equal "infinite: -inf" (infinite? (/ 1.0 0.0)) #t) + (test-equal "infinite: nan" (infinite? (/ 0.0 0.0)) #f) + (test-equal "infinite: inf+infi" (infinite? (make-rectangular (/ 1.0 0.0) (/ 1.0 0.0))) #t) + (test-equal "infinite: flo+infi" (infinite? (make-rectangular 1.0 (/ 1.0 0.0))) #t) + (test-equal "infinite: inf+floi" (infinite? (make-rectangular (/ 1.0 0.0) 1.0)) #t) + (test-error "infinite: no number" (infinite? 'x)) + + (test-equal "cplxnum: compintintnum" (cplxnum? c1) #t) + (test-equal "cplxnum: compintflointnum" (cplxnum? 1.0+1i) #t) + (test-equal "cplxnum: compflointnum" (cplxnum? c2) #t) + (test-equal "cplxnum: compfloflonum" (cplxnum? 3.4-4.3i) #t) + (test-equal "not cplxnum: fixnum" (cplxnum? 1) #f) +) + +;; The usual comparator doesn't work, because zero or a very small number +;; is many times any other small number, but the absolute difference should +;; be minimal, so we compare for that instead. +(parameterize ((current-test-epsilon 1e-9) + (current-test-comparator + (lambda (exp act) + (or (and (nan? exp) (nan? act)) + (and (< (abs (- (real-part exp) (real-part act))) + (current-test-epsilon)) + (< (abs (- (imag-part exp) (imag-part act))) + (current-test-epsilon))))))) + + ;; We're using (acos (cos x)) instead of just (acos y) because we want + ;; to test the compiler's specialization rules of cos output. + + (test-group "trigonometric functions" + (test-group "flonums" + ;; Note: we don't *actually* distinguish -nan from +nan, but whatever :) + (test-equal "acos(-inf)" (acos -inf.0) -nan.0) + (test-equal "acos(<small number>)" (acos -1e100) -nan.0) + (test-equal "cos(-1/3pi)" (cos (- (/ pi 3))) 0.5) + (test-equal "acos(cos(-1/3pi))" (acos (cos (- (/ pi 3)))) (/ pi 3)) + (test-equal "cos(-1/4pi)" (cos (- (/ pi 4))) 0.7071067811865476) + (test-equal "acos(cos(-1/4pi))" (acos (cos (- (/ pi 4)))) (/ pi 4)) + (test-equal "cos(-1/2pi)" (cos (- (/ pi 2))) 0.0) + (test-equal "acos(cos(-1/2pi))" (acos (cos (- (/ pi 2)))) (/ pi 2)) + (test-equal "cos(-pi)" (cos (- pi)) -1.0) + (test-equal "acos(cos(-pi))" (acos (cos (- pi))) pi) + (test-equal "cos(0)" (cos 0.0) 1.0) + (test-equal "acos(cos(0))" (acos (cos 0.0)) 0.0) + (test-equal "cos( 1/4pi)" (cos (/ pi 4)) 0.7071067811865476) + (test-equal "acos(cos( 1/4pi))" (acos (cos (/ pi 4))) (/ pi 4)) + (test-equal "cos( 1/3pi)" (cos (/ pi 3)) 0.5) + (test-equal "acos(cos( 1/3pi))" (acos (cos (/ pi 3))) (/ pi 3)) + (test-equal "cos( 1/2pi)" (cos (/ pi 2)) 0.0) + (test-equal "acos(cos( 1/2pi))" (acos (cos (/ pi 2))) (/ pi 2)) + (test-equal "cos( 2/3pi)" (cos (/ (* 2 pi) 3)) -0.5) + (test-equal "acos(cos( 2/3pi))" (acos (cos (/ (* 2 pi) 3))) (/ (* 2 pi) 3)) + (test-equal "cos( 3/4pi)" (cos (* (/ pi 4) 3)) -0.7071067811865476) + (test-equal "acos(cos( 3/4pi))" (acos (cos (* (/ pi 4) 3))) (* (/ pi 4) 3)) + (test-equal "cos( pi)" (cos pi) -1.0) + (test-equal "acos(cos( pi))" (acos (cos pi)) pi) + (test-equal "cos( 3/2pi)" (cos (+ pi (/ pi 2))) 0.0) + (test-equal "acos(cos( 3/2pi))" (acos (cos (+ pi (/ pi 2)))) (/ pi 2)) + (test-equal "cos( 4/3pi)" (cos (+ pi (/ pi 3))) -0.5) + (test-equal "acos(cos( 4/3pi))" (acos (cos (+ pi (/ pi 3)))) (* 2 (/ pi 3))) + (test-equal "cos( 5/4pi)" (cos (+ pi (/ pi 4))) -0.7071067811865476) + (test-equal "acos(cos( 5/4pi))" (acos (cos (+ pi (/ pi 4)))) (* 3 (/ pi 4))) + (test-equal "cos( 2pi)" (cos (* 2 pi)) 1.0) + (test-equal "acos(cos( 2pi))" (acos (cos (* 2 pi))) 0) + (test-equal "acos(pi)" (acos pi) 0.0+1.81152627246085i) + (test-equal "acos(+inf)" (acos +inf.0) -nan.0) + + (test-equal "asin(-inf)" (asin -inf.0) -nan.0) + (test-equal "asin(<small number>)" (asin -1e100) -nan.0) + (test-equal "sin(-1/3pi)" (sin (- (/ pi 3))) -0.8660254037844386) + (test-equal "asin(sin(-1/3pi))" (asin (sin (- (/ pi 3)))) (- (/ pi 3))) + (test-equal "sin(-1/4pi)" (sin (- (/ pi 4))) -0.7071067811865476) + (test-equal "asin(sin(-1/4pi))" (asin (sin (- (/ pi 4)))) (- (/ pi 4))) + (test-equal "sin(-1/2pi)" (sin (- (/ pi 2))) -1.0) + (test-equal "asin(sin(-1/2pi))" (asin (sin (- (/ pi 2)))) (- (/ pi 2))) + (test-equal "sin(-pi)" (sin (- pi)) 0.0) + (test-equal "asin(sin(-pi))" (asin (sin (- pi))) 0.0) + (test-equal "sin(0)" (sin 0.0) 0.0) + (test-equal "asin(sin(0))" (asin (sin 0.0)) 0.0) + (test-equal "sin( 1/4pi)" (sin (/ pi 4)) 0.7071067811865476) + (test-equal "asin(sin( 1/4pi))" (asin (sin (/ pi 4))) (/ pi 4)) + (test-equal "sin( 1/3pi)" (sin (/ pi 3)) 0.8660254037844386) + (test-equal "asin(sin( 1/3pi))" (asin (sin (/ pi 3))) (/ pi 3)) + (test-equal "sin( 1/2pi)" (sin (/ pi 2)) 1.0) + (test-equal "asin(sin( 1/2pi))" (asin (sin (/ pi 2))) (/ pi 2)) + (test-equal "sin( 2/3pi)" (sin (/ (* 2 pi) 3)) 0.8660254037844386) + (test-equal "asin(sin( 2/3pi))" (asin (sin (/ (* 2 pi) 3))) (/ pi 3)) + (test-equal "sin( 3/4pi)" (sin (* (/ pi 4) 3)) 0.7071067811865476) + (test-equal "asin(sin( 3/4pi))" (asin (sin (* (/ pi 4) 3))) (/ pi 4)) + (test-equal "sin( pi)" (sin pi) 0.0) + (test-equal "asin(sin( pi))" (asin (sin pi)) 0.0) + (test-equal "sin( 3/2pi)" (sin (+ pi (/ pi 2))) -1.0) + (test-equal "asin(sin( 3/2pi))" (asin (sin (+ pi (/ pi 2)))) (- (/ pi 2))) + (test-equal "sin( 4/3pi)" (sin (+ pi (/ pi 3))) -0.8660254037844386) + (test-equal "asin(sin( 4/3pi))" (asin (sin (+ pi (/ pi 3)))) (- (/ pi 3))) + (test-equal "sin( 5/4pi)" (sin (+ pi (/ pi 4))) -0.7071067811865476) + (test-equal "asin(sin( 5/4pi))" (asin (sin (+ pi (/ pi 4)))) (- (/ pi 4))) + (test-equal "sin( 2pi)" (sin (* 2 pi)) 0.0) + (test-equal "asin(sin( 2pi))" (asin (sin (* 2 pi))) 0.0) + (test-equal "asin(pi)" (asin pi) 1.57079632679490-1.81152627246085i) + (test-equal "asin(+inf)" (asin +inf.0) -nan.0) + + (test-equal "atan(-inf)" (atan -inf.0) (- (/ pi 2))) + (test-equal "atan(<small number>)" (atan -1e100) (- (/ pi 2))) + (test-equal "tan(-1/3pi)" (tan (- (/ pi 3))) -1.7320508075688773) + (test-equal "atan(tan(-1/3pi))" (atan (tan (- (/ pi 3)))) (- (/ pi 3))) + (test-equal "tan(-1/4pi)" (tan (- (/ pi 4))) -1.0) + (test-equal "atan(tan(-1/4pi))" (atan (tan (- (/ pi 4)))) (- (/ pi 4))) + ;; NOTE: tan(-(/ pi 2)) should be -inf(?), but isn't. Is that a bug? + (test-equal "tan(-pi)" (tan (- pi)) 0.0) + (test-equal "atan(tan(-pi))" (atan (tan (- pi))) 0.0) + (test-equal "tan(0)" (tan 0.0) 0.0) + (test-equal "atan(tan(0))" (atan (tan 0.0)) 0.0) + (test-equal "tan( 1/4pi)" (tan (/ pi 4)) 1.0) + (test-equal "atan(tan( 1/4pi))" (atan (tan (/ pi 4))) (/ pi 4)) + (test-equal "tan( 1/3pi)" (tan (/ pi 3)) 1.7320508075688773) + (test-equal "atan(tan( 1/3pi))" (atan (tan (/ pi 3))) (/ pi 3)) + (test-equal "tan( 2/3pi)" (tan (/ (* 2 pi) 3)) -1.7320508075688773) + (test-equal "atan(tan( 2/3pi))" (atan (tan (/ (* 2 pi) 3))) (- (/ pi 3))) + (test-equal "tan( 3/4pi)" (tan (* (/ pi 4) 3)) -1.0) + (test-equal "atan(tan( 3/4pi))" (atan (tan (* (/ pi 4) 3))) (- (/ pi 4))) + (test-equal "tan( pi)" (tan pi) 0.0) + (test-equal "atan(tan( pi))" (atan (tan pi)) 0.0) + (test-equal "tan( 4/3pi)" (tan (+ pi (/ pi 3))) 1.7320508075688773) + (test-equal "atan(tan( 4/3pi))" (atan (tan (+ pi (/ pi 3)))) (/ pi 3)) + (test-equal "tan( 5/4pi)" (tan (+ pi (/ pi 4))) 1.0) + (test-equal "atan(tan( 5/4pi))" (atan (tan (+ pi (/ pi 4)))) (/ pi 4)) + (test-equal "tan( 2pi)" (tan (* 2 pi)) 0.0) + (test-equal "atan(tan( 2pi))" (atan (tan (* 2 pi))) 0.0) + (test-equal "atan(pi)" (atan 1e100) (/ pi 2)) + (test-equal "atan(+inf)" (atan +inf.0) (/ pi 2)) + + (test-equal "atan2(3, tan(pi))" (atan 3 (tan pi)) (/ pi 2)) + (test-equal "atan2(3, -tan(pi))" (atan 3 (- (tan pi))) (/ pi 2)) + (test-equal "atan2(-3, tan(pi))" (atan -3 (tan pi)) (- (/ pi 2))) + (test-equal "atan2(-3, -tan(pi))" (atan -3 (- (tan pi))) (- (/ pi 2))) + ;; Equivalence described in R5RS + (test-equal "atan2(1, 2) = angle(2+i)" + (angle (make-rectangular 2 1)) (atan 1 2)) + (test-equal "atan2(1, b1) = angle(2+i)" + (angle (make-rectangular b1 1)) (atan 1 b1)) + (test-equal "atan2(b1, 1) = angle(2+i)" + (angle (make-rectangular 1 b1)) (atan b1 1)) + (test-equal "atan2(-0.1, 3.2) = angle(3.2-0.1i)" + (angle (make-rectangular 3.2 -0.1)) (atan -0.1 3.2)) + ) + + ;; Cross-checked against Gauche and Scheme48's output + (test-group "compnums" + (test-equal "cos(0.0+1.0i)" (cos (make-rectangular 0.0 1.0)) + 1.5430806348152437) + (test-equal "acos(cos(0.0+1.0i))" (acos (cos (make-rectangular 0.0 1.0))) + 0.0+1.0i) + (test-equal "cos(0.0-1.0i)" (cos (make-rectangular 0.0 -1.0)) + 1.5430806348152437) + (test-equal "acos(cos(0.0-1.0i))" (acos (cos (make-rectangular 0.0 -1.0))) + 0.0+1.0i) + (test-equal "cos(0.0+3.0i)" (cos (make-rectangular 0.0 3.0)) + 10.067661995777765) + (test-equal "acos(cos(0.0+3.0i))" (acos (cos (make-rectangular 0.0 3.0))) + 0.0+3.0i) + (test-equal "cos(0.0-3.0i)" (cos (make-rectangular 0.0 -3.0)) + 10.067661995777765) + (test-equal "acos(cos(0.0-3.0i))" (acos (cos (make-rectangular 0.0 -3.0))) + 0.0+3.0i) + (test-equal "cos(0.5+0.5i)" + (cos (make-rectangular 0.5 0.5)) + (make-rectangular 0.9895848833999199 -0.24982639750046154)) + (test-equal "acos(cos(0.5+0.5i))" + (acos (cos (make-rectangular 0.5 0.5))) + (make-rectangular 0.5 0.5)) + (test-equal "cos(0.5-0.5i)" + (cos (make-rectangular 0.5 -0.5)) + (make-rectangular 0.9895848833999199 0.24982639750046154)) + (test-equal "acos(cos(0.5-0.5i))" + (acos (cos (make-rectangular 0.5 -0.5))) + (make-rectangular 0.5 -0.5)) + (test-equal "cos(-0.5-0.5i)" + (cos (make-rectangular -0.5 -0.5)) + (make-rectangular 0.9895848833999199 -0.24982639750046154)) + (test-equal "acos(cos(-0.5-0.5i))" + (acos (cos (make-rectangular -0.5 -0.5))) + (make-rectangular 0.5 0.5)) + (test-equal "cos(-0.5+0.5i)" + (cos (make-rectangular -0.5 0.5)) + (make-rectangular 0.9895848833999199 0.24982639750046154)) + (test-equal "acos(cos(-0.5+0.5i))" + (acos (cos (make-rectangular -0.5 0.5))) + (make-rectangular 0.5 -0.5)) + (test-equal "cos(-1.0+1.0i)" + (cos (make-rectangular -1.0 1.0)) + (make-rectangular 0.8337300251311491 0.9888977057628651)) + (test-equal "acos(cos(-1.0+1.0i))" + (acos (cos (make-rectangular -1.0 1.0))) + (make-rectangular 1.0 -1.0)) + (test-equal "cos(-1.0-1.0i)" + (cos (make-rectangular -1.0 -1.0)) + (make-rectangular 0.8337300251311491 -0.9888977057628651)) + (test-equal "acos(cos(-1.0-1.0i))" + (acos (cos (make-rectangular -1.0 -1.0))) + (make-rectangular 1.0 1.0)) + (test-equal "cos(1.0-1.0i)" + (cos (make-rectangular 1.0 -1.0)) + (make-rectangular 0.8337300251311491 0.9888977057628651)) + (test-equal "acos(cos(1.0-1.0i))" + (acos (cos (make-rectangular 1.0 -1.0))) + (make-rectangular 1.0 -1.0)) + (test-equal "cos(1.0+1.0i)" + (cos (make-rectangular 1.0 1.0)) + (make-rectangular 0.8337300251311491 -0.9888977057628651)) + (test-equal "acos(cos(1.0+1.0i))" + (acos (cos (make-rectangular 1.0 1.0))) + (make-rectangular 1.0 1.0)) + (test-equal "cos(2.0+3.0i)" + (cos (make-rectangular 2.0 3.0)) + (make-rectangular -4.189625690968807 -9.109227893755337)) + (test-equal "acos(cos(2.0+3.0i))" + (acos (cos (make-rectangular 2.0 3.0))) + (make-rectangular 2.0 3.0)) + (test-equal "cos(-2.0+3.0i)" + (cos (make-rectangular -2.0 3.0)) + (make-rectangular -4.189625690968807 9.109227893755337)) + (test-equal "acos(cos(-2.0+3.0i))" + (acos (cos (make-rectangular -2.0 3.0))) + (make-rectangular 2.0 -3.0)) + (test-equal "cos(-2.0-3.0i)" + (cos (make-rectangular -2.0 -3.0)) + (make-rectangular -4.189625690968807 -9.109227893755337)) + (test-equal "acos(cos(-2.0-3.0i))" + (acos (cos (make-rectangular -2.0 -3.0))) + (make-rectangular 2.0 3.0)) + (test-equal "cos(2.0-3.0i)" + (cos (make-rectangular 2.0 -3.0)) + (make-rectangular -4.189625690968807 9.109227893755337)) + (test-equal "acos(cos(2.0-3.0i))" + (acos (cos (make-rectangular 2.0 -3.0))) + (make-rectangular 2.0 -3.0)) + ;; Specialization check + (test-equal "cos(acos(2.0-3.0i))" + (cos (acos (make-rectangular 2.0 -3.0))) + (make-rectangular 2.0 -3.0)) + + (test-equal "sin(0.0+1.0i)" + (sin (make-rectangular 0.0 1.0)) + (make-rectangular 0.0 1.1752011936438014)) + (test-equal "asin(sin(0.0+1.0i))" + (asin (sin (make-rectangular 0.0 1.0))) + (make-rectangular 0.0 1.0)) + (test-equal "sin(0.0-1.0i)" + (sin (make-rectangular 0.0 -1.0)) + (make-rectangular 0.0 -1.1752011936438014)) + (test-equal "asin(sin(0.0-1.0i))" + (asin (sin (make-rectangular 0.0 -1.0))) + (make-rectangular 0.0 -1.0)) + (test-equal "sin(0.0+3.0i)" + (sin (make-rectangular 0.0 3.0)) + (make-rectangular 0.0 10.017874927409903)) + (test-equal "asin(sin(0.0+3.0i))" + (asin (sin (make-rectangular 0.0 3.0))) + (make-rectangular 0.0 3.0)) + (test-equal "sin(0.0-3.0i)" + (sin (make-rectangular 0.0 -3.0)) + (make-rectangular 0.0 -10.017874927409903)) + (test-equal "asin(sin(0.0-3.0i))" + (asin (sin (make-rectangular 0.0 -3.0))) + (make-rectangular 0.0 -3.0)) + (test-equal "sin(0.5+0.5i)" + (sin (make-rectangular 0.5 0.5)) + (make-rectangular 0.5406126857131534 0.4573041531842493)) + (test-equal "asin(sin(0.5+0.5i))" + (asin (sin (make-rectangular 0.5 0.5))) + (make-rectangular 0.5 0.5)) + (test-equal "sin(0.5-0.5i)" + (sin (make-rectangular 0.5 -0.5)) + (make-rectangular 0.5406126857131534 -0.4573041531842493)) + (test-equal "asin(sin(0.5-0.5i))" + (asin (sin (make-rectangular 0.5 -0.5))) + (make-rectangular 0.5 -0.5)) + (test-equal "sin(-0.5-0.5i)" + (sin (make-rectangular -0.5 -0.5)) + (make-rectangular -0.5406126857131534 -0.4573041531842493)) + (test-equal "asin(sin(-0.5-0.5i))" + (asin (sin (make-rectangular -0.5 -0.5))) + (make-rectangular -0.5 -0.5)) + (test-equal "sin(-0.5+0.5i)" + (sin (make-rectangular -0.5 0.5)) + (make-rectangular -0.5406126857131534 +0.457304153184249)) + (test-equal "asin(sin(-0.5+0.5i))" + (asin (sin (make-rectangular -0.5 0.5))) + (make-rectangular -0.5 +0.5)) + (test-equal "sin(-1.0+1.0i)" + (sin (make-rectangular -1.0 1.0)) + (make-rectangular -1.2984575814159773 0.6349639147847361)) + (test-equal "asin(sin(-1.0+1.0i))" + (asin (sin (make-rectangular -1.0 1.0))) + (make-rectangular -1.0 1.0)) + (test-equal "sin(-1.0-1.0i)" + (sin (make-rectangular -1.0 -1.0)) + (make-rectangular -1.2984575814159773 -0.6349639147847361)) + (test-equal "asin(sin(-1.0-1.0i))" + (asin (sin (make-rectangular -1.0 -1.0))) + (make-rectangular -1.0 -1.0)) + (test-equal "sin(1.0-1.0i)" + (sin (make-rectangular 1.0 -1.0)) + (make-rectangular 1.2984575814159773 -0.6349639147847361)) + (test-equal "asin(sin(1.0-1.0i))" + (asin (sin (make-rectangular 1.0 -1.0))) + (make-rectangular 1.0 -1.0)) + (test-equal "sin(2.0+3.0i)" + (sin (make-rectangular 2.0 3.0)) + (make-rectangular 9.15449914691143 -4.168906959966565)) + (test-equal "asin(sin(2.0+3.0i))" + (asin (sin (make-rectangular 2.0 3.0))) + (make-rectangular 1.1415926535898042 -3.0)) + (test-equal "sin(-2.0+3.0i)" + (sin (make-rectangular -2.0 3.0)) + (make-rectangular -9.15449914691143 -4.168906959966565)) + (test-equal "asin(sin(-2.0+3.0i))" + (asin (sin (make-rectangular -2.0 3.0))) + (make-rectangular -1.1415926535898042 -3.0)) + (test-equal "sin(-2.0-3.0i)" + (sin (make-rectangular -2.0 -3.0)) + (make-rectangular -9.15449914691143 4.168906959966565)) + (test-equal "asin(sin(-2.0-3.0i))" + (asin (sin (make-rectangular -2.0 -3.0))) + (make-rectangular -1.1415926535898042 3.0)) + (test-equal "sin(2.0-3.0i)" + (sin (make-rectangular 2.0 -3.0)) + (make-rectangular 9.15449914691143 4.168906959966565)) + (test-equal "asin(sin(2.0-3.0i))" + (asin (sin (make-rectangular 2.0 -3.0))) + (make-rectangular 1.1415926535898042 3.0)) + ;; Specialization check + (test-equal "sin(asin(1.1415926535898042+3.0i))" + (sin (asin (make-rectangular 2.0 3.0))) + (make-rectangular 2.0 3.0)) + + (test-equal "tan(0.0+1.0i)" + (tan (make-rectangular 0.0 1.0)) + (make-rectangular 0.0 0.7615941559557649)) + (test-equal "atan(tan(0.0+1.0i))" + (atan (tan (make-rectangular 0.0 1.0))) + (make-rectangular 0.0 1.0)) + (test-equal "tan(0.0-1.0i)" + (tan (make-rectangular 0.0 -1.0)) + (make-rectangular 0.0 -0.7615941559557649)) + (test-equal "atan(tan(0.0-1.0i))" + (atan (tan (make-rectangular 0.0 -1.0))) + (make-rectangular 0.0 -1.0)) + (test-equal "tan(0.0+3.0i)" + (tan (make-rectangular 0.0 3.0)) + (make-rectangular 0.0 0.9950547536867306)) + (test-equal "atan(tan(0.0+3.0i))" + (atan (tan (make-rectangular 0.0 3.0))) + (make-rectangular 0.0 3.0)) + (test-equal "tan(0.0-3.0i)" + (tan (make-rectangular 0.0 -3.0)) + (make-rectangular 0.0 -0.9950547536867306)) + (test-equal "atan(tan(0.0-3.0i))" + (atan (tan (make-rectangular 0.0 -3.0))) + (make-rectangular 0.0 -3.0)) + (test-equal "tan(0.5+0.5i)" + (tan (make-rectangular 0.5 0.5)) + (make-rectangular 0.4038964553160257 0.5640831412674985)) + (test-equal "atan(tan(0.5+0.5i))" + (atan (tan (make-rectangular 0.5 0.5))) + (make-rectangular 0.5 0.5)) + (test-equal "tan(0.5-0.5i)" + (tan (make-rectangular 0.5 -0.5)) + (make-rectangular 0.4038964553160257 -0.5640831412674985)) + (test-equal "atan(tan(0.5-0.5i))" + (atan (tan (make-rectangular 0.5 -0.5))) + (make-rectangular 0.5 -0.5)) + (test-equal "tan(-0.5-0.5i)" + (tan (make-rectangular -0.5 -0.5)) + (make-rectangular -0.4038964553160257 -0.5640831412674985)) + (test-equal "atan(tan(-0.5-0.5i))" + (atan (tan (make-rectangular -0.5 -0.5))) + (make-rectangular -0.5 -0.5)) + (test-equal "tan(-0.5+0.5i)" + (tan (make-rectangular -0.5 0.5)) + (make-rectangular -0.4038964553160257 0.5640831412674985)) + (test-equal "atan(tan(-0.5+0.5i))" + (atan (tan (make-rectangular -0.5 0.5))) + (make-rectangular -0.5 0.5)) + (test-equal "tan(-1.0+1.0i)" + (tan (make-rectangular -1.0 1.0)) + (make-rectangular -0.27175258531951174 1.0839233273386948)) + (test-equal "atan(tan(-1.0+1.0i))" + (atan (tan (make-rectangular -1.0 1.0))) + (make-rectangular -1.0 1.0)) + (test-equal "tan(-1.0-1.0i)" + (tan (make-rectangular -1.0 -1.0)) + (make-rectangular -0.27175258531951174 -1.0839233273386948)) + (test-equal "atan(tan(-1.0-1.0i))" + (atan (tan (make-rectangular -1.0 -1.0))) + (make-rectangular -1.0 -1.0)) + (test-equal "tan(1.0-1.0i)" + (tan (make-rectangular 1.0 -1.0)) + (make-rectangular 0.27175258531951174 -1.0839233273386948)) + (test-equal "atan(tan(1.0-1.0i))" + (atan (tan (make-rectangular 1.0 -1.0))) + (make-rectangular 1.0 -1.0)) + (test-equal "tan(2.0+3.0i)" + (tan (make-rectangular 2.0 3.0)) + (make-rectangular -0.0037640256415040815 1.0032386273536098)) + (test-equal "atan(tan(2.0+3.0i))" + (atan (tan (make-rectangular 2.0 3.0))) + (make-rectangular -1.1415926535898042 3.0)) + (test-equal "tan(-2.0+3.0i)" + (tan (make-rectangular -2.0 3.0)) + (make-rectangular 0.0037640256415040815 1.0032386273536098)) + (test-equal "atan(tan(-2.0+3.0i))" + (atan (tan (make-rectangular -2.0 3.0))) + (make-rectangular 1.1415926535898042 3.0)) + (test-equal "tan(-2.0-3.0i)" + (tan (make-rectangular -2.0 -3.0)) + (make-rectangular 0.0037640256415040815 -1.0032386273536098)) + (test-equal "atan(tan(-2.0-3.0i))" + (atan (tan (make-rectangular -2.0 -3.0))) + (make-rectangular 1.1415926535898042 -3.0)) + (test-equal "tan(2.0-3.0i)" + (tan (make-rectangular 2.0 -3.0)) + (make-rectangular -0.0037640256415040815 -1.0032386273536098)) + (test-equal "atan(tan(2.0-3.0i))" + (atan (tan (make-rectangular 2.0 -3.0))) + (make-rectangular -1.1415926535898042 -3.0)) + ;; Specialization check + (test-equal "tan(atan(2.0-3.0i))" + (tan (atan (make-rectangular 2.0 -3.0))) + (make-rectangular 2.0 -3.0)) + + ) + + ;; This is just a handful to determine that we're able to accept these. + ;; Maybe determine better values to test with? + (test-group "bignums" + (test-equal "acos(<negative bignum>)" (acos (- b1)) -nan.0) + ;; These are bogus (maybe the negative ones too!), but I don't want to + ;; "fix" them by copying the output and assume it's alright. + #;(test-equal "acos(<bignum>)" (acos b1) +nan.0) + (test-equal "asin(<negative bignum>)" (asin (- b1)) -nan.0) + #;(test-equal "asin(<bignum>)" (asin b1) +nan.0) + (test-equal "atan(<negative bignum>)" (atan (- b1)) (- (/ pi 2))) + (test-equal "atan(<bignum>)" (atan b1) (/ pi 2))) + + ;; This should probably be enough; we're only testing conversion to flonums + ;; and specialization. The actual functionality of cos is checked above. + (test-group "fixnums" + (test-equal "cos(0)" (cos 0) 1.0) + (test-equal "acos(0)" (acos 0) (/ pi 2)) + (test-equal "cos(1)" (cos 1) (cos 1.0)) + (test-equal "acos(1)" (acos 1) 0.0) + (test-equal "cos(-1)" (cos -1) (cos -1.0)) + (test-equal "acos(-1)" (acos -1) pi) + (test-equal "acos(-2)" (acos -2) (make-rectangular pi -1.31695789692482)) + (test-equal "acos(2)" (acos 2) 0.0+1.31695789692482i) + (test-equal "asin(1)" (asin 1) (/ pi 2)) + (test-equal "asin(-1)" (asin -1) (/ pi -2)) + (test-equal "asin(2)" (asin 2) (make-rectangular (/ pi 2) -1.31695789692482)) + (test-equal "asin(-2)" (asin -2) (make-rectangular (/ pi -2) 1.31695789692482))) + + (test-group "ratnums" + (test-equal "acos(<small number>)" (acos (/ -999999999 2)) -nan.0) + (test-equal "cos(-1/3pi)" (cos (- (/ ratpi 3))) 0.5) + (test-equal "acos(cos(-1/3pi))" (acos (cos (- (/ ratpi 3)))) (/ pi 3)) + (test-equal "cos(-1/4pi)" (cos (- (/ ratpi 4))) 0.7071067811865476) + (test-equal "acos(cos(-1/4pi))" (acos (cos (- (/ ratpi 4)))) (/ pi 4)) + (test-equal "cos(-1/2pi)" (cos (- (/ ratpi 2))) 0.0) + (test-equal "acos(cos(-1/2pi))" (acos (cos (- (/ ratpi 2)))) (/ pi 2)) + (test-equal "cos(-pi)" (cos (- ratpi)) -1.0) + (test-equal "acos(cos(-pi))" (acos (cos (- ratpi))) pi) + (test-equal "cos(0)" (cos 0.0) 1.0) + (test-equal "acos(cos(0))" (acos (cos 0.0)) 0.0) + (test-equal "cos( 1/4pi)" (cos (/ ratpi 4)) 0.7071067811865476) + (test-equal "acos(cos( 1/4pi))" (acos (cos (/ ratpi 4))) (/ pi 4)) + (test-equal "cos( 1/3pi)" (cos (/ ratpi 3)) 0.5) + (test-equal "acos(cos( 1/3pi))" (acos (cos (/ ratpi 3))) (/ pi 3)) + (test-equal "cos( 1/2pi)" (cos (/ ratpi 2)) 0.0) + (test-equal "acos(cos( 1/2pi))" (acos (cos (/ ratpi 2))) (/ pi 2)) + (test-equal "cos( 2/3pi)" (cos (/ (* 2 ratpi) 3)) -0.5) + (test-equal "acos(cos( 2/3pi))" (acos (cos (/ (* 2 ratpi) 3))) (/ (* 2 pi) 3)) + (test-equal "cos( 3/4pi)" (cos (* (/ ratpi 4) 3)) -0.7071067811865476) + (test-equal "acos(cos( 3/4pi))" (acos (cos (* (/ ratpi 4) 3))) (* (/ pi 4) 3)) + (test-equal "cos( pi)" (cos ratpi) -1.0) + (test-equal "acos(cos( pi))" (acos (cos ratpi)) pi) + (test-equal "cos( 3/2pi)" (cos (+ ratpi (/ ratpi 2))) 0.0) + (test-equal "acos(cos( 3/2pi))" (acos (cos (+ ratpi (/ ratpi 2)))) (/ pi 2)) + (test-equal "cos( 4/3pi)" (cos (+ ratpi (/ ratpi 3))) -0.5) + (test-equal "acos(cos( 4/3pi))" (acos (cos (+ ratpi (/ ratpi 3)))) (* 2 (/ pi 3))) + (test-equal "cos( 5/4pi)" (cos (+ ratpi (/ ratpi 4))) -0.7071067811865476) + (test-equal "acos(cos( 5/4pi))" (acos (cos (+ ratpi (/ ratpi 4)))) (* 3 (/ pi 4))) + (test-equal "cos( 2pi)" (cos (* 2 pi)) 1.0) + (test-equal "acos(cos( 2pi))" (acos (cos (* 2 ratpi))) 0) + + (test-equal "sin(-1/3pi)" (sin (- (/ ratpi 3))) -0.8660254037844386) + (test-equal "asin(sin(-1/3pi))" (asin (sin (- (/ ratpi 3)))) (- (/ pi 3))) + (test-equal "sin(-1/4pi)" (sin (- (/ ratpi 4))) -0.7071067811865476) + (test-equal "asin(sin(-1/4pi))" (asin (sin (- (/ ratpi 4)))) (- (/ pi 4))) + (test-equal "sin(-1/2pi)" (sin (- (/ ratpi 2))) -1.0) + (test-equal "asin(sin(-1/2pi))" (asin (sin (- (/ ratpi 2)))) (- (/ pi 2))) + (test-equal "sin(-pi)" (sin (- ratpi)) 0.0) + (test-equal "asin(sin(-pi))" (asin (sin (- ratpi))) 0.0) + (test-equal "sin(0)" (sin 0.0) 0.0) + (test-equal "asin(sin(0))" (asin (sin 0.0)) 0.0) + (test-equal "sin( 1/4pi)" (sin (/ ratpi 4)) 0.7071067811865476) + (test-equal "asin(sin( 1/4pi))" (asin (sin (/ ratpi 4))) (/ pi 4)) + (test-equal "sin( 1/3pi)" (sin (/ ratpi 3)) 0.8660254037844386) + (test-equal "asin(sin( 1/3pi))" (asin (sin (/ ratpi 3))) (/ pi 3)) + (test-equal "sin( 1/2pi)" (sin (/ ratpi 2)) 1.0) + (test-equal "asin(sin( 1/2pi))" (asin (sin (/ ratpi 2))) (/ pi 2)) + (test-equal "sin( 2/3pi)" (sin (/ (* 2 ratpi) 3)) 0.8660254037844386) + (test-equal "asin(sin( 2/3pi))" (asin (sin (/ (* 2 ratpi) 3))) (/ pi 3)) + (test-equal "sin( 3/4pi)" (sin (* (/ ratpi 4) 3)) 0.7071067811865476) + (test-equal "asin(sin( 3/4pi))" (asin (sin (* (/ ratpi 4) 3))) (/ pi 4)) + (test-equal "sin( pi)" (sin ratpi) 0.0) + (test-equal "asin(sin( pi))" (asin (sin ratpi)) 0.0) + (test-equal "sin( 3/2pi)" (sin (+ ratpi (/ ratpi 2))) -1.0) + (test-equal "asin(sin( 3/2pi))" (asin (sin (+ ratpi (/ ratpi 2)))) (- (/ pi 2))) + (test-equal "sin( 4/3pi)" (sin (+ ratpi (/ ratpi 3))) -0.8660254037844386) + (test-equal "asin(sin( 4/3pi))" (asin (sin (+ ratpi (/ ratpi 3)))) (- (/ pi 3))) + (test-equal "sin( 5/4pi)" (sin (+ ratpi (/ ratpi 4))) -0.7071067811865476) + (test-equal "asin(sin( 5/4pi))" (asin (sin (+ ratpi (/ ratpi 4)))) (- (/ pi 4))) + (test-equal "sin( 2pi)" (sin (* 2 ratpi)) 0.0) + (test-equal "asin(sin( 2pi))" (asin (sin (* 2 ratpi))) 0.0) + + (test-equal "tan(-1/3pi)" (tan (- (/ ratpi 3))) -1.7320508075688773) + (test-equal "atan(tan(-1/3pi))" (atan (tan (- (/ ratpi 3)))) (- (/ pi 3))) + (test-equal "tan(-1/4pi)" (tan (- (/ ratpi 4))) -1.0) + (test-equal "atan(tan(-1/4pi))" (atan (tan (- (/ ratpi 4)))) (- (/ pi 4))) + ;; NOTE: tan(-(/ pi 2)) should be -inf(?), but isn't. Is that a bug? + (test-equal "tan(-pi)" (tan (- ratpi)) 0.0) + (test-equal "atan(tan(-pi))" (atan (tan (- ratpi))) 0.0) + (test-equal "tan(0)" (tan 0.0) 0.0) + (test-equal "atan(tan(0))" (atan (tan 0.0)) 0.0) + (test-equal "tan( 1/4pi)" (tan (/ ratpi 4)) 1.0) + (test-equal "atan(tan( 1/4pi))" (atan (tan (/ ratpi 4))) (/ pi 4)) + (test-equal "tan( 1/3pi)" (tan (/ ratpi 3)) 1.7320508075688773) + (test-equal "atan(tan( 1/3pi))" (atan (tan (/ ratpi 3))) (/ pi 3)) + (test-equal "tan( 2/3pi)" (tan (/ (* 2 ratpi) 3)) -1.7320508075688773) + (test-equal "atan(tan( 2/3pi))" (atan (tan (/ (* 2 ratpi) 3))) (- (/ pi 3))) + (test-equal "tan( 3/4pi)" (tan (* (/ ratpi 4) 3)) -1.0) + (test-equal "atan(tan( 3/4pi))" (atan (tan (* (/ ratpi 4) 3))) (- (/ pi 4))) + (test-equal "tan( pi)" (tan ratpi) 0.0) + (test-equal "atan(tan( pi))" (atan (tan ratpi)) 0.0) + (test-equal "tan( 4/3pi)" (tan (+ ratpi (/ ratpi 3))) 1.7320508075688773) + (test-equal "atan(tan( 4/3pi))" (atan (tan (+ ratpi (/ ratpi 3)))) (/ pi 3)) + (test-equal "tan( 5/4pi)" (tan (+ ratpi (/ ratpi 4))) 1.0) + (test-equal "atan(tan( 5/4pi))" (atan (tan (+ ratpi (/ ratpi 4)))) (/ pi 4)) + (test-equal "tan( 2pi)" (tan (* 2 ratpi)) 0.0) + (test-equal "atan(tan( 2i))" (atan (tan (* 2 ratpi))) 0.0) + + (test-equal "atan2(3, tan(pi))" (atan 3 (tan ratpi)) (/ pi 2)) + (test-equal "atan2(3, -tan(pi))" (atan 3 (- (tan ratpi))) (/ pi 2)) + (test-equal "atan2(-3, tan(pi))" (atan -3 (tan ratpi)) (- (/ pi 2))) + (test-equal "atan2(-3, -tan(pi))" (atan -3 (- (tan ratpi))) (- (/ pi 2)))))) + +(test-end) + +;(unless (zero? (test-failure-count)) (exit 1)) diff --git a/tests/runtests.bat b/tests/runtests.bat index 1405b0e4..44985608 100644 --- a/tests/runtests.bat +++ b/tests/runtests.bat @@ -366,7 +366,33 @@ a.out if errorlevel 1 exit /b 1 echo ======================================== string->number tests ... -%compile% numbers-string-conversion-tests.scm +%interpret% -s numbers-string-conversion-tests.scm +if errorlevel 1 exit /b 1 +%compile% -specialize numbers-string-conversion-tests.scm +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 + +echo ======================================== basic numeric ops tests ... +%interpret% -s numbers-test.scm +if errorlevel 1 exit /b 1 +%compile% -specialize numbers-test.scm +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 + +echo ======================================== Alex Shinns numeric ops tests ... +%interpret% -s numbers-test-ashinn.scm +if errorlevel 1 exit /b 1 +%compile% -specialize numbers-test-ashinn.scm +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 + +echo ======================================== Gauche numeric ops tests ... +%interpret% -s numbers-test-gauche.scm +if errorlevel 1 exit /b 1 +%compile% -specialize numbers-test-gauche.scm if errorlevel 1 exit /b 1 a.out if errorlevel 1 exit /b 1 diff --git a/tests/runtests.sh b/tests/runtests.sh index 1af81556..18dee088 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -305,7 +305,23 @@ $compile fixnum-tests.scm ./a.out echo "======================================== string->number tests ..." -$compile numbers-string-conversion-tests.scm +$interpret -s numbers-string-conversion-tests.scm +$compile -specialize numbers-string-conversion-tests.scm +./a.out + +echo "======================================== basic numeric ops tests ..." +$interpret -s numbers-test.scm +$compile -specialize numbers-test.scm +./a.out + +echo "======================================== Alex Shinn's numeric ops tests ..." +$interpret -s numbers-test-ashinn.scm +$compile -specialize numbers-test-ashinn.scm +./a.out + +echo "======================================== Gauche's numeric ops tests ..." +$interpret -s numbers-test-gauche.scm +$compile -specialize numbers-test-gauche.scm ./a.out echo "======================================== srfi-4 tests ..." diff --git a/tests/test.scm b/tests/test.scm index bbe07f8c..0db53d06 100644 --- a/tests/test.scm +++ b/tests/test.scm @@ -2,6 +2,7 @@ ; ; by Alex Shinn, lifted from match-test by felix +(use data-structures) ; for "->string" (define *pass* 0) (define *fail* 0) @@ -74,11 +75,28 @@ '("(PASS)" name) '("(FAIL)" name ": expected " expect " but got " result))) +(define current-test-epsilon (make-parameter 1e-5)) + +(define (approx-equal? a b epsilon) + (cond + ((> (abs a) (abs b)) (approx-equal? b a epsilon)) + ((zero? a) (< (abs b) epsilon)) + (else (< (abs (/ (- a b) b)) epsilon)))) + +(define (test-equal? expect res) + (or (equal? expect res) + (and (number? expect) + (inexact? expect) + (inexact? res) + (approx-equal? expect res (current-test-epsilon))))) + +(define current-test-comparator (make-parameter test-equal?)) + (define-syntax test-equal (syntax-rules () ((_ name expr value eq) (run-equal name (lambda () expr) value eq)) - ((_ name expr value) (run-equal name (lambda () expr) value equal?)) - ((_ expr value) (run-equal (->string 'expr) (lambda () expr) value equal?)))) + ((_ name expr value) (run-equal name (lambda () expr) value (current-test-comparator))) + ((_ expr value) (run-equal (->string 'expr) (lambda () expr) value (current-test-comparator))))) (define-syntax test-error (syntax-rules ()Trap