ikarus/scheme/ikarus.sort.ss

110 lines
3.3 KiB
Scheme

;;; Ikarus Scheme -- A compiler for R6RS Scheme.
;;; Copyright (C) 2006,2007 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.sort)
(export list-sort vector-sort vector-sort!)
(import
(ikarus system $fx)
(except (ikarus) list-sort vector-sort vector-sort!))
(module (sort-tail)
(define (merge1 <? a1 ls1 ls2)
(cond
[(null? ls2) ls1]
[else
(let ([a2 (car ls2)])
(cond
[(<? a2 a1)
(cons a2 (merge1 <? a1 ls1 (cdr ls2)))]
[else
(cons a1 (merge2 <? a2 (cdr ls1) ls2))]))]))
(define (merge2 <? a2 ls1 ls2)
(cond
[(null? ls1) ls2]
[else
(let ([a1 (car ls1)])
(cond
[(<? a2 a1)
(cons a2 (merge1 <? a1 ls1 (cdr ls2)))]
[else
(cons a1 (merge2 <? a2 (cdr ls1) ls2))]))]))
(define (merge <? ls1 ls2)
(cond
[(null? ls2) ls1]
[else
(let ([a1 (car ls1)] [a2 (car ls2)])
(cond
[(<? a2 a1)
(cons a2 (merge1 <? a1 ls1 (cdr ls2)))]
[else
(cons a1 (merge2 <? a2 (cdr ls1) ls2))]))]))
(define (sort-head <? ls n)
(cond
[($fx= n 0) (values '() ls)]
[($fx= n 1)
(values (cons (car ls) '()) (cdr ls))]
[else
(let-values ([(sorted-head tail)
(sort-head <? ls ($fxsra n 1))])
(let-values ([(sorted-tail tail)
(sort-head <? tail ($fx- n ($fxsra n 1)))])
(values (merge <? sorted-head sorted-tail) tail)))]))
(define (sort-tail <? ls n)
(cond
[($fx<= n 1) ls]
[else
(let-values ([(sorted-head tail)
(sort-head <? ls ($fxsra n 1))])
(merge <? sorted-head
(sort-tail <? tail ($fx- n ($fxsra n 1)))))])))
(define (list-sort <? ls)
(unless (procedure? <?)
(error 'list-sort "not a procedure" <?))
(sort-tail <? ls (length ls)))
(define (vector-sort <? v)
;;; FIXME: improve
(unless (procedure? <?)
(error 'vector-sort "not a procedure" <?))
(unless (vector? v)
(error 'vector-sort "not a vector" v))
(list->vector
(sort-tail <? (vector->list v) (vector-length v))))
(define (vector-sort! <? v)
(import (ikarus system $vectors))
(import (ikarus system $pairs))
(unless (procedure? <?)
(error 'vector-sort! "not a procedure" <?))
(unless (vector? v)
(error 'vector-sort! "not a vector" v))
(let f ([i 0] [v v]
[ls (sort-tail <? (vector->list v) (vector-length v))])
(unless (null? ls)
($vector-set! v i ($car ls))
(f ($fx+ i 1) v ($cdr ls)))))
)