You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

336 lines
12 KiB
Scheme

;;; 5_1.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.
;;; type and generic predicates
(begin
(define boolean?
(lambda (x)
(or (eq? x #t) (eq? x #f))))
(define not
(lambda (x)
(if x #f #t)))
(define eqv?
(lambda (x y)
(eqv? x y)))
(define (equal? x y)
(define k0 200)
(define kb -20)
#;(define (union-find ht x y) ; hashtable-ref/set! version
(define (find b) ; splitting
(let ([n (car b)]) ; next or census
(if (pair? n)
(let loop ([b b] [n n])
(let ([nn (car n)])
(if (pair? nn)
(begin (set-car! b nn) (loop n nn))
n)))
b)))
(let ([bx (eq-hashtable-ref ht x #f)]
[by (eq-hashtable-ref ht y #f)])
(if (not bx)
(if (not by)
(let ([b (list 1)])
(eq-hashtable-set! ht x b)
(eq-hashtable-set! ht y b)
#f)
(begin
(eq-hashtable-set! ht x (find by))
#f))
(if (not by)
(begin
(eq-hashtable-set! ht y (find bx))
#f)
(let ([rx (find bx)] [ry (find by)])
(or (eq? rx ry)
(let ([nx (car rx)] [ny (car ry)])
(if (fx> nx ny)
(begin
(set-car! ry rx)
(set-car! rx (fx+ nx ny))
#f)
(begin
(set-car! rx ry)
(set-car! ry (fx+ ny nx))
#f)))))))))
(define (union-find ht x y) ; htcell version
(define (find p n) ; splitting
(if (pair? n)
(let loop ([p p] [n n])
(let ([nn (cdr n)])
(if (pair? nn)
(begin (set-cdr! p nn) (loop n nn))
n)))
p))
(let ([ax (eq-hashtable-cell ht x 0)]
[ay (eq-hashtable-cell ht y 0)])
(let ([nx (cdr ax)] [ny (cdr ay)])
(if (eq? nx 0)
(if (eq? ny 0)
(begin
(set-cdr! ax ay)
(set-cdr! ay 1)
#f)
(begin
(set-cdr! ax (find ay ny))
#f))
(if (eq? ny 0)
(begin
(set-cdr! ay (find ax nx))
#f)
(let ([rx (find ax nx)] [ry (find ay ny)])
(or (eq? rx ry)
(let ([nx (cdr rx)] [ny (cdr ry)])
(if (fx> nx ny)
(begin
(set-cdr! ry rx)
(set-cdr! rx (fx+ nx ny))
#f)
(begin
(set-cdr! rx ry)
(set-cdr! ry (fx+ ny nx))
#f))))))))))
(define (interleave? x y k)
(let ([ht (make-eq-hashtable)])
(define (e? x y k)
(if (fx<= k 0)
(if (fx= k kb)
(fast? x y (random (* 2 k0)))
(slow? x y k))
(fast? x y k)))
(define (slow? x y k)
(cond
[(eq? x y) k]
[(pair? x)
(and (pair? y)
(if (union-find ht x y)
0
(let ([k (e? (car x) (car y) (fx- k 1))])
(and k (e? (cdr x) (cdr y) k)))))]
[(vector? x)
(and (vector? y)
(let ([n (vector-length x)])
(and (fx= (vector-length y) n)
(if (union-find ht x y)
0
(let f ([i 0] [k (fx- k 1)])
(if (fx= i n)
k
(let ([k (e? (vector-ref x i) (vector-ref y i) k)])
(and k (f (fx+ i 1) k)))))))))]
[(string? x) (and (string? y) (string=? x y) k)]
[(flonum? x) (and (flonum? y) ($fleqv? x y) k)]
[($inexactnum? x)
(and ($inexactnum? y)
($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y))
($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y))
k)]
[(bignum? x) (and (bignum? y) (= x y) k)]
[(ratnum? x) (and (ratnum? y) (= x y) k)]
[($exactnum? x) (and ($exactnum? y) (= x y) k)]
[(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)]
[(fxvector? x)
(and (fxvector? y)
(fx= (fxvector-length x) (fxvector-length y))
(let f ([i (fx- (fxvector-length x) 1)])
(if (fx< i 0)
k
(and (fx= (fxvector-ref x i) (fxvector-ref y i))
(f (fx1- i))))))]
[(box? x)
(and (box? y)
(if (union-find ht x y)
0
(e? (unbox x) (unbox y) (fx- k 1))))]
[($record? x)
(and ($record? y)
(let ([rec-equal? ($record-equal-procedure x y)])
(and rec-equal?
(if (union-find ht x y)
0
(let ([next-k k] [decr 1])
(and (rec-equal? x y
(lambda (x1 y1)
; decrementing only on first subfield, if any, like vectors and pairs
(let ([k (e? x1 y1 (fx- next-k decr))])
(and k
(begin
(set! next-k k)
(set! decr 0)
#t)))))
next-k))))))]
[else (and (eqv? x y) k)]))
(define (fast? x y k)
(let ([k (fx- k 1)])
(cond
[(eq? x y) k]
[(pair? x)
(and (pair? y)
(let ([k (e? (car x) (car y) k)])
(and k (e? (cdr x) (cdr y) k))))]
[(vector? x)
(and (vector? y)
(let ([n (vector-length x)])
(and (fx= (vector-length y) n)
(let f ([i 0] [k k])
(if (fx= i n)
k
(let ([k (e? (vector-ref x i) (vector-ref y i) k)])
(and k (f (fx+ i 1) k))))))))]
[(string? x) (and (string? y) (string=? x y) k)]
[(flonum? x) (and (flonum? y) ($fleqv? x y) k)]
[($inexactnum? x)
(and ($inexactnum? y)
($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y))
($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y))
k)]
[(bignum? x) (and (bignum? y) (= x y) k)]
[(ratnum? x) (and (ratnum? y) (= x y) k)]
[($exactnum? x) (and ($exactnum? y) (= x y) k)]
[(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)]
[(fxvector? x)
(and (fxvector? y)
(fx= (fxvector-length x) (fxvector-length y))
(let f ([i (fx- (fxvector-length x) 1)])
(if (fx< i 0)
k
(and (fx= (fxvector-ref x i) (fxvector-ref y i))
(f (fx1- i))))))]
[(box? x) (and (box? y) (e? (unbox x) (unbox y) k))]
[($record? x)
(and ($record? y)
(let ([rec-equal? ($record-equal-procedure x y)])
(and rec-equal?
(let ([next-k k])
(and (rec-equal? x y
(lambda (x1 y1)
(let ([k (e? x1 y1 next-k)])
(and k
(begin
(set! next-k k)
#t)))))
next-k)))))]
[else (and (eqv? x y) k)])))
(and (e? x y k) #t)))
(define (precheck? x y k)
(cond
[(eq? x y) k]
[(pair? x)
(and (pair? y)
(if (fx<= k 0)
k
(let ([k (precheck? (car x) (car y) (fx- k 1))])
(and k (precheck? (cdr x) (cdr y) k)))))]
[(vector? x)
(and (vector? y)
(let ([n (vector-length x)])
(and (fx= (vector-length y) n)
(let f ([i 0] [k k])
(if (or (fx= i n) (fx<= k 0))
k
(let ([k (precheck?
(vector-ref x i)
(vector-ref y i)
(fx- k 1))])
(and k (f (fx+ i 1) k))))))))]
[(string? x) (and (string? y) (string=? x y) k)]
[(flonum? x) (and (flonum? y) ($fleqv? x y) k)]
[($inexactnum? x)
(and ($inexactnum? y)
($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y))
($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y))
k)]
[(bignum? x) (and (bignum? y) (= x y) k)]
[(ratnum? x) (and (ratnum? y) (= x y) k)]
[($exactnum? x) (and ($exactnum? y) (= x y) k)]
[(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)]
[(fxvector? x)
(and (fxvector? y)
(fx= (fxvector-length x) (fxvector-length y))
(let f ([i (fx- (fxvector-length x) 1)])
(if (fx< i 0)
k
(and (fx= (fxvector-ref x i) (fxvector-ref y i))
(f (fx1- i))))))]
[(box? x)
(and (box? y)
(if (fx<= k 0)
k
(precheck? (unbox x) (unbox y) (fx- k 1))))]
[($record? x)
(and ($record? y)
(let ([rec-equal? ($record-equal-procedure x y)])
(and rec-equal?
(if (fx<= k 0)
k
(let ([next-k k])
(and (rec-equal? x y
(lambda (x1 y1)
; decrementing k for each field, like vectors but unlike pairs
(let ([k (precheck? x1 y1 (fx- next-k 1))])
(and k
(begin
(set! next-k k)
#t)))))
next-k))))))]
[else (and (eqv? x y) k)]))
(let ([k (precheck? x y k0)])
(and k (or (fx> k 0) (interleave? x y 0)))))
(define boolean=?
(case-lambda
[(b1 b2)
(unless (boolean? b1) ($oops 'boolean=? "~s is not a boolean" b1))
(unless (boolean? b2) ($oops 'boolean=? "~s is not a boolean" b2))
(#3%boolean=? b1 b2)]
[(b1 b2 . b*)
(unless (boolean? b1) ($oops 'boolean=? "~s is not a boolean" b1))
(unless (boolean? b2) ($oops 'boolean=? "~s is not a boolean" b2))
(for-each
(lambda (b) (unless (boolean? b) ($oops 'boolean=? "~s is not a boolean" b)))
b*)
(and (#3%boolean=? b1 b2)
(let f ([b* b*])
(or (null? b*)
(and (#3%boolean=? (car b*) b1)
(f (cdr b*))))))]))
(define symbol=?
(case-lambda
[(s1 s2)
(unless (symbol? s1) ($oops 'symbol=? "~s is not a symbol" s1))
(unless (symbol? s2) ($oops 'symbol=? "~s is not a symbol" s2))
(#3%symbol=? s1 s2)]
[(s1 s2 . s*)
(unless (symbol? s1) ($oops 'symbol=? "~s is not a symbol" s1))
(unless (symbol? s2) ($oops 'symbol=? "~s is not a symbol" s2))
(for-each
(lambda (s) (unless (symbol? s) ($oops 'symbol=? "~s is not a symbol" s)))
s*)
(and (#3%symbol=? s1 s2)
(let f ([s* s*])
(or (null? s*)
(and (#3%symbol=? (car s*) s1)
(f (cdr s*))))))]))
)