インライン展開手作り風味 その2 — #:g1

Posted 2011-11-14 04:01:00 GMT

先日「インライン展開手作り風味」でマクロ展開を使って手作りのインライン化をしてみましたが、コンパイラマクロでもできる(というかむしろこちらの方が使い方としては正しそう)ので書いてみました。 マクロとしては、こっちの方がずっとシンプルになりました。 ちなみに、速度は、ほぼ同じです。

(defvar *depth* 0)
(declaim (fixnum *depth*))

(defmacro defun-inline-self-b (name level (&rest args) &body body) (let ((binds (mapcar (lambda (x) ``(,',x ,,x)) args ))) `(progn (defun ,name (,@args) ,@body) (define-compiler-macro ,name (&whole form ,@args) (if (<= *depth* ,level) `(compiler-let ((*depth* (1+ *depth*))) (let (,,@binds) ,@',body)) form )))))

使ってみる
(defun-inline-self-b fibb 4 (n)
  (declare (optimize (safety 0) (speed 3) (debug 0)))
  (declare (fixnum n))
  (if (<= n 1)
      1
      (the fixnum
        (+ (the fixnum (fib (1- n)))
           (the fixnum (fib (- n 2))) ))))

(fibb 38) ;⇒ 63245986 ---------- Evaluation took: 0.258 seconds of real time 0.260000 seconds of total run time (0.260000 user, 0.000000 system) 100.78% CPU 616,582,818 processor cycles 0 bytes consed

Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz

コンパイラマクロを使ったバージョンも展開回数の制御のためにcompiler-letを使っていますが、macroletとなにかを巧妙に組み合せれば、ANSI CLの範囲で書けるんじゃないかと思います。多分。 ■

comments powered by Disqus