
(if (not (defined? 'SECTION))
    (load-relative "testing.ss"))

(SECTION 'numbers)

(SECTION 6 5 5)
(test #f number? 'a)
(test #f complex? 'a)
(test #f real? 'a)
(test #f rational? 'a)
(test #f integer? 'a)

(test #t number? 3)
(test #t complex? 3)
(test #t real? 3)
(test #t rational? 3)
(test #t integer? 3)

(test #t number? 3.0)
(test #t complex? 3.0)
(test #t real? 3.0)
(test #t rational? 3.0)
(test #t integer? 3.0)

(test #t number? 3.1)
(test #t complex? 3.1)
(test #t real? 3.1)
(test #t rational? 3.1)
(test #f integer? 3.1)

(test #t number? 3/2)
(test #t complex? 3/2)
(test #t real? 3/2)
(test #t rational? 3/2)
(test #f integer? 3/2)

(test #t number? 3+i)
(test #t complex? 3+i)
(test #f real? 3+i)
(test #f rational? 3+i)
(test #f integer? 3+i)

(test #t number? 3.0+0i)
(test #t complex? 3.0+0i)
(test #t real? 3.0+0i)
(test #t rational? 3.0+0i)
(test #t integer? 3.0+0i)

(test #t number? 3.0+0.0i)
(test #t complex? 3.0+0.0i)
(test #t real? 3.0+0.0i)
(test #t rational? 3.0+0.0i)
(test #t integer? 3.0+0.0i)

(test #t number? 3.1+0.0i)
(test #t complex? 3.1+0.0i)
(test #t real? 3.1+0.0i)
(test #t rational? 3.1+0.0i)
(test #f integer? 3.1+0.0i)

(test #t exact? 3)
(test #t exact? 3/4)
(test #f exact? 3.0)
(test #t exact? (expt 2 100))
(test #t exact? 3+4i)
(test #f exact? 3.0+4i)

(test #f inexact? 3)
(test #f inexact? 3/4)
(test #t inexact? 3.0)
(test #f inexact? (expt 2 100))
(test #f inexact? 3+4i)
(test #t inexact? 3.0+4i)
(test #t inexact? 0+4.0i)
(test #t inexact? 4+0.i)

(test #t complex? -4.242154731064108e-5-6.865001427422244e-5i)
(test #f exact? -4.242154731064108e-5-6.865001427422244e-5i)
(test #t inexact? -4.242154731064108e-5-6.865001427422244e-5i)

(test #t complex? -4.242154731064108f-5-6.865001427422244f-5i)
(test #f exact? -4.242154731064108f-5-6.865001427422244f-5i)
(test #t inexact? -4.242154731064108f-5-6.865001427422244f-5i)

(test #t number? +inf.0)
(test #t complex? +inf.0)
(test #t real? +inf.0)
(test #t rational? +inf.0)
(test #t integer? +inf.0)

(test #t number? -inf.0)
(test #t complex? -inf.0)
(test #t real? -inf.0)
(test #t rational? -inf.0)
(test #t integer? -inf.0)

(test #t number? +nan.0)
(test #t complex? +nan.0)
(test #t real? +nan.0)
(test #t rational? +nan.0)
(test #f integer? +nan.0)

(arity-test inexact? 1 1)
(arity-test number? 1 1)
(arity-test complex? 1 1)
(arity-test real? 1 1)
(arity-test rational? 1 1)
(arity-test integer? 1 1)
(arity-test exact? 1 1)
(arity-test inexact? 1 1)

(error-test '(exact? 'a))
(error-test '(inexact? 'a))

(test "+inf.0" number->string +inf.0)
(test "-inf.0" number->string -inf.0)
(test "+nan.0" number->string +nan.0)
(test "+nan.0" number->string +nan.0)

(test #t = 0.0 -0.0)
(test #f eqv? 0.0 -0.0)

(test #t = 0)
(test #t > 0)
(test #t < 0)
(test #t >= 0)
(test #t <= 0)
(test #t = 22 22 22)
(test #t = 22 22)
(test #f = 34 34 35)
(test #f = 34 35)
(test #t > 3 -6246)
(test #f > 9 9 -2424)
(test #t >= 3 -4 -6246)
(test #t >= 9 9)
(test #f >= 8 9)
(test #t < -1 2 3 4 5 6 7 8)
(test #f < -1 2 3 4 4 5 6 7)
(test #t <= -1 2 3 4 5 6 7 8)
(test #t <= -1 2 3 4 4 5 6 7)
(test #f < 1 3 2)
(test #f >= 1 3 2)

(define (test-compare lo m hi) ; all positive!
  (define -lo (- lo))
  (define -m (- m))
  (define -hi (- hi))

  (define (test-lh l h)
    (test #f > l h)
    (test #t < l h)
    (test #f = l h)
    (test #f >= l h)
    (test #t <= l h))

  (define (test-hl h l)
    (test #t > h l)
    (test #f < h l)
    (test #f = h l)
    (test #t >= h l)
    (test #f <= h l))

  (define (test-zero z)
    (test-hl m z)
    (test-lh -m z)
    (test-hl z -m)
    (test-lh z m))

  (test-lh m hi)
  (test-hl -m -hi)

  (test #f > m m)
  (test #f < m m)
  (test #t = m m)
  (test #t >= m m)
  (test #t <= m m)

  (test-hl m -m)
  (test-lh -m m)

  (test-hl m lo)
  (test-lh -m -lo)

  (test-zero 0)
  (test-zero 0.0))
  
(test-compare 0.5 1.2 2.3)
(test-compare 2/5 1/2 2/3)
(test #t = 1/2 2/4)

(test-compare 0.5 6/5 2.3)
(test-compare 1 11922615739/10210200 3000)
(test-compare 1.0 11922615739/10210200 3000.0)

(test-compare 0.4+0.i 1/2 2.3+0.i)

(test #f > 0 (/ 1 (expt 2 400)))

(test #t < 0.5 2/3)
(test #f < 2/3 0.5)
(test #t = 0.5 1/2)
(test #t = +0.5i +1/2i)
(test #f = +0.5i 1+1/2i)
(test #t = 1 1.0+0i)
(test #t = 1 1.0+0.0i)
(test #f eqv? 1.0 1.0+0.0i)
(test #f eqv? 1.0-0.0i 1.0+0.0i)

(test #f = 1+2i 2+i)

(define (test-nan.0 f . args)
  (apply test +nan.0 f args))

(define (test-i-nan.0 f . args)
  (apply test (make-rectangular +nan.0 +nan.0) f args))

(define (test-nan c)
  (test #f < +nan.0 c)
  (test #f > +nan.0 c)
  (test #f = +nan.0 c)
  (test #f <= +nan.0 c)
  (test #f >= +nan.0 c))
(test-nan 0)
(test-nan 0.0)
(test-nan 0.3)
(test-nan +nan.0)
(test-nan +inf.0)
(test-nan -inf.0)
(test-nan 0.3+0.0i)
(test #f = +nan.0 1+2i)
(test #f = +nan.0 (make-rectangular +inf.0 -inf.0))

(test-compare 999999999999 1000000000000 1000000000001)
(define big-num (expt 2 1500))
(test-compare (sub1 big-num) big-num (add1 big-num))
(test-compare 1.0 (expt 10 100) 1e200)

(define (inf-zero-test inf rx negnot)
  (let ([inf-test-x
	 (lambda (r v)
	   (test r < v inf)
	   (test (not r) > v inf)
	   (test r <= v inf)
	   (test (not r) >= v inf)
	   
	   (test (not r) < inf v)
	   (test r > inf v)
	   (test (not r) <= inf v)
	   (test r >= inf v))])
    (inf-test-x rx 5)
    (inf-test-x (negnot rx) -5)
    (inf-test-x rx big-num)
    (inf-test-x (negnot rx) (- big-num))
    (inf-test-x rx (/ big-num 3))
    (inf-test-x (negnot rx) (/ (- big-num) 3))
    (inf-test-x rx (/ 1 big-num))
    (inf-test-x (negnot rx) (/ 1 (- big-num)))))
(inf-zero-test +inf.0 #t (lambda (x) x))
(inf-zero-test -inf.0 #f (lambda (x) x))
(inf-zero-test 0.0 #f not)

(error-test '(= 1 'a))
(error-test '(= 1 1 'a))
(error-test '(= 1 2 'a))
(error-test '(= 'a 1))
(error-test '(= 'a))
(error-test '(> 1 'a))
(error-test '(> 1 0 'a))
(error-test '(> 1 2 'a))
(error-test '(> 'a 1))
(error-test '(> 0.5+0.1i 1))
(error-test '(> 1 0.5+0.1i))
(error-test '(< 1 'a))
(error-test '(< 1 2 'a))
(error-test '(< 1 0 'a))
(error-test '(< 'a 1))
(error-test '(< 0.5+0.1i 1))
(error-test '(< 1 0.5+0.1i))
(error-test '(>= 1 'a))
(error-test '(>= 1 1 'a))
(error-test '(>= 1 2 'a))
(error-test '(>= 'a 1))
(error-test '(>= 0.5+0.1i 1))
(error-test '(>= 1 0.5+0.1i))
(error-test '(<= 1 'a))
(error-test '(<= 1 1 'a))
(error-test '(<= 1 0 'a))
(error-test '(<= 'a 1))
(error-test '(<= 0.5+0.1i 1))
(error-test '(<= 1 0.5+0.1i))

(arity-test = 1 -1)
(arity-test < 1 -1)
(arity-test > 1 -1)
(arity-test <= 1 -1)
(arity-test >= 1 -1)

(test #t zero? 0)
(test #t zero? 0.0)
(test #t zero? +0.0i)
(test #t zero? -0.0i)
(test #t zero? 0.0+0.0i)
(test #f zero? 1.0+0.0i)
(test #f zero? 1.0+1.0i)
(test #f zero? 0.0+1.0i)
(test #t zero? 0/1)
(test #f zero? 1)
(test #f zero? -1)
(test #f zero? -100)
(test #f zero? 1.0)
(test #f zero? -1.0)
(test #f zero? 1/2)
(test #f zero? -1/2)
(test #f zero? -1/2+2i)
(test #f zero? +inf.0)
(test #f zero? -inf.0)
(test #f zero? +nan.0)
(test #f zero? (expt 2 37))
(test #f zero? (expt -2 37))
(test #t positive? 4)
(test #f positive? -4)
(test #f positive? 0)
(test #t positive? 4.0)
(test #f positive? -4.0)
(test #f positive? 0.0)
(test #t positive? 2/4)
(test #f positive? -2/4)
(test #f positive? 0/2)
(test #t positive? +inf.0)
(test #f positive? -inf.0)
(test #f positive? +nan.0)
(test #t positive? 5+0.0i)
(test #f positive? -5+0.0i)
(test #t positive? (expt 2 37))
(test #f positive? (expt -2 37))
(test #f negative? 4)
(test #t negative? -4)
(test #f negative? 0)
(test #f negative? 4.0)
(test #t negative? -4.0)
(test #f negative? 0.0)
(test #f negative? 2/4)
(test #t negative? -2/4)
(test #f negative? 0/4)
(test #f negative? (expt 2 37))
(test #t negative? (expt -2 37))
(test #f negative? +inf.0)
(test #t negative? -inf.0)
(test #f negative? +nan.0)
(test #f negative? 5+0.0i)
(test #t negative? -5+0.0i)
(test #t odd? 3)
(test #f odd? 2)
(test #f odd? -4)
(test #t odd? -1)
(test #t odd? +inf.0)
(test #t odd? -inf.0)
(test #t odd? 5+0.0i)
(test #f odd? 4+0.0i)
(test #f odd? (expt 2 37))
(test #f odd? (expt -2 37))
(test #t odd? (add1 (expt 2 37)))
(test #t odd? (sub1 (expt -2 37)))
(test #f even? 3)
(test #t even? 2)
(test #t even? -4)
(test #f even? -1)
(test #t even? +inf.0)
(test #t even? -inf.0)
(test #t even? 4+0.0i)
(test #f even? 5+0.0i)
(test #t even? (expt 2 37))
(test #t even? (expt -2 37))
(test #f even? (add1 (expt 2 37)))
(test #f even? (sub1 (expt -2 37)))

(arity-test zero? 1 1)
(arity-test positive? 1 1)
(arity-test negative? 1 1)
(arity-test odd? 1 1)
(arity-test even? 1 1)

(error-test '(positive? 2+i))
(error-test '(negative? 2+i))
(error-test '(odd? 4.1))
(error-test '(odd? 4.1+0.0i))
(error-test '(odd? 4+1i))
(error-test '(even? 4.1))
(error-test '(even? 4.1+0.0i))
(error-test '(even? 4+1i))
(error-test '(even? +nan.0))

(error-test '(positive? 'i))
(error-test '(negative? 'i))
(error-test '(odd? 'a))
(error-test '(even? 'a))
(error-test '(odd? 'i))
(error-test '(even? 'i))

(test 5 max 5)
(test 5 min 5)
(test 38 max 34 5 7 38 6)
(test -24 min 3  5 5 330 4 -24)
(test 38.0 max 34 5.0 7 38 6)
(test -24.0 min 3  5 5 330 4 -24.0)
(test 2/3 max 1/2 2/3)
(test 2/3 max 2/3 1/2)
(test 2/3 max 2/3 -4/5)
(test 1/2 min 1/2 2/3)
(test 1/2 min 2/3 1/2)
(test -4/5 min 2/3 -4/5)
(test +inf.0 max +inf.0 0 -inf.0)
(test -inf.0 min +inf.0 0 -inf.0)
(test-nan.0 max +inf.0 +nan.0 0 -inf.0)
(test-nan.0 min +inf.0 0 +nan.0 -inf.0)
(test 9.0 min 9.0+0.0i 100)
(test 8.0 min 9.0+0.0i 8)
(test 9.0 min 100 9.0+0.0i)
(test 8.0 min 8 9.0+0.0i)
(test 100.0 max 9.0+0.0i 100)
(test 9.0 max 9.0+0.0i 8)
(test 100.0 max 100 9.0+0.0i)
(test 9.0 max 8 9.0+0.0i)

(test (expt 5 27) max 9 (expt 5 27))
(test (expt 5 29) max (expt 5 29) (expt 5 27))
(test (expt 5 29) max (expt 5 27) (expt 5 29))
(test (expt 5 27) max (expt 5 27) 9)
(test (expt 5 27) max (expt 5 27) (- (expt 5 29)))
(test (expt 5 27) max (- (expt 5 29)) (expt 5 27))
(test (- (expt 5 27)) max (- (expt 5 27)) (- (expt 5 29)))
(test (- (expt 5 27)) max (- (expt 5 29)) (- (expt 5 27)))
(test 9 min 9 (expt 5 27))
(test (expt 5 27) min (expt 5 29) (expt 5 27))
(test (expt 5 27) min (expt 5 27) (expt 5 29))
(test 9 min (expt 5 27) 9)
(test (- (expt 5 29)) min (expt 5 27) (- (expt 5 29)))
(test (- (expt 5 29)) min (- (expt 5 29)) (expt 5 27))
(test (- (expt 5 29)) min (- (expt 5 27)) (- (expt 5 29)))
(test (- (expt 5 29)) min (- (expt 5 29)) (- (expt 5 27)))

(error-test '(max 0 'a))
(error-test '(min 0 'a))
(error-test '(max 'a 0))
(error-test '(min 'a 0))
(error-test '(max 'a))
(error-test '(min 'a))
(error-test '(min 2 4+i))
(error-test '(max 2 4+i))
(error-test '(min 4+i))
(error-test '(max 4+i))

(arity-test max 1 -1)
(arity-test min 1 -1)

(test 0 +)
(test 7 + 3 4)
(test 6 + 1 2 3)
(test 7.0 + 3 4.0)
(test 6.0 + 1 2.0 3)
(test 19/12 + 1/4 1/3 1)
(test +i + +i)
(test 3/2+1i + 1 2+2i -i -3/2)
(test 3 + 3)
(test 0 +)
(test 4 * 4)
(test 16.0 * 4 4.0)
(test 1 *)
(test 6/25 * 3/5 1/5 2)
(test #i+6/25 * 3/5 1/5 2.0)
(test +6/25i * 3/5 1/5 2 +i)
(test (make-rectangular 0 #i+6/25) * 3/5 1/5 2.0 +i)
(test 18805208620685182736256260714897 
      * (sub1 (expt 2 31))  
      8756857658476587568751)
(test 1073741874 + (- (expt 2 30) 50) 100) ; fixnum -> bignum for 32 bits
(test -1073741874 - (- 50 (expt 2 30)) 100) ; fixnum -> bignum for 32 bits
(test 10.0+0.0i + 9.0+0.0i 1)
(test 10.0+0.0i + 9.0+0.0i 1-0.0i)
(test 9.0+0.0i * 9.0+0.0i 1)
(test 10.0-1.0i + 9.0+0.0i 1-1.0i)
(test 0 * 0 10.0)
(test 0 * 0 +inf.0)
(test 0 * 0 +nan.0)
(test 0 / 0 0.0)
(test 0 / 0 +inf.0)
(test 0 / 0 -inf.0)
(test 0 / 0 +nan.0)
(test -0.0 + 0 -0.0)
(test -0.0 + -0.0 0)
(test -0.0 - -0.0 0)

(test -0.0 - 0.0)
(test 0.0 - -0.0)
(test -0.0 - 0 0.0)
(test 0.0 - 0 -0.0)

(arity-test * 0 -1)
(arity-test + 0 -1)
(arity-test - 1 -1)
(arity-test / 1 -1)

(test 2 add1 1)
(test 0 add1 -1)
(test 2.0 add1 1.0)
(test 0.0 add1 -1.0)
(test 3/2 add1 1/2)
(test 1/2 add1 -1/2)
(test 2.0+i add1 1.0+i)
(test 0.0+i add1 -1.0+i)
(test 0.0+0.0i add1 -1+0.0i)
(test 0.0-0.0i add1 -1-0.0i)
(test 1073741824 add1 #x3FFFFFFF) ; fixnum boundary case

(error-test '(add1 "a"))
(arity-test add1 1 1)

(test 1 sub1 2)
(test -2 sub1 -1)
(test 1.0 sub1 2.0)
(test -2.0 sub1 -1.0)
(test -1/2 sub1 1/2)
(test -3/2 sub1 -1/2)
(test 1.0+i sub1 2.0+i)
(test -2.0+i sub1 -1.0+i)
(test -2.0+0.0i sub1 -1+0.0i)
(test -2.0-0.0i sub1 -1-0.0i)
(test -1073741824 sub1 -1073741823) ; fixnum boundary case

(error-test '(sub1 "a"))
(arity-test sub1 1 1)

(test 1024 expt 2 10)
(test 1/1024 expt 2 -10)
(arity-test expt 2 2)

(test 0 apply + (map inexact->exact (list 3.2e+270 -2.4e+270 -8e+269)))
(test 0 apply + (map inexact->exact (list 3.2f+7 -2.4f+7 -8f+6)))

(test #t positive? (inexact->exact 0.1))
(test #t negative? (inexact->exact -0.1))
(test 0 + (inexact->exact -0.1) (inexact->exact 0.1))
(arity-test inexact->exact 1 1)
(error-test '(inexact->exact 'a))
(test 1+i inexact->exact 1.0+1.0i)
(test 1 inexact->exact 1.0+0.0i)
(test 1 inexact->exact 1.0-0.0i)

(test #t positive? (exact->inexact 1/10))
(test #t negative? (exact->inexact -1/10))
(test 0.0 + (exact->inexact -1/10) (exact->inexact 1/10))
(arity-test exact->inexact 1 1)
(error-test '(exact->inexact 'a))
(test 1.0+1.0i exact->inexact 1+1i)
(test 1.0+0.0i exact->inexact 1+0.0i)
(test (expt 7 30) inexact->exact (expt 7 30))

(error-test '(inexact->exact +inf.0))
(error-test '(inexact->exact -inf.0))
(error-test '(inexact->exact +nan.0))

(error-test '(* 'a 0))
(error-test '(+ 'a 0))
(error-test '(/ 'a 0))
(error-test '(- 'a 0))
(error-test '(+ 0 'a))
(error-test '(* 0 'a))
(error-test '(- 0 'a))
(error-test '(/ 0 'a))
(error-test '(+ 'a))
(error-test '(* 'a))
(error-test '(- 'a))
(error-test '(/ 'a))

(define (test-inf-plus-times v)
  (define (test+ +)
    (test +inf.0 + v (+ +inf.0))
    (test -inf.0 + v (+ -inf.0))
    (test +inf.0 + (- v) (+ +inf.0))
    (test -inf.0 + (- v) (+ -inf.0))
    
    (test +inf.0 + +inf.0 v)
    (test -inf.0 + -inf.0 v)
    (test +inf.0 + +inf.0 (- v))
    (test -inf.0 + -inf.0 (- v))

    (test-nan.0 + +nan.0 v)
    (test-nan.0 + v +nan.0))

  (test+ +)
  (test+ -)
  
  (test +inf.0 * +inf.0 v)
  (test -inf.0 * -inf.0 v)
  (test -inf.0 * +inf.0 (- v))
  (test +inf.0 * -inf.0 (- v))

  (test +inf.0 * v +inf.0)
  (test -inf.0 * v -inf.0)
  (test -inf.0 * (- v) +inf.0)
  (test +inf.0 * (- v) -inf.0)

  (test-nan.0 * +nan.0 v)
  (test-nan.0 * v +nan.0))

(test-inf-plus-times 1)
(test-inf-plus-times 1.0)
(test-inf-plus-times (expt 2 100))

(test -inf.0 - +inf.0)
(test +inf.0 - -inf.0)
(test +inf.0 + +inf.0 +inf.0)
(test -inf.0 + -inf.0 -inf.0)
(test-nan.0 + +inf.0 -inf.0)
(test-nan.0 - +inf.0 +inf.0)
(test-nan.0 - -inf.0 -inf.0)
(test +inf.0 * +inf.0 +inf.0)
(test -inf.0 * +inf.0 -inf.0)
(test 0 * +inf.0 0)
(test-nan.0 * +inf.0 0.0)
(test-nan.0 + +nan.0 +nan.0)
(test-nan.0 - +nan.0 +nan.0)
(test-nan.0 * +nan.0 +nan.0)

(test 1/2 / 1 2)
(test 1/2 / 1/4 1/2)
(test 0.5 / 1 2.0)
(test 0.5 / 1.0 2)
(test 1/2+3/2i / 1+3i 2)
(test 1/5-3/5i / 2 1+3i)
(test 0.5+0.0i / 1+0.0i 2)
(test 0.25-0.0i / 1 4+0.0i)
(test 0.25+0.0i / 1+0.0i 4+0.0i)

(test +inf.0 / 1.0 0.0)
(test -inf.0 / -1.0 0.0)
(test +inf.0 / -1.0 -0.0)
(test -inf.0 / 1.0 -0.0)

(define (make-test-inf-zero-div zero -zero inf -inf)
  (lambda (v)
    (test zero / v +inf.0)
    (test -zero / v -inf.0)
    (test -zero / (- v) +inf.0)
    (test zero / (- v) -inf.0)
    
    (test inf / +inf.0 v)
    (test -inf / -inf.0 v)
    (test -inf / +inf.0 (- v))
    (test inf / -inf.0 (- v))
    
    (unless (zero? v)
      (test zero / 0.0 v)
      (test -zero / 0.0 (- v))
      (test -zero / -0.0 v)
      (test zero / -0.0 (- v))
      
      (test inf / v 0.0)
      (test -inf / (- v) 0.0)
      (test -inf / v -0.0)
      (test inf / (- v) -0.0))
    
    (test-nan.0 / +nan.0 v)
    (test-nan.0 / v +nan.0)))

(define test-inf-zero-div (make-test-inf-zero-div 0.0 -0.0 +inf.0 -inf.0))
(define test-neg-inf-zero-div (make-test-inf-zero-div -0.0 0.0 -inf.0 +inf.0))

(test-inf-zero-div big-num)
(test-inf-zero-div (/ big-num 3))
(test-inf-zero-div 0.0)

(test-neg-inf-zero-div (- big-num))
(test-neg-inf-zero-div (- (/ big-num 3)))
(test-neg-inf-zero-div -0.0)

(test-nan.0 / +inf.0 +inf.0)
(test-nan.0 / +inf.0 -inf.0)
(test-nan.0 / +nan.0 -nan.0)

(test 1.0 exact->inexact (/ big-num (add1 big-num)))

(error-test '(/ 0) exn:application:divide-by-zero?)
(error-test '(/ 1 0) exn:application:divide-by-zero?)
(error-test '(/ 1/2 0) exn:application:divide-by-zero?)
(error-test '(/ 1+2i 0) exn:application:divide-by-zero?)
(error-test '(/ 1.0 0) exn:application:divide-by-zero?)

(test -1 - 3 4)
(test -3 - 3)
(test -1.0 - 3.0 4)
(test -3.0 - 3.0)
(test 7 abs -7)
(test 7.0 abs -7.0)
(test 7 abs 7)
(test 0 abs 0)
(test 1/2 abs 1/2)
(test 1/2 abs -1/2)
(test +inf.0 abs +inf.0)
(test +inf.0 abs -inf.0)
(test-nan.0 abs -nan.0)
(test 4.0 abs -4.0+0.0i)

(arity-test abs 1 1)
(error-test '(-) exn:application:arity?)
(error-test '(abs 'a))
(error-test '(abs +5i))

(test 5 quotient 35 7)
(test 5.0 quotient 35 7.0)
(test 5.0 quotient 36 7.0)
(test 5.0 quotient 36.0 7)
(test -5 quotient -35 7)
(test -5.0 quotient -35 7.0)
(test -5 quotient 35 -7)
(test -5.0 quotient 35 -7.0)
(test 5 quotient -35 -7)
(test 5.0 quotient -35 -7.0)
(test -5.0 quotient -36 7.0)
(test -5.0 quotient 36.0 -7)
(test -5.0 quotient 36.0 -7+0.0i)
(test -5.0 quotient 36.0+0.0i -7)
(test 1 modulo 13 4)
(test 1 remainder 13 4)
(test 1.0 modulo 13 4.0)
(test 1.0 remainder 13 4.0)
(test 3 modulo -13 4)
(test -1 remainder -13 4)
(test 3.0 modulo -13 4.0)
(test -1.0 remainder -13 4.0)
(test -3 modulo 13 -4)
(test 1 remainder 13 -4)
(test -3.0 modulo 13.0 -4)
(test 1.0 remainder 13.0 -4)
(test -1 modulo -13 -4)
(test -1 remainder -13 -4)
(test -1.0 modulo -13 -4.0)
(test -1.0 remainder -13 -4.0)
(test -1.0 modulo -13 -4.0+0.0i)
(test -1.0 remainder -13 -4.0+0.0i)
(test -1.0 modulo -13+0.0i -4.0)
(test -1.0 remainder -13+0.0i -4.0)
(test -2 remainder -3333333332 -3)
(test -2 modulo -3333333332 -3)
(test 2 remainder 3333333332 -3)
(test -1 modulo 3333333332 -3)
(test 0 modulo 4 2)
(test 0 modulo -4 2)
(test 0 modulo 4 -2)
(test 0 modulo -4 -2)
(test 0.0 modulo 4.0 2)
(test 0.0 modulo -4.0 2)
(test 0.0 modulo 4.0 -2)
(test 0.0 modulo -4.0 -2)
(test 0 remainder 4 2)
(test 0 remainder -4 2)
(test 0 remainder 4 -2)
(test 0 remainder -4 -2)
(test 0.0 remainder 4.0 2)
(test 0.0 remainder -4.0 2)
(test 0.0 remainder 4.0 -2)
(test 0.0 remainder -4.0 -2)
(define (divtest n1 n2)
	(= n1 (+ (* n2 (quotient n1 n2))
		 (remainder n1 n2))))
(test #t divtest 238 9)
(test #t divtest -238 9)
(test #t divtest 238 -9)
(test #t divtest -238 -9)

(test 13.0 quotient 1324.0 100)

(error-test '(quotient 6 0) exn:application:divide-by-zero?)
(error-test '(modulo 6 0) exn:application:divide-by-zero?)
(error-test '(remainder 6 0) exn:application:divide-by-zero?)
(error-test '(quotient 6 0.0) exn:application:divide-by-zero?)
(error-test '(modulo 6 0.0) exn:application:divide-by-zero?)
(error-test '(remainder 6 0.0) exn:application:divide-by-zero?)
(error-test '(quotient 6 -0.0) exn:application:divide-by-zero?)
(error-test '(modulo 6 -0.0) exn:application:divide-by-zero?)
(error-test '(remainder 6 -0.0) exn:application:divide-by-zero?)

(define (test-qrm-inf v)
  (define iv (exact->inexact v))

  (test 0.0 quotient v +inf.0)
  (test -0.0 quotient v -inf.0)
  (test iv remainder v +inf.0)
  (test iv remainder v -inf.0)
  (test iv modulo v +inf.0)
  (test -inf.0 modulo v -inf.0)

  (test +inf.0 quotient +inf.0 v)
  (test -inf.0 quotient -inf.0 v)
  (test 0.0 remainder +inf.0 v)
  (test 0.0 remainder -inf.0 v)
  (test 0.0 modulo +inf.0 v)
  (test 0.0 modulo -inf.0 v))

(test-qrm-inf 9)
(test-qrm-inf 9.0)
(test-qrm-inf (expt 2 100))

;; Check 0.0 combinations
(test -0.0 quotient -0.0 +inf.0)
(test 0.0 quotient -0.0 -inf.0)
(test -0.0 quotient -0.0 2.0)
(test 0.0 quotient -0.0 -2.0)
(test 0.0 quotient 0.0 +inf.0)
(test -0.0 quotient 0.0 -inf.0)
(test 0.0 quotient 0.0 2.0)
(test -0.0 quotient 0.0 -2.0)
(test 0.0 modulo -0.0 +inf.0)
(test 0.0 modulo -0.0 -inf.0)
(test 0.0 modulo -0.0 2.0)
(test 0.0 modulo -0.0 -2.0)
(test 0.0 modulo 0.0 +inf.0)
(test 0.0 modulo 0.0 -inf.0)
(test 0.0 modulo 0.0 2.0)
(test 0.0 modulo 0.0 -2.0)
(test 0.0 remainder -0.0 +inf.0)
(test 0.0 remainder -0.0 -inf.0)
(test 0.0 remainder -0.0 2.0)
(test 0.0 remainder -0.0 -2.0)
(test 0.0 remainder 0.0 +inf.0)
(test 0.0 remainder 0.0 -inf.0)
(test 0.0 remainder 0.0 2.0)
(test 0.0 remainder 0.0 -2.0)

(arity-test quotient 2 2)
(arity-test modulo 2 2)
(arity-test remainder 2 2)

(error-test '(quotient 'a 1))
(error-test '(quotient 1 'a))
(error-test '(quotient 1 +nan.0))
(error-test '(quotient +nan.0 1))
(error-test '(modulo 'a 1))
(error-test '(modulo 1 'a))
(error-test '(modulo +nan.0 1))
(error-test '(modulo 1 +nan.0))
(error-test '(remainder 'a 1))
(error-test '(remainder 1 'a))
(error-test '(remainder +nan.0 1))
(error-test '(remainder 1 +nan.0))
(error-test '(quotient 'a 1.0))
(error-test '(quotient 1.0 'a))
(error-test '(modulo 'a 1.0))
(error-test '(modulo 1.0 'a))
(error-test '(remainder 'a 1.0))
(error-test '(remainder 1.0 'a))
(error-test '(quotient 1/2 1))
(error-test '(remainder 1/2 1))
(error-test '(modulo 1/2 1))
(error-test '(quotient 2 1/2))
(error-test '(remainder 2 1/2))
(error-test '(modulo 2 1/2))
(error-test '(quotient 12.3 1))
(error-test '(remainder 12.3 1))
(error-test '(modulo 12.3 1))
(error-test '(quotient 2 12.3))
(error-test '(remainder 2 12.3))
(error-test '(modulo 2 12.3))
(error-test '(quotient 1+2i 1))
(error-test '(remainder 1+2i 1))
(error-test '(modulo 1+2i 1))
(error-test '(quotient 2 1+2i))
(error-test '(remainder 2 1+2i))
(error-test '(modulo 2 1+2i))

(test 10 bitwise-ior 10)
(test 10 bitwise-and 10)
(test 10 bitwise-xor 10)
(test 7 bitwise-ior 3 4)
(test 0 bitwise-and 3 4)
(test 7 bitwise-xor 3 4)
(test 7 bitwise-ior 3 4 1)
(test 1 bitwise-and 3 5 1)
(test 6 bitwise-xor 3 4 1)

(test #x1ffff7777 bitwise-ior #x1aaaa5555 #x155553333)
(test #x100001111 bitwise-and #x1aaaa5555 #x155553333)
(test #x0ffff6666 bitwise-xor #x1aaaa5555 #x155553333)

(test #x3ffff7777 bitwise-ior #x2aaaa5555 #x155553333)
(test #x000001111 bitwise-and #x2aaaa5555 #x155553333)
(test #x3ffff6666 bitwise-xor #x2aaaa5555 #x155553333)

(test #x3ffff7777 bitwise-ior #x2aaaa5555 #x155553333)
(test #x000001111 bitwise-and #x2aaaa5555 #x155553333)
(test #x3ffff6666 bitwise-xor #x2aaaa5555 #x155553333)

(test #xfffffffffffffe bitwise-not #x-FFFFFFFFFFFFFF)
(test #x-100000000000000 bitwise-not #xFFFFFFFFFFFFFF)

(test (bitwise-and (bitwise-not #x-2aaaa5555) (bitwise-not #x-15555aaaa))
      bitwise-not (bitwise-ior #x-2aaaa5555 #x-15555aaaa))
(test (bitwise-and (bitwise-not #x-2aaaa5555) (bitwise-not #x-155553333))
      bitwise-not (bitwise-ior #x-2aaaa5555 #x-155553333))
(test (bitwise-and (bitwise-not #x-2aaaa5555) (bitwise-not #x-15555333))
      bitwise-not (bitwise-ior #x-2aaaa5555 #x-15555333))

(test #x-155553333 bitwise-xor #x-2aaaa5555 (bitwise-xor #x-2aaaa5555 #x-155553333))
(test #x-15555333 bitwise-xor #x-2aaaa5555 (bitwise-xor #x-2aaaa5555 #x-15555333))

(arity-test bitwise-ior 1 -1)
(arity-test bitwise-and 1 -1)
(arity-test bitwise-xor 1 -1)
(arity-test bitwise-not 1 1)

(define error-test-bitwise-procs
  (lambda (v)
    (error-test `(bitwise-ior ,v))
    (error-test `(bitwise-and ,v))
    (error-test `(bitwise-xor ,v))
    (error-test `(bitwise-not ,v))
    (error-test `(bitwise-ior 1 ,v))
    (error-test `(bitwise-and 1 ,v))
    (error-test `(bitwise-xor 1 ,v))
    (error-test `(bitwise-ior ,v 1))
    (error-test `(bitwise-and ,v 1))
    (error-test `(bitwise-xor ,v 1))))

(error-test-bitwise-procs 1.0)
(error-test-bitwise-procs 1/2)
(error-test-bitwise-procs 1+2i)
(error-test-bitwise-procs 1.0+0.0i)
(error-test-bitwise-procs +inf.0)
(error-test-bitwise-procs ''a)

(test 1 arithmetic-shift 1 0)
(test 1024 arithmetic-shift 1 10)
(test 1 arithmetic-shift 1024 -10)
(test 256 arithmetic-shift 1024 -2)
(test 0 arithmetic-shift 1024 -11)
(test 0 arithmetic-shift 1024 -20)
(test 0 arithmetic-shift 1024 -40)
(test 0 arithmetic-shift 1024 -20000000000000000000)
(test 0 arithmetic-shift 0 100)
(test 0 arithmetic-shift 0 -100)
(test 0 arithmetic-shift 17 -32)

(test (expt 2 40) arithmetic-shift (expt 2 40) 0)
(test (expt 2 50) arithmetic-shift (expt 2 40) 10)
(test (expt 2 30) arithmetic-shift (expt 2 40) -10) ; somewhere close to here is a boundary...
(test (expt 2 29) arithmetic-shift (expt 2 40) -11)
(test (expt 2 31) arithmetic-shift (expt 2 40) -9)
(test 1 arithmetic-shift (expt 2 40) -40)
(test 0 arithmetic-shift (expt 2 40) -41)
(test 0 arithmetic-shift (expt 2 40) -100)

(test -1 arithmetic-shift -1 0)
(test -1024 arithmetic-shift -1 10)
(test -1 arithmetic-shift -1024 -10)
(test -256 arithmetic-shift -1024 -2)
(test -1 arithmetic-shift -1024 -11)
(test -1 arithmetic-shift -1024 -20)
(test -1 arithmetic-shift -1024 -20000000000000000000)

(test (- (expt 2 40)) arithmetic-shift (- (expt 2 40)) 0)
(test (- (expt 2 50)) arithmetic-shift (- (expt 2 40)) 10)
(test (- (expt 2 30)) arithmetic-shift (- (expt 2 40)) -10) ; somewhere close to here is a boundary...
(test (- (expt 2 29)) arithmetic-shift (- (expt 2 40)) -11)
(test (- (expt 2 31)) arithmetic-shift (- (expt 2 40)) -9)
(test -1 arithmetic-shift (- (expt 2 40)) -40)
(test -1 arithmetic-shift (- (expt 2 40)) -41)
(test -1 arithmetic-shift (- (expt 2 40)) -100)

(test 0 arithmetic-shift (sub1 (expt 2 30)) -32)
(test 0 arithmetic-shift (sub1 (expt 2 31)) -32)
(test 0 arithmetic-shift (sub1 (expt 2 32)) -32)
(test 1 arithmetic-shift (expt 2 32) -32)

(arity-test arithmetic-shift 2 2)
(error-test '(arithmetic-shift "a" 1))
(error-test '(arithmetic-shift 1 "a"))
(error-test '(arithmetic-shift 1.0 1))
(error-test '(arithmetic-shift 1 1.0))
(error-test '(arithmetic-shift 1 1.0+0.0i))
(error-test '(arithmetic-shift 1 (expt 2 80)) exn:misc:out-of-memory?)

(test 4 gcd 0 4)
(test 4 gcd -4 0)
(test 4 gcd 32 -36)
(test 2 gcd 6 10 14)
(test 0 gcd)
(test 5 gcd 5)
(test 5.0 gcd 5.0 10)
(test 5.0 gcd -5.0 10)
(test 5.0 gcd 5.0 -10)
(test 5.0 gcd 5.0+0.0i 10)
(test 5.0 gcd 5.0 10+0.0i)
(test (expt 3 37) gcd (expt 9 35) (expt 6 37))
(test (expt 3 37) gcd (- (expt 9 35)) (expt 6 37))
(test (expt 3 37) gcd (expt 9 35) (- (expt 6 37)))
(test 201 gcd (* 67 (expt 3 20)) (* 67 3))
(test 201 gcd (* 67 3) (* 67 (expt 3 20)))
(test 201.0 gcd (* 67 (expt 3 20)) (* 67. 3))
(test 201.0 gcd (* 67. 3) (* 67 (expt 3 20)))
(test 9.0 gcd +inf.0 9)
(test 9.0 gcd -inf.0 9)
(test 288 lcm 32 -36)
(test 12 lcm 2 3 4)
(test 1 lcm)
(test 5 lcm 5)
(test 0 lcm 123 0)
(test 30.0 lcm 5 6.0)
(test 30.0 lcm 5 6.0+0.0i)
(test 30.0 lcm 5+0.0i 6.0)
(test 0.0 lcm 123 0.0)
(test 0.0 lcm 123 -0.0)
(test (* (expt 2 37) (expt 9 35)) lcm (expt 9 35) (expt 6 37))
(test (* (expt 2 37) (expt 9 35)) lcm (- (expt 9 35)) (expt 6 37))
(test (* (expt 2 37) (expt 9 35)) lcm (expt 9 35) (- (expt 6 37)))

(error-test '(gcd +nan.0))
(error-test '(gcd 'a))
(error-test '(gcd 'a 1))
(error-test '(gcd 1 'a))
(error-test '(lcm +nan.0))
(error-test '(lcm 'a))
(error-test '(lcm 'a 1))
(error-test '(lcm 1 'a))
(error-test '(gcd 1/2))
(error-test '(gcd 3 1/2))
(error-test '(gcd 1/2 3))
(error-test '(lcm 1/2))
(error-test '(lcm 3 1/2))
(error-test '(lcm 1/2 3))
(error-test '(gcd 1+2i))
(error-test '(lcm 1+2i))
(error-test '(gcd 1 1+2i))
(error-test '(lcm 1 1+2i))
(error-test '(gcd +nan.0 5.0))
(error-test '(gcd 5.0 +nan.0))
(error-test '(lcm +nan.0 5.0))
(error-test '(lcm 5.0 +nan.0))

(arity-test gcd 0 -1)
(arity-test lcm 0 -1)

(test 2 floor 5/2)
(test 3 ceiling 5/2)
(test 2 round 5/2)
(test 2 truncate 5/2)
(test -3 floor -5/2)
(test -2 ceiling -5/2)
(test -2 round -5/2)
(test -2 truncate -5/2)

(test 1 floor 4/3)
(test 2 ceiling 4/3)
(test 1 round 4/3)
(test 1 truncate 4/3)
(test -2 floor -4/3)
(test -1 ceiling -4/3)
(test -1 round -4/3)
(test -1 truncate -4/3)

(test 1 floor 5/3)
(test 2 ceiling 5/3)
(test 2 round 5/3)
(test 1 truncate 5/3)
(test -2 floor -5/3)
(test -1 ceiling -5/3)
(test -2 round -5/3)
(test -1 truncate -5/3)

(test 2 floor 11/4)
(test 3 ceiling 11/4)
(test 3 round 11/4)
(test 2 truncate 11/4)
(test -3 floor -11/4)
(test -2 ceiling -11/4)
(test -3 round -11/4)
(test -2 truncate -11/4)

(test 2 floor 9/4)
(test 3 ceiling 9/4)
(test 2 round 9/4)
(test 2 truncate 9/4)
(test -3 floor -9/4)
(test -2 ceiling -9/4)
(test -2 round -9/4)
(test -2 truncate -9/4)

(test 2.0 floor 2.4)
(test 3.0 ceiling 2.4)
(test 2.0 round 2.4)
(test 2.0 truncate 2.4)
(test -3.0 floor -2.4)
(test -2.0 ceiling -2.4)
(test -2.0 round -2.4)
(test -2.0 truncate -2.4)

(test 2.0 floor 2.6)
(test 3.0 ceiling 2.6)
(test 3.0 round 2.6)
(test 2.0 truncate 2.6)
(test -3.0 floor -2.6)
(test -2.0 ceiling -2.6)
(test -3.0 round -2.6)
(test -2.0 truncate -2.6)

(test 2.0 round 2.5)
(test -2.0 round -2.5)
(test 4.0 round 3.5)
(test -4.0 round -3.5)

(test 2.0 floor 2.6+0.0i)
(test 3.0 ceiling 2.6+0.0i)
(test 3.0 round 2.6+0.0i)
(test 2.0 truncate 2.6+0.0i)

(define (test-fcrt-int v)
  (test v floor v)
  (test v ceiling v)
  (test v round v)
  (test v truncate v))

(test-fcrt-int 2)
(test-fcrt-int 2.0)
(test-fcrt-int (expt 2 100))
(test-fcrt-int +inf.0)
(test-fcrt-int -inf.0)

(test-nan.0 floor +nan.0)
(test-nan.0 ceiling +nan.0)
(test-nan.0 round +nan.0)
(test-nan.0 truncate +nan.0)

(arity-test round 1 1)
(arity-test floor 1 1)
(arity-test ceiling 1 1)
(arity-test truncate 1 1)

(error-test '(floor 2+i))
(error-test '(ceiling 2+i))
(error-test '(truncate 2+i))
(error-test '(round 2+i))

(error-test '(floor "a"))
(error-test '(ceiling "a"))
(error-test '(truncate "a"))
(error-test '(round "a"))

(test 5 numerator 5)
(test 5000000000000 numerator 5000000000000)
(test 5.0 numerator 5.0)
(test 5.0 numerator 5.0+0.0i)
(test 1 denominator 5)
(test 1 denominator 5000000000000)
(test 1.0 denominator 5.0)
(test 1.0 denominator 5.0+0.0i)
(test 2 numerator 2/3)
(test 3 denominator 2/3)
(test 1000.0 round (* 10000.0 (/ (numerator 0.1) (denominator 0.1))))

(test +inf.0 numerator +inf.0)
(test -inf.0 numerator -inf.0)
(test-nan.0 numerator +nan.0)
(test 1.0 denominator +inf.0)
(test 1.0 denominator -inf.0)
(test-nan.0 denominator +nan.0)

(error-test '(numerator 'a))
(error-test '(numerator 1+2i))
(error-test '(denominator 'a))
(error-test '(denominator 1+2i))

(arity-test numerator 1 1)
(arity-test denominator 1 1)

(define (test-on-reals f filter)
  (test (filter 5) f 5)
  (test (filter 5.0) f 5.0)
  (test (filter 1/5) f 1/5)
  (test (filter (expt 2 100)) f (expt 2 100)))

(test 1+2i make-rectangular 1 2)
(test 1.0+2.0i make-rectangular 1.0 2)
(test 1.0+2.0i make-rectangular 1.0+0.0i 2)
(test 1.0+2.0i make-rectangular 1.0 2+0.0i)
(test-nan.0 real-part (make-rectangular +nan.0 1))
(test 1.0 imag-part (make-rectangular +nan.0 1))
(test-nan.0 imag-part (make-rectangular 1 +nan.0))
(test 1.0 real-part (make-rectangular 1 +nan.0))
(test +inf.0 real-part (make-rectangular +inf.0 -inf.0))
(test -inf.0 imag-part (make-rectangular +inf.0 -inf.0))

(test (make-rectangular +inf.0 -inf.0) * 1. (make-rectangular +inf.0 -inf.0))
(test (make-rectangular +inf.0 +inf.0) * +1.0i (make-rectangular +inf.0 -inf.0))
(test (make-rectangular -inf.0 +inf.0) * -3. (make-rectangular +inf.0 -inf.0))
(test (make-rectangular +inf.0 -inf.0) * (make-rectangular +inf.0 -inf.0) 1.)
(test (make-rectangular +inf.0 +inf.0) * (make-rectangular +inf.0 -inf.0) +1.0i)
(test (make-rectangular -inf.0 +inf.0) * (make-rectangular +inf.0 -inf.0) -3.)
(test (make-rectangular +inf.0 -inf.0) / (make-rectangular +inf.0 -inf.0) 1.)
(test (make-rectangular -inf.0 -inf.0) / (make-rectangular +inf.0 -inf.0) +1.0i)
(test (make-rectangular -inf.0 +inf.0) / (make-rectangular +inf.0 -inf.0) -3.)

(test-i-nan.0 * 1.+0.i (make-rectangular +inf.0 -inf.0))
(test-i-nan.0 * 0.+1.0i (make-rectangular +inf.0 -inf.0))
(test-i-nan.0 * -3.+0.i (make-rectangular +inf.0 -inf.0))
(test-i-nan.0 * (make-rectangular +inf.0 -inf.0) 1.+0.i)
(test-i-nan.0 * (make-rectangular +inf.0 -inf.0) 0.+1.0i)
(test-i-nan.0 * (make-rectangular +inf.0 -inf.0) -3.+0.i)
(test-i-nan.0 / (make-rectangular +inf.0 -inf.0) 1.+0.i)
(test-i-nan.0 / (make-rectangular +inf.0 -inf.0) 0.+1.0i)
(test-i-nan.0 / (make-rectangular +inf.0 -inf.0) -3.+0.i)

(test 1 magnitude 1)
(test 1 magnitude -1)
(test 1.0 magnitude 1.0)
(test 1.0 magnitude -1.0)
(test big-num magnitude big-num)
(test big-num magnitude (- big-num))
(test 3/4 magnitude 3/4)
(test 3/4 magnitude -3/4)
(test 10.0 magnitude 10.0+0.0i)
(test 10.0 magnitude -10.0+0.0i)

(test 0 angle 1)
(test 0 angle 1.0)
(test 0 angle 0.0)
(test 0 angle big-num)
(test 0 angle 3/4)
(test 0.0 angle 3+0.0i)
(test-nan.0 angle +nan.0)
(let ([pi (atan 0 -1)])
  (test pi angle -1)
  (test pi angle -1.0)
  (test pi angle -0.0)
  (test pi angle (- big-num))
  (test pi angle -3/4)
  (test pi angle -3+0.0i))
(test -inf.0 atan 0+i)
(test -inf.0 atan 0-i)

(error-test '(angle 'a))
(error-test '(angle 0) exn:application:divide-by-zero?)
(error-test '(magnitude 'a))
(arity-test angle 1 1)
(arity-test magnitude 1 1)

(test 1 real-part 1+2i)
(test 1.0 real-part 1+2.0i)
(test 1.0 real-part 1+0.0i)
(test 1/5 real-part 1/5+2i)
(test-on-reals real-part (lambda (x) x))
(test 2.0 imag-part 1+2.0i)
(test 0.0 imag-part 1+0.0i)
(test -0.0 imag-part 1-0.0i)
(test 1/5 imag-part 1+1/5i)
(test-on-reals imag-part (lambda (x) 0))
(test-nan.0 real-part +nan.0)
(test 0 imag-part +nan.0)
(test 6@1 (lambda (x) x) 6.0@1.0)
(test 324.0 floor (* 100 (real-part 6@1)))
(test 50488.0 floor (* 10000 (imag-part 6@1)))
(test 1 make-polar 1 0)
(test 1.0+0.0i make-polar 1 0.0)
(test 1.0 make-polar 1.0 0)
(test 1.0+0.0i make-polar 1.0 0.0)
(test 1.0+0.0i make-polar 1.0 0.0+0.0i)
(test 1.0+0.0i make-polar 1.0+0.0i 0.0)
(let ([v (make-polar 1 1)])
  (test 5403.0 floor (* 10000 (real-part v)))
  (test 84147.0 floor (* 100000 (imag-part v)))
  (test 10000.0 round (* 10000.0 (magnitude v))))
(let ([v (make-polar 1 2)])
  (test -416.0 ceiling (* 1000 (real-part v)))
  (test 909.0 floor (* 1000 (imag-part v)))
  (test 1.0 magnitude v)
  (test 2.0 angle v))
(test-nan.0 make-polar +nan.0 0)
(test-i-nan.0 make-polar +nan.0 1)
(test-i-nan.0 make-polar 1 +nan.0)
(test-i-nan.0 make-polar 1 +inf.0)
(test-i-nan.0 make-polar 1 -inf.0)
(test +inf.0 make-polar +inf.0 0)
(test -inf.0 make-polar -inf.0 0)
(test (make-rectangular +inf.0 +inf.0) make-polar +inf.0 (atan 1 1))
(test (make-rectangular -inf.0 +inf.0) make-polar +inf.0 (atan 1 -1))
(test (make-rectangular +inf.0 -inf.0) make-polar +inf.0 (atan -1 1))
(test 785.0 floor (* 1000 (angle (make-rectangular 1 1))))
(test 14142.0 floor (* 10000 (magnitude (make-rectangular 1 1))))

(error-test '(make-rectangular 1 'a))
(error-test '(make-rectangular 'a 1))
(error-test '(make-rectangular 1+2i 1))
(error-test '(make-rectangular 1 1+2i))
(arity-test make-rectangular 2 2)

(error-test '(make-polar 1 'a))
(error-test '(make-polar 'a 1))
(error-test '(make-polar 1+2i 1))
(error-test '(make-polar 1 1+2i))
(arity-test make-polar 2 2)

(error-test '(real-part 'a))
(error-test '(imag-part 'a))
(arity-test real-part 1 1)
(arity-test imag-part 1 1)

(define (z-round c) (make-rectangular (round (real-part c)) (round (imag-part c))))

(test -1 * +i +i)
(test 1 * +i -i)
(test 2 * 1+i 1-i)
(test +2i * 1+i 1+i)
(test 0.5 - (+ 0.5 +i) +i)
(test 1/2 - (+ 1/2 +i) +i)
(test 1.0+0.0i - (+ 1 +0.5i) +1/2i)

(test 1 sqrt 1)
(test 1.0 sqrt 1.0)
(test 25 sqrt 625)
(test 3/7 sqrt 9/49)
(test 0.5 sqrt 0.25)
(test +1i sqrt -1)
(test +2/3i sqrt -4/9)
(test +1.0i sqrt -1.0)
(test 1+1i sqrt +2i)
(test 2+1i sqrt 3+4i)
(test 2.0+0.0i sqrt 4+0.0i)
(test +inf.0 sqrt +inf.0)
(test (make-rectangular 0 +inf.0) sqrt -inf.0)
(test-nan.0 sqrt +nan.0)

(test (expt 5 13) sqrt (expt 5 26))
(test 545915034.0 round (sqrt (expt 5 25)))
(test (make-rectangular 0 (expt 5 13)) sqrt (- (expt 5 26)))
(test (make-rectangular 0 545915034.0) z-round (sqrt (- (expt 5 25))))

(error-test '(sqrt "a"))
(arity-test sqrt 1 1)

(test -13/64-21/16i expt -3/4+7/8i 2)
(let ([v (expt -3/4+7/8i 2+3i)])
  (test 3826.0 floor (* 10000000 (real-part v)))
  (test -137.0 ceiling (* 100000 (imag-part v))))
(test 49.0+0.0i expt 7 2+0.0i)
(test 49.0 floor (* 10 (expt 2 2.3)))
(test 189.0 floor (* 1000 (expt 2.3 -2)))
(test 1/4 expt 2 -2)
(test 1/1125899906842624 expt 2 -50)
(test 1/1024 expt 1/2 10)
(test 1024 expt 1/2 -10)
(test 707.0 floor (* 1000 (expt 1/2 1/2)))
(test 707.0 floor (* 1000 (expt 1/2 0.5)))
(test 707.0 floor (* 1000 (expt 0.5 1/2)))
(test 100.0+173.0i z-round (* 100 (expt -8 1/3)))
(test 100.0+173.0i z-round (* 100 (expt -8.0 1/3)))
(test 101.0+171.0i z-round (* 100 (expt -8 0.33)))
(test 101.0+171.0i z-round (* 100 (expt -8.0 0.33)))
(test 108.0+29.0i z-round (* 100 (expt 1+i 1/3)))
(test 25.0-43.0i z-round (* 100 (expt -8 -1/3)))

(test +inf.0 expt 2 +inf.0)
(test +inf.0 expt +inf.0 10)
(test 1 expt +inf.0 0)
(test 1.0 expt +inf.0 0.)
(test 0.0 expt 2 -inf.0)
(test -inf.0 expt -inf.0 11)
(test +inf.0 expt -inf.0 10)
(test 1 expt -inf.0 0)
(test 1.0 expt -inf.0 0.0)
(test 1 expt +nan.0 0)
(test 0 expt 0 10)
(test 0 expt 0 10.0)
(test 0 expt 0 +inf.0)
(test-nan.0 expt 0 +nan.0)
(test 1 expt 1 +inf.0)
(test 1 expt 1 -inf.0)
(test 1 expt 1 -nan.0)
(test 0.0 expt 0.0 10)
(test 0.0 expt 0.0 +inf.0)
(test +inf.0 expt 0.0 -5)
(test -inf.0 expt -0.0 -5)
(test +inf.0 expt 0.0 -4)
(test +inf.0 expt -0.0 -4)
(test +inf.0 expt 0.0 -4.3)
(test +inf.0 expt -0.0 -4.3)
(test +inf.0 expt 0.0 -inf.0)
(test-nan.0 expt 0.0 +nan.0)
(test 1 expt 0 0)
(test 1.0 expt 0 0.0) ; to match (expt 0 0)
(test 1.0 expt 0 -0.0)
(test 1.0 expt 0.0 0.0)
(test 1.0 expt 0.0 0.0)
(test -0.0 expt -0.0 1)
(test-nan.0 expt +nan.0 10)
(test-nan.0 expt 2 +nan.0)

(test 0 expt 0 1+i)
(test 0 expt 0 1-i)

(test-nan.0 expt 1.0 +inf.0)
(test-nan.0 expt 1.0 -inf.0)
(test-nan.0 expt 1.0 +nan.0)

(test 0.0 expt 0.0 5)
(test -0.0 expt -0.0 5)
(test 0.0 expt 0.0 4)
(test 0.0 expt -0.0 4)
(test 0.0 expt 0.0 4.3)
(test 0.0 expt -0.0 4.3)

(test 0.0 expt 0.5 +inf.0)
(test +inf.0 expt 0.5 -inf.0)
(test +inf.0 expt 1.5 +inf.0)
(test 0.0 expt 1.5 -inf.0)
(test 0.0 expt -0.5 +inf.0)
(test +inf.0 expt -0.5 -inf.0)
(test +inf.0 expt -1.5 +inf.0)
(test 0.0 expt -1.5 -inf.0)

(error-test '(expt 0 -1) exn:application:divide-by-zero?)
(error-test '(expt 0 -1.0) exn:application:divide-by-zero?)
(error-test '(expt 0 -inf.0) exn:application:divide-by-zero?)
(error-test '(expt 0 -1+2i) exn:application:divide-by-zero?)
(error-test '(expt 0 -1.0+2i) exn:application:divide-by-zero?)
(error-test '(expt 0 0+2i) exn:application:divide-by-zero?)
(error-test '(expt 0 0.0+2i) exn:application:divide-by-zero?)
(error-test '(expt 0 -0.0+2i) exn:application:divide-by-zero?)
(error-test '(expt 0 0+0.0i) exn:application:divide-by-zero?)

(error-test '(expt 'a 0))
(error-test '(expt 'a 1))
(error-test '(expt 'a 3))
(error-test '(expt 0 'a))
(error-test '(expt 1 'a))
(error-test '(expt 3 'a))

;;;;From: fred@sce.carleton.ca (Fred J Kaudel)
;;; Modified by jaffer.
(define f3.9 (string->number "3.9"))
(define f4.0 (string->number "4.0"))
(define f-3.25 (string->number "-3.25"))
(define f.25 (string->number ".25"))
(define f4.5 (string->number "4.5"))
(define f3.5 (string->number "3.5"))
(define f0.0 (string->number "0.0"))
(define f0.8 (string->number "0.8"))
(define f1.0 (string->number "1.0"))
(newline)
(display ";testing inexact numbers; ")
(newline)
(SECTION 6 5 5)
(test #t inexact? f3.9)
(test #f exact? f3.9)
(test #t 'inexact? (inexact? (max f3.9 4)))
(test f4.0 'max (max f3.9 4))
(test f4.0 'exact->inexact (exact->inexact 4))

; Should at least be close...
(test 4.0 round (log (exp 4.0)))
(test 125.0 round (* 1000 (asin (sin 0.125))))
(test 125.0 round (* 1000 (asin (sin 0.125+0.0i))))
(test 125.0 round (* 1000 (asin (sin 1/8))))
(test 125.0 round (* 1000 (acos (cos 0.125))))
(test 125.0 round (* 1000 (acos (cos 0.125+0.0i))))
(test 125.0 round (* 1000 (acos (cos 1/8))))
(test 785.0 round (* 1000 (atan 1 1)))
(test 785.0 round (* 1000 (atan 1.0 1.0)))
(test 785.0 round (* 1000 (atan 1.0 1.0+0.0i)))
(test 785.0 round (* 1000 (atan 1.0+0.0i 1.0)))
(test 2356.0 round (* 1000 (atan 1 -1)))
(test -785.0 round (* 1000 (atan -1 1)))
(test 785.0 round (* 1000 (atan 1)))
(test 100.0 round (* 100 (tan (atan 1))))
(test 100.0 round (* 100 (tan (+ +0.0i (atan 1)))))
(test 0.0 atan 0.0 0)
(error-test '(atan 0 0) exn:application:divide-by-zero?)
(test 1024.0 round (expt 2.0 10.0))
(test 1024.0 round (expt -2.0 10.0))
(test -512.0 round (expt -2.0 9.0))
(test 32.0 round (sqrt 1024.0))
(test 32.0 round (sqrt 1024.0+0.0i))

(test 1 exp 0)
(test 1.0 exp 0.0)
(test 1.0 exp -0.0)
(test 272.0 round (* 100 (exp 1)))

(test 0 log 1)
(test 0.0 log 1.0)
(test -inf.0 log 0.0)
(test -inf.0 log -0.0)
(error-test '(log 0) exn:application:divide-by-zero?)

(test 1 cos 0)
(test 1.0 cos 0.0)
(test 0 sin 0)
(test 0.0 sin 0.0)
(test -0.0 sin -0.0)
(test 0 tan 0)
(test 0.0 tan 0.0)
(test -0.0 tan -0.0)

(test 0 atan 0)
(test 0.0 atan 0.0)
(test -0.0 atan -0.0)
(test 314.0 round (* 400 (atan 1)))
(test 314.0 round (* 400 (atan 1.0)))
(test 0 asin 0)
(test 0.0 asin 0.0)
(test -0.0 asin -0.0)
(test 314.0 round (* 200 (asin 1)))
(test 314.0 round (* 200 (asin 1.0)))
(test 0 acos 1)
(test 0.0 acos 1.0)
(test 314.0 round (* 200 (acos 0)))
(test 314.0 round (* 200 (acos 0.0)))
(test 314.0 round (* 200 (acos -0.0)))

(define (test-inf-bad f)
  (test-nan.0 f +inf.0)
  (test-nan.0 f -inf.0)
  (test-nan.0 f +nan.0))

(test-inf-bad tan)
(test-inf-bad sin)
(test-inf-bad cos)
(test-inf-bad asin)
(test-inf-bad acos)

(test 11/7 rationalize (inexact->exact (atan +inf.0 1)) 1/100)
(test -11/7 rationalize (inexact->exact (atan -inf.0 1)) 1/100)
(test 0.0 atan 1 +inf.0)
(test 22/7 rationalize (inexact->exact (atan 1 -inf.0)) 1/100)

; Note on the following tests with atan and inf.0:
;  The IEEE standard makes this decision. I think it's a bad one,
;  since (limit (atan (g x) (f x))) as x -> +inf.0 is not necessarily
;  (atan 1 1) when (limit (f x)) and (limit (g x)) are +inf.0.
;  Perhaps IEEE makes this choice because it's easiest to compute.
(test 7/9 rationalize (inexact->exact (atan +inf.0 +inf.0)) 1/100)
(test 26/11 rationalize (inexact->exact (atan +inf.0 -inf.0)) 1/100)
(test -7/9 rationalize (inexact->exact (atan -inf.0 +inf.0)) 1/100)

(test-nan.0 atan +nan.0)
(test-nan.0 atan 1 +nan.0)
(test-nan.0 atan +nan.0 1)

(test -1178.+173.i  z-round (* 1000 (atan -2+1i)))

(map (lambda (f fname) 
       (error-test `(,fname "a"))
       (arity-test f 1 1))
     (list log exp asin acos tan)
     `(log exp asin acos tan))
(error-test '(atan "a" 1))
(error-test '(atan 2+i 1))
(error-test '(atan "a"))
(error-test '(atan 1 "a"))
(error-test '(atan 1 2+i))
(arity-test atan 1 2)

(test 3166.+1960.i  z-round (* 1000 (sin 1+2i)))
(test -3166.-1960.i  z-round (* 1000 (sin -1-2i)))
(test 0+1175.i z-round (* 1000 (sin 0+i)))
(test -642.-1069.i z-round (* 1000 (cos 2+i)))
(test -642.-1069.i z-round (* 1000 (cos -2-i)))
(test 1543. z-round (* 1000 (cos 0+i)))
(test 272-1084.i z-round (* 1000 (tan 1-i)))
(test -272+1084.i z-round (* 1000 (tan -1+i)))

(test 693.+3142.i z-round (* 1000 (log -2)))
(test 1571.-1317.i z-round (* 1000 (asin 2)))
(test -1571.+1317.i z-round (* 1000 (asin -2)))
(test 0+3688.i z-round (* 1000 (acos 20)))
(test 3142.-3688.i z-round (* 1000 (acos -20)))

(define (cs2 c) (+ (* (cos c) (cos c)) (* (sin c) (sin c))))
(test 0.0 imag-part (cs2 2+3i))
(test 1000.0 round (* 1000 (real-part (cs2 2+3i))))
(test 0.0 imag-part (cs2 -2+3i))
(test 1000.0 round (* 1000 (real-part (cs2 -2+3i))))
(test 0.0 imag-part (cs2 2-3i))
(test 1000.0 round (* 1000 (real-part (cs2 2-3i))))

(test #t positive? (real-part (sqrt (- 1 (* 2+3i 2+3i)))))

(test (- f4.0) round (- f4.5))
(test (- f4.0) round (- f3.5))
(test (- f4.0) round (- f3.9))
(test f0.0 round f0.0)
(test f0.0 round f.25)
(test f1.0 round f0.8)
(test f4.0 round f3.5)
(test f4.0 round f4.5)
(let ((x (string->number "4195835.0"))
      (y (string->number "3145727.0")))
  (test #t 'pentium-fdiv-bug (> f1.0 (- x (* (/ x y) y)))))

(test (exact->inexact 1/3) rationalize .3 1/10)
(test 1/3 rationalize 3/10 1/10)
(test (exact->inexact 1/3) rationalize .3 -1/10)
(test 1/3 rationalize 3/10 -1/10)
(test 0 rationalize 3/10 4/10)
(test 0.0 rationalize .3 4/10)
(test 0.0 rationalize .3+0.0i 4/10)
(test #i1/3 rationalize .3+0.0i 1/10)

(define (test-rat-inf v)
  (define zero (if (exact? v) 0 0.0))

  (test +inf.0 rationalize +inf.0 v)
  (test -inf.0 rationalize -inf.0 v)
  (test-nan.0 rationalize +nan.0 v)

  (test zero rationalize v +inf.0)
  (test zero rationalize v -inf.0)
  (test-nan.0 rationalize v +nan.0))

(let loop ([i 100])
  (unless (= i -100)
	  (test (/ i 100) rationalize (inexact->exact (/ i 100.0)) 1/100000)
	  (loop (sub1 i))))

(arity-test rationalize 2 2)

(define tb
  (lambda (n1 n2)
    (= n1 (+ (* n2 (quotient n1 n2))
	     (remainder n1 n2)))))


(SECTION 6 5 5)

(test -2147483648 - 2147483648)
(test 2147483648 - -2147483648)
(test #f = -2147483648 2147483648)
(test #t = -2147483648 -2147483648)
(test #t = 2147483648 2147483648)
(test 2147483647 sub1 2147483648)
(test 2147483648 add1 2147483647)
(test 2147483648 * 1 2147483648)

(test 437893890380859375 expt 15 15)

(test 0 modulo -2177452800 86400)
(test 0 modulo 2177452800 -86400)
(test 0 modulo 2177452800 86400)
(test 0 modulo -2177452800 -86400)

(test 86399 modulo -2177452801 86400)
(test -1 modulo 2177452799 -86400)
(test 1 modulo 2177452801 86400)
(test -86399 modulo -2177452799 -86400)

(test #t 'remainder (tb 281474976710655 65535))
(test #t 'remainder (tb 281474976710654 65535))
(SECTION 6 5 6)
(test 281474976710655 string->number "281474976710655")
(test "281474976710655" number->string 281474976710655)
(test "-4" number->string -4 16)
(test "-e" number->string -14 16)
(test "0" number->string 0 16)
(test "30000000" number->string #x30000000 16)


(SECTION 6 5 6)
(test "0" number->string 0)
(test "100" number->string 100)
(test "100" number->string 256 16)
(test 256 string->number "100" 16)
(test 15 string->number "#o17")
(test 15 string->number "#o17" 10)

(load-relative "numstrs.ss")
(let loop ([l number-table])
  (unless (null? l)
	  (let* ([pair (car l)]
		 [v (car pair)]
		 [v (if (or (eq? v 'X)
			    (symbol? v)
			    (eof-object? v))
			#f 
			v)]
		 [s (cadr pair)])
	    (test v string->number s))
	  (loop (cdr l))))

;; Test special inexact names in complex combinations:
(let ([parts '(+inf.0 -inf.0 +nan.0 1 0 0.0 1/2)])
  (for-each
   (lambda (a)
     (for-each
      (lambda (b)
	(let ([rect (format "~a~a~ai"
			    a
			    (if (member b '(+inf.0 -inf.0 +nan.0))
				""
				"+")
			    b)]
	      [polar (format "~a@~a" a b)])
	  (test (make-rectangular a b) string->number rect)
	  (test (make-polar a b) string->number polar)))
      parts))
   parts)

  (for-each
   (lambda (a)
     (let ([rect1 (format "~a+1/0i" a)]
	   [rect2 (format "1/0~a~ai"
			  (if (member a '(+inf.0 -inf.0 +nan.0))
			      ""
			      "+")
			  a)]
	   [polar1 (format "~a@1/0" a)]
	   [polar2 (format "1/0@~a" a)]
	   [dbz-test (lambda (s)
		       (test 'div 'divide-by-zero
			     (with-handlers ([(lambda (x)
						(and (exn:read? x)
						     (regexp-match "division by zero" 
								   (exn-message x))))
					      (lambda (x) 'div)])
			       (read (open-input-string s)))))])
       (test #f string->number rect1)
       (test #f string->number rect2)
       (test #f string->number polar1)
       (test #f string->number polar2)
       (dbz-test rect1)
       (dbz-test rect2)
       (dbz-test polar1)
       (dbz-test polar2)))
   parts))

(test #f string->number "88" 7)
(test #f string->number "")
(test #f string->number " 1")
(test #f string->number ".")
(test #f string->number "#4@#i5")
(test #f string->number "190888 qwerqwerq")
(test #t symbol? '1/x)
(test #t symbol? '1+ei)
(test #t symbol? '|1/0|)

(arity-test string->number 1 2)
(arity-test number->string 1 2)

(error-test '(number->string 'a))
(error-test '(number->string 1 'a))
(error-test '(number->string 'a 10))
(error-test '(number->string 1.8 8) exn:application:mismatch?)
(error-test '(number->string 1 -1))

(error-test '(string->number 'a))
(error-test '(string->number 'a 'a))
(error-test '(string->number "12" -1))
(error-test '(string->number "12" 17))
(error-test '(string->number "1" "1"))
(error-test '(string->number 1 1))

(test #t andmap (lambda (x) (and (>= x 0) (< x 10))) (map random '(10 10 10 10)))
(test (void) random-seed 5)
(test (begin (random-seed 23) (list (random 10) (random 20) (random 30)))
      'random-seed-same
      (begin (random-seed 23) (list (random 10) (random 20) (random 30))))
(arity-test random-seed 1 1)
(arity-test random 1 1)
(error-test '(random-seed "apple"))
(error-test '(random-seed 4.5))
(error-test '(random-seed -1))
(error-test '(random-seed (expt 2 31)))
(error-test '(random-seed big-num))
(error-test '(random "apple"))
(error-test '(random 0))
(error-test '(random -6))
(error-test '(random (expt 2 31)))
(error-test '(random big-num))

(random-seed 101)
(define x (list (random 10) (random 20) (random 30)))
(random-seed 101)
(parameterize ([current-pseudo-random-generator (make-pseudo-random-generator)])
  (random 10)
  (random 10))
(test x 'generator-preserved (list (random 10) (random 20) (random 30)))
(random-seed 101)
(thread-wait (thread (lambda ()
		       (random 10)
		       (random 10))))
(test #f 'generator-not-preserved (equal? x (list (random 10) (random 20) (random 30))))
(test #t pseudo-random-generator? (make-pseudo-random-generator))
(test #t pseudo-random-generator? (current-pseudo-random-generator))
(test #f pseudo-random-generator? 10)
(arity-test pseudo-random-generator? 1 1)
(arity-test make-pseudo-random-generator 0 0)
(arity-test current-pseudo-random-generator 0 1)
(error-test '(current-pseudo-random-generator 10))

(report-errs)
