LISP on TeX におけるパーサのフックな話
生きてます(唐突に).
LISP on TeX更新情報
最近,修士論文も無事に提出できたので,LISP on TeXに機能拡張とかしてみた.
パーサのフック機能.
LISP on TeXの整数型,dimen型,およびskip型にリテラルには,それぞれ決まったプレフィクスをつけることにしている.
しかし,ユーザが新しい型を追加できない*1という問題があった.また,これ以上型を増やすと適当なプレフィクスがなくなってしまうという問題も出てきた.
そこで,汎用的にパーサを操作できる構文を追加することとした.構文は,次で示される.
+{mod::foo}
modはモジュール名,fooはモジュールmodによってパースするトークン列である.
例えば,lisp-mod-stdout.styでは,stdoutモジュールを提供している.
\documentclass{article} \usepackage{lisp} \usepackage{lisp-mod-stdout} \begin{document} \lispinterpl{+{stdout::orz}} \end{document}
と書いてタイプセットすると,
$ latex hatena.tex This is pdfTeX, Version 3.1415926-2.5-1.40.13 (TeX Live 2012/W32TeX) restricted \write18 enabled. entering extended mode (./hatena.tex LaTeX2e <2011/06/27> Babel <v3.8m> and hyphenation patterns for english, dumylang, nohyphenation, ge rman-x-2012-05-30, ngerman-x-2012-05-30, afrikaans, ancientgreek, ibycus, arabi c, armenian, basque, bulgarian, catalan, pinyin, coptic, croatian, czech, danis h, dutch, ukenglish, usenglishmax, esperanto, estonian, ethiopic, farsi, finnis h, french, friulan, galician, german, ngerman, swissgerman, monogreek, greek, h ungarian, icelandic, assamese, bengali, gujarati, hindi, kannada, malayalam, ma rathi, oriya, panjabi, tamil, telugu, indonesian, interlingua, irish, italian, kurmanji, latin, latvian, lithuanian, mongolian, mongolianlmc, bokmal, nynorsk, polish, portuguese, romanian, romansh, russian, sanskrit, serbian, serbianc, s lovak, slovenian, spanish, swedish, turkish, turkmen, ukrainian, uppersorbian, welsh, loaded. (i:/W32TeX/share/texmf/tex/latex/base/article.cls Document Class: article 2007/10/19 v1.4h Standard LaTeX document class (i:/W32TeX/share/texmf/tex/latex/base/size10.clo)) (./lisp.sty (./lisp-read.tex ) (./lisp-arith.tex) (./lisp-string.tex) (./lisp-latexutil.tex) (./lisp-prim.tex)) (./lisp-mod-stdout.sty) No file hatena.aux. orz (./hatena.aux) ) No pages of output. Transcript written on hatena.log. [1]+ Done sublime_text.exe hatena.tex
コンソールにorzが表示される*2.
また,現在のLISP on TeXでは,fpnumモジュールをlisp-mod-fpnum.styで提供している.これは,TeXのdimenを使って固定小数点数計算を行うためのモジュールで,
+{fpnum::1.0}
と記述すると,内部でfpnum型の1.0として扱われるオブジェクトを生成する.この型のオブジェクトに関する加算,減算,乗算および比較演算もlisp-mod-fpnum.styは提供している.
これを使って,マンデルブロ集合に再挑戦した.前回は,TeX on LaTeX なあれに,実行時間,精度共に惨敗したが,fpnumがなかっただけで,今ならいけるはず!
ソースはこんな感じ
\documentclass{article} \usepackage[dvipdfm,a3paper,margin=1pt,landscape]{geometry} \newcount\mlength \newcount\cstate \newdimen\mandelunit \mandelunit=0.5pt \def\w{% \ifnum\cstate=1 \global\advance\mlength1 \else \vrule width \mlength\mandelunit height \mandelunit depth 0pt \global\mlength1 \fi \global\cstate1} \def\b{% \ifnum\cstate=-1 \global\advance\mlength1 \else \hspace*{\mlength\mandelunit}\global\mlength1 \fi \global\cstate-1} \def\r{% \ifnum\cstate=1\hspace*{\mlength\mandelunit}\else\vrule width \mlength\mandelunit height \mandelunit depth 0pt \fi \global\cstate0 \global\mlength0} \usepackage{lisp} \usepackage{lisp-mod-stdout} \usepackage{lisp-mod-fpnum} \lispinterpl{% (\define \maxloop :20) (\define \scale +{fpnum::0.002}) (\define \isMandell (\lambda (\a \b \k \x \y) (\lispif (\< \maxloop \k) /t (\lispif (\fplt +{fpnum::4.0} (\fpplus (\fpmul \x \x) (\fpmul \y \y))) /f (\isMandell \a \b (\+ \k :1) (\fpplus \a (\fpmul \x \x) (\fpminus (\fpmul \y \y))) (\fpplus \b (\fpmul +{fpnum::2.0} \x \y))))))) (\define \drawMandell (\lambda (\a \b) (\begin (\lispif (\isMandell \a \b :0 +{fpnum::0} +{fpnum::0}) (\texprint '\b') (\texprint '\w')) (\immediatewrite)))) (\define \loopMandell (\lambda (\a \b) (\lispif (\fplt \b +{fpnum::-1.0}) () (\begin (\drawMandell \a \b) (\lispif (\fplt +{fpnum::0.5} \a) (\begin (\texprint '\r\\') (\immediatewrite) (\loopMandell +{fpnum::-1.5} (\fpminus \b \scale))) (\loopMandell (\fpplus \a \scale) \b)))))) } \begin{document} \noindent \leavevmode\baselineskip=\mandelunit \lispinterpl{(\loopMandell +{fpnum::-1.5} +{fpnum::1.0})} \end{document}
これで勝つる.実行結果はこんな感じ.
実行時間はというと……
real 274m44.480s user 0m0.000s sys 0m0.031s
惨敗でしたー*3.
追記
前回と同ループ回数,同メッシュでやったら37分だった.また,前回のメッシュ + ループ制限は今回のものでやったら10分で計算終了.
評価ルーチンのブラッシュアップ
これは拡張じゃないけども一応.\if系トークンの使用回数を減らしたし,若干早くなった+軽くなった,はず……