// 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にするとなんかエラーが 一杯出て分からない.