4065 lines
133 KiB
Scheme
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
|
|
( |