🔙 Back to Top

Mon Feb 25 13:46:11 JST 2013

Stalinの使い方

// ta.c
int tarai(int x,int y,int z){
    if (x<=y)  return y;
    return tarai(tarai(x-1,y,z), tarai(y-1,z,x),tarai(z-1,x,y));
}
main(){
    printf("%d\n",tarai(13,6,0));
}
; tarai.scm
(define (tarai x y z)
    (if (<= x y) y
        (tarai (tarai (- x 1) y z)
               (tarai (- y 1) z x)
               (tarai (- z 1) x y))))

(write (tarai 13 6 0))
$ gcc -O3 ta.c; time ./a.out
ta.c: In function ‘main’:
ta.c:6:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
13

real    0m0.205s
user    0m0.204s
sys     0m0.000s

$ stalin tarai.scm
For now, you must specify -On because safe fixnum arithmetic is not (yet) implemented

何もオプション付けないと -On はつけろと言われる.intのoverflowチェックで あると man stalin には書いてある.

$ stalin -On tarai.scm; time ./tarai
13
real    0m0.635s
user    0m0.628s
sys     0m0.004s

全然速くないじゃん、と思ってたけど、以下のようにするのが正しい.

$ stalin -On -copt -O3 tarai.scm; time ./tarai
13
real    0m0.191s
user    0m0.188s
sys     0m0.000s

stalinはそもそもschemeソースコードをCのソースコードに翻訳するもので、 あとはcc、デフォルトではgccに投げるものらしい. -copt の後ろのオプションは gcc へのオプションとして働く.

$ stalin -On -k tarai.scm

とすると、翻訳されたCのソースコードが残って見ることができる.

まあでも実際、StalinのSchemeは実用に耐えない.SRFIとかないし.


たらい回し関数は、遅延評価でかなり計算が削減されて、

(define (tarai x y z)
    (if (<= (force x) (force y)) (force y)
        (tarai (lazy (tarai (- (force x) 1) (force y) (force z)))
               (lazy (tarai (- (force y) 1) (force z) (force x)))
               (lazy (tarai (- (force z) 1) (force x) (force y))))))

(write (tarai (lazy 13) (lazy 6) (lazy 0)))
$ time gosh tarai.scm
13

real    0m0.143s
user    0m0.104s
sys     0m0.024s

Gaucheのほうが,Stalinコンパイルしたものより速い. 速いというか計算を削減してるんだから.

Stalinだとまずlazyって名前がダメでdelayにするとなんかエラーが 一杯出て分からない.