ikarus/scheme/ikarus.numerics.ss

4065 lines
133 KiB
Scheme

;;; Ikarus Scheme -- A compiler for R6RS Scheme.
;;; Copyright (C) 2006,2007,2008 Abdulaziz Ghuloum
;;;
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License version 3 as
;;; published by the Free Software Foundation.
;;;
;;; This program is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(library (ikarus flonums)
(export $flonum->exact flonum-parts
inexact->exact exact $flonum-rational? $flonum-integer? $flzero?
$flnegative? flpositive? flabs fixnum->flonum
flsin flcos fltan flasin flacos flatan fleven? flodd?
flfloor flceiling flnumerator fldenominator flexp fllog
flinteger? flonum-bytes flnan? flfinite? flinfinite?
flexpt $flround flround)
(import
(ikarus system $bytevectors)
(ikarus system $fx)
(only (ikarus system $flonums) $fl>= $flonum-sbe)
(ikarus system $bignums)
(except (ikarus system $flonums) $flonum-rational?
$flonum-integer? $flround)
(except (ikarus) inexact->exact exact flpositive? flabs fixnum->flonum
flsin flcos fltan flasin flacos flatan fleven? flodd?
flfloor flceiling flnumerator fldenominator flexp fllog
flexpt flinteger? flonum-parts flonum-bytes flnan? flfinite?
flinfinite? flround))
(define (flonum-bytes f)
(unless (flonum? f)
(die 'flonum-bytes "not a flonum" f))
(values
($flonum-u8-ref f 0)
($flonum-u8-ref f 1)
($flonum-u8-ref f 2)
($flonum-u8-ref f 3)
($flonum-u8-ref f 4)
($flonum-u8-ref f 5)
($flonum-u8-ref f 6)
($flonum-u8-ref f 7)))
(define (flonum-parts x)
(unless (flonum? x)
(die 'flonum-parts "not a flonum" x))
(let-values ([(b0 b1 b2 b3 b4 b5 b6 b7) (flonum-bytes x)])
(values
(zero? (fxlogand b0 128))
(+ (fxsll (fxlogand b0 127) 4)
(fxsra b1 4))
(+ (+ b7 (fxsll b6 8) (fxsll b5 16))
(* (+ b4
(fxsll b3 8)
(fxsll b2 16)
(fxsll (fxlogand b1 #b1111) 24))
(expt 2 24))))))
(define ($zero-m? f)
(and ($fxzero? ($flonum-u8-ref f 7))
($fxzero? ($flonum-u8-ref f 6))
($fxzero? ($flonum-u8-ref f 5))
($fxzero? ($flonum-u8-ref f 4))
($fxzero? ($flonum-u8-ref f 3))
($fxzero? ($flonum-u8-ref f 2))
($fxzero? ($fxlogand ($flonum-u8-ref f 1) #b1111))))
(define ($flonum-rational? x)
(let ([be ($fxlogand ($flonum-sbe x)
($fxsub1 ($fxsll 1 11)))])
($fx< be 2047)))
(define ($flonum-integer? x)
(let ([be ($fxlogand ($flonum-sbe x)
($fxsub1 ($fxsll 1 11)))])
(cond
[($fx= be 2047) ;;; nans and infs
#f]
[($fx>= be 1075) ;;; magnitue large enough
#t]
[($fx= be 0) ;;; denormalized double, only +/-0.0 is integer
(and ($fx= ($flonum-u8-ref x 7) 0)
($fx= ($flonum-u8-ref x 6) 0)
($fx= ($flonum-u8-ref x 5) 0)
($fx= ($flonum-u8-ref x 4) 0)
($fx= ($flonum-u8-ref x 3) 0)
($fx= ($flonum-u8-ref x 2) 0)
($fx= ($flonum-u8-ref x 1) 0))]
[($fx< be ($fx+ 1075 -52)) ;;; too small to be an integer
#f]
[else ($fl= x ($$flround x))])))
(define ($$flround x)
(foreign-call "ikrt_fl_round" x ($make-flonum)))
(define ($flround x)
;;; optimize for integer flonums case
(define (ratnum-round n nbe)
(let ([d (sll 1 nbe)])
(let ([q (sra n nbe)]
[r (bitwise-and n (sub1 d))])
(let ([r2 (+ r r)])
(cond
[(< r2 d) q]
[(> r2 d) (+ q 1)]
[else (if (even? q) q (+ q 1))])))))
(let ([sbe ($flonum-sbe x)])
(let ([be ($fxlogand sbe #x7FF)])
(cond
;;; nans/infs/magnitude large enough to be an integer
[($fx>= be 1075) x]
[else
;;; this really needs to get optimized.
(let-values ([(pos? be m) (flonum-parts x)])
(cond
[(= be 0) ;;; denormalized
(if pos? +0.0 -0.0)]
[else ; normalized flonum
(let ([r
(inexact
(ratnum-round (+ m (expt 2 52)) (- 1075 be)))])
(if pos? r ($fl* r -1.0)))]))]))))
(define (flround x)
(if (flonum? x)
($flround x)
(die 'flround "not a flonum" x)))
(module ($flonum->exact)
(define ($flonum-signed-mantissa x)
(let ([b0 ($flonum-u8-ref x 0)])
(let ([m0 ($fx+ ($flonum-u8-ref x 7)
($fx+ ($fxsll ($flonum-u8-ref x 6) 8)
($fxsll ($flonum-u8-ref x 5) 16)))]
[m1 ($fx+ ($flonum-u8-ref x 4)
($fx+ ($fxsll ($flonum-u8-ref x 3) 8)
($fxsll ($flonum-u8-ref x 2) 16)))]
[m2 (let ([b1 ($flonum-u8-ref x 1)])
(if (and ($fx= ($fxlogand b0 #x7F) 0)
($fx= ($fxsra b1 4) 0))
($fxlogand b1 #xF)
($fxlogor ($fxlogand b1 #xF) #x10)))])
(if ($fx= 0 ($fxlogand #x80 b0))
(+ (bitwise-arithmetic-shift-left ($fxlogor m1 ($fxsll m2 24)) 24) m0)
(+ (bitwise-arithmetic-shift-left
($fx- 0 ($fxlogor m1 ($fxsll m2 24))) 24)
($fx- 0 m0))))))
(define ($flonum->exact x)
(import (ikarus))
(let ([sbe ($flonum-sbe x)])
(let ([be ($fxlogand sbe #x7FF)])
(cond
[($fx= be 2047) #f] ;;; nans/infs
[($fx>= be 1075) ;;; magnitude large enough to be an integer
(bitwise-arithmetic-shift-left
($flonum-signed-mantissa x)
(- be 1075))]
[else
;;; this really needs to get optimized.
(let-values ([(pos? be m) (flonum-parts x)])
(cond
[(= be 0) ;;; denormalized
(if (= m 0)
0
(* (if pos? 1 -1)
(/ m (expt 2 1074))))]
[else ; normalized flonum
(/ (+ m (expt 2 52))
(bitwise-arithmetic-shift-left
(if pos? 1 -1)
(- 1075 be)))]))])))))
(define (flnumerator x)
(unless (flonum? x)
(die 'flnumerator "not a flonum" x))
(cond
[($flonum-integer? x) x]
[($flonum-rational? x)
(exact->inexact (numerator ($flonum->exact x)))]
[else x]))
(define (fldenominator x)
(unless (flonum? x)
(die 'fldenominator "not a flonum" x))
(cond
[($flonum-integer? x) 1.0]
[($flonum-rational? x)
(exact->inexact (denominator ($flonum->exact x)))]
[(flnan? x) x]
[else 1.0]))
(define (fleven? x)
;;; FIXME: optimize
(unless (flonum? x)
(die 'fleven? "not a flonum" x))
(let ([v ($flonum->exact x)])
(cond
[(fixnum? v) ($fx= ($fxlogand v 1) 0)]
[(bignum? v)
(foreign-call "ikrt_even_bn" v)]
[else (die 'fleven? "not an integer flonum" x)])))
(define (flodd? x)
(unless (flonum? x)
(die 'flodd? "not a flonum" x))
;;; FIXME: optimize
(let ([v ($flonum->exact x)])
(cond
[(fixnum? v) ($fx= ($fxlogand v 1) 1)]
[(bignum? v)
(not (foreign-call "ikrt_even_bn" v))]
[else (die 'flodd? "not an integer flonum" x)])))
(define (flinteger? x)
(if (flonum? x)
($flonum-integer? x)
(die 'flinteger? "not a flonum" x)))
(define (flinfinite? x)
(if (flonum? x)
(let ([be (fxlogand ($flonum-sbe x) (sub1 (fxsll 1 11)))])
(and (fx= be 2047) ;;; nans and infs
($zero-m? x)))
(die 'flinfinite? "not a flonum" x)))
(define (flnan? x)
(if (flonum? x)
(let ([be (fxlogand ($flonum-sbe x) (sub1 (fxsll 1 11)))])
(and (fx= be 2047) ;;; nans and infs
(not ($zero-m? x))))
(die 'flnan? "not a flonum" x)))
(define (flfinite? x)
(if (flonum? x)
(let ([be (fxlogand ($flonum-sbe x) (sub1 (fxsll 1 11)))])
(not (fx= be 2047)))
(die 'flfinite? "not a flonum" x)))
(define ($flzero? x)
(let ([be (fxlogand ($flonum-sbe x) (sub1 (fxsll 1 11)))])
(and
(fx= be 0) ;;; denormalized double, only +/-0.0 is integer
(and (fx= ($flonum-u8-ref x 7) 0)
(fx= ($flonum-u8-ref x 6) 0)
(fx= ($flonum-u8-ref x 5) 0)
(fx= ($flonum-u8-ref x 4) 0)
(fx= ($flonum-u8-ref x 3) 0)
(fx= ($flonum-u8-ref x 2) 0)
(fx= ($flonum-u8-ref x 1) 0)))))
(define ($flnegative? x)
(let ([b0 ($flonum-u8-ref x 0)])
(fx> b0 127)))
(define ($exact x who)
(import (ikarus system $compnums))
(cond
[(flonum? x)
(or ($flonum->exact x)
(die who "number has no real value" x))]
[(cflonum? x)
(make-rectangular
(or ($flonum->exact ($cflonum-real x))
(die who "number has no real value" x))
(or ($flonum->exact ($cflonum-imag x))
(die who "number has no real value" x)))]
[(or (fixnum? x) (ratnum? x) (bignum? x) (compnum? x)) x]
[else (die who "not a number" x)]))
(define (inexact->exact x) ($exact x 'inexact->exact))
(define (exact x) ($exact x 'exact))
(define (flpositive? x)
(if (flonum? x)
($fl> x 0.0)
(die 'flpositive? "not a flonum" x)))
(define (flabs x)
(if (flonum? x)
(if ($fx> ($flonum-u8-ref x 0) 127)
($fl* x -1.0)
x)
(die 'flabs "not a flonum" x)))
(define (fixnum->flonum x)
(if (fixnum? x)
($fixnum->flonum x)
(die 'fixnum->flonum "not a fixnum")))
(define (flsin x)
(if (flonum? x)
(foreign-call "ikrt_fl_sin" x)
(die 'flsin "not a flonum" x)))
(define (flcos x)
(if (flonum? x)
(foreign-call "ikrt_fl_cos" x)
(die 'flcos "not a flonum" x)))
(define (fltan x)
(if (flonum? x)
(foreign-call "ikrt_fl_tan" x)
(die 'fltan "not a flonum" x)))
(define (flasin x)
(if (flonum? x)
(foreign-call "ikrt_fl_asin" x)
(die 'flasin "not a flonum" x)))
(define (flacos x)
(if (flonum? x)
(foreign-call "ikrt_fl_acos" x)
(die 'flacos "not a flonum" x)))
(define flatan
(case-lambda
[(x)
(if (flonum? x)
(foreign-call "ikrt_fl_atan" x)
(die 'flatan "not a flonum" x))]
[(x y)
(if (flonum? x)
(if (flonum? y)
(foreign-call "ikrt_atan2" x y)
(die 'flatan "not a flonum" y))
(die 'flatan "not a flonum" x))]))
(define (flfloor x)
(define (ratnum-floor x)
(let ([n (numerator x)] [d (denominator x)])
(let ([q (quotient n d)])
(if (>= n 0) q (- q 1)))))
(cond
[(flonum? x)
;;; optimize for integer flonums case
(let ([e ($flonum->exact x)])
(cond
[(ratnum? e)
(exact->inexact (ratnum-floor e))]
[else x]))]
[else (die 'flfloor "not a flonum" x)]))
(define (flceiling x)
(cond
[(flonum? x)
;;; optimize for integer flonums case
(let ([e ($flonum->exact x)])
(cond
[(ratnum? e)
(exact->inexact (ceiling e))]
[else x]))]
[else (die 'flceiling "not a flonum" x)]))
(define (flexp x)
(if (flonum? x)
(foreign-call "ikrt_fl_exp" x ($make-flonum))
(die 'flexp "not a flonum" x)))
(define fllog
(case-lambda
[(x)
(if (flonum? x)
(foreign-call "ikrt_fl_log" x)
(die 'fllog "not a flonum" x))]
[(x y)
(if (flonum? x)
(if (flonum? y)
(fl/ (foreign-call "ikrt_fl_log" x)
(foreign-call "ikrt_fl_log" y))
(die 'fllog "not a flonum" y))
(die 'fllog "not a flonum" x))]))
(define (flexpt x y)
(if (flonum? x)
(if (flonum? y)
(let ([y^ ($flonum->exact y)])
;;; FIXME: performance bottleneck?
(cond
[(fixnum? y^) (inexact (expt x y^))]
[(bignum? y^) (inexact (expt x y^))]
[else
(foreign-call "ikrt_flfl_expt" x y ($make-flonum))]))
(die 'flexpt "not a flonum" y))
(die 'fllog "not a flonum" x)))
)
(library (ikarus generic-arithmetic)
(export + - * / zero? = < <= > >= add1 sub1 quotient remainder
modulo even? odd? bitwise-and bitwise-not bitwise-ior
bitwise-xor bitwise-if
bitwise-arithmetic-shift-right bitwise-arithmetic-shift-left
bitwise-arithmetic-shift
bitwise-length bitwise-copy-bit-field
bitwise-copy-bit bitwise-bit-field
positive? negative? expt gcd lcm numerator denominator
exact-integer-sqrt
quotient+remainder number->string min max
abs truncate fltruncate sra sll real->flonum
exact->inexact inexact floor ceiling round log fl=? fl<? fl<=? fl>?
fl>=? fl+ fl- fl* fl/ flsqrt flmin flzero? flnegative?
sin cos tan asin acos atan sqrt exp
sinh cosh tanh asinh acosh atanh
flmax random
error@add1 error@sub1)
(import
(ikarus system $fx)
(ikarus system $flonums)
(ikarus system $ratnums)
(ikarus system $bignums)
(ikarus system $compnums)
(ikarus system $chars)
(ikarus system $strings)
(only (ikarus flonums) $flonum->exact $flzero? $flnegative?
$flround)
(except (ikarus) + - * / zero? = < <= > >= add1 sub1 quotient
remainder modulo even? odd? quotient+remainder number->string
bitwise-arithmetic-shift-right bitwise-arithmetic-shift-left
bitwise-arithmetic-shift
bitwise-length bitwise-copy-bit-field
bitwise-copy-bit bitwise-bit-field
positive? negative? bitwise-and bitwise-not bitwise-ior
bitwise-xor bitwise-if
expt gcd lcm numerator denominator
exact->inexact inexact floor ceiling round log
exact-integer-sqrt min max abs real->flonum
fl=? fl<? fl<=? fl>? fl>=? fl+ fl- fl* fl/ flsqrt flmin
flzero? flnegative? sra sll exp
sin cos tan asin acos atan sqrt truncate fltruncate
sinh cosh tanh asinh acosh atanh
flmax random))
(define (bignum->flonum x)
(foreign-call "ikrt_bignum_to_flonum" x 0 ($make-flonum)))
;;; (define (ratnum->flonum x)
;;; (define (->flonum n d)
;;; (let-values ([(q r) (quotient+remainder n d)])
;;; (if (= r 0)
;;; (inexact q)
;;; (if (= q 0)
;;; (/ (->flonum d n))
;;; (+ q (->flonum r d))))))
;;; (let ([n (numerator x)] [d (denominator x)])
;;; (let ([b (bitwise-first-bit-set n)])
;;; (if (eqv? b 0)
;;; (let ([b (bitwise-first-bit-set d)])
;;; (if (eqv? b 0)
;;; (->flonum n d)
;;; (/ (->flonum n (bitwise-arithmetic-shift-right d b))
;;; (expt 2.0 b))))
;;; (* (->flonum (bitwise-arithmetic-shift-right n b) d)
;;; (expt 2.0 b))))))
;;; (define (ratnum->flonum x)
;;; (let f ([n ($ratnum-n x)] [d ($ratnum-d x)])
;;; (let-values ([(q r) (quotient+remainder n d)])
;;; (if (= q 0)
;;; (/ 1.0 (f d n))
;;; (if (= r 0)
;;; (inexact q)
;;; (+ q (f r d)))))))
(define (ratnum->flonum num)
(define (rat n m)
(let-values ([(q r) (quotient+remainder n m)])
(if (= r 0)
(inexact q)
(fl+ (inexact q) (fl/ 1.0 (rat m r))))))
(define (pos n d)
(cond
[(> n d) (rat n d)]
[(even? n)
(* (pos (sra n 1) d) 2.0)]
[(even? d)
(/ (pos n (sra d 1)) 2.0)]
[else
(/ (rat d n))]))
(let ([n ($ratnum-n num)] [d ($ratnum-d num)])
(if (> n 0)
(pos n d)
(- (pos (- n) d)))))
(define (err who x)
(die who (if (number? x) "invalid argument" "not a number") x))
(define binary+
(lambda (x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxfxplus" x y)]
[(bignum? y)
(foreign-call "ikrt_fxbnplus" x y)]
[(flonum? y)
($fl+ ($fixnum->flonum x) y)]
[(ratnum? y)
($make-ratnum
(+ (* x ($ratnum-d y)) ($ratnum-n y))
($ratnum-d y))]
[(compnum? y)
($make-compnum
(binary+ x ($compnum-real y))
($compnum-imag y))]
[(cflonum? y)
($make-cflonum
(binary+ x ($cflonum-real y))
($cflonum-imag y))]
[else (err '+ y)])]
[(bignum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxbnplus" y x)]
[(bignum? y)
(foreign-call "ikrt_bnbnplus" x y)]
[(flonum? y)
($fl+ (bignum->flonum x) y)]
[(ratnum? y)
($make-ratnum
(+ (* x ($ratnum-d y)) ($ratnum-n y))
($ratnum-d y))]
[(compnum? y)
($make-compnum
(binary+ x ($compnum-real y))
($compnum-imag y))]
[(cflonum? y)
($make-cflonum
(binary+ x ($cflonum-real y))
($cflonum-imag y))]
[else (err '+ y)])]
[(flonum? x)
(cond
[(fixnum? y)
($fl+ x ($fixnum->flonum y))]
[(bignum? y)
($fl+ x (bignum->flonum y))]
[(flonum? y)
($fl+ x y)]
[(ratnum? y)
($fl+ x (ratnum->flonum y))]
[(cflonum? y)
($make-cflonum
($fl+ x ($cflonum-real y))
($cflonum-imag y))]
[(compnum? y)
($make-cflonum
(binary+ x ($compnum-real y))
(inexact ($compnum-imag y)))]
[else (err '+ y)])]
[(ratnum? x)
(cond
[(or (fixnum? y) (bignum? y))
($make-ratnum
(+ (* y ($ratnum-d x)) ($ratnum-n x))
($ratnum-d x))]
[(flonum? y)
($fl+ y (ratnum->flonum x))]
[(ratnum? y)
(let ([n0 ($ratnum-n x)] [n1 ($ratnum-n y)]
[d0 ($ratnum-d x)] [d1 ($ratnum-d y)])
;;; FIXME: inefficient
(/ (+ (* n0 d1) (* n1 d0)) (* d0 d1)))]
[(compnum? y)
($make-compnum
(binary+ x ($compnum-real y))
($compnum-imag y))]
[(cflonum? y)
($make-cflonum
(binary+ x ($cflonum-real y))
($cflonum-imag y))]
[else (err '+ y)])]
[(compnum? x)
(cond
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-compnum
(binary+ ($compnum-real x) y)
($compnum-imag x))]
[(compnum? y)
($make-rectangular
(binary+ ($compnum-real x) ($compnum-real y))
(binary+ ($compnum-imag x) ($compnum-imag y)))]
[(flonum? y)
($make-cflonum
(binary+ y ($compnum-real x))
(inexact ($compnum-imag x)))]
[(cflonum? y)
($make-cflonum
(binary+ ($compnum-real x) ($cflonum-real y))
(binary+ ($compnum-imag x) ($cflonum-imag y)))]
[else (err '+ y)])]
[(cflonum? x)
(cond
[(cflonum? y)
($make-cflonum
(binary+ ($cflonum-real x) ($cflonum-real y))
(binary+ ($cflonum-imag x) ($cflonum-imag y)))]
[(flonum? y)
($make-cflonum
($fl+ ($cflonum-real x) y)
($cflonum-imag x))]
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-compnum
(binary+ ($compnum-real x) y)
($compnum-imag x))]
[(compnum? y)
($make-cflonum
(binary+ ($cflonum-real x) ($compnum-real y))
(binary+ ($cflonum-imag x) ($compnum-imag y)))]
[else (err '+ y)])]
[else (err '+ x)])))
(define binary-bitwise-and
(lambda (x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y) ($fxlogand x y)]
[(bignum? y)
(foreign-call "ikrt_fxbnlogand" x y)]
[else
(die 'bitwise-and "not an exact integer" y)])]
[(bignum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxbnlogand" y x)]
[(bignum? y)
(foreign-call "ikrt_bnbnlogand" x y)]
[else
(die 'bitwise-and "not an exact integer" y)])]
[else (die 'bitwise-and "not an exact integer" x)])))
(define binary-bitwise-ior
(lambda (x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y) ($fxlogor x y)]
[(bignum? y)
(foreign-call "ikrt_fxbnlogor" x y)]
[else
(die 'bitwise-ior "not an exact integer" y)])]
[(bignum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxbnlogor" y x)]
[(bignum? y)
(foreign-call "ikrt_bnbnlogor" x y)]
[else
(die 'bitwise-ior "not an exact integer" y)])]
[else (die 'bitwise-ior "not an exact integer" x)])))
(define binary-bitwise-xor
(lambda (x y)
(define (fxbn x y)
(let ([y0 (bitwise-and y (greatest-fixnum))]
[y1 (bitwise-arithmetic-shift-right y (- (fixnum-width) 1))])
(bitwise-ior
($fxlogand ($fxlogxor x y0) (greatest-fixnum))
(bitwise-arithmetic-shift-left
(bitwise-arithmetic-shift-right
(if ($fx>= x 0) y (bitwise-not y))
(- (fixnum-width) 1))
(- (fixnum-width) 1)))))
(define (bnbn x y)
(let ([x0 (bitwise-and x (greatest-fixnum))]
[x1 (bitwise-arithmetic-shift-right x (- (fixnum-width) 1))]
[y0 (bitwise-and y (greatest-fixnum))]
[y1 (bitwise-arithmetic-shift-right y (- (fixnum-width) 1))])
(bitwise-ior
($fxlogand ($fxlogxor x0 y0) (greatest-fixnum))
(bitwise-arithmetic-shift-left
(binary-bitwise-xor x1 y1)
(- (fixnum-width) 1)))))
(cond
[(fixnum? x)
(cond
[(fixnum? y) ($fxlogxor x y)]
[(bignum? y) (fxbn x y)]
[else
(die 'bitwise-xor "not an exact integer" y)])]
[(bignum? x)
(cond
[(fixnum? y) (fxbn y x)]
[(bignum? y) (bnbn x y)]
[else
(die 'bitwise-xor "not an exact integer" y)])]
[else (die 'bitwise-xor "not an exact integer" x)])))
(define binary-
(lambda (x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxfxminus" x y)]
[(bignum? y)
(foreign-call "ikrt_fxbnminus" x y)]
[(flonum? y)
(if ($fx= x 0)
($fl* y -1.0)
($fl- ($fixnum->flonum x) y))]
[(ratnum? y)
(let ([n ($ratnum-n y)] [d ($ratnum-d y)])
(binary/ (binary- (binary* d x) n) d))]
[(compnum? y)
($make-compnum
(binary- x ($compnum-real y))
(binary- 0 ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary- x ($cflonum-real y))
($fl- 0.0 ($cflonum-imag y)))]
[else (err '- y)])]
[(bignum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_bnfxminus" x y)]
[(bignum? y)
(foreign-call "ikrt_bnbnminus" x y)]
[(flonum? y)
($fl- (bignum->flonum x) y)]
[(ratnum? y)
(let ([n ($ratnum-n y)] [d ($ratnum-d y)])
(binary/ (binary- (binary* d x) n) d))]
[(compnum? y)
($make-compnum
(binary- x ($compnum-real y))
(binary- 0 ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary- x ($cflonum-real y))
($fl- 0.0 ($cflonum-imag y)))]
[else (err '- y)])]
[(flonum? x)
(cond
[(flonum? y)
($fl- x y)]
[(cflonum? y)
($make-cflonum
($fl- x ($cflonum-real y))
($fl- 0.0 ($cflonum-imag y)))]
[(fixnum? y)
($fl- x ($fixnum->flonum y))]
[(bignum? y)
($fl- x (bignum->flonum y))]
[(ratnum? y)
(let ([n ($ratnum-n y)] [d ($ratnum-d y)])
(binary/ (binary- (binary* d x) n) d))]
[(compnum? y)
($make-cflonum
(binary- x ($compnum-real y))
(binary- 0.0 ($compnum-imag y)))]
[else (err '- y)])]
[(ratnum? x)
(let ([nx ($ratnum-n x)] [dx ($ratnum-d x)])
(cond
[(or (fixnum? y) (bignum? y) (flonum? y))
(binary/ (binary- nx (binary* dx y)) dx)]
[(ratnum? y)
(let ([ny ($ratnum-n y)] [dy ($ratnum-d y)])
(binary/ (binary- (binary* nx dy) (binary* ny dx))
(binary* dx dy)))]
[(compnum? y)
($make-compnum
(binary- x ($compnum-real y))
(binary- 0 ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary- x ($cflonum-real y))
($fl- 0.0 ($cflonum-imag y)))]
[else (err '- y)]))]
[(compnum? x)
(cond
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-compnum
(binary- ($compnum-real x) y)
($compnum-imag x))]
[(compnum? y)
($make-rectangular
(binary- ($compnum-real x) ($compnum-real y))
(binary- ($compnum-imag x) ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary- ($compnum-real x) ($cflonum-real y))
(binary- ($compnum-imag x) ($cflonum-imag y)))]
[else
(err '- y)])]
[(cflonum? x)
(cond
[(flonum? y)
($make-cflonum
($fl- ($cflonum-real x) y)
($cflonum-imag x))]
[(cflonum? y)
($make-cflonum
(binary- ($cflonum-real x) ($cflonum-real y))
(binary- ($cflonum-imag x) ($cflonum-imag y)))]
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-cflonum
(binary- ($cflonum-real x) y)
($cflonum-imag x))]
[(compnum? y)
($make-cflonum
(binary- ($cflonum-real x) ($compnum-real y))
(binary- ($cflonum-imag x) ($compnum-imag y)))]
[else
(err '- y)])]
[else (err '- x)])))
(define binary*
(lambda (x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxfxmult" x y)]
[(bignum? y)
(foreign-call "ikrt_fxbnmult" x y)]
[(flonum? y)
($fl* ($fixnum->flonum x) y)]
[(ratnum? y)
(binary/ (binary* x ($ratnum-n y)) ($ratnum-d y))]
[(compnum? y)
($make-rectangular
(binary* x ($compnum-real y))
(binary* x ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary* x ($cflonum-real y))
(binary* x ($cflonum-imag y)))]
[else (err '* y)])]
[(bignum? x)
(cond
[(fixnum? y)
(foreign-call "ikrt_fxbnmult" y x)]
[(bignum? y)
(foreign-call "ikrt_bnbnmult" x y)]
[(flonum? y)
($fl* (bignum->flonum x) y)]
[(ratnum? y)
(binary/ (binary* x ($ratnum-n y)) ($ratnum-d y))]
[(compnum? y)
($make-rectangular
(binary* x ($compnum-real y))
(binary* x ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary* x ($cflonum-real y))
(binary* x ($cflonum-imag y)))]
[else (err '* y)])]
[(flonum? x)
(cond
[(flonum? y)
($fl* x y)]
[(cflonum? y)
($make-cflonum
($fl* x ($cflonum-real y))
($fl* x ($cflonum-imag y)))]
[(fixnum? y)
($fl* x ($fixnum->flonum y))]
[(bignum? y)
($fl* x (bignum->flonum y))]
[(ratnum? y)
(binary/ (binary* x ($ratnum-n y)) ($ratnum-d y))]
[(compnum? y)
($make-cflonum
(binary* x ($compnum-real y))
(binary* x ($compnum-imag y)))]
[else (err '* y)])]
[(ratnum? x)
(cond
[(ratnum? y)
(binary/ (binary* ($ratnum-n x) ($ratnum-n y))
(binary* ($ratnum-d x) ($ratnum-d y)))]
[(compnum? y)
($make-rectangular
(binary* x ($compnum-real y))
(binary* x ($compnum-imag y)))]
[(cflonum? y)
($make-cflonum
(binary* x ($cflonum-real y))
(binary* x ($cflonum-imag y)))]
[else (binary* y x)])]
[(compnum? x)
(cond
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-rectangular
(binary* ($compnum-real x) y)
(binary* ($compnum-imag x) y))]
[(flonum? y)
($make-cflonum
(binary* ($compnum-real x) y)
(binary* ($compnum-imag x) y))]
[(compnum? y)
(let ([r0 ($compnum-real x)]
[r1 ($compnum-real y)]
[i0 ($compnum-imag x)]
[i1 ($compnum-imag y)])
(make-rectangular
(- (* r0 r1) (* i0 i1))
(+ (* r0 i1) (* i0 r1))))]
[(cflonum? y)
(let ([r0 ($compnum-real x)]
[r1 ($cflonum-real y)]
[i0 ($compnum-imag x)]
[i1 ($cflonum-imag y)])
(make-rectangular
(- (* r0 r1) (* i0 i1))
(+ (* r0 i1) (* i0 r1))))]
[else (err '* y)])]
[(cflonum? x)
(cond
[(flonum? y)
($make-cflonum
($fl* ($cflonum-real x) y)
($fl* ($cflonum-imag x) y))]
[(cflonum? y)
(let ([r0 ($cflonum-real x)]
[r1 ($cflonum-real y)]
[i0 ($cflonum-imag x)]
[i1 ($cflonum-imag y)])
($make-cflonum
($fl- ($fl* r0 r1) ($fl* i0 i1))
($fl+ ($fl* r0 i1) ($fl* i0 r1))))]
[(or (fixnum? y) (bignum? y) (ratnum? y))
($make-cflonum
(binary* ($compnum-real x) y)
(binary* ($compnum-imag x) y))]
[(compnum? y)
(let ([r0 ($compnum-real x)]
[r1 ($compnum-real y)]
[i0 ($compnum-imag x)]
[i1 ($compnum-imag y)])
(make-rectangular
(- (* r0 r1) (* i0 i1))
(+ (* r0 i1) (* i0 r1))))]
[else (err '* y)])]
[else (err '* x)])))
(define +
(case-lambda
[(x y) (binary+ x y)]
[(x y z) (binary+ (binary+ x y) z)]
[(a)
(cond
[(fixnum? a) a]
[(number? a) a]
[else (die '+ "not a number" a)])]
[() 0]
[(a b c d . e*)
(let f ([ac (binary+ (binary+ (binary+ a b) c) d)]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary+ ac (car e*)) (cdr e*))]))]))
(define bitwise-and
(case-lambda
[(x y) (binary-bitwise-and x y)]
[(x y z) (binary-bitwise-and (binary-bitwise-and x y) z)]
[(a)
(cond
[(fixnum? a) a]
[(bignum? a) a]
[else (die 'bitwise-and "not a number" a)])]
[() -1]
[(a b c d . e*)
(let f ([ac (binary-bitwise-and a
(binary-bitwise-and b
(binary-bitwise-and c d)))]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary-bitwise-and ac (car e*)) (cdr e*))]))]))
(define bitwise-ior
(case-lambda
[(x y) (binary-bitwise-ior x y)]
[(x y z) (binary-bitwise-ior (binary-bitwise-ior x y) z)]
[(a)
(cond
[(fixnum? a) a]
[(bignum? a) a]
[else (die 'bitwise-ior "not a number" a)])]
[() 0]
[(a b c d . e*)
(let f ([ac (binary-bitwise-ior a
(binary-bitwise-ior b
(binary-bitwise-ior c d)))]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary-bitwise-ior ac (car e*)) (cdr e*))]))]))
(define bitwise-xor
(case-lambda
[(x y) (binary-bitwise-xor x y)]
[(x y z) (binary-bitwise-xor (binary-bitwise-xor x y) z)]
[(a)
(cond
[(fixnum? a) a]
[(bignum? a) a]
[else (die 'bitwise-xor "not a number" a)])]
[() 0]
[(a b c d . e*)
(let f ([ac (binary-bitwise-xor a
(binary-bitwise-xor b
(binary-bitwise-xor c d)))]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary-bitwise-xor ac (car e*)) (cdr e*))]))]))
(define (bitwise-not x)
(cond
[(fixnum? x) ($fxlognot x)]
[(bignum? x) (foreign-call "ikrt_bnlognot" x)]
[else (die 'bitwise-not "invalid argument" x)]))
(define (bitwise-if x y z)
(define who 'bitwise-if)
(define (err x) (die who "not an exact integer" x))
(unless (or (fixnum? x) (bignum? x)) (err x))
(unless (or (fixnum? y) (bignum? y)) (err y))
(unless (or (fixnum? z) (bignum? z)) (err z))
(bitwise-ior
(bitwise-and x y)
(bitwise-and (bitwise-not x) z)))
(define (bitwise-copy-bit-field x i j n)
(define who 'bitwise-copy-bit-field)
(define (err x) (die who "not an exact integer" x))
(define (err2 x) (die who "index must be nonnegative" x))
(define (err3 x y) (die who "indices must be in nondescending order" x y))
(unless (or (fixnum? x) (bignum? x)) (err x))
(unless (or (fixnum? i) (bignum? i)) (err i))
(unless (or (fixnum? j) (bignum? j)) (err j))
(unless (or (fixnum? n) (bignum? n)) (err n))
(when (< i 0) (err2 i))
(when (< j i) (err3 i j))
(bitwise-if (sll (sub1 (sll 1 (- j i))) i) (sll n i) x))
(define -
(case-lambda
[(x y) (binary- x y)]
[(x y z) (binary- (binary- x y) z)]
[(a) (binary- 0 a)]
[(a b c d . e*)
(let f ([ac (binary- (binary- (binary- a b) c) d)]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary- ac (car e*)) (cdr e*))]))]))
(define *
(case-lambda
[(x y) (binary* x y)]
[(x y z) (binary* (binary* x y) z)]
[(a)
(cond
[(fixnum? a) a]
[(number? a) a]
[else (die '* "not a number" a)])]
[() 1]
[(a b c d . e*)
(let f ([ac (binary* (binary* (binary* a b) c) d)]
[e* e*])
(cond
[(null? e*) ac]
[else (f (binary* ac (car e*)) (cdr e*))]))]))
(define (binary-gcd x y)
(define (gcd x y)
(cond
[($fx= y 0) x]
[else (gcd y (remainder x y))]))
(let ([x (if (< x 0) (- x) x)]
[y (if (< y 0) (- y) y)])
(cond
[(> x y) (gcd x y)]
[(< x y) (gcd y x)]
[else x])))
(define gcd
(case-lambda
[(x y)
(cond
[(or (fixnum? x) (bignum? x))
(cond
[(or (fixnum? y) (bignum? y))
(binary-gcd x y)]
[(number? y)
(die 'gcd "not an exact integer" y)]
[else
(die 'gcd "not a number" y)])]
[(number? x)
(die 'gcd "not an exact integer" x)]
[else
(die 'gcd "not a number" x)])]
[(x)
(cond
[(or (fixnum? x) (bignum? x)) x]
[(number? x)
(die 'gcd "not an exact integer" x)]
[else
(die 'gcd "not a number" x)])]
[() 0]
[(x y z . ls)
(let f ([g (gcd (gcd x y) z)] [ls ls])
(cond
[(null? ls) g]
[else (f (gcd g (car ls)) (cdr ls))]))]))
(define lcm
(case-lambda
[(x y)
(cond
[(or (fixnum? x) (bignum? x))
(cond
[(or (fixnum? y) (bignum? y))
(let ([x (if (< x 0) (- x) x)]
[y (if (< y 0) (- y) y)])
(let ([g (binary-gcd x y)])
(binary* y (quotient x g))))]
[(flonum? y)
(let ([v ($flonum->exact y)])
(cond
[(or (fixnum? v) (bignum? v))
(inexact (lcm x v))]
[else (die 'lcm "not an integer" y)]))]
[else
(die 'lcm "not an integer" y)])]
[(flonum? x)
(let ([v ($flonum->exact x)])
(cond
[(or (fixnum? v) (bignum? v))
(inexact (lcm v y))]
[else (die 'lcm "not an integer" x)]))]
[else
(die 'lcm "not an integer" x)])]
[(x)
(cond
[(or (fixnum? x) (bignum? x)) x]
[(flonum? x)
(let ([v ($flonum->exact x)])
(cond
[(or (fixnum? v) (bignum? v)) x]
[else (die 'lcm "not an integer" x)]))]
[else
(die 'lcm "not an integer" x)])]
[() 1]
[(x y z . ls)
;;; FIXME: incorrect for multiple roundings
(let f ([g (lcm (lcm x y) z)] [ls ls])
(cond
[(null? ls) g]
[else (f (lcm g (car ls)) (cdr ls))]))]))
(define binary/
(lambda (x y)
(define (x/compy x y)
(let ([yr (real-part y)]
[yi (imag-part y)])
(let ([denom (+ (* yr yr) (* yi yi))])
(make-rectangular
(binary/ (* x yr) denom)
(binary/ (* (- x) yi) denom)))))
(define (compx/y x y)
(let ([xr (real-part x)]
[xi (imag-part x)])
(make-rectangular
(binary/ xr y)
(binary/ xi y))))
(define (compx/compy x y)
(let ([xr (real-part x)]
[xi (imag-part x)]
[yr (real-part y)]
[yi (imag-part y)])
(let ([denom (+ (* yr yr) (* yi yi))])
(make-rectangular
(binary/ (+ (* xr yr) (* xi yi)) denom)
(binary/ (- (* xi yr) (* xr yi)) denom)))))
(cond
[(flonum? x)
(cond
[(flonum? y) ($fl/ x y)]
[(fixnum? y) ($fl/ x ($fixnum->flonum y))]
[(bignum? y) ($fl/ x (bignum->flonum y))]
[(ratnum? y) ($fl/ x (ratnum->flonum y))]
[(or (cflonum? y) (compnum? y)) (x/compy x y)]
[else (err '/ y)])]
[(fixnum? x)
(cond
[(flonum? y) ($fl/ ($fixnum->flonum x) y)]
[(fixnum? y)
(cond
[($fx= y 0) (die '/ "division by 0")]
[($fx> y 0)
(if ($fx= y 1)
x
(let ([g (binary-gcd x y)])
(cond
[($fx= g y) (fxquotient x g)]
[($fx= g 1) ($make-ratnum x y)]
[else
($make-ratnum (fxquotient x g) (fxquotient y g))])))]
[else
(if ($fx= y -1)
(binary- 0 x)
(let ([g (binary-gcd x y)])
(cond
[($fx= ($fx- 0 g) y) (binary- 0 (fxquotient x g))]
[($fx= g 1) ($make-ratnum (binary- 0 x) (binary- 0 y))]
[else
($make-ratnum
(binary- 0 (fxquotient x g))
(binary- 0 (fxquotient y g)))])))])]
[(bignum? y)
(if ($fx= x 0)
0
(let ([g (binary-gcd x y)])
(cond
[(= g y) (quotient x g)]
[($bignum-positive? y)
(if ($fx= g 1)
($make-ratnum x y)
($make-ratnum (fxquotient x g) (quotient y g)))]
[else
(if ($fx= g 1)
($make-ratnum (binary- 0 x) (binary- 0 y))
($make-ratnum
(binary- 0 (fxquotient x g))
(binary- 0 (quotient y g))))])))]
[(ratnum? y)
(/ (* x ($ratnum-d y)) ($ratnum-n y))]
[(or (compnum? y) (cflonum? y)) (x/compy x y)]
[else (err '/ y)])]
[(bignum? x)
(cond
[(fixnum? y)
(cond
[($fx= y 0) (die '/ "division by 0")]
[($fx> y 0)
(if ($fx= y 1)
x
(let ([g (binary-gcd x y)])
(cond
[($fx= g 1) ($make-ratnum x y)]
[($fx= g y) (quotient x g)]
[else
($make-ratnum (quotient x g) (quotient y g))])))]
[else
(if ($fx= y -1)
(- x)
(let ([g (binary-gcd x y)])
(cond
[(= (- g) y) (- (quotient x g))]
[else
($make-ratnum
(- (quotient x g))
(- (quotient y g)))])))])]
[(bignum? y)
(let ([g (binary-gcd x y)])
(cond
[($fx= g 1)
(if ($bignum-positive? y)
($make-ratnum x y)
($make-ratnum
(binary- 0 x)
(binary- 0 y)))]
[($bignum-positive? y)
(if (= g y)
(quotient x g)
($make-ratnum (quotient x g) (quotient y g)))]
[else
(let ([y (binary- 0 y)])
(if (= g y)
(binary- 0 (quotient x g))
($make-ratnum
(binary- 0 (quotient x g))
(quotient y g))))]))]
[(flonum? y) ($fl/ (bignum->flonum x) y)]
[(ratnum? y)
(binary/ (binary* x ($ratnum-d y)) ($ratnum-n y))]
[(or (compnum? y) (cflonum? y)) (x/compy x y)]
[else (err '/ y)])]
[(ratnum? x)
(cond
[(ratnum? y)
(binary/
(binary* ($ratnum-n x) ($ratnum-d y))
(binary* ($ratnum-n y) ($ratnum-d x)))]
[(or (compnum? y) (cflonum? y)) (x/compy x y)]
[else (binary/ 1 (binary/ y x))])]
[(or (compnum? x) (cflonum? x))
(cond
[(or (compnum? y) (cflonum? y)) (compx/compy x y)]
[(or (fixnum? y) (bignum? y) (ratnum? y) (flonum? y)) (compx/y x y)]
[else (err '/ y)])]
[else (err '/ x)])))
(define /
(case-lambda
[(x y) (binary/ x y)]
[(x)
(cond
[(fixnum? x)
(cond
[($fxzero? x) (die '/ "division by 0")]
[($fx> x 0)
(if ($fx= x 1)
1
($make-ratnum 1 x))]
[else
(if ($fx= x -1)
-1
($make-ratnum -1 (- x)))])]
[(bignum? x)
(if ($bignum-positive? x)
($make-ratnum 1 x)
($make-ratnum -1 (- x)))]
[(flonum? x) (foreign-call "ikrt_fl_invert" x)]
[(ratnum? x)
(let ([n ($ratnum-n x)] [d ($ratnum-d x)])
(cond
[($fx= n 1) d]
[($fx= n -1) (- d)]
[else ($make-ratnum d n)]))]
[(compnum? x) (binary/ 1 x)]
[else (die '/ "not a number" x)])]
[(x y z . ls)
(let f ([a (binary/ x y)] [b z] [ls ls])
(cond
[(null? ls) (binary/ a b)]
[else (f (binary/ a b) (car ls) (cdr ls))]))]))
(define flmax
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
(if ($fl< x y)
y
x)
(die 'flmax "not a flonum" y))
(die 'flmax "not a flonum" x))]
[(x y z . rest)
(let f ([a (flmax x y)] [b z] [ls rest])
(cond
[(null? ls) (flmax a b)]
[else
(f (flmax a b) (car ls) (cdr ls))]))]
[(x)
(if (flonum? x)
x
(die 'flmax "not a number" x))]))
(define max
(case-lambda
[(x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y)
(if ($fx> x y) x y)]
[(bignum? y)
(if (positive-bignum? y) y x)]
[(flonum? y)
(let ([x ($fixnum->flonum x)])
(if ($fl>= y x) y x))]
[(ratnum? y) ;;; FIXME: optimize
(if (>= x y) x y)]
[else (die 'max "not a number" y)])]
[(bignum? x)
(cond
[(fixnum? y)
(if (positive-bignum? x) x y)]
[(bignum? y)
(if (bnbn> x y) x y)]
[(flonum? y)
(let ([x (bignum->flonum x)])
(if ($fl>= y x) y x))]
[(ratnum? y) ;;; FIXME: optimize
(if (>= x y) x y)]
[else (die 'max "not a number" y)])]
[(flonum? x)
(cond
[(flonum? y)
(if ($fl>= x y) x y)]
[(fixnum? y)
(let ([y ($fixnum->flonum y)])
(if ($fl>= y x) y x))]
[(bignum? y)
(let ([y (bignum->flonum y)])
(if ($fl>= y x) y x))]
[(ratnum? y)
;;; FIXME: may be incorrect
(let ([y (ratnum->flonum y)])
(if ($fl>= y x) y x))]
[else (die 'max "not a number" y)])]
[(ratnum? x)
(cond
[(or (fixnum? y) (bignum? y) (ratnum? y))
(if (>= x y) x y)]
[(flonum? y)
(let ([x (ratnum->flonum x)])
(if ($fl>= x y) x y))]
[else (die 'max "not a number" y)])]
[else (die 'max "not a number" x)])]
[(x y z . rest)
(let f ([a (max x y)] [b z] [ls rest])
(cond
[(null? ls) (max a b)]
[else
(f (max a b) (car ls) (cdr ls))]))]
[(x)
(cond
[(or (fixnum? x) (bignum? x) (ratnum? x) (flonum? x)) x]
[else (die 'max "not a number" x)])]))
(define min
(case-lambda
[(x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y)
(if ($fx> x y) y x)]
[(bignum? y)
(if (positive-bignum? y) x y)]
[(flonum? y)
(let ([x ($fixnum->flonum x)])
(if ($fl>= y x) x y))]
[(ratnum? y) ;;; FIXME: optimize
(if (>= x y) y x)]
[else (die 'min "not a number" y)])]
[(bignum? x)
(cond
[(fixnum? y)
(if (positive-bignum? x) y x)]
[(bignum? y)
(if (bnbn> x y) y x)]
[(flonum? y)
(let ([x (bignum->flonum x)])
(if ($fl>= y x) x y))]
[(ratnum? y) ;;; FIXME: optimize
(if (>= x y) y x)]
[else (die 'min "not a number" y)])]
[(flonum? x)
(cond
[(flonum? y)
(if ($fl>= x y) y x)]
[(fixnum? y)
(let ([y ($fixnum->flonum y)])
(if ($fl>= y x) x y))]
[(bignum? y)
(let ([y (bignum->flonum y)])
(if ($fl>= y x) x y))]
[(ratnum? y)
;;; FIXME: may be incorrect
(let ([y (ratnum->flonum y)])
(if ($fl>= y x) x y))]
[else (die 'min "not a number" y)])]
[(ratnum? x)
(cond
[(or (fixnum? y) (bignum? y) (ratnum? y))
(if (>= x y) y x)]
[(flonum? y)
(let ([x (ratnum->flonum x)])
(if ($fl>= x y) y x))]
[else (die 'min "not a number" y)])]
[else (die 'min "not a number" x)])]
[(x y z . rest)
(let f ([a (min x y)] [b z] [ls rest])
(cond
[(null? ls) (min a b)]
[else
(f (min a b) (car ls) (cdr ls))]))]
[(x)
(cond
[(or (fixnum? x) (bignum? x) (ratnum? x) (flonum? x)) x]
[else (die 'min "not a number" x)])]))
(define (abs x)
(cond
[(fixnum? x)
(if ($fx< x 0) (- x) x)]
[(bignum? x)
(if ($bignum-positive? x) x (- x))]
[(flonum? x)
(if ($fx> ($flonum-u8-ref x 0) 127)
($fl* x -1.0)
x)]
[(ratnum? x)
(let ([n ($ratnum-n x)])
(if (< n 0)
($make-ratnum (- n) ($ratnum-d x))
x))]
[else (die 'abs "not a number" x)]))
(define flmin
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
(if ($fl< x y) x y)
(die 'flmin "not a flonum" y))
(die 'flmin "not a flonum" x))]
[(x y z . rest)
(let f ([a (flmin x y)] [b z] [ls rest])
(cond
[(null? ls) (flmin a b)]
[else
(f (flmin a b) (car ls) (cdr ls))]))]
[(x)
(if (flonum? x)
x
(die 'flmin "not a flonum" x))]))
(define (->inexact x who)
(cond
[(fixnum? x) ($fixnum->flonum x)]
[(bignum? x) (bignum->flonum x)]
[(ratnum? x) (ratnum->flonum x)]
[(flonum? x) x]
[(compnum? x)
(make-rectangular
(->inexact (real-part x) who)
(->inexact (imag-part x) who))]
[(cflonum? x) x]
[else
(die who "not a number" x)]))
(define (exact->inexact x)
(->inexact x 'exact->inexact))
(define (inexact x)
(->inexact x 'inexact))
(define real->flonum
(lambda (x)
(cond
[(fixnum? x) ($fixnum->flonum x)]
[(bignum? x) (bignum->flonum x)]
[(ratnum? x) (ratnum->flonum x)]
[(flonum? x) x]
[else
(die 'real->flonum "not a real number" x)])))
(define positive-bignum?
(lambda (x)
(foreign-call "ikrt_positive_bn" x)))
(define even-bignum?
(lambda (x)
(foreign-call "ikrt_even_bn" x)))
(define ($fxeven? x)
($fxzero? ($fxlogand x 1)))
(define (even? x)
(cond
[(fixnum? x) ($fxeven? x)]
[(bignum? x) (even-bignum? x)]
[(flonum? x)
(let ([v ($flonum->exact x)])
(cond
[(fixnum? v) ($fxeven? v)]
[(bignum? v) (even-bignum? v)]
[else (die 'even? "not an integer" x)]))]
[else (die 'even? "not an integer" x)]))
(define (odd? x)
(cond
[(fixnum? x) (not ($fxeven? x))]
[(bignum? x) (not (even-bignum? x))]
[(flonum? x)
(let ([v ($flonum->exact x)])
(cond
[(fixnum? v) (not ($fxeven? v))]
[(bignum? v) (not (even-bignum? v))]
[else (die 'odd? "not an integer" x)]))]
[else (die 'odd? "not an integer" x)]))
(module (number->string)
(module (bignum->string)
(define (bignum->decimal-string x)
(utf8->string (foreign-call "ikrt_bignum_to_bytevector" x)))
(module (bignum->power-string)
(define string-map "0123456789ABCDEF")
(define (init-string x chars)
(if ($bignum-positive? x)
(make-string chars)
(let ([s (make-string ($fxadd1 chars))])
(string-set! s 0 #\-)
s)))
(define (bignum-bits x)
(define (add-bits b n)
(cond
[($fxzero? b) n]
[else (add-bits ($fxsra b 1) ($fx+ n 1))]))
(let f ([i ($fxsub1 ($bignum-size x))])
(let ([b ($bignum-byte-ref x i)])
(cond
[($fxzero? b) (f ($fxsub1 i))]
[else (add-bits b ($fxsll i 3))]))))
(define (bignum->power-string x mask shift)
(let ([bits (bignum-bits x)])
(let ([chars (fxquotient (fx+ bits (fx- shift 1)) shift)])
(let* ([s (init-string x chars)]
[n ($fx- (string-length s) 1)])
(let f ([i 0] [j 0] [k 0] [b 0])
(cond
[($fx= i chars) s]
[($fx< k 8)
(f i ($fxadd1 j) ($fx+ k 8)
($fxlogor b
($fxsll ($bignum-byte-ref x j) k)))]
[else
(string-set! s ($fx- n i)
(string-ref string-map
($fxlogand mask b)))
(f ($fxadd1 i) j ($fx- k shift) ($fxsra b shift))])))))))
(define (bignum->string x r)
(case r
[(10) (bignum->decimal-string x)]
[(2) (bignum->power-string x 1 1)]
[(8) (bignum->power-string x 7 3)]
[(16) (bignum->power-string x 15 4)]
[else (die 'number->string "BUG")])))
(define ratnum->string
(lambda (x r)
(string-append
($number->string ($ratnum-n x) r)
"/"
($number->string ($ratnum-d x) r))))
(define (imag x r)
(cond
[(eqv? x 1) "+"]
[(eqv? x -1) "-"]
[(or (< x 0) (eqv? x -0.0))
($number->string x r)]
[else (string-append "+" ($number->string x r))]))
(define $number->string
(lambda (x r)
(import (ikarus system $compnums))
(cond
[(fixnum? x) (fixnum->string x r)]
[(bignum? x) (bignum->string x r)]
[(flonum? x)
(unless (eqv? r 10)
(die 'number->string
"invalid radix for inexact number"
r x))
(flonum->string x)]
[(ratnum? x) (ratnum->string x r)]
[(compnum? x)
(let ([xr ($compnum-real x)]
[xi ($compnum-imag x)])
(if (eqv? xr 0)
(string-append (imag xi r) "i")
(string-append
($number->string xr r)
(imag xi r)
"i")))]
[(cflonum? x)
(let ([xr ($cflonum-real x)]
[xi ($cflonum-imag x)])
(cond
[(flnan? xi)
(string-append ($number->string xr r) "+nan.0i")]
[(flinfinite? xi)
(string-append ($number->string xr r)
(if ($fl> xi 0.0) "+inf.0i" "-inf.0i"))]
[else
(string-append
($number->string xr r) (imag xi r) "i")]))]
[else (die 'number->string "not a number" x)])))
(define do-warn
(lambda ()
(set! do-warn values)
(raise-continuable
(condition
(make-warning)
(make-who-condition 'number->string)
(make-message-condition
"precision argument is not supported")))))
(define number->string
(case-lambda
[(x) ($number->string x 10)]
[(x r)
(unless (memv r '(2 8 10 16))
(die 'number->string "invalid radix" r))
($number->string x r)]
[(x r precision)
;(do-warn)
(number->string x r)])))
(define modulo
(lambda (n m)
(cond
[(fixnum? n)
(cond
[(fixnum? m) ($fxmodulo n m)]
[(bignum? m)
(if ($fx< n 0)
(if ($bignum-positive? m)
(foreign-call "ikrt_fxbnplus" n m)
n)
(if ($bignum-positive? m)
n
(foreign-call "ikrt_fxbnplus" n m)))]
[(flonum? m)
(let ([v ($flonum->exact m)])
(cond
[(or (fixnum? v) (bignum? v))
(inexact (modulo n v))]
[else
(die 'modulo "not an integer" m)]))]
[(ratnum? m) (die 'modulo "not an integer" m)]
[else (die 'modulo "not a number" m)])]
[(bignum? n)
(cond
[(fixnum? m)
(foreign-call "ikrt_bnfx_modulo" n m)]
[(bignum? m)
(if ($bignum-positive? n)
(if ($bignum-positive? m)
(remainder n m)
(+ m (remainder n m)))
(if ($bignum-positive? m)
(+ m (remainder n m))
(remainder n m)))]
[(flonum? m)
(let ([v ($flonum->exact m)])
(cond
[(or (fixnum? v) (bignum? v))
(inexact (modulo n v))]
[else
(die 'modulo "not an integer" m)]))]
[(ratnum? m) (die 'modulo "not an integer" m)]
[else (die 'modulo "not a number" m)])]
[(flonum? n)
(let ([v ($flonum->exact n)])
(cond
[(or (fixnum? v) (bignum? v))
(inexact (modulo v m))]
[else
(die 'modulo "not an integer" n)]))]
[(ratnum? n) (die 'modulo "not an integer" n)]
[else (die 'modulo "not a number" n)])))
(define-syntax mk<
(syntax-rules ()
[(_ name fxfx< fxbn< bnfx< bnbn<
fxfl< flfx< bnfl< flbn< flfl<
fxrt< rtfx< bnrt< rtbn< flrt< rtfl< rtrt<)
(let ()
(define err
(lambda (x) (die 'name "not a real number" x)))
(define fxloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
(fxfx< x y)
(if (fxfx< x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y)
(if (null? ls)
(fxbn< x y)
(if (fxbn< x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(fxfl< x y)
(if (fxfl< x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(fxrt< x y)
(if (fxrt< x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[else (err y)])))
(define bnloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
(bnfx< x y)
(if (bnfx< x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y)
(if (null? ls)
(bnbn< x y)
(if (bnbn< x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(bnfl< x y)
(if (bnfl< x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(bnrt< x y)
(if (bnrt< x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[else (err y)])))
(define flloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
(flfx< x y)
(if (flfx< x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y)
(if (null? ls)
(flbn< x y)
(if (flbn< x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(flfl< x y)
(if (flfl< x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(flrt< x y)
(if (flrt< x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[else (err y)])))
(define rtloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
(rtfx< x y)
(if (rtfx< x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y)
(if (null? ls)
(rtbn< x y)
(if (rtbn< x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(rtfl< x y)
(if (rtfl< x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(rtrt< x y)
(if (rtrt< x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[else (err y)])))
(define loopf
(lambda (x ls)
(cond
[(number? x)
(if (null? ls)
#f
(loopf (car ls) (cdr ls)))]
[else (err x)])))
(define name
(case-lambda
[(x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y) (fxfx< x y)]
[(bignum? y) (fxbn< x y)]
[(flonum? y) (fxfl< x y)]
[(ratnum? y) (fxrt< x y)]
[else (err y)])]
[(bignum? x)
(cond
[(fixnum? y) (bnfx< x y)]
[(bignum? y) (bnbn< x y)]
[(flonum? y) (bnfl< x y)]
[(ratnum? y) (bnrt< x y)]
[else (err y)])]
[(flonum? x)
(cond
[(fixnum? y) (flfx< x y)]
[(bignum? y) (flbn< x y)]
[(flonum? y) (flfl< x y)]
[(ratnum? y) (flrt< x y)]
[else (err y)])]
[(ratnum? x)
(cond
[(fixnum? y) (rtfx< x y)]
[(bignum? y) (rtbn< x y)]
[(flonum? y) (rtfl< x y)]
[(ratnum? y) (rtrt< x y)]
[else (err y)])]
[else (err x)])]
[(x y z) (and (name x y) (name y z))]
[(x) (if (number? x) #t (err x))]
[(x y . ls)
(cond
[(fixnum? x) (fxloopt x y ls)]
[(bignum? x) (bnloopt x y ls)]
[(flonum? x) (flloopt x y ls)]
[(ratnum? x) (rtloopt x y ls)]
[else (err x)])]))
name)]))
(define-syntax false (syntax-rules () [(_ x y) #f]))
(define-syntax bnbncmp
(syntax-rules ()
[(_ x y cmp)
(cmp (foreign-call "ikrt_bnbncomp" x y) 0)]))
(define-syntax bnbn= (syntax-rules () [(_ x y) (bnbncmp x y $fx=)]))
(define-syntax bnbn< (syntax-rules () [(_ x y) (bnbncmp x y $fx<)]))
(define-syntax bnbn> (syntax-rules () [(_ x y) (bnbncmp x y $fx>)]))
(define-syntax bnbn<= (syntax-rules () [(_ x y) (bnbncmp x y $fx<=)]))
(define-syntax bnbn>= (syntax-rules () [(_ x y) (bnbncmp x y $fx>=)]))
(define-syntax fxbn< (syntax-rules () [(_ x y) (positive-bignum? y)]))
(define-syntax bnfx< (syntax-rules () [(_ x y) (not (positive-bignum? x))]))
(define-syntax fxbn> (syntax-rules () [(_ x y) (not (positive-bignum? y))]))
(define-syntax bnfx> (syntax-rules () [(_ x y) (positive-bignum? x)]))
(define-syntax flcmp
(syntax-rules ()
[(_ flfl? flfx? fxfl? flbn? bnfl? fl?)
(begin
(define-syntax flfl?
(syntax-rules () [(_ x y) (fl? x y)]))
(define-syntax flfx?
(syntax-rules () [(_ x y) (fl? x ($fixnum->flonum y))]))
(define-syntax flbn?
(syntax-rules () [(_ x y) (fl? x (bignum->flonum y))]))
(define-syntax fxfl?
(syntax-rules () [(_ x y) (fl? ($fixnum->flonum x) y)]))
(define-syntax bnfl?
(syntax-rules () [(_ x y) (fl? (bignum->flonum x) y)])))]))
;;; #;
;;; (begin
;;; (define-syntax $fl=
;;; (syntax-rules () [(_ x y) (foreign-call "ikrt_fl_equal" x y)]))
;;; (define-syntax $fl<
;;; (syntax-rules () [(_ x y) (foreign-call "ikrt_fl_less" x y)]))
;;; (define-syntax $fl<=
;;; (syntax-rules () [(_ x y) (foreign-call "ikrt_fl_less_or_equal" x y)]))
;;; (define-syntax $fl>
;;; (syntax-rules () [(_ x y) (foreign-call "ikrt_fl_less" y x)]))
;;; (define-syntax $fl>=
;;; (syntax-rules () [(_ x y) (foreign-call "ikrt_fl_less_or_equal" y x)])))
(define-syntax define-flcmp
(syntax-rules ()
[(_ fl<? $fl<)
(define fl<?
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
($fl< x y)
(die 'fl<? "not a flonum" y))
(die 'fl<? "not a flonum" x))]
[(x y z)
(if (flonum? x)
(if (flonum? y)
(if (flonum? z)
(and ($fl< x y) ($fl< y z))
(die 'fl<? "not a flonum" z))
(die 'fl<? "not a flonum" y))
(die 'fl<? "not a flonum" x))]
[(x)
(or (flonum? x)
(die 'fl<? "not a flonum" x))]
[(x y . rest)
(let ()
(define (loopf a ls)
(unless (flonum? a)
(die 'fl<? "not a flonum" a))
(if (null? ls)
#f
(loopf (car ls) (cdr ls))))
(if (flonum? x)
(if (flonum? y)
(if ($fl< x y)
(let f ([x y] [y (car rest)] [ls (cdr rest)])
(if (flonum? y)
(if (null? ls)
($fl< x y)
(if ($fl< x y)
(f y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))
(die 'fl<? "not a flonum" y)))
(loopf (car rest) (cdr rest)))
(die 'fl<? "not a flonum" y))
(die 'fl<? "not a flonum" x)))]))]))
(define-flcmp fl=? $fl=)
(define-flcmp fl<? $fl<)
(define-flcmp fl<=? $fl<=)
(define-flcmp fl>? $fl>)
(define-flcmp fl>=? $fl>=)
(define fl+
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
($fl+ x y)
(die 'fl+ "not a flonum" y))
(die 'fl+ "not a flonum" x))]
[(x y z)
(fl+ (fl+ x y) z)]
[(x y z q . rest)
(let f ([ac (fl+ (fl+ (fl+ x y) z) q)] [rest rest])
(if (null? rest)
ac
(f (fl+ ac (car rest)) (cdr rest))))]
[(x)
(if (flonum? x)
x
(die 'fl+ "not a flonum" x))]
[() (exact->inexact 0)]))
(define fl-
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
($fl- x y)
(die 'fl- "not a flonum" y))
(die 'fl- "not a flonum" x))]
[(x y z)
(fl- (fl- x y) z)]
[(x y z q . rest)
(let f ([ac (fl- (fl- (fl- x y) z) q)] [rest rest])
(if (null? rest)
ac
(f (fl- ac (car rest)) (cdr rest))))]
[(x)
(if (flonum? x)
($fl* -1.0 x)
(die 'fl+ "not a flonum" x))]))
(define fl*
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
($fl* x y)
(die 'fl* "not a flonum" y))
(die 'fl* "not a flonum" x))]
[(x y z)
(fl* (fl* x y) z)]
[(x y z q . rest)
(let f ([ac (fl* (fl* (fl* x y) z) q)] [rest rest])
(if (null? rest)
ac
(f (fl* ac (car rest)) (cdr rest))))]
[(x)
(if (flonum? x)
x
(die 'fl* "not a flonum" x))]
[() 1.0]))
(define fl/
(case-lambda
[(x y)
(if (flonum? x)
(if (flonum? y)
($fl/ x y)
(die 'fl/ "not a flonum" y))
(die 'fl/ "not a flonum" x))]
[(x y z)
(fl/ (fl/ x y) z)]
[(x y z q . rest)
(let f ([ac (fl/ (fl/ (fl/ x y) z) q)] [rest rest])
(if (null? rest)
ac
(f (fl/ ac (car rest)) (cdr rest))))]
[(x)
(if (flonum? x)
($fl/ 1.0 x)
(die 'fl/ "not a flonum" x))]))
(flcmp flfl= flfx= fxfl= flbn= bnfl= $fl=)
(flcmp flfl< flfx< fxfl< flbn< bnfl< $fl<)
(flcmp flfl> flfx> fxfl> flbn> bnfl> $fl>)
(flcmp flfl<= flfx<= fxfl<= flbn<= bnfl<= $fl<=)
(flcmp flfl>= flfx>= fxfl>= flbn>= bnfl>= $fl>=)
(define-syntax cmp-ex/in
(syntax-rules ()
[(_ pred)
(syntax-rules ()
[(_ ex in)
(let ([x ex] [y in])
(if ($flonum-rational? y)
(pred x (exact y))
(pred (inexact x) y)))])]))
(define-syntax cmp-in/ex
(syntax-rules ()
[(_ pred)
(syntax-rules ()
[(_ in ex)
(let ([x in] [y ex])
(if ($flonum-rational? x)
(pred (exact x) y)
(pred x (inexact y))))])]))
(define-syntax flrt= (cmp-in/ex =))
(define-syntax rtfl= (cmp-ex/in =))
(define-syntax flrt< (cmp-in/ex <))
(define-syntax rtfl< (cmp-ex/in <))
(define-syntax flrt<= (cmp-in/ex <=))
(define-syntax rtfl<= (cmp-ex/in <=))
(define-syntax flrt> (cmp-in/ex >))
(define-syntax rtfl> (cmp-ex/in >))
(define-syntax flrt>= (cmp-in/ex >=))
(define-syntax rtfl>= (cmp-ex/in >=))
(define (exrt< x y) (< (* x ($ratnum-d y)) ($ratnum-n y)))
(define (rtex< x y) (< ($ratnum-n x) (* y ($ratnum-d x))))
(define (rtrt< x y) (< (* ($ratnum-n x) ($ratnum-d y)) (* ($ratnum-n y) ($ratnum-d x))))
(define (rtrt<= x y) (<= (* ($ratnum-n x) ($ratnum-d y)) (* ($ratnum-n y) ($ratnum-d x))))
(define (exrt> x y) (> (* x ($ratnum-d y)) ($ratnum-n y)))
(define (rtex> x y) (> ($ratnum-n x) (* y ($ratnum-d x))))
(define (rtrt> x y) (> (* ($ratnum-n x) ($ratnum-d y)) (* ($ratnum-n y) ($ratnum-d x))))
(define (rtrt>= x y) (>= (* ($ratnum-n x) ($ratnum-d y)) (* ($ratnum-n y) ($ratnum-d x))))
(define (rtrt= x y)
(and (= ($ratnum-n x) ($ratnum-n y)) (= ($ratnum-d x) ($ratnum-d y))))
(define =
(let ()
(define err
(lambda (x) (die '= "not a number" x)))
(define fxloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
($fx= x y)
(if ($fx= x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y) (loopf (car ls) (cdr ls))]
[(flonum? y)
(if (null? ls)
(fxfl= x y)
(if (fxfl= x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (ratnum? y) (compnum? y) (cflonum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define bnloopt
(lambda (x y ls)
(cond
[(fixnum? y) (loopf (car ls) (cdr ls))]
[(bignum? y)
(if (null? ls)
(bnbn= x y)
(if (bnbn= x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(bnfl= x y)
(if (bnfl= x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (ratnum? y) (compnum? y) (cflonum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define flloopt
(lambda (x y ls)
(cond
[(fixnum? y)
(if (null? ls)
(flfx= x y)
(if (flfx= x y)
(fxloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(bignum? y)
(if (null? ls)
(flbn= x y)
(if (flbn= x y)
(bnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(flonum? y)
(if (null? ls)
(flfl= x y)
(if (flfl= x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(flrt= x y)
(if (flrt= x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (compnum? y) (cflonum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define rtloopt
(lambda (x y ls)
(cond
[(flonum? y)
(if (null? ls)
(rtfl= x y)
(if (rtfl= x y)
(flloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(ratnum? y)
(if (null? ls)
(rtrt= x y)
(if (rtrt= x y)
(rtloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (fixnum? y) (bignum? y) (compnum? y) (cflonum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define cnloopt
(lambda (x y ls)
(cond
[(compnum? y)
(if (null? ls)
(cncn= x y)
(if (cncn= x y)
(cnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(cflonum? y)
(if (null? ls)
(cncf= x y)
(if (cncf= x y)
(cfloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (fixnum? y) (bignum? y) (flonum? y) (ratnum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define cfloopt
(lambda (x y ls)
(cond
[(cflonum? y)
(if (null? ls)
(cfcf= x y)
(if (cfcf= x y)
(cfloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(compnum? y)
(if (null? ls)
(cncf= y x)
(if (cncf= y x)
(cnloopt y (car ls) (cdr ls))
(loopf (car ls) (cdr ls))))]
[(or (fixnum? y) (bignum? y) (flonum? y) (ratnum? y))
(and (pair? ls) (loopf (car ls) (cdr ls)))]
[else (err y)])))
(define loopf
(lambda (x ls)
(cond
[(number? x)
(if (null? ls)
#f
(loopf (car ls) (cdr ls)))]
[else (err x)])))
(define (cncn= x y)
(and
(= ($compnum-real x) ($compnum-real y))
(= ($compnum-imag x) ($compnum-imag y))))
(define (cncf= x y)
(and
(= ($compnum-real x) ($cflonum-real y))
(= ($compnum-imag x) ($cflonum-imag y))))
(define (cfcf= x y)
(and
(= ($cflonum-real x) ($cflonum-real y))
(= ($cflonum-imag x) ($cflonum-imag y))))
(define =
(case-lambda
[(x y)
(cond
[(fixnum? x)
(cond
[(fixnum? y) ($fx= x y)]
[(flonum? y) (fxfl= x y)]
[(or (bignum? y) (ratnum? y) (compnum? y) (cflonum? y)) #f]
[else (err y)])]
[(bignum? x)
(cond
[(bignum? y) (bnbn= x y)]
[(flonum? y) (bnfl= x y)]
[(or (fixnum? y) (ratnum? y) (compnum? y) (cflonum? y)) #f]
[else (err y)])]
[(flonum? x)
(cond
[(fixnum? y) (flfx= x y)]
[(bignum? y) (flbn= x y)]
[(flonum? y) (flfl= x y)]
[(ratnum? y) (flrt= x y)]
[(or (compnum? y) (cflonum? y)) #f]
[else (err y)])]
[(ratnum? x)
(cond
[(flonum? y) (rtfl= x y)]
[(ratnum? y) (rtrt= x y)]
[(or (fixnum? y) (bignum? y) (compnum? y) (cflonum? y)) #f]
[else (err y)])]
[(compnum? x)
(cond
[(compnum? y) (cncn= x y)]
[(cflonum? y) (cncf= x y)]
[(or (fixnum? y) (bignum? y) (flonum? y) (ratnum? y)) #f]
[else (err y)])]
[(cflonum? x)
(cond
[(cflonum? y) (cfcf= x y)]
[(compnum? y) (cncf= y x)]
[(or (fixnum? y) (bignum? y) (flonum? y) (ratnum? y)) #f]
[else (err y)])]
[else (err x)])]
[(x y z) (and (= x y) (= y z))]
[(x) (if (number? x) #t (err x))]
[(x y . ls)
(cond
[(fixnum? x) (fxloopt x y ls)]
[(bignum? x) (bnloopt x y ls)]
[(flonum? x) (flloopt x y ls)]
[(ratnum? x) (rtloopt x y ls)]
[(compnum? x) (cnloopt x y ls)]
[(cflonum? x) (cfloopt x y ls)]
[else (err x)])]))
=))
;(define =
; (mk< = $fx= false false bnbn= fxfl= flfx= bnfl= flbn= flfl=
; false false false false flrt= rtfl= rtrt=))
(define <
(mk< < $fx< fxbn< bnfx< bnbn< fxfl< flfx< bnfl< flbn< flfl<
exrt< rtex< exrt< rtex< flrt< rtfl< rtrt<))
(define >
(mk< > $fx> fxbn> bnfx> bnbn> fxfl> flfx> bnfl> flbn> flfl>
exrt> rtex> exrt> rtex> flrt> rtfl> rtrt>))
(define <=
(mk< <= $fx<= fxbn< bnfx< bnbn<= fxfl<= flfx<= bnfl<= flbn<= flfl<=
exrt< rtex< exrt< rtex< flrt<= rtfl<= rtrt<=))
(define >=
(mk< >= $fx>= fxbn> bnfx> bnbn>= fxfl>= flfx>= bnfl>= flbn>= flfl>=
exrt> rtex> exrt> rtex> flrt>= rtfl>= rtrt>=))
(define error@add1
(