770 lines
24 KiB
Scheme
770 lines
24 KiB
Scheme
;;; mathprims.ss
|
|
;;; Copyright 1984-2017 Cisco Systems, Inc.
|
|
;;;
|
|
;;; Licensed under the Apache License, Version 2.0 (the "License");
|
|
;;; you may not use this file except in compliance with the License.
|
|
;;; You may obtain a copy of the License at
|
|
;;;
|
|
;;; http://www.apache.org/licenses/LICENSE-2.0
|
|
;;;
|
|
;;; Unless required by applicable law or agreed to in writing, software
|
|
;;; distributed under the License is distributed on an "AS IS" BASIS,
|
|
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
;;; See the License for the specific language governing permissions and
|
|
;;; limitations under the License.
|
|
|
|
(begin
|
|
(eval-when (compile)
|
|
|
|
(define-syntax define-relop
|
|
(syntax-rules ()
|
|
[(_ name pred? err not-nan?)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))]
|
|
[(x1 x2 . rest)
|
|
(let loop ([x1 x1] [x2 x2] [rest rest])
|
|
(if (#2%name x1 x2)
|
|
(or (null? rest) (loop x2 (car rest) (cdr rest)))
|
|
(let loop ([rest rest])
|
|
(cond
|
|
[(null? rest) #f]
|
|
[(pred? (car rest)) (loop (cdr rest))]
|
|
[else (err 'name (car rest))]))))]
|
|
[(x1)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(#3%not-nan? x1)]))]))
|
|
|
|
(define-syntax define-r6rs-relop ; requires 2+ arguments
|
|
(syntax-rules ()
|
|
[(_ name pred? err)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))]
|
|
[(x1 x2 . rest)
|
|
(let loop ([x1 x1] [x2 x2] [rest rest])
|
|
(if (#2%name x1 x2)
|
|
(or (null? rest) (loop x2 (car rest) (cdr rest)))
|
|
(let loop ([rest rest])
|
|
(cond
|
|
[(null? rest) #f]
|
|
[(pred? (car rest)) (loop (cdr rest))]
|
|
[else (err 'name (car rest))]))))]))]))
|
|
|
|
(define-syntax define-addop
|
|
(syntax-rules ()
|
|
[(_ name)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (#2%name (#2%name x1 x2) x3)]
|
|
[(x1 x2 . rest)
|
|
(let loop ([x1 x1] [x2 x2] [rest rest])
|
|
(let ([x (#2%name x1 x2)])
|
|
(if (null? rest) x (loop x (car rest) (cdr rest)))))]
|
|
[(x1) (#2%name x1)]
|
|
[() (#2%name)]))]))
|
|
|
|
(define-syntax define-subop
|
|
(syntax-rules ()
|
|
[(_ name pred? err)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (#2%name (#2%name x1 x2) x3)]
|
|
[(x1) (#2%name x1)]
|
|
[(x0 x1 . rest)
|
|
(unless (pred? x0) (err 'name x0))
|
|
(let loop ([x0 x0] [x1 x1] [rest rest])
|
|
(unless (pred? x1) (err 'name x1))
|
|
(if (null? rest)
|
|
(#3%name x0 x1)
|
|
(loop (#3%name x0 x1) (car rest) (cdr rest))))]))]))
|
|
|
|
(define-syntax define-generic-subop
|
|
(syntax-rules ()
|
|
[(_ name)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (#2%name (#2%name x1 x2) x3)]
|
|
[(x1) (#2%name x1)]
|
|
[(x0 x1 . rest)
|
|
(let loop ([x0 x0] [x1 x1] [rest rest])
|
|
(if (null? rest)
|
|
(#2%name x0 x1)
|
|
(loop (#2%name x0 x1) (car rest) (cdr rest))))]))]))
|
|
|
|
(define-syntax define-cfl-relop
|
|
(syntax-rules ()
|
|
[(_ name pred? err not-nan?)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(#3%name x1 x2)]
|
|
[(x1 x2 x3)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(unless (pred? x3) (err 'name x3))
|
|
(and (#3%name x1 x2) (#3%name x2 x3))]
|
|
[(x1 x2 . rest)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(let loop ([x1 x1] [x2 x2] [rest rest])
|
|
(unless (pred? x2) (err 'name x2))
|
|
(if (#3%name x1 x2)
|
|
(or (null? rest) (loop x2 (car rest) (cdr rest)))
|
|
(let loop ([rest rest])
|
|
(cond
|
|
[(null? rest) #f]
|
|
[(pred? (car rest)) (loop (cdr rest))]
|
|
[else (err 'name (car rest))]))))]
|
|
[(x1)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(not-nan? x1)]))]))
|
|
|
|
(define-syntax define-cfl-addop
|
|
(syntax-rules ()
|
|
[(_ name pred? err)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(#3%name x1 x2)]
|
|
[(x1 x2 x3)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(unless (pred? x3) (err 'name x3))
|
|
(#3%name (#3%name x1 x2) x3)]
|
|
[(x1 x2 . rest)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(let loop ([x1 x1] [x2 x2] [rest rest])
|
|
(unless (pred? x2) (err 'name x2))
|
|
(let ([x (#3%name x1 x2)])
|
|
(if (null? rest) x (loop x (car rest) (cdr rest)))))]
|
|
[(x1)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(#3%name x1)]
|
|
[() (name)]))]))
|
|
|
|
(define-syntax define-cfl-subop
|
|
(syntax-rules ()
|
|
[(_ name pred? err)
|
|
(set! name
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(#3%name x1 x2)]
|
|
[(x1 x2 x3)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(unless (pred? x2) (err 'name x2))
|
|
(unless (pred? x3) (err 'name x3))
|
|
(#3%name (#3%name x1 x2) x3)]
|
|
[(x1)
|
|
(unless (pred? x1) (err 'name x1))
|
|
(#3%name x1)]
|
|
[(x0 x1 . rest)
|
|
(unless (pred? x0) (err 'name x0))
|
|
(let loop ([x0 x0] [x1 x1] [rest rest])
|
|
(unless (pred? x1) (err 'name x1))
|
|
(if (null? rest)
|
|
(#3%name x0 x1)
|
|
(loop (#3%name x0 x1) (car rest) (cdr rest))))]))]))
|
|
)
|
|
|
|
(define 1- (lambda (x) (#2%1- x)))
|
|
|
|
(define 1+ (lambda (x) (#2%1+ x)))
|
|
|
|
(define sub1 (lambda (x) (#2%sub1 x)))
|
|
|
|
(define -1+ (lambda (x) (#2%-1+ x)))
|
|
|
|
(define add1 (lambda (x) (#2%add1 x)))
|
|
|
|
(define-addop +)
|
|
(define-generic-subop -)
|
|
(define-addop *)
|
|
(define-generic-subop /)
|
|
|
|
(define-addop logand)
|
|
(define-addop bitwise-and)
|
|
(define-addop logior)
|
|
(define-addop bitwise-ior)
|
|
(define-addop logor)
|
|
(define-addop logxor)
|
|
(define-addop bitwise-xor)
|
|
|
|
(define (lognot x) (#2%lognot x))
|
|
(define (bitwise-not x) (#2%bitwise-not x))
|
|
|
|
(define (logbit? x y) (#2%logbit? x y))
|
|
(define (bitwise-bit-set? x y) (#2%bitwise-bit-set? x y))
|
|
(define (logbit0 x y) (#2%logbit0 x y))
|
|
(define (logbit1 x y) (#2%logbit1 x y))
|
|
(define (logtest x y) (#2%logtest x y))
|
|
|
|
(eval-when (compile)
|
|
(define-syntax define-number-relop
|
|
(syntax-rules ()
|
|
[(_ name)
|
|
(define name
|
|
(case-lambda
|
|
[(x1 x2) (#2%name x1 x2)]
|
|
[(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))]
|
|
[(x1) (begin (#2%name x1 0) #t)]
|
|
[(x1 x2 . rest)
|
|
(let loop ([x1 x1] [x2 x2] [ls rest])
|
|
(if (or (null? ls) (loop x2 (car ls) (cdr ls)))
|
|
(#2%name x1 x2)
|
|
(begin (#2%name x1 x2) #f)))]))])))
|
|
|
|
(define-number-relop =)
|
|
(define-number-relop <)
|
|
(define-number-relop >)
|
|
(define-number-relop <=)
|
|
(define-number-relop >=)
|
|
|
|
(eval-when (compile)
|
|
(define-syntax define-r6rs-number-relop ; requires 2+ argument
|
|
(syntax-rules ()
|
|
[(_ r6rs:name name)
|
|
(define-who #(r6rs: name)
|
|
(case-lambda
|
|
[(x1 x2) (#2%r6rs:name x1 x2)]
|
|
[(x1 x2 x3) (if (#2%r6rs:name x1 x2)
|
|
(#2%r6rs:name x2 x3)
|
|
(begin (#2%r6rs:name x2 x3) #f))]
|
|
[(x1 x2 . rest)
|
|
(let loop ([x1 x1] [x2 x2] [ls rest])
|
|
(if (or (null? ls) (loop x2 (car ls) (cdr ls)))
|
|
(#2%r6rs:name x1 x2)
|
|
(begin (#2%r6rs:name x1 x2) #f)))]))])))
|
|
|
|
(define-r6rs-number-relop r6rs:= =)
|
|
(define-r6rs-number-relop r6rs:< <)
|
|
(define-r6rs-number-relop r6rs:> >)
|
|
(define-r6rs-number-relop r6rs:<= <=)
|
|
(define-r6rs-number-relop r6rs:>= >=)
|
|
|
|
(eval-when (compile) (optimize-level 3))
|
|
|
|
(let ()
|
|
(define flargerr
|
|
(lambda (who x)
|
|
($oops who "~s is not a flonum" x)))
|
|
|
|
(set! fl-make-rectangular
|
|
(lambda (x y)
|
|
(unless (flonum? x) (flargerr 'fl-make-rectangular x))
|
|
(unless (flonum? y) (flargerr 'fl-make-rectangular y))
|
|
(#3%fl-make-rectangular x y)))
|
|
|
|
(define-addop fl+)
|
|
(define-subop fl- flonum? flargerr)
|
|
(define-addop fl*)
|
|
(define-subop fl/ flonum? flargerr)
|
|
|
|
(set! flabs
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr 'flabs x))
|
|
(#3%flabs x)))
|
|
|
|
(set! flround
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr 'flround x))
|
|
(#3%flround x)))
|
|
|
|
(set! fllp
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr 'fllp x))
|
|
(#3%fllp x)))
|
|
|
|
(define-relop fl= flonum? flargerr fl=)
|
|
(define-relop fl< flonum? flargerr fl=)
|
|
(define-relop fl> flonum? flargerr fl=)
|
|
(define-relop fl<= flonum? flargerr fl=)
|
|
(define-relop fl>= flonum? flargerr fl=)
|
|
(define-r6rs-relop fl=? flonum? flargerr)
|
|
(define-r6rs-relop fl<? flonum? flargerr)
|
|
(define-r6rs-relop fl>? flonum? flargerr)
|
|
(define-r6rs-relop fl<=? flonum? flargerr)
|
|
(define-r6rs-relop fl>=? flonum? flargerr)
|
|
|
|
(set-who! $fleqv?
|
|
(lambda (x y)
|
|
(unless (flonum? x) (flargerr who x))
|
|
(unless (flonum? y) (flargerr who y))
|
|
(#3%$fleqv? x y)))
|
|
|
|
(set-who! $flhash
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr who x))
|
|
(#3%$flhash x)))
|
|
|
|
(set-who! $flonum-exponent ; requires optimize-level 3
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr who x))
|
|
($flonum-exponent x)))
|
|
|
|
(set-who! $flonum-sign ; requires optimize-level 3
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr who x))
|
|
($flonum-sign x)))
|
|
|
|
(set-who! flonum->fixnum
|
|
(let ([flmnf (fixnum->flonum (most-negative-fixnum))]
|
|
[flmpf (fixnum->flonum (most-positive-fixnum))])
|
|
(lambda (x)
|
|
(unless (flonum? x) (flargerr who x))
|
|
(unless (fl<= flmnf x flmpf)
|
|
($oops who "result for ~s would be outside of fixnum range" x))
|
|
(#3%flonum->fixnum x))))
|
|
)
|
|
|
|
(let ()
|
|
(define fxargerr
|
|
(lambda (who x)
|
|
($oops who "~s is not a fixnum" x)))
|
|
|
|
(define /zeroerr
|
|
(lambda (who)
|
|
($oops who "attempt to divide by zero")))
|
|
|
|
(define fxanserr
|
|
(lambda (who . args)
|
|
($impoops who "fixnum overflow computing ~s" (cons who args))))
|
|
|
|
(define-addop fx+)
|
|
(define-subop fx- fixnum? fxargerr)
|
|
|
|
(set-who! #(r6rs: fx+) (lambda (x y) (#2%r6rs:fx+ x y)))
|
|
(set-who! #(r6rs: fx-)
|
|
(case-lambda
|
|
[(x) (#2%r6rs:fx- x)]
|
|
[(x y) (#2%r6rs:fx- x y)]))
|
|
|
|
(set! fx1-
|
|
(lambda (x)
|
|
(#2%fx1- x)))
|
|
|
|
(set! fx1+
|
|
(lambda (x)
|
|
(#2%fx1+ x)))
|
|
|
|
(set! fxzero?
|
|
(lambda (x)
|
|
(#2%fxzero? x)))
|
|
|
|
(set! fx*
|
|
(rec fx*
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
; should handle fixnums (avoiding overflow)
|
|
(let ([n (* x1 x2)])
|
|
(if (fixnum? n) n (fxanserr 'fx* x1 x2)))
|
|
(fxargerr 'fx* x2))
|
|
(fxargerr 'fx* x1))]
|
|
[(x1 x2 x3)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
(if (fixnum? x3)
|
|
; should handle fixnums (avoiding overflow)
|
|
(let ([n (* x1 x2)])
|
|
(if (fixnum? n)
|
|
; should handle fixnums (avoiding overflow)
|
|
(let ([n (* n x3)])
|
|
(if (fixnum? n) n (fxanserr 'fx* x1 x2 x3)))
|
|
(fxanserr 'fx* x1 x2 x3)))
|
|
(fxargerr 'fx* x3))
|
|
(fxargerr 'fx* x2))
|
|
(fxargerr 'fx* x1))]
|
|
[(x1) (if (fixnum? x1) x1 (fxargerr 'fx* x1))]
|
|
[() 1]
|
|
[(x1 . rest)
|
|
(let loop ([a x1] [ls rest])
|
|
(if (null? ls)
|
|
a
|
|
(loop (fx* a (car ls)) (cdr ls))))])))
|
|
|
|
(set-who! #(r6rs: fx*)
|
|
(lambda (x1 x2)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
; should handle fixnums (avoiding overflow)
|
|
(let ([n (* x1 x2)])
|
|
(if (fixnum? n) n (fxanserr who x1 x2)))
|
|
(fxargerr who x2))
|
|
(fxargerr who x1))))
|
|
|
|
(set! fxquotient
|
|
(rec fxquotient
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
(begin
|
|
(when (fx= x2 0) (/zeroerr 'fxquotient))
|
|
(if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum)))
|
|
(fxanserr 'fxquotient x1 x2)
|
|
(#3%fxquotient x1 x2)))
|
|
(fxargerr 'fxquotient x2))
|
|
(fxargerr 'fxquotient x1))]
|
|
[(x1 x2 x3)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
(if (fixnum? x3)
|
|
(begin
|
|
(when (fx= x2 0) (/zeroerr 'fxquotient))
|
|
(if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum)))
|
|
(fxanserr 'fxquotient x1 x2 x3)
|
|
(let ([n (#3%fxquotient x1 x2)])
|
|
(when (fx= x3 0) (/zeroerr 'fxquotient))
|
|
(if (and (fx= x3 -1) (fx= n (most-negative-fixnum)))
|
|
(fxanserr 'fxquotient x1 x2 x3)
|
|
(#3%fxquotient n x3)))))
|
|
(fxargerr 'fxquotient x3))
|
|
(fxargerr 'fxquotient x2))
|
|
(fxargerr 'fxquotient x1))]
|
|
[(x1)
|
|
(if (fixnum? x1)
|
|
(if (fx= x1 0)
|
|
(/zeroerr 'fxquotient)
|
|
(#3%fxquotient 1 x1))
|
|
(fxargerr 'fxquotient x1))]
|
|
[(x1 . rest)
|
|
(let loop ([a x1] [ls rest])
|
|
(if (null? ls)
|
|
a
|
|
(loop (fxquotient a (car ls)) (cdr ls))))])))
|
|
|
|
(set! fx/
|
|
(rec fx/ ;; same as fxquotient---should it be?
|
|
(case-lambda
|
|
[(x1 x2)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
(begin
|
|
(when (fx= x2 0) (/zeroerr 'fx/))
|
|
(if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum)))
|
|
(fxanserr 'fx/ x1 x2)
|
|
(#3%fx/ x1 x2)))
|
|
(fxargerr 'fx/ x2))
|
|
(fxargerr 'fx/ x1))]
|
|
[(x1 x2 x3)
|
|
(if (fixnum? x1)
|
|
(if (fixnum? x2)
|
|
(if (fixnum? x3)
|
|
(begin
|
|
(when (fx= x2 0) (/zeroerr 'fx/))
|
|
(if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum)))
|
|
(fxanserr 'fx/ x1 x2 x3)
|
|
(let ([n (#3%fx/ x1 x2)])
|
|
(when (fx= x3 0) (/zeroerr 'fx/))
|
|
(if (and (fx= x3 -1) (fx= n (most-negative-fixnum)))
|
|
(fxanserr 'fx/ x1 x2 x3)
|
|
(#3%fx/ n x3)))))
|
|
(fxargerr 'fx/ x3))
|
|
(fxargerr 'fx/ x2))
|
|
(fxargerr 'fx/ x1))]
|
|
[(x1)
|
|
(if (fixnum? x1)
|
|
(if (fx= x1 0)
|
|
(/zeroerr 'fx/)
|
|
(#3%fx/ 1 x1))
|
|
(fxargerr 'fx/ x1))]
|
|
[(x1 . rest)
|
|
(let loop ([a x1] [ls rest])
|
|
(if (null? ls)
|
|
a
|
|
(loop (fx/ a (car ls)) (cdr ls))))])))
|
|
|
|
(set! fxabs
|
|
(lambda (x)
|
|
(unless (fixnum? x) (fxargerr 'fxabs x))
|
|
(when (fx= x (most-negative-fixnum)) (fxanserr 'fxabs x))
|
|
(#3%fxabs x)))
|
|
|
|
(define-relop fx= fixnum? fxargerr fx=)
|
|
(define-relop fx< fixnum? fxargerr fx=)
|
|
(define-relop fx> fixnum? fxargerr fx=)
|
|
(define-relop fx<= fixnum? fxargerr fx=)
|
|
(define-relop fx>= fixnum? fxargerr fx=)
|
|
(define-r6rs-relop fx=? fixnum? fxargerr)
|
|
(define-r6rs-relop fx<? fixnum? fxargerr)
|
|
(define-r6rs-relop fx>? fixnum? fxargerr)
|
|
(define-r6rs-relop fx<=? fixnum? fxargerr)
|
|
(define-r6rs-relop fx>=? fixnum? fxargerr)
|
|
|
|
(set! $fxu<
|
|
(lambda (x y)
|
|
(unless (fixnum? x) (fxargerr '$fxu< x))
|
|
(unless (fixnum? y) (fxargerr '$fxu< y))
|
|
(#3%$fxu< x y)))
|
|
|
|
(define-addop fxlogand)
|
|
(define-addop fxlogior)
|
|
(define-addop fxlogor)
|
|
(define-addop fxlogxor)
|
|
(define-addop fxand)
|
|
(define-addop fxior)
|
|
(define-addop fxxor)
|
|
|
|
(set! fxsll
|
|
(lambda (x y)
|
|
(#2%fxsll x y)))
|
|
|
|
(set! fxarithmetic-shift-left
|
|
(lambda (x y)
|
|
(#2%fxarithmetic-shift-left x y)))
|
|
|
|
(set! fxsrl
|
|
(lambda (x y)
|
|
(#2%fxsrl x y)))
|
|
|
|
(set! fxsra
|
|
(lambda (x y)
|
|
(#2%fxsra x y)))
|
|
|
|
(set! fxarithmetic-shift-right
|
|
(lambda (x y)
|
|
(#2%fxarithmetic-shift-right x y)))
|
|
|
|
(set! fxarithmetic-shift
|
|
(lambda (x y)
|
|
(#2%fxarithmetic-shift x y)))
|
|
|
|
(set! fxlognot
|
|
(lambda (x)
|
|
(#2%fxlognot x)))
|
|
|
|
(set! fxnot
|
|
(lambda (x)
|
|
(#2%fxnot x)))
|
|
|
|
(set! fxlogtest
|
|
(lambda (x y)
|
|
(#2%fxlogtest x y)))
|
|
|
|
(set! fxlogbit?
|
|
(lambda (x y)
|
|
(#2%fxlogbit? x y)))
|
|
|
|
(set! fxbit-set?
|
|
(lambda (x y)
|
|
(#2%fxbit-set? x y)))
|
|
|
|
(set! fxlogbit0
|
|
(lambda (x y)
|
|
(#2%fxlogbit0 x y)))
|
|
|
|
(set! fxlogbit1
|
|
(lambda (x y)
|
|
(#2%fxlogbit1 x y)))
|
|
|
|
(set-who! fxcopy-bit
|
|
(lambda (n k b)
|
|
; optimize-level 2 handler doesn't kick in unless b=0 or b=1
|
|
(unless (fixnum? n) (fxargerr who n))
|
|
(unless (fixnum? k) (fxargerr who k))
|
|
(unless ($fxu< k (fx- (fixnum-width) 1))
|
|
($oops who "invalid bit index ~s" k))
|
|
(case b
|
|
[(0) (#3%fxlogbit0 k n)]
|
|
[(1) (#3%fxlogbit1 k n)]
|
|
[else ($oops who "invalid bit value ~s" b)])))
|
|
|
|
(set! fxeven?
|
|
(lambda (x)
|
|
(#2%fxeven? x)))
|
|
|
|
(set! fxodd?
|
|
(lambda (x)
|
|
(#2%fxodd? x)))
|
|
|
|
(set! fxremainder
|
|
(lambda (x y)
|
|
(unless (fixnum? x) (fxargerr 'fxremainder x))
|
|
(unless (fixnum? y) (fxargerr 'fxremainder y))
|
|
(when (fx= y 0) (/zeroerr 'fxremainder))
|
|
(#3%fxremainder x y)))
|
|
|
|
(set! fxmodulo
|
|
(lambda (x y)
|
|
(unless (fixnum? x) (fxargerr 'fxmodulo x))
|
|
(unless (fixnum? y) (fxargerr 'fxmodulo y))
|
|
(when (fx= y 0) (/zeroerr 'fxmodulo))
|
|
(let ([r (fxremainder x y)])
|
|
(if (if (fxnegative? y) (fxpositive? r) (fxnegative? r))
|
|
(fx+ r y)
|
|
r))))
|
|
|
|
(set! fxmin
|
|
(case-lambda
|
|
[(x y)
|
|
(unless (fixnum? x) (fxargerr 'fxmin x))
|
|
(unless (fixnum? y) (fxargerr 'fxmin y))
|
|
(if (fx< y x) y x)]
|
|
[(x y z)
|
|
(unless (fixnum? x) (fxargerr 'fxmin x))
|
|
(unless (fixnum? y) (fxargerr 'fxmin y))
|
|
(unless (fixnum? z) (fxargerr 'fxmin z))
|
|
(if (fx< y x)
|
|
(if (fx< z y) z y)
|
|
(if (fx< z x) z x))]
|
|
[(x . y)
|
|
(unless (fixnum? x) (fxargerr 'fxmin x))
|
|
(let f ([x x] [y y])
|
|
(if (null? y)
|
|
x
|
|
(f (let ([z (car y)])
|
|
(unless (fixnum? z) (fxargerr 'fxmin z))
|
|
(if (fx< z x) z x))
|
|
(cdr y))))]))
|
|
|
|
(set! fxmax
|
|
(case-lambda
|
|
[(x y)
|
|
(unless (fixnum? x) (fxargerr 'fxmax x))
|
|
(unless (fixnum? y) (fxargerr 'fxmax y))
|
|
(if (fx> y x) y x)]
|
|
[(x y z)
|
|
(unless (fixnum? x) (fxargerr 'fxmax x))
|
|
(unless (fixnum? y) (fxargerr 'fxmax y))
|
|
(unless (fixnum? z) (fxargerr 'fxmax z))
|
|
(if (fx> y x)
|
|
(if (fx> z y) z y)
|
|
(if (fx> z x) z x))]
|
|
[(x . y)
|
|
(unless (fixnum? x) (fxargerr 'fxmax x))
|
|
(let f ([x x] [y y])
|
|
(if (null? y)
|
|
x
|
|
(f (let ([z (car y)])
|
|
(unless (fixnum? z) (fxargerr 'fxmax z))
|
|
(if (fx> z x) z x))
|
|
(cdr y))))]))
|
|
|
|
(set! fxnegative?
|
|
(lambda (x)
|
|
(#2%fxnegative? x)))
|
|
|
|
(set! fxpositive?
|
|
(lambda (x)
|
|
(#2%fxpositive? x)))
|
|
|
|
(set! fxnonnegative?
|
|
(lambda (x)
|
|
(#2%fxnonnegative? x)))
|
|
|
|
(set! fxnonpositive?
|
|
(lambda (x)
|
|
(#2%fxnonpositive? x)))
|
|
|
|
(set! fixnum->flonum
|
|
(lambda (x)
|
|
(unless (fixnum? x) (fxargerr 'fixnum->flonum x))
|
|
(#3%fixnum->flonum x)))
|
|
|
|
(set-who! fxlength
|
|
(lambda (x)
|
|
(if (fixnum? x)
|
|
(#3%fxlength x)
|
|
(fxargerr who x))))
|
|
|
|
(set-who! fxfirst-bit-set
|
|
(lambda (x)
|
|
(if (fixnum? x)
|
|
(#3%fxfirst-bit-set x)
|
|
(fxargerr who x))))
|
|
|
|
(set-who! fxif
|
|
(lambda (x y z)
|
|
(if (fixnum? x)
|
|
(if (fixnum? y)
|
|
(if (fixnum? z)
|
|
(#3%fxif x y z)
|
|
(fxargerr who z))
|
|
(fxargerr who y))
|
|
(fxargerr who x))))
|
|
|
|
(set-who! fxbit-field
|
|
(lambda (n start end)
|
|
(if (fixnum? n)
|
|
(if (and (fixnum? start) ($fxu< start (fixnum-width)))
|
|
(if (and (fixnum? end) ($fxu< end (fixnum-width)))
|
|
(if (fx<= start end)
|
|
(fxsra (fxand n (fxnot (fxsll -1 end))) start)
|
|
($oops who "start index ~s is greater than end index ~s" start end))
|
|
($oops who "~s is not a valid end index" end))
|
|
($oops who "~s is not a valid start index" start))
|
|
(fxargerr who n))))
|
|
|
|
(set-who! fxcopy-bit-field
|
|
(lambda (n start end m)
|
|
(if (fixnum? n)
|
|
(if (and (fixnum? start) ($fxu< start (fixnum-width)))
|
|
(if (and (fixnum? end) ($fxu< end (fixnum-width)))
|
|
(if (fx<= start end)
|
|
(if (fixnum? m)
|
|
(let ([mask (fx- (fxsll 1 (fx- end start)) 1)])
|
|
(fxior
|
|
(fxand n (fxnot (fxsll mask start)))
|
|
(fxsll (fxand m mask) start)))
|
|
(fxargerr who m))
|
|
($oops who "start index ~s is greater than end index ~s" start end))
|
|
($oops who "~s is not a valid end index" end))
|
|
($oops who "~s is not a valid start index" start))
|
|
(fxargerr who n))))
|
|
)
|
|
|
|
;;; The "cfl" operations could be done at level 0 by expanding them out.
|
|
;;; They might be more efficient that way since they wouldn't have to
|
|
;;; do double flonum checking.
|
|
|
|
(define cflonum?
|
|
(lambda (x)
|
|
(cflonum? x)))
|
|
|
|
(let ()
|
|
|
|
(define noncflonum-error
|
|
(lambda (who x)
|
|
($oops who "~s is not a cflonum" x)))
|
|
|
|
(set! cfl-real-part
|
|
(lambda (z)
|
|
(type-case z
|
|
[($inexactnum?) ($inexactnum-real-part z)]
|
|
[(flonum?) z]
|
|
[else (noncflonum-error 'cfl-real-part z)])))
|
|
|
|
(set! cfl-imag-part
|
|
(lambda (z)
|
|
(type-case z
|
|
[($inexactnum?) ($inexactnum-imag-part z)]
|
|
[(flonum?) 0.0]
|
|
[else (noncflonum-error 'cfl-imag-part z)])))
|
|
|
|
(define-cfl-addop cfl+ cflonum? noncflonum-error)
|
|
(define-cfl-addop cfl* cflonum? noncflonum-error)
|
|
(define-cfl-subop cfl- cflonum? noncflonum-error)
|
|
(define-cfl-subop cfl/ cflonum? noncflonum-error)
|
|
(define-cfl-relop cfl= cflonum? noncflonum-error cfl=)
|
|
|
|
(set! cfl-conjugate
|
|
(lambda (x)
|
|
(type-case x
|
|
[(cflonum?) (#3%cfl-conjugate x)]
|
|
[else (noncflonum-error 'cfl-conjugate x)])))
|
|
|
|
)
|
|
)
|