A => counting-sort.scm +28 -0
@@ 0,0 1,28 @@
+;; PUBLIC DOMAIN or CC0 - whatever fits your use-case or jurisdiction best
+;;
+;; sort-u8 sorts a list of unsigned bytes using a simple counting sort.
+;; about 30x faster than guile's built in sort for one million random bytes.
+;; For additional speedup you can make a sort-u8! that overwrites the list
+;; in place.
+(use-modules ((srfi srfi-43) #:select (vector-fold)))
+
+(define (sort-u8 ls <?)
+ (define vec (make-vector 256 0))
+ ;; populate the vector with the contents of ls
+ (let loop ((ls ls))
+ (unless (null? ls)
+ (vector-set! vec (car ls) (+ (vector-ref vec (car ls)) 1))
+ (loop (cdr ls))))
+
+ ;; turn vec into an alist of (index . count) and sort by index
+ (let* ((ls (vector-fold (lambda (i state val) (cons (cons i val) state)) '() vec))
+ (ls (sort ls (lambda (l r) (<? (car l) (car r))))))
+ ;; build a list from the alist
+ (let outer ((ls ls))
+ (if (null? ls)
+ '()
+ (let ((byte (caar ls)))
+ (let inner ((n (cdar ls)))
+ (if (zero? n)
+ (outer (cdr ls))
+ (cons byte (inner (- n 1))))))))))