2011年9月24日土曜日

Falling Rigid Bunnies


Falling rigid bunnies, with particle-based simulation.

400 bunnies are falling, which consist of about 100 particles respectively.



粒子法のプログラム
粒子法のプログラム第1回(概要)
粒子法のプログラム第2回(プログラムの大枠)
粒子法のプログラム第3回(データ構造)
粒子法のプログラム第4回(密度と圧力の計算)
粒子法のプログラム第5回(力の計算)
粒子法のプログラム第6回(境界条件と粒子位置の更新)
粒子法のプログラム最終回(粒子の出力)
SPHによる巻き波のシミュレーション1
SPHによる巻き波のシミュレーション2
SPHによる巻き波のシミュレーション3
このあとやりたいこと

固液連成シミュレーションに関するエントリ
粒子法による固液連成シミュレーション

流体シミュレーションに関するエントリ
【粒子法】粒子を流体としてレンダリング
3次元の粒子法シミュレーション
粒子法のシーンを2倍のサイズにしてみたが…
粒子法のシーンを2倍のサイズにしてみた
Haskell、OCamlでSPH法
カメラ位置を変えて流体をレンダリング
Bunny-shaped fluid simulation

剛体シミュレーションに関するエントリ
粒子ベース剛体シミュレーション(プレビュー)
粒子ベース多体衝突シミュレーション
引き続き、粒子ベース剛体シミュレーション
Falling Rigid Bunnies

--

2011年8月4日木曜日

L-systemでのモデル生成



新しくPixarの中の人になったらしい人のエントリが面白かった。

Homage to Structure Synth

L-systemでモデルを生成して、RenderManでレンダリングしている。

--

2011年7月31日日曜日

構文チェックツールのFlymakeを、Haskell用に設定する方法


Emacsでは、Flymakeを使うことで、コードを書くと随時文法チェックが行われ、エラーのある行がバッファ上に表示されるようになる。

Haskell用にFlymakeを設定したので、その設定を書いておく。.emacsを編集するだけでOKだ。

Flymakeでは、基本的にコードと同じディレクトリにあるMakefileを使って文法チェックを行う形になっているが、いちいちMakefileを用意するのは煩わしいので、Makefileなしでも動作するようにした。特定のパラメータが必要な場合などは、Makefileを用意すれば自動的にそちらを使って文法チェックが行われるようにしてある。

.emacsの設定


以下のelispを.emacsに追加するだけでOK。

※Emacs21以前の場合は、flymake.elが標準で付属していないので、自分でインストールする必要がある。Emacs22以降であれば、標準で付属している。
;; Flymake Haskell

(require 'flymake)

(defun flymake-haskell-make-command (temp-file)
  (list "make"
        (flymake-haskell-make-parameters temp-file)))

(defun flymake-haskell-make-parameters (temp-file)
  (list "-s"
        "-C"
        "."
        (concat "CHK_SOURCES=" temp-file)
        "SYNTAX_CHECK_MODE=1"
        "check-syntax"))

(defun flymake-haskell-default-ghc-command (local-file)
  (list "ghc"
        (flymake-haskell-default-ghc-parameters
          (file-name-nondirectory local-file))))

(defun flymake-haskell-default-ghc-parameters (local-file)
  (list "-fno-code" local-file))

(defun makefile-exists-p (path)
  (file-exists-p (concat path "Makefile")))

(defun flymake-haskell-init()
  (let* ((temp-file  (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
         (local-file (file-relative-name
                       temp-file
                       (file-name-directory buffer-file-name))))
    (if (makefile-exists-p (file-name-directory buffer-file-name))
        (flymake-haskell-make-command temp-file)
        (flymake-haskell-default-ghc-command local-file))))

(push '(".+\\hs$" flymake-haskell-init) flymake-allowed-file-name-masks)
(push '(".+\\lhs$" flymake-haskell-init) flymake-allowed-file-name-masks)
(push '("^\\(\.+\.hs\\|\.lhs\\):\\([0-9]+\\):\\([0-9]+\\):\\(\.+\\)" 1 2 3 4)
      flymake-err-line-patterns)

(add-hook 'haskell-mode-hook
    '(lambda ()
       (if (not (null buffer-file-name))
           (flymake-mode))))

説明


flymakeの有効化
add-hookによって、haskell-modeに入ったときに(flymake-mode)が実行される。

拡張子の対応付け、エラーメッセージの正規表現の定義
add-hookの上でpushしているのは、Haskellの.hsファイル、.lhsファイルとflymakeの初期化関数との紐付け、及び、ghcの出力から行番号やエラーメッセージを抽出するための正規表現である。

flymake haskellの初期化
flymake-modeに入ると、flymake-haskell-initが実行される。flymake-haskell-initでは、構文チェック用にコードをコピーし、そのコードを構文チェックするためのコマンドをflymake本体に返している。このとき、チェック対象のコードと同じディレクトリにMakefileがあるかどうかでコマンドを変えている。

チェック対象のコードと同じディレクトリにMakefileがある場合
この場合、構文チェックのコマンドはflymake-haskell-make-command関数によって生成される。flymakeがデフォルトで使用するmakeコマンドと同じものを生成している。

チェック対象のコードと同じディレクトリにMakefileがない場合
一方、この場合は、Makefileなしで構文チェックを行うよう、GHCを使ったコマンドを、flymake-haskell-default-ghc-command関数で生成している。生成するコマンドの形式は、
("ghc" ("-fno-code" 構文チェック用ファイルの名前))
となる。外側のリストのcarがghcコマンド、cadrがghcコマンドに渡すパラメータのリストである。これがflymakeに渡され、実行される。

補足


flymakeではエラーメッセージも表示してくれるのだが、ghcが複数行にわたるエラーメッセージを返す場合にはうまく処理できない。

flymakeは、それだけで完全にコンパイルをとおすためではなく、コードを書くときのタイポ回避程度に位置づけると良いだろう。

参考


http://www.emacswiki.org/emacs/FlymakeHaskell




--

2011年7月23日土曜日

【まとめ】埋め込みDSL関係の論文(2)


引き続き、埋め込みDSL(Domain Specific Language)関係の論文をまとめたので書いておく。

Template Meta-programming for Haskell (2002) - Tim Sheard, and Simon Peyton Jones
→Haskellでコンパイル時メタプログラミングを行うTemplate Haskellの論文

A Special-Purpose Language for Picture Drawing (1997) - Samuel N. Kamin, and David Hyatt
→MLを使って、2次元の絵を表現するための組み込みDSLを作る

Compiling Embedded Languages (2000) - Conal Elliott, Sigbjorn Finne, and Oege de Moor
→Kaminのプログラム生成のアイデアを元に、組み込みDSLの最適化コンパイラを示す。計算効率が重要な分野の応用例として、この方法を画像合成・操作のための言語Panに適用する。

Functional Implementations of Continuous Modeled Animation (1997) - Conal Elliott, and Paul Hudak
→連続的アニメーションのモデルを設計し、それを試作として実装してみせる。

Programming Graphics Processors Functionally (2004) - Conal Elliott
→3Dグラフィクスのための組み込みDSLであるVertigoを紹介する。VertigoはHaskellで書かれている。Vertigoは、GPUのコードを生成する最適化コンパイラである。

Functional Reactive Animation (1997) - Conal Elliott, and Paul Hudak
→インタラクティブでリッチなアニメーションを構築するためのフレームワークFRAN(Functional Reactive Animation)を紹介する。

Building Domain-Specific Embedded Languages (1996) - Paul Hudak
→良いソフトウェアを書くには抽象化が重要であり、最も"理想的"な抽象化は問題に合わせて設計されたプログラム言語を作ることであるとして、その障害である言語設計と実装の困難さを、組み込みDSLというアプローチで回避することを提案する。

Applicative programming with effects (2008) - Conor McBride, and Ross Paterson
→副作用を持つプログラムの抽象化の方法として、Monadよりも弱いため広く使えるApplicativeファンクタを紹介する。

Arrows, Robots, and Functional Reactive Programming - Paul Hudak, Antony Courteny, Henrik Nilsson, and John Peterson
→FRP(Functional Reactive Programming)の実例として、Haskellによる組み込みDSLであるYampaを紹介する。Yampaではモナドの一般化としてアローを使用する。Yampaによって、時間変化を扱うプログラムを宣言的なスタイルで実現できる。


■関連エントリ

【まとめ】埋め込みDSL関係の論文(1)

--

2011年7月8日金曜日

【まとめ】埋め込みDSL関係の論文(1)


埋め込みDSL(Domain Specific Language)関係の論文をまとめたので書いておく。

Plugging Haskell in (2004) - Andre Pang, Don Stewart, Sean Seefried, and Manuel M. T. Chakravarty
→Haskellをプラグインとして使う方法を紹介している。紹介されているプラグインは、HaskellでもHaskell FFIがサポートしている他の言語でも使用できる。GHCで提供されている仕組みを使って、プラグイン、実行時コンパイル、動的リンクを実現する方法を示している。また、サンプルも紹介されている。

Standard ML as a Meta-Programming Language (1996) - Samuel Kamin
→Standard MLをメタプログラミング言語として使うことを提案し、4つの実例を示している。Standard MLのコードからCのコードを生成。

Building program generators the easy way - Samuel Kamin
→関数型プログラミング言語で簡単にプログラムジェネレータを作ることができることを紹介している。この方法によって、ソフトウェア開発に関数型プログラム言語を便利に応用できる可能性を示している。

Effecient Image Manipulation via Run-time Compilation (1999) - Oege de Moor, Conal Elliott, and Sigbjorn Finne
→DSLとして定義したイメージ操作システムを、実行時に最適化・コンパイルすることで、その効率化する方法を紹介している。

Optimizing Embedded DSLs using Template Haskell (2004) - Sean Seefried, Manuel Chakravarty, and Gabriele Keller
→コンパイル時メタプログラミングによってEDSLの実行効率を改善する方法を示している。EDSLとしてのシンプルさを保ったまま実行効率を改善する。

GPU Kernels as Data-Parallel Array Computation in Haskell (2009) - Sean Lee, Manuel M. T. Chakravarty, and Vinod Grover
→HaskellにGPUカーネルを埋め込んでデータ並列の配列計算を行う方法を示している。

Accelerating Haskell Array Codes with Multicore GPUs (2011) - Manuel M. T. Chakravarty, Gabriele Keller, Sean Lee, Trevor L. McDonell, and Vinod Grover
→GPUコーンピューティングの抽象度を上げるために、配列計算の高レベルDSLを提案する。HaskellにこのDSLを埋め込み、NVIDIAのCUDAのためのコードを実行時に生成する。


■関連エントリ

【まとめ】埋め込みDSL関係の論文(2)

--

2011年7月6日水曜日

Language-oriented programming


A kind of programming that's quite common in Common Lisp and relatively uncommon in non-Lisp Languages.

Rather than provide an API built primarily out of functions, classes and macros, language-oriented programming provides language that you can embed in your Common Lisp programs.



--

2011年7月5日火曜日

LispマクロとTemplate Haskellの違い


LispマクロとTemplate Haskellには違いがある。

LispのマクロはS式を変換する。一方、Template Haskellが変換するものはHaskellのAST(Abstract Syntax Tree)である。

従って、Template Haskellで変換できる式は、まずASTとして有効でなければならない。ASTとして有効な式でなければTemplate Haskellに渡せない。Lispの場合はS式でさえあれば良い。シンボルをただ並べたリストでも良い。

制限が小さい分、Lispマクロの方が強力だといえるだろう。



--

2011年7月4日月曜日

【書評】実用Common Lisp

実用Common Lisp では、人工知能(AI)、コンピュータプログラミング技術、Common Lispを扱っている。原題はParadigms of Artificial Intelligence Programming : Case Studies in Common Lisp。

「第7章 STUDENT:代数の文章題を解く」
代数の文章題を解く。方法は、文章題を代数の数式に変換してそれを解くというもの。自然言語(英語)と数式の翻訳表をプログラムとして持つ。

「第8章 記号計算:簡単化プログラム」
Common Lispの数式処理システムであるMaximaのサブセットを作る。

「第9章 効率性の問題」
高速化の手法の1つとしてコンパイルをとりあげる。宣言的に記述された問題を、マクロを使ってコンパイル時にLispコードに変換する。

こういうのを「知能」だと見なしていた時代があったんだなぁ。

Lispは人工知能の分野で使われるというが、その理由が腹落ちした。この本によると、解き方が不明な問題に対するアプローチとしては、問題をそのまま宣言的に記述しそれをプログラムコードに変換するプログラムを書くのが適切であるという。そのような問題を扱う代表例がAIだった。そして、宣言的に記述された問題をプログラムコードに変換するのにLisp(のマクロ)が向いていたということだった。

2011年5月30日月曜日

【ドラフト】物理シミュレーションを対象としたDSELについての試み

Abstract


物理シミュレーションを対象としたDSELについての試みを紹介する。このDSELを使うことで、数式に極めて近い形で宣言的に定義を記述するだけで物理シミュレーションのプログラムを書くことができる。

組み込みドメイン固有言語(DSEL)とは


ドメイン固有言語(Domain-Specific Language, DSL)は、特定の問題領域に特化したプログラム言語を提供することでソフトウェア開発の生産性を向上させるものである。DSLは問題領域に適した抽象レベルでの記述を可能にするため、コード量の低減やそれに伴うメンテナンス性の向上といったメリットがある一方、新しく言語を作ること自体が高コストであるという問題がある。

その問題に対する解として、組み込みドメイン固有言語(Domain-Specific Embedded Language, DSEL)は、既存の汎用言語に組み込む形でドメイン固有言語を実装するものである。このアプローチによって、ホスト言語のライブラリやコンパイラ、デバッガ、プロファイラを再利用できるというメリットが得られる。

DSELについては、以下の文献がある。
・Building domain-specific embedded languages
・Huddakの、Haskore music notation
・conal elliot, Functional Image
・金融契約
・Haskell School of Expression

ここでは、物理シミュレーションを対象としたDSELについての試みを紹介する。ホスト言語にはDSELを作るのに向いているという理由でHaskellを選んでいる。

物理シミュレーションを対象としたDSEL


まず具体的な例を挙げよう。簡単な例として、質点の自由落下のシミュレーションを考えてみる。

自由落下を数式で表現すると以下のようになる。

... 数式 ...

提案するDSELを使うことで、質点の位置の時間過程を出力するプログラムを以下のように記述できる。(これは、そのまま実行可能なコードである)

import Process                -- DSELを定義したモジュール

main = print $ take 10 $ process x
                              -- 10ステップ分の位置を表示

x = x0 +: integral' (v * dt)  -- 質点の位置
v = v0 +: integral (a * dt)   -- 質点の速度
a = g                         -- 質点の加速度

x0 = 10.0                     -- 質点の初期位置
v0 = 0                        -- 質点の初期速度
dt = constant 0.01            -- 時間刻み
g  = constant (-9.8)          -- 重力加速度

これだけである。このコードをコンパイルして実行すると、10タイムステップ分の質点の位置が出力される。質点の位置、速度、加速度について、数式そのままの定義を宣言的に記述するだけであることに注目されたい。計算順序について考慮する必要はない。つまり、定義さえ記述すれば「実装」はもはや不要なのである。

もしこれをDSELを使わずにそのまま書くと、「aからvを計算し、vからxを計算する。それをタイムステップごとに繰り返す」という実装を自分で書くことになるだろう。ごく普通の、シミュレーションのプログラムの流れである。

DSELの設計


...DSELの設計について

DSELの実装


...DSELの実装について

DSELの適用可能条件


DSELの課題


・計算効率
 ・持ち上げられているため、コンパイラの最適化が効かない
  →メタプログラミングによるコンパイル時最適化 or コードジェネレータ
・スペースリーク
 ・condAを使うとスペースリークする

DSEL、現状での利用可能範囲


・配列まるごとをProcessの対象とする。そのなかの要素1つ1つは特定のタイムステップについて明示的に記述
 →上記の2つの問題は生じない
 →ただし、フルにDSELで書くことができず、DSELとpure Haskellのハイブリッドでの記述となる
  ・配列まるごと→DSELの世界での記述
  ・配列内の要素1つ1つについて→あるタイムステップについて明示的にpure Haskellの世界に下ろして記述

2011年4月26日火曜日

【まとめ】Haskellでの正格評価とWHNF


Haskellは遅延評価を特徴とする言語ですが、seq関数や!パターンを使うことで正格評価をさせることもできます。

ただし、最終的な値まで完全に評価(deepseq)されるわけではなく、WHNF(Week Head Normal Form)に簡約されるまでの評価です。

WHNFとは、簡単にいうと、以下のいずれかの形をもつ式です。
  • プリミティブである
  • 式の一番左にデータコンストラクタがある
  • 式の一番左にλがある
正格評価を使ったときにコードの挙動がどう変わるのか、具体的には以下のようになります。

ケース1(遅延評価)

$ cat case1.hs
loop 0 i = i
loop n i = loop (n-1) (i+1)

n = 100000000

main = let x = loop n 0
       in putStrLn "1"
$ ghc --make -O case1.hs
$ time ./case1
1

real    0m0.008s
user    0m0.001s
sys     0m0.003s
遅延評価の場合、let式の中のxは評価されません。評価されるのは文字の出力のみのため、実行時間はごくわずかです。

ケース2(xを正格評価)

$ cat case2.hs 
loop 0 i = i
loop n i = loop (n-1) (i+1)

n = 100000000

main = let !x = loop n 0
       in putStrLn "1"
$ ghc --make -O -XBangPatterns case2.hs
$ time ./case2
1

real    0m3.470s
user    0m1.873s
sys     0m0.032s
xに正格フラグ(!)を付けて正格評価にします。xは実際には使われませんが、評価はされるため、その分実行時間が長くなっています。

ケース3(代数データ型を使い、遅延評価)

$ cat case3.hs
data X = X Int

loop 0 i = i
loop n i = loop (n-1) (i+1)

n = 100000000

main = let x = X $ loop n 0
       in putStrLn "1"
$ ghc --make -O case3.hs
$ time ./case3
1

real    0m0.006s
user    0m0.001s
sys     0m0.003s
ケース1と同様に遅延評価ですが、loop関数の結果をデータコンストラクタXに適用してからxに束縛しています。ケース1と同様、xは評価されません。評価されるのは文字の出力のみのため、実行時間はごくわずかです。

ケース4(代数データ型を使い、正格評価)

$ cat case4.hs
data X = X Int

loop 0 i = i
loop n i = loop (n-1) (i+1)

n = 100000000

main = let !x = X $ loop n 0
       in putStrLn "1"
$ ghc --make -O -XBangPatterns case4.hs
$ time ./case4
1

real    0m0.006s
user    0m0.001s
sys     0m0.002s
ケース2と同様に、xに正格フラグ(!)を付けて正格評価にします。注目するのは、ケース2と異なり実行時間がほとんどかかっていない点です。

評価されるのはWHNFまでであるため、xにはデータコンストラクタについての関数適用がサンクとして束縛され、それ以上の評価はされません。そのため、loop関数は評価されていないのです。

もう1つ、ケースを追加してみましょう。

ケース5(代数データ型のフィールドを正格評価にする)

$ cat case5.hs 
data X = X !Int

loop 0 i = i
loop n i = loop (n-1) (i+1)

n = 100000000

main = let !x = X $ loop n 0
       in putStrLn "1"
$ ghc --make -O -XBangPatterns case5.hs
$ time ./case5
1

real    0m1.788s
user    0m0.997s
sys     0m0.020s
ケース4に加えて、型Xのフィールドに正格フラグを付けます。今度は、型Xのフィールドも評価されるため、実行時間が長くなっています。


以上のように、Haskellで正格評価を使う場合には、評価されるのがWHNFまでである点に注意が必要です。

ちなみに、WHNFまででなく完全に評価したい場合には、Control.Strategies.DeepSeqライブラリというものがあるので、そちらを検討してみると良いでしょう。

--

2011年3月3日木曜日

iPad2について検討


iPad2について。

重さをみてみると、600gある。iPad1とあんまり変わってない。

Kindleが、小さい方で240g、DXでも540gだから、iPadは重たいな。

2万円程度で、防水で、重くなくて、7インチくらいのウェブブラウジング端末なら買うのに。残念。

--

2010年12月27日月曜日

【まとめ】CG、シミュレーション関係の論文



CG、シミュレーション関係の論文を整理したので、一部をここに書いておく。


流体シミュレーション


Fluid Flow for the Rest of Us: Tutorial of the Marker and Cell Method in Computer Graphics - David Cline, David Cardon and Parris K. Egbert
→マーカー&セル法のチュートリアル

Smoothed Particles: A new paradigm for animating highly deformable bodies - Mathieu Desbrun, Marie-Paule Gascuel
→SPHを変形体のシミュレーションに応用

Particle-Based Fluid Simulation for Interactive Application - Matthias Muller, David Charypar and Markus Gross
→SPHを使った流体のシミュレーション。インタラクティブに動作することを目指す。

Smoothed Particle Hydrodynamics - J. J. Monaghan
→SPHの元祖。もともとは宇宙物理シミュレーションのための手法。

Lagrangian finit element analytics of newtonian fluid flows - R. Radovitzky and M. Ortiz
→ラグランジュアン有限要素法によって、巻き波のシミュレーションを実施

Animation and Rendering of Complex Water Surfaces - Douglas Enright, Stephen Marschner and Ronald Fedkiw
→複雑な流体表面のアニメーションについて、表面構築の新しい方法を示している

Two-way Coupled SPH and Particle Level Set Fluid Simulation - Frank Losasso, Jerry O. Talton, Nipun Kwatra and Ron Fedkiw
→SPHとレベルセット法を組み合わせた流体シミュレーション

自由表面の構築


Marching cubes: A high resolution 3D surface construction algorithm - William E. Lorensen and Harwey E. Cline
→マーチングキューブによる、表面の構築

Particle Splatting: Interactive Rendering of Particle-Based Simulation Data - Bart Adams, Toon Lenaerts and Philip Dutre
→粒子ベースシミュレーションのための表面構築の方法


■流体シミュレーションに関するエントリ
粒子法のプログラム第1回(概要)
粒子法のプログラム第2回(プログラムの大枠)
粒子法のプログラム第3回(データ構造)
粒子法のプログラム第4回(密度と圧力の計算)
粒子法のプログラム第5回(力の計算)
粒子法のプログラム第6回(境界条件と粒子位置の更新)
粒子法のプログラム最終回(粒子の出力)
【粒子法】粒子を流体としてレンダリング
3次元の粒子法シミュレーション
粒子法のシーンを2倍のサイズにしてみたが…
粒子法のシーンを2倍のサイズにしてみた
SPHによる巻き波のシミュレーション2
Haskell、OCamlでSPH法
このあとやりたいこと
カメラ位置を変えて流体をレンダリング
固液連成シミュレーション


■剛体シミュレーションに関するエントリ
粒子ベース剛体シミュレーション(プレビュー)
粒子ベース多体衝突シミュレーション
引き続き、粒子ベース剛体シミュレーション

--

2010年12月26日日曜日

【OCaml】スタンフォードバニーの読み込みライブラリ


スタンフォードバニーの読み込みライブラリを書きました。言語はOCamlです。

※.plyファイル全般には対応していない簡易版です

●実装ファイルとシグニチャ
PlyReader.ml
PlyReader.mli

●使用方法
使う関数は、以下の1つだけです。
PlyReader.read_ply : string -> vertex array * face array

読み込む.plyファイルを渡すと、頂点情報が入った配列と面情報が入った配列をタプルにして返します。



■流体シミュレーションに関するエントリ
粒子法のプログラム第1回(概要)
粒子法のプログラム第2回(プログラムの大枠)
粒子法のプログラム第3回(データ構造)
粒子法のプログラム第4回(密度と圧力の計算)
粒子法のプログラム第5回(力の計算)
粒子法のプログラム第6回(境界条件と粒子位置の更新)
粒子法のプログラム最終回(粒子の出力)
【粒子法】粒子を流体としてレンダリング
3次元の粒子法シミュレーション
粒子法のシーンを2倍のサイズにしてみたが…
粒子法のシーンを2倍のサイズにしてみた
SPHによる巻き波のシミュレーション2
Haskell、OCamlでSPH法
このあとやりたいこと
カメラ位置を変えて流体をレンダリング
固液連成シミュレーション


■剛体シミュレーションに関するエントリ
粒子ベース剛体シミュレーション(プレビュー)
粒子ベース多体衝突シミュレーション
引き続き、粒子ベース剛体シミュレーション

--

2010年11月22日月曜日

【Emacs】タブを使わずに空白のみでインデントするには


Emacsで、タブを使わずに空白のみでインデントするには、.emacsに以下を追記します。
(setq-default tab-width 4 indent-tabs-mode nil)

--

CommonLispの処理系SBCLで、コマンドラインからLispコードを実行するには


SBCLでコマンドラインからLispコードを実行するには、--scriptオプションを使って以下のようにします。
$ sbcl --script hello.lisp
同じようにして、コンパイルしたコードも実行できます。
$ sbcl --script hello.fasl

--

2010年11月15日月曜日

GnuTLSの使い方(第2回)

前回のエントリでは、「GnuTLSの使い方(第1回)」として、GnuTLSを使って、HTTPSでWebサーバに接続してHTMLを取得しようとしましたが、handshakeに失敗して通信できませんでした。

失敗の原因がどうもよく分かりません。APIの使い方の問題ではなさそうなものの、サーバの環境によるものか、GnuTLSを使う上で何か忘れているものがあるのか。

そこで、いったんGnuTLSの代わりに、OpenSSLを試してみることにしました。

「OpenSSL sample」で検索すると、
An Introduction to OpenSSL Programming(Part I)[PDF]
というちょうどいいドキュメントがひっかかるので、これを参考にします。

このドキュメントにはサンプルコードが用意されており、まずはこのサンプルを動かしてみます。

http://www.rtfm.com/openssl-examples/

まず、OpenSSLをインストールします。
手元の環境はMaxOS Xなので、MacPortを使います。
$ port install OpenSSL
次に、サンプルをビルドします。
$ ./configure --with-openssl=/opt/local/
$ make
MacPortを使ってOpenSSLをインストールしたため、そのインストール場所を--with-opensslオプションによって指定しています。

問題なくビルドができれば、SSLを通してウェブサーバからHTMLを取得してみます。
$ ./wclient -h twitter.com -p 443 -i
今度は、GnuTLSを使った場合と違い、すんなりとHTMLを取得できました。

GnuTLSを使ったときにhandshakeに失敗するのはなぜだろう?

とはいえ、これでSSL通信をする方法はわかったので、もともとのきっかけだった、HaskellからのSMTP over SSL/TLSを実装できそうです。

■関連するエントリ
GnuTLSの使い方(第1回)

--

2010年10月26日火曜日

GnuTLSの使い方(第1回)

GnuTLSとは


GnuTLSはSSL/TLSプロトコルのフリーな実装です。

SSL/TLSプロトコルの実装としてはOpenSSLが有名ですが、OpenSSLのライセンスはGPLに対し非互換のため、GPLの下にあるソフトウェアはOpenSSLを使うことができませんでした。

GnuTLSは、その問題を解決しGNUプロジェクトのアプリケーションでもTLSのようなプロトコルを扱えることを目的として開発されました。

GnuTLSのインストール


MacOSXの場合は、MacPortを使うことで簡単にGnuTLSをインストールできます。
$ port install gnutls
他の環境でもパッケージシステムから同様にインストールできると思います。

GnuTLSのソースコードは、以下のページからダウンロードできます。
http://www.gnu.org/software/gnutls/download.html

GnuTLSを使ったサンプルを試してみる


GnuTLSのドキュメント7.3.1に、HTTPSでサーバに接続してデータを取得するサンプルがあるので、それを試してみました。

sample.c
/* This example code is placed in the public domain. */
 
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <gnutls/gnutls.h>
 
/* A very basic TLS client, with anonymous authentication.
 */
 
#define MAX_BUF 1024
#define MSG "GET / HTTP/1.0\r\n\r\n"
 
extern int tcp_connect (void);
extern void tcp_close (int sd);
 
int
main (void)
{
  int ret, sd, ii;
  gnutls_session_t session;
  char buffer[MAX_BUF + 1];
  gnutls_anon_client_credentials_t anoncred;
  /* Need to enable anonymous KX specifically. */
 
  gnutls_global_init ();
 
  gnutls_anon_allocate_client_credentials (&anoncred);
 
  /* Initialize TLS session 
   */
  gnutls_init (&session, GNUTLS_CLIENT);
 
  /* Use default priorities */
  gnutls_priority_set_direct (session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128",
         NULL);
 
  /* put the anonymous credentials to the current session
   */
  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
 
  /* connect to the peer
   */
  sd = tcp_connect ();
 
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
 
  /* Perform the TLS handshake
   */
  ret = gnutls_handshake (session);
 
  if (ret < 0)
    {
      fprintf (stderr, "*** Handshake failed\n");
      gnutls_perror (ret);
      goto end;
    }
  else
    {
      printf ("- Handshake was completed\n");
    }
 
  gnutls_record_send (session, MSG, strlen (MSG));
 
  ret = gnutls_record_recv (session, buffer, MAX_BUF);
  if (ret == 0)
    {
      printf ("- Peer has closed the TLS connection\n");
      goto end;
    }
  else if (ret < 0)
    {
      fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
      goto end;
    }
 
  printf ("- Received %d bytes: ", ret);
  for (ii = 0; ii < ret; ii++)
    {
      fputc (buffer[ii], stdout);
    }
  fputs ("\n", stdout);
 
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
end:
 
  tcp_close (sd);
 
  gnutls_deinit (session);
 
  gnutls_anon_free_client_credentials (anoncred);
 
  gnutls_global_deinit ();
 
  return 0;
}

このサンプルでは、同ドキュメントの7.3.10に書かれている、TCP接続のためのヘルパー関数を使うため、そのコードも用意します。

helper.c
/* This example code is placed in the public domain. */
 
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
 
#define SA struct sockaddr
 
/* tcp.c */
int tcp_connect (void);
void tcp_close (int sd);
 
/* Connects to the peer and returns a socket
 * descriptor.
 */
extern int
tcp_connect (void)
{
  const char *PORT = "5556";
  const char *SERVER = "127.0.0.1";
  int err, sd;
  struct sockaddr_in sa;
 
  /* connects to server
   */
  sd = socket (AF_INET, SOCK_STREAM, 0);
 
  memset (&sa, '\0', sizeof (sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (atoi (PORT));
  inet_pton (AF_INET, SERVER, &sa.sin_addr);
 
  err = connect (sd, (SA *) & sa, sizeof (sa));
  if (err < 0)
    {
      fprintf (stderr, "Connect error\n");
      exit (1);
    }
 
  return sd;
}
 
/* closes the given socket descriptor.
 */
extern void
tcp_close (int sd)
{
  shutdown (sd, SHUT_RDWR); /* no more receptions */
  close (sd);
}
※IP、ポートは適切に変更してください

ビルドするためにMakefileを用意します。

Makefile
sample: sample.o helper.o
 gcc -o sample sample.o helper.o `pkg-config gnutls --libs`

.c.o:
 gcc -c $< -I/opt/local/include

makeして実行してみると、handshakeに失敗してエラーになります。
$ make
$ ./sample
*** Handshake failed
GNUTLS ERROR: A TLS fatal alert has been received.

handshakeとは何でしょうか?HTTPSの仕組みを調べる必要がありそうです。

--

2010年10月24日日曜日

豪ドル高は危ない?


最近、豪ドル債が人気です。

しかし、豪ドルは今、円以上に米ドルに対して高くなっています。これは、輸出依存型であるオーストラリア経済にとって悪影響を与えないのでしょうか?

答えはNoです。日本と違い、オーストラリアにとって豪ドル高は経済への大きなマイナスにはなりません。

理由はなんでしょう?

2つあります。
  1. 豪ドル安へ誘導する余地があること
  2.  輸出入の内容が良いこと

豪ドルへ誘導する余地があること


オーストラリアは景気が過熱しないように金利を上げて抑えているため、その金利を下げることで豪ドル安へ誘導してコントロールする余地があります。

逆に、日本はもうこれ以上金利をさげることができないところまできているので、コントロール不能になってしまっています。

これが、オーストラリアと日本の違いの1つです。

輸出入の内容が良いこと


日本は5兆円の貿易黒字のため円高のマイナス影響が大きくなってしまいますが、オーストラリアの貿易収支はトントンです。

さらに、日本と違い、材料を輸出して製品を輸入する形になっているため、豪ドル高の場合は材料を売るのが安くなってしまいますがその分製品を買うのも安くすむので、それで相殺されます。そのため、日本ほど自国通貨高によるダメージを受けません。

これが、もう1つの違いです。

いかがでしょうか。

--

2010年10月12日火曜日

さくらインターネットでcronを使うときの注意点


さくらインターネットのレンタルサーバでcronを使おうとしたときにはまったのでメモ。

pythonスクリプトを動かすときには、
/usr/local/bin/python
のようにフルパスでpythonコマンドを指定しなければいけない。

単にpythonとだけ指定してもコマンドが動作しないので注意。