何かを書き留める何か

数学や読んだ本について書く何かです。最近は社会人として生き残りの術を学ぶ日々です。

CTeX(もどき) -TeX & LaTeX Advent Calendar 2013-

TeX & LaTeX Advent Calendar 2013のために書かれた記事です。
<12月5日:Xaro Cydeykn||12月7日:hak7a3>


家にあるアドベントカレンダーを一日で空けまくる子供みたいだな、と思いつつ先に進む。2日連続ですがご容赦ください。
PythonTeXとはLaTeXドキュメントの中に埋め込んだPythonソースを実行してその結果をLaTeXドキュメントに埋め込むためのパッケージである、と昔誰かが言っていた。
Pythonにはctypesと呼ばれるライブラリがあり、公式のドキュメントから引用すると

ctypes は Python のための外部関数ライブラリです。このライブラリは C と互換性のあるデータ型を提供し、動的リンク/共有ライブラリ内の関数呼び出しを可能にします。動的リンク/共有ライブラリを純粋な Python でラップするために使うことができます。

http://docs.python.jp/3/library/ctypes.html

とある。つまり、Pythonから比較的気軽にC言語で書かれた函数を実行することが出来る。これを見て、私はLaTeXからC言語で書かれた函数をPythonを介して呼び出すことが出来るのではないか?と考えた。言わば「CTeX」(造語)みたいなことができるのではないか。

まず、次のようなC言語のソースを用意する。名前はisprime.cでその名の通り素数かどうかを素朴な方法で判定する函数を提供する。なお素数判定 - Wikipediaから引用した。

#include<stdio.h>
/******************************************
*	素数を判定する素朴な函数
*	素数ならば 1 を、合成数ならば 0 を返す 
*******************************************/
int isprime(int n){
    int i;
 
	if(n < 2)
		return 0;
	else if(n == 2)
		return 1;
 
	if(n % 2 == 0)
        return 0;

	for(i = 3; i * i <= n; i += 2){
		if(n % i == 0){
			return 0;
		}
	}
	return 1;
};

/******************************************
*	テスト函数
*	 1からMAX(=50)までの数で素数判定を行う
*******************************************/
int main(void){
	int n;
	const int MAX = 50;
	
	for(n=1; n<=MAX; ++n){
		if(isprime(n) == 1){
			printf("%3d is Prime number\n", n);
		}
		else{
			printf("%3d is Composite number\n", n);
		}
	};
	
	return 0;
}

次にLaTeX文章を用意する。ファイル名はCTeX.texとしておく。

\documentclass{ltjsarticle}
\usepackage{amsmath}
\usepackage{lmodern}
\usepackage[ipaex]{luatexja-preset}
\usepackage{luatexja-otf}
\usepackage[makestderr]{pythontex}
\begin{pycode}
import ctypes
import os

# この操作はLaTeX外で行ってもOK
# isprime.soがあるディレクトリを指示すればよい
os.chdir(r"dir_name") #isprime.cがあるディレクトリ
os.system("gcc -shared -o isprime.so isprime.c")
mydll = ctypes.CDLL("./isprime.so")

# 自作のisprimeで素数のリストを作る
primelist = [x for x in range(1,100) if mydll.isprime(x) == 1]
\end{pycode}

\begin{document}
TeX \& LaTeX Advent Calendar 2013 !

\py{primelist}

\LaTeX ったら最強ね
\end{document}

後は

$ lualatex CTeX.tex
$ pythontex CTeX.tex
$ lualatex CTeX.tex

と処理すればよい。当然、gccなどのCコンパイラが必要なのは言うまでもない。PythonTeXにos.chdir()やos.system()を行わせたくない場合は上記のLuaLaTeXの処理を行う前に

$ gcc -shared -o isprime.so isprime.c

を実行しておく。

これで手元に存在するであろうC言語で書かれた資産*1を活用できる日がくるかもしれない。

*1:Pythonにも便利なパッケージが沢山あるのでそれをまず検討すること