Mandelbrot View
Table of Contents
1 なんすか?これ?
マンデルブロ集合のビュアです。 暇つぶしに作ったものをなんとなく公開してみたという感じです。
2 遊び方
動作確認はWindowsXP SP3と Windows7 SP1 64bit で行いました。W系APIを使用していますのでWindows98 とかでは動かないかも。以下の7zファイルを適当なディレクトリに展開します。
7zファイルを展開して、mandelview.exeを実行するとウインドが開くと思います。 初期画像を計算で求めているので、立ち上がりに少し時間がかかります。
ざっくり操作方法は以下の通り。
- パラメータ類
- 「Zoom:」パラメータ
描画サイズに対する拡大率を指定します。範囲は1.0e-1(0.1倍)〜1.0e+200(なんか大きい数)です。 テキストボックスを直接編集する事もできます。
- 「OX:」,「OY:」パラメータ
マンデルブロ集合の描画中心座標を指定します。値指定する事もできますが、 描画エリアをマウスの左ボタンドラッグすることでも取得できます。マウスで 拡大したい点を指定して、「Zoom:」パラメータで少し拡大する.....を繰り返す感じに なるかと思います。
- 「Use MPFR」チェックボックス
チェックを入れると、多倍長浮動小数点ライブラリのMPFRを使用して計算します。 チェックを入れないと 「Zoom:」パラメータが 1.0e+17倍 を越えたあたりから 描画解像度が低くなります。チェックを入れると更に拡大する事が可能になります。 ただし、計算にものすごく時間がかかるようになります。
- 「CPUs:」パラメータ
計算に使用するCPU数を指定します。最小数は1、最大数はハードウェアに応じて変わります。
- 「MAXcount:」パラメータ
ざっくりマンデルブロ集合の判定閾値です。この値が小さいと本来模様のある所が 黒くなります。もし模様があるハズなのに見当たらなくなったら値を大きくしてみて 下さい。
- 「ColorStep:」,「ColorPhase:」パラメータ
ざっくり色づけのパラメータです。なんか適当にいじって気に入った色になれば ラッキーくらいの感じで。これらのパラメータは計算中でなければ任意のタイミングで 操作する事ができます。
- 「ReCalc」ボタン
「Zoom:」,「OX:」,「OY:」,「Use MPFR」,「MAXcount:」の値に従って再計算します。 再計算が完了すると実行時間(ElapsTime)を示すダイアログが開きます。
- 「Zoom:」パラメータ
- メニュー
- File→New
描画サイズを変更します。縦横それぞれ256〜8192の範囲で指定できます。 変更後は黒で初期化されますので、再描画の為に「ReCalc」ボタンを押す必要があります。
※最大8192の範囲内であってもメモリが確保できずに異常終了する場合があります。
- File→Save
描画した画像をPNG形式のファイルにセーブします。
- File→Exit
mandelviewの実行を終了します。
- Help→Version
バージョンを表示します。
- File→New
かなり雑な説明ですがそんな感じで。
あまり動作確認をしていないので、バグが潜んでいる可能性は多々あります。もしずっこけた場合は 「しょうがないなぁ〜」という寛大な心で許してやってください。
3 既知のバグ
2012/12/23時点で確認されているバグ一覧。
ver | 内容 |
---|---|
001,002 | 通常精度(MPFRを使用しない)の描画を2つ以上のCPUで行ったとき、1.0e+14くらいの拡大率になるとラインによって解像度が荒くなる場合がある(参考)。プログラムはreal型(80bit浮動小数点)で演算するように書かれているのですが、スレッドによって何故かdouble型(64bit浮動小数点)で演算されている場合があるようです。gdcコンパイラのバグのようですが原因は判っていません。 |
4 プログラムソース
D言語(2.0)で書かれています。
Windows API プロジェクトのWinAPIバインディングを少し手を入れて利用させていただいています。 D言語はコンパイラバージョンが変わると、すぐにコンパイルが通らなくなりますので、 現時点でコンパイルできるセットをwin32-r391c.tar.xzとして勝手に固めさせてもらいました。 そんな訳で、Windowsでしか動きません(^^;
zlib, libpng, libjpeg を、MinGW用に野良ビルドしたものをスタティックリンク しています。また、多倍長浮動小数点を扱う為に、 GMP, MPFR もMinGW用に野良ビルドしています。 GMPをD言語で簡単に使う為のバインディングを dsource.orgのtrunk よりゲットして、具合の悪い点があったのを直して使用しています。
コンパイラは2012/12時点でgithubでメンテされている GDC を使用しました。 ただし、メインラインのtrunkはMinGW向けにビルドできません。 このため、MinGW向けに venix1さんがforkしているDMD2.060対応されたバージョンに少し手を入れて 使用しています(ビルドの参考)。
$ gdc -v Using built-in specs. COLLECT_GCC=C:\MinGW\gdc031_2060_463\bin\gdc.exe COLLECT_LTO_WRAPPER=c:/mingw/gdc031_2060_463/bin/../libexec/gcc/mingw32/4.6.3/lto-wrapper.exe Target: mingw32 Configured with: ../gcc-4.6.3/configure --build=mingw32 --with-arch=i686 --enable-languages=c,d --prefix=/mingw/gdc031_2060_463 --enable-threads --enable-fully-dynamic-string --enable-libstdcxx-debug --enable-version-specific-runtime-libs --disable-nls --disable-win32-registry --disable-symvers --disable-werror --enable-sjlj-exceptions --with-bugurl=https://bitbucket.org/goshawk/gdc/issue --disable-bootstrap --disable-shared --disable-libgomp --disable-libmudflap Thread model: win32 gcc version 4.6.3 (GCC)
ビルド方法は以下の通り。~/download/ の下にtar.xzアーカイブをダウンロードしたとします。 作業ディレクトリは適当な場所だとします。
xz -dc ~/download/mandelview_v002_src.tar.xz | tar xvf -
cd mandelview_v002_src
xz -dc ~/download/win32-r391c.tar.xz | tar xvf -
./mk.sh -a
どちらかと言うとコンパイル環境を整えるのにかなり手間がかかりますが、それをいとわないという方 ならば適当に改造するなどして遊んでみてください。
5 制作メモ
マンデルブロ集合ってどうやって描くんだっけ?と調べ始めたのが作るきっかけでした。 最初はD言語の複素数型を使って、ソースコードの見た目が簡単に書けるなぁくらいで終わるつもり でした。しかし、調子に乗って拡大していると浮動小数点数の解像度限界に直ぐに 達してしまい、それじゃつまらんなぁという事でGMP/MPFRについて調べて使って 色々ハマってどうにか組み込んでみました(^^;; GMP/MPFRはgdcをソースからビルドする のに必要な外付けライブラリなのですが意識して使った事はありませんでした。世の中では こんな巨大な数を扱う事は殆ど無いのかも知れませんが、簡単に扱えて(しかも非常に高速らしい) 便利だなぁと思いました。
実は、v000ではMPFRは使用されてませんでした(^^; それはTANEがGMP内のMPFとMPFRの 区別が付いてなくて、MPFをMPFRと勘違いしていた為です(^^;;;;; v001ではちゃんとMPFRを 使用していますm(_ _)m
こんな簡単な式にあんな模様が仕込まれているなんて不思議だなぁ くらいの数学レベルの人 なので、難しい説明はできません(^^; が、拡大しても拡大しても模様が出てくる様は 無限に広がり続ける宇宙を連想させてくれます。
マンデルブロ集合 は フラクタル の 一つなのですが、フラクタルという幾何学の概念を導入したのが ブノワ・マンデルブロ です。2010年10月14に亡くなったそうで、 Web検索してみると、その頃に追悼の意味でマンデルブロ集合を描くプログラムを色んな人が 作った痕跡が見られました。
一つのピクセルを計算する材料は複素平面上の座標だけです。また、あるピクセルを 求めるのに他のピクセルの結果は必要ありません。この為、マルチコアCPUやGPGPUを 使えば、リニアに高速化できます。そんな訳でPCを新調したのでv001で マルチコアCPU対応してみました。D言語ではstd.parallelismというライブラリを使用すれば簡単に ループをマルチスレッド化できます。ただ、GMP/MPFRを使用した時に クラッシュするバグの原因がなかなか分からなくてリリースできずじまいでした。 でも偶然原因判明して修正できたのでリリースしてみたという次第です。一番面白い 改造要素を取ってしまって申し訳無いm(_ _)m