[Shootout-list] fannkuch in Scheme

Dima Dorfman d+shootout@trit.org
Tue, 21 Dec 2004 16:40:05 +0000


--L6iaP+gRLNZHKoI4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Attached is a fannkuch implementation in Scheme. It uses the same
successor algorithm as Simon Geard's f90 implementation posted on
Sunday, but I actually wrote this last week (it's a well-known
algorithm).

Dima.

--L6iaP+gRLNZHKoI4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fannkuch.scm"

;; fannkuch benchmark for The Computer Language Shootout
;; Written by Dima Dorfman, 2004
;; Compile with bigloo: bigloo -Obench -unsafe -o fannkuch_bigloo fannkuch.scm

(module nsieve (main main))

(define (1+ i) (+ i 1))
(define (1- i) (- i 1))

(define (vector-swap! v i j)
  (let ((t (vector-ref v i)))
    (vector-set! v i (vector-ref v j))
    (vector-set! v j t)))

(define (vector-reverse-slice! v i j)
  (do ((i i (1+ i))
       (j j (1- j)))
      ((<= (- j i) 1))
    (vector-swap! v i (1- j))))

(define (count-flips pi)
  (do ((rho (vector-copy pi))
       (i 0 (1+ i)))
      ((= (vector-ref rho 0) 1) i)
    (vector-reverse-slice! rho 0 (vector-ref rho 0))))

(define (successor! pi)
  (let ((i (let loop ((i (- (vector-length pi) 2)))
	     (cond ((< i 0) #f)
		   ((> (vector-ref pi (1+ i)) (vector-ref pi i)) i)
		   (else (loop (1- i)))))))
    (if (not i) #f
	(let* ((ith (vector-ref pi i))
	       (j (do ((j (1- (vector-length pi)) (1- j)))
		      ((> (vector-ref pi j) ith) j))))
	  (vector-swap! pi i j)
	  (vector-reverse-slice! pi (1+ i) (vector-length pi))
	  #t))))

(define (fannkuch n)
  (let ((pi (do ((pi (make-vector n))
		 (i 0 (1+ i)))
		((= i (vector-length pi)) pi)
	      (vector-set! pi i (1+ i)))))
    (let loop ((flips 0))
      (let ((flips (max (count-flips pi) flips)))
	(if (successor! pi)
	    (loop flips)
	    flips)))))

(define (main args)
  (if (< (length args) 2)
      (begin (display "An argument is required") (newline) 2)
      (let ((n (string->number (cadr args))))
	(if (not n)
	    (begin (display "An integer is required") (newline) 2)
	    (let ((f (fannkuch n)))
	      (begin
		(display "fannkuch(")
		(display n)
		(display ") = ")
		(display f)
		(newline))
	      0)))))

--L6iaP+gRLNZHKoI4--