(module sort '#%kernel (#%require "small-scheme.ss" "define.ss" (for-syntax "stxcase-scheme.ss")) (#%provide sort) #| Based on "Fast mergesort implementation based on half-copying merge algorithm", Cezary Juszczak, http://kicia.ift.uni.wroc.pl/algorytmy/mergesortpaper.pdf Written in Scheme by Eli Barzilay. (Note: the reason for the seemingly redundant pointer arithmetic in that paper is dealing with cases of uneven number of elements.) The source uses macros to optimize some common cases (eg, no `getkey' function, or precompiled versions with inlinable common comparison predicates) -- they are local macros so they're not left in the compiled code. Note that there is no error checking on the arguments -- the `sort' function that this module provide is then wrapped up by a keyworded version in "scheme/private/list.ss", and that's what everybody sees. The wrapper is doing these checks. |# ;; This code works with unsafe operations, but don't use it for a while to ;; catch potential problems. ;; (#%require (rename '#%unsafe i+ unsafe-fx+) ;; (rename '#%unsafe i- unsafe-fx-) ;; (rename '#%unsafe i= unsafe-fx=) ;; (rename '#%unsafe i< unsafe-fx<) ;; (rename '#%unsafe i<= unsafe-fx<=) ;; (rename '#%unsafe i>> unsafe-fxrshift) ;; (rename '#%unsafe vref unsafe-vector-ref) ;; (rename '#%unsafe vset! unsafe-vector-set!)) (define sort (let () (define-syntax define-syntax-rule (syntax-rules () [(dr (foo . pattern) template) (define-syntax foo (syntax-rules () [(_ . pattern) template]))])) (define-syntax-rule (i+ x y) (+ x y)) (define-syntax-rule (i- x y) (- x y)) (define-syntax-rule (i= x y) (= x y)) (define-syntax-rule (i< x y) (< x y)) (define-syntax-rule (i<= x y) (<= x y)) (define-syntax-rule (i>> x y) (arithmetic-shift x (- y))) (define-syntax-rule (vref v i) (vector-ref v i)) (define-syntax-rule (vset! v i x) (vector-set! v i x)) (define-syntax-rule (sort-internal-body v *> n 1)] [n/2+ (i- n n/2-)]) (define-syntax-rule (> n 1)] [n/2+ (i- n n/2-)]) (let ([Amid1 (i+ Alo n/2-)] [Amid2 (i+ Alo n/2+)] [Bmid1 (i+ Blo n/2-)]) (copying-mergesort Amid1 Bmid1 n/2+) (copying-mergesort Alo Amid2 n/2-) (merge #t Amid2 (i+ Alo n) Bmid1 (i+ Blo n) Blo)))])) (let ([Alo 0] [Amid1 n/2-] [Amid2 n/2+] [Ahi n] [B1lo n]) (copying-mergesort Amid1 B1lo n/2+) (unless (zero? n/2-) (copying-mergesort Alo Amid2 n/2-)) (merge #f B1lo (i+ B1lo n/2+) Amid2 Ahi Alo)))) (define sort-internals (make-hasheq)) (define _ (let () (define-syntax-rule (precomp >=) (precomp string decorated-vector (let loop ([i 0] [lst lst]) (when (pair? lst) (let ([x (car lst)]) (vector-set! vec i (cons (getkey x) x)) (loop (add1 i) (cdr lst))))) ;; sort (sort-internal * list (let loop ([i n] [r '()]) (let ([i (sub1 i)]) (if (< i 0) r (loop i (cons (cdr (vector-ref vec i)) r))))))] ;; trivial cases [(< n 2) lst] ;; check if the list is already sorted (which can be common, eg, ;; directory lists) [(let loop ([last (car lst)] [next (cdr lst)]) (or (null? next) (and (not ( vector (let loop ([i 0] [lst lst]) (when (pair? lst) (vector-set! vec i (car lst)) (loop (add1 i) (cdr lst)))) ;; sort (if getkey (sort-internal * list (let loop ([i n] [r '()]) (let ([i (sub1 i)]) (if (< i 0) r (loop i (cons (vector-ref vec i) r))))))]))) ;; Finally, this is the provided `sort' value (case-lambda [(lst