diff --git a/scheme/Makefile.am b/scheme/Makefile.am index e7fa6c3..45ce157 100644 --- a/scheme/Makefile.am +++ b/scheme/Makefile.am @@ -28,7 +28,7 @@ EXTRA_DIST=ikarus.boot.4.prebuilt ikarus.boot.8.prebuilt \ ikarus.io.ss ikarus.time-and-date.ss ikarus.not-yet-implemented.ss \ ikarus.string-to-number.ss ikarus.compiler.source-optimizer.ss \ ikarus.compiler.tag-annotation-analysis.ss ikarus.ontology.ss \ - ikarus.reader.annotated.ss ikarus.pointers.ss + ikarus.reader.annotated.ss ikarus.pointers.ss ikarus.equal.ss all: $(nodist_pkglib_DATA) diff --git a/scheme/Makefile.in b/scheme/Makefile.in index e64a161..35f7a0d 100644 --- a/scheme/Makefile.in +++ b/scheme/Makefile.in @@ -183,7 +183,7 @@ EXTRA_DIST = ikarus.boot.4.prebuilt ikarus.boot.8.prebuilt \ ikarus.io.ss ikarus.time-and-date.ss ikarus.not-yet-implemented.ss \ ikarus.string-to-number.ss ikarus.compiler.source-optimizer.ss \ ikarus.compiler.tag-annotation-analysis.ss ikarus.ontology.ss \ - ikarus.reader.annotated.ss ikarus.pointers.ss + ikarus.reader.annotated.ss ikarus.pointers.ss ikarus.equal.ss revno = "$(shell sed 's/ .*//' ../.bzr/branch/last-revision 2>/dev/null)" sizeofvoidp = $(shell grep SIZEOF_VOID_P ../config.h | sed "s/.*\(.\)/\1/g") diff --git a/scheme/ikarus.equal.ss b/scheme/ikarus.equal.ss new file mode 100644 index 0000000..ad68ca6 --- /dev/null +++ b/scheme/ikarus.equal.ss @@ -0,0 +1,166 @@ + + +;;; Copied from +;;; Efficient Nondestructive Equality Checking for Trees and Graphs +;;; Michael D. Adams and R. Kent Dybvig +;;; ICFP 2008 + +(library (ikarus.equal) + (export equal?) + (import (except (ikarus) equal?)) + + (module UNSAFE + (< <= > >= = + - vector-ref vector-length car cdr) + (import + (rename (ikarus system $vectors) + ($vector-length vector-length) + ($vector-ref vector-ref)) + (rename (ikarus system $pairs) + ($car car) + ($cdr cdr)) + (rename (ikarus system $fx) + ($fx+ +) + ($fx- -) + ($fx< <) + ($fx> >) + ($fx>= >=) + ($fx<= <=) + ($fx= =)))) + + + + (define eq-hashtable-ref hashtable-ref) + (define eq-hashtable-set! hashtable-set!) + + (define-struct box (content)) + + (define (union-find ht x y) + (import UNSAFE) + (define (find b) + (let ([n (box-content b)]) + (if (box? n) + (let loop ([b b] [n n]) + (let ([nn (box-content n)]) + (if (box? nn) (begin (set-box-content! 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 (make-box 1)]) + (eq-hashtable-set! ht x b) + (eq-hashtable-set! ht y b) + #f) + (let ([ry (find by)]) (eq-hashtable-set! ht x ry) #f)) + (if (not by) + (let ([rx (find bx)]) (eq-hashtable-set! ht y rx) #f) + (let ([rx (find bx)] [ry (find by)]) + (or (eq? rx ry) + (let ([nx (box-content rx)] [ny (box-content ry)]) + (if (> nx ny) + (begin + (set-box-content! ry rx) + (set-box-content! rx (+ nx ny)) + #f) + (begin + (set-box-content! rx ry) + (set-box-content! ry (+ ny nx)) + #f))))))))) + + (define (pre? x y k) + (import UNSAFE) + (cond + [(eq? x y) k] + [(pair? x) + (and (pair? y) + (if (<= k 0) + k + (let ([k (pre? (car x) (car y) (- k 1))]) + (and k (pre? (cdr x) (cdr y) k)))))] + [(vector? x) + (and (vector? y) + (let ([n (vector-length x)]) + (and (= (vector-length y) n) + (let f ([i 0] [k k]) + (if (or (= i n) (<= k 0)) + k + (let ([k (pre? + (vector-ref x i) + (vector-ref y i) + (- k 1))]) + (and k (f (+ i 1) k))))))))] + [(string? x) (and (string? y) (string=? x y) k)] + [else (and (eqv? x y) k)])) + + (define (interleave? x y k) + (import UNSAFE) + (let ([ht #f]) + (define (call-union-find x y) + (unless ht (set! ht (make-eq-hashtable))) + (union-find ht x y)) + (define (e? x y k) + (if (<= k 0) + (if (= 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 (call-union-find x y) + 0 + (let ([k (e? (car x) (car y) (- k 1))]) + (and k (e? (cdr x) (cdr y) k)))))] + [(vector? x) + (and (vector? y) + (let ([n (vector-length x)]) + (and (= (vector-length y) n) + (if (call-union-find x y) + 0 + (let f ([i 0] [k (- k 1)]) + (if (= i n) + k + (let ([k (e? (vector-ref x i) + (vector-ref y i) + k)]) + (and k (f (+ i 1) k)))))))))] + [(string? x) (and (string? y) (string=? x y) k)] + [else (and (eqv? x y) k)])) + (define (fast? x y k) + (let ([k (- 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 (= (vector-length y) n) + (let f ([i 0] [k k]) + (if (= i n) + k + (let ([k (e? (vector-ref x i) + (vector-ref y i) + k)]) + (and k (f (+ i 1) k))))))))] + [(string? x) (and (string? y) (string=? x y) k)] + [else (and (eqv? x y) k)]))) + (and (e? x y k) #t))) + + (define k0 400) + + (define kb -40) + + (define (interleave-equal? x y) + (interleave? x y k0)) + + (define (precheck/interleave-equal? x y) + (let ([k (pre? x y k0)]) + (and k (or (> k 0) (interleave? x y 0))))) + + (define (equal? x y) + (precheck/interleave-equal? x y)) + + ) diff --git a/scheme/ikarus.predicates.ss b/scheme/ikarus.predicates.ss index e861ba5..476b255 100644 --- a/scheme/ikarus.predicates.ss +++ b/scheme/ikarus.predicates.ss @@ -20,7 +20,7 @@ number? complex? real? rational? integer? exact? inexact? eof-object? bwp-object? immediate? boolean? char? vector? bytevector? string? procedure? null? pair? - symbol? code? not weak-pair? eq? eqv? equal? boolean=? + symbol? code? not weak-pair? eq? eqv? boolean=? symbol=? finite? infinite? nan? real-valued? rational-valued? integer-valued? transcoder?) (import @@ -28,7 +28,7 @@ number? complex? real? rational? integer? exact? inexact? eof-object? bwp-object? immediate? boolean? char? vector? bytevector? string? procedure? - null? pair? weak-pair? symbol? code? not eq? eqv? equal? + null? pair? weak-pair? symbol? code? not eq? eqv? transcoder? boolean=? symbol=? finite? infinite? nan? real-valued? rational-valued? integer-valued?) @@ -313,39 +313,6 @@ (define-pred symbol=? sys:symbol? "not a symbol") (define-pred boolean=? sys:boolean? "not a boolean") - (module (equal?) - (define vector-loop - (lambda (x y i n) - (or ($fx= i n) - (and (equal? ($vector-ref x i) ($vector-ref y i)) - (vector-loop x y ($fxadd1 i) n))))) - (define string-loop - (lambda (x y i n) - (or ($fx= i n) - (and ($char= ($string-ref x i) ($string-ref y i)) - (string-loop x y ($fxadd1 i) n))))) - (define equal? - (lambda (x y) - (cond - [(sys:eq? x y) #t] - [(pair? x) - (and (pair? y) - (equal? ($car x) ($car y)) - (equal? ($cdr x) ($cdr y)))] - [(vector? x) - (and (vector? y) - (let ([n ($vector-length x)]) - (and ($fx= n ($vector-length y)) - (vector-loop x y 0 n))))] - [(string? x) - (and (string? y) - (let ([n ($string-length x)]) - (and ($fx= n ($string-length y)) - (string-loop x y 0 n))))] - [(sys:bytevector? x) - (and (sys:bytevector? y) (bytevector=? x y))] - [(number? x) (eqv? x y)] - [else #f])))) ) diff --git a/scheme/last-revision b/scheme/last-revision index 8912fa1..a8a4f74 100644 --- a/scheme/last-revision +++ b/scheme/last-revision @@ -1 +1 @@ -1665 +1666 diff --git a/scheme/makefile.ss b/scheme/makefile.ss index 7f18925..22efd2e 100755 --- a/scheme/makefile.ss +++ b/scheme/makefile.ss @@ -58,6 +58,7 @@ "ikarus.collect.ss" "ikarus.apply.ss" "ikarus.predicates.ss" + "ikarus.equal.ss" "ikarus.pairs.ss" "ikarus.lists.ss" "ikarus.fixnums.ss"