2007-05-26

高部真規子裁判長のおかげで、日本国内においてネットワークストレージが違法と相成りました

http://headlines.yahoo.co.jp/hl?a=20070525-00000119-mai-soci

これはどんなサービスかというと、ユーザが、自分の持っているCDを、MYUTAの提供するサーバにアップロードでき、そのユーザの携帯電話に落とすことができるというものだ。記事やプレスリリースを見る限り、ユーザ個人だけで完結するサービスのようで、他のユーザの音楽を落とせるサービスではないようだ。

東京地裁の「高部真規子」裁判長がだした判決のようだ。こんなもので訴えるJASRACもJASRACだが、判決を出す高部真規子も高部真規子だ。もはやこれはJASRACがどうとかいう問題を通り越してあきれてしまう。なんという裁判長。

これはすばらしい。日本国内では、ネットストレージサービスが違法になってしまった。この解釈で行くと、Webサーバ、POP3サーバなどのレンタルは違法になってしまうだろう。

なんという判決だろう。これはまずい。

 しかし、ぐぐってみたところ、この高部真規子という人間、恐ろしくトンデモ判決を多数出しているようだ。  あの有名な、松下がヘルプの機能で一太郎を訴えた裁判も、この高部真規子が出したらしい。  裁判官ってどうやって罷免させられるのだろう。

2007-05-19

FLV file structure

 最近、ニコニコ動画にハマっているのだが、FLVファイルの構造について知りたくなったので、調べていた。いくつか参考になりそうな情報が見つかった。 まず、ファイルの構造については、大まかにhttp://www.osflash.org/flvで情報がある。  直接のコードで読めて、参考になりそうなソースは、まずFLV Extractだ。これは、C#のコードだ。C#にはなじみがないのだが、かなりC++に似ている、というよりも、そのままだ。FLV Extractについては、単純なGUIとファイルアクセスなので、これをC++に移植することは、優しいことだろう。詳細な構造についてのソースコードが見たければ、ffmpegのコードを参考になりそうだ。  で、何がしたいかというと、どこの馬の骨かもわからないあのツールでマージするのではなく、自前でFLVのマージツールを作ってみようかと。

2007-05-17

how to change console's font?

 old new thingは実に役に立つ。たまたまコンソールについて悩んでいたら、ちょうどいいタイミングで、コンソールのフォントについて解説してくれた。 http://blogs.msdn.com/oldnewthing/archive/2007/05/16/2659903.aspx  なるほど、フォントの仕組みについてはよく知らなかったのだが、はみ出す文字というのがあるのか。  それにしても、ABCなんて名前の構造体を定義しているPSDKもどうかとおもう。もちろん、そんな名前が実際に使われることは、まずないだろうとしても。  一応、スーパーギークのために、フォントを変える方法はある。http://support.microsoft.com/kb/247815 HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Console\TrueTypeFont 下に、00という名前の文字列を付け加えて、値をフォントフェイスにすればよい。複数のフォントを付け加えたい場合は、000, 0000,などというように、レジストリエントリの名前に、0を付け加えていく。

2007-05-13

一度生を受け、滅せぬ物のあるべきか

思へば、此世は常の住処にあらず。草葉に置く白露、水に宿る月より猶あやし。金谷に花を詠じ、栄花は先立て、無常の風に誘はるゝ。南楼の月をもてあそぶ輩も、月に先立つて、有為の雲に隠れり。人間五十年、化天の内を比ぶれば、夢幻のごとくなり。一度生を受け、滅せぬ物のあるべきか。これを菩提の種と思ひ定めざらんは、口惜しかりき次第ぞ

有名なところを超口語訳

つーか、人間ってせいぜい50年しか生きられねーよ。最下層の天使でさえも、八百年ぐらいはいきるっつーのによぅ。生まれたらそりゃ当然死ぬんだよ。これが定めか。なんつーこった

幸若舞『敦盛』(全文)
http://www.ikedakai.com/atsumori.html

2007-05-12

動画サイトの未来

ひろゆき氏、「ニコニコ」ヒットでも「動画は“来て”ない」

http://www.itmedia.co.jp/news/articles/0705/11/news117.html

まあ、PV数だけは無駄に稼いでいるが、大赤字だろう。トラフィックが膨大だからといって、広告料も上げてくれるわけではない。それもあるのだが、日本の動画の特徴が気になるところだ。ほとんどがアニメである。確かに、アニメといえば日本なのだが、それは所詮、作られたコンテンツである。自分で動画を作ってあげようという人が、あまりにも少ない。たとえば、YouTubeで最も人気の高い動画は何かというと。

つまり、個人が作った動画というのがほとんどない。たとえば有名なUnreal Gamer(キーボードクラッシャー)の動画は、狙って作られたものである。この少年が、別の動画でなにやら話しているものも、アップロードされている。こちらは普通に話しているだけなので、あまり人気はないが。

これは、誰でも作れるのだ。しかし、日本人はこういう動画を作ろうとしない。既存のアニメをいかに画質良くエンコードしてニコニコに上げるかにはこだわっても、自前でいかに面白い動画を作るかについては、まったく考慮しない。まあ、かく偉そうなことをいうからには、自分で作って見なければならない。そんなわけで一連の動画をここにリンクしておく。

http://www.nicovideo.jp/search/hito

2007-05-09

how do i use mencoder for two pass encoding

 さて、2パスエンコードを説明する。これまでのmencoderにはバグがあり、VP62の2パスエンコードがうまくいかなかった。.sstファイルが正常に出力されないのが原因である。これが、2chの有志により、直されたので、2パスエンコードができるようになった。ちなみに、CBRだと、バグがあってもできてしまったりする。公式にパッチは上げてくれるのだろうか。  それにしても、やはり、2パスはすばらしい。動き始めのブロックノイズが激減する。いままで2パスを敬遠してきたのは、mencoderだけで完結する方法がなかったからだ。
echo オーディオのビットレートを指定(kbps) 例:64 set Audiobitrate=64 REM ビデオフォーマット設定(出力拡張子で自動的に確定) set FORMAT=-of lavf set FOPT=-lavfopts i_certify_that_my_video_stream_does_not_use_b_frames REM 一応入力側の名前に合わせてみる set OUTPUT=-o "%~n1.flv" set INPUT="%~1" REM ビデオコーデック設定 set VCODEC=-ovc vfw REM 音声コーデック設定 set ACODEC=-oac mp3lame set ACOPT=-lameopts abr:br=%Audiobitrate% -af resample=44100 REM その他フィルタオプション(現状は上下反転+LanczosResize512x384)-ffourcc VP6F set EXTOPT=-vf flip,scale=512:384 -sws 9 REM 2pass用 set VCOPT=-xvfwopts codec=codecs\vp6vfw.dll:compdata=firstpass.mcf mencoder %FORMAT% %FOPT% %VCODEC% %VCOPT% %ACODEC% %ACOPT% %EXTOPT% %OUTPUT% %INPUT% set VCOPT=-xvfwopts codec=codecs\vp6vfw.dll:compdata=secondpass.mcf mencoder %FORMAT% %FOPT% %VCODEC% %VCOPT% %ACODEC% %ACOPT% %EXTOPT% %OUTPUT% %INPUT% あとは各自試行錯誤でもしてくれってことで。
 これが、2パスに必要なバッチファイルである。例の如く、自分好みに変えてある。さて、とりあえず試したい場合は、コーデックの指定を、vp6vfw.dll:compdata=dialogにすれば良い。設定ダイアログが表示されるので、それぞれ、Two Pass - First Pass, Two Pass - Second Passを選べば良い。しかし、それでは人間が応答しなければならない。私の理想は、無人のまま自働エンコードである。そこで、コーデックの設定を、保存しておく必要がある。これには、.mcfというファイルを生成する必要がある。このバッチファイルに添う形では、firstpass.mcfと、secondpass.mcfである。.mcfファイルはどうやって生成するか。それには、vfw2menc.exeを使う。次のように呼び出せば良い。
vfw2menc -f VP62 -d codecs\vp6vfw.dll -s firstpass.mcf vfw2menc -f VP62 -d codecs\vp6vfw.dll -s secondpass.mcf
それぞれ、1パス目、2パス目を設定する。このようにしておけば、人間が応答することなく2パスエンコードができる。

what niconico wiki's mencoder batch file doing?

前回、mplayerとmencoderについての概要を説明した。今回は、ニコニコ動画のまとめWikiにある、mencoderのバッチファイルが何をしているかを説明してみる。なお、今回は、mencoderのドキュメントを参照しつつ、読んで欲しい。 http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html

echo オーディオのビットレートを指定(kbps) 例:64 set /p ABITRATE=AudioBitrate: set Audiobitrate=%ABITRATE% REM ビデオフォーマット設定(出力拡張子で自動的に確定) set FORMAT=-of lavf set FOPT=-lavfopts i_certify_that_my_video_stream_does_not_use_b_frames REM 一応入力側の名前に合わせてみる set OUTPUT=-o "%~n1.flv" set INPUT="%~1" REM ビデオコーデック設定 set VCODEC=-ovc vfw set VCOPT=-xvfwopts codec=codecs\vp6vfw.dll:compdata=dialog REM 音声コーデック設定 set ACODEC=-oac mp3lame set ACOPT=-lameopts abr:br=%Audiobitrate% -afresample=44100 REM その他フィルタオプション(現状は上下反転+LanczosResize512x384)-ffourcc VP6F set EXTOPT=-vf flip,scale=512:384 -sws 9 mencoder %FORMAT% %FOPT% %VCODEC% %VCOPT% %ACODEC% %ACOPT%%EXTOPT% %OUTPUT% %INPUT% あとは各自試行錯誤でもしてくれってことで。

これが、FLV4enc_D&D.batの中身である。1パスの、重要な部分だけを抜き出してある。基本的に、最後のmencoderが重要なのだ。このバッチファイルは、FLVにエンコードして、ニコニコにうpするための、最小限のことだけをしている。これを理解して、自分で変更できるようになれば、さらに画質や音質を上げられるだろう。

まず最初のFORMAT変数には、-ofオプションを使い、どのフォーマットで出力するかが指定されている。明示的にflvを指定してもいいのだが、このバッチファイルではそれはしていない。次に、-lavfoptsオプションを使い、出力する動画が、Bフレームを使用していないことを明示している。現在、mencoderではBフレームの出力がサポートされていないからである。 VCODEC変数で、コーデックを指定している、これは、vfw(Video For Windows)を使う。つまり、vp6vfw.dllのことだ。次に続く-xvfwoptsオプションで、読み込むDLLファイルを指定している。また、コーデックの設定ダイアログを開くようにしている。コーデックの設定を自動化する方法があるのだが、それは2パスエンコードのときに説明するつもりだ。

余談だが、mencoderで、とうとう2パスエンコードができるようになったのだ。パッチがいつ、公式のMLに投げられるのか、不明ではあるが、diffは確保したので、いざとなればなんとでもなるだろう。私もUNIX環境のプログラミングを勉強すべきだろうか。

次は音声である。このバッチファイルは、いかなる動画ソースからでも、ニコニコに受け付けられるFLVを作成することを目的としているので、音声はエンコードされる。もし、自前でエンコードした音声がある場合、それを単にコピーすれば、再エンコードされずに、音質がよくなるだろう。FLVコンテナでは、無圧縮PCM、ADPCM、mp3をサポートしている。また、マイクで録音する際に、Nellymoser codecを使用しているようだが、このコーデックの仕様はよく分からない。現在のところ、オープンソースのデコーダーも見当たらない。 mp3へのエンコードは、-oacオプションで、mencoderに組み込まれているmp3lameを利用している。また、FLVコンテナは、 44.1kHz 22.05kHz 11.025kHzのいずれかのサンプリングレートでなければならないようなので、トラブルを防ぐために、-afオプションで、44.1kHzにリサンプルしている。ただし、このリサンプルは、次のEXTOPTで設定されている。ここが個人的に好きではないので、私の自前のバッチファイルでは、変更しているが。

さて、いよいよEXTOPT変数だ。ここにはまず、-vfオプションが指定されている。これは、ビデオフィルタという意味で、文字通りフィルタだ。 まず、flip、これは、VP6のデコーダであるVP6Fが上下反転した出力をするので、workaroundとして入れてある。最初から上下反転したフレームにしておけば、さらに上下反転して、意図通りにデコードされるという寸法だ。しかし、なぜこんなあまのじゃくな仕様なのだろう その次に、動画を512x384にスケーリングする。この解像度でなければ、SIMLEは再エンコードをしてしまうからだ。次に、-swsオプションで、スケーリングのアルゴリズムを設定してる。現在のところ11種類のアルゴリズムが実装されている。9というのは、lanczosアルゴリズムである。非常に品質のいいアルゴリズムとして有名だ。ほとんどの場合はこれでいいのだが、たとえばドット絵、ファミコンやスーパーファミコンなどの動画をエンコードするときは、4のnearest neighborがお勧めかもしれない。もちろん、エンコードする過程でかなり劣化するし、元ソースの画質にも影響されるので、どちらがいいかは、好みの問題ではある。また、先に説明したように、ここで音声リサンプルのための-afオプションが指定されている。 そのあとは、出力と入力のファイルを指定しているだけだ。

PS. やはり、バッチファイルを修正した。-afオプションと、%INPUT%にダブルクオーテーションがついているのを修正した。ダブルクオーテーションは、INPUT変数自体に含めるべき。

what is mplayer and mencoder and why i have to use them?

mplayerと、mencoderについて、説明を試みる。なお、これはニコニコ動画に動画をアップロードすることを前提に書いている。

mplayerとは、恐ろしく高機能な動画プレイヤーである。かなりの数の動画を再生できる。何がすごいのかというと、すべて自前でデコードしていることだ。しかし、もともとはLinux用のプログラムであり、Windowsで使う上では、必ずしも使い勝手や画質がいいとは言いがたい。基本はCUIである。ではなぜ、これがニコニコ動画にアップロードする上で、最適なのか。それは、mencoderの存在である。 mencoderは、mplayerとほぼおなじコマンドラインオプションを持っている。mplayerはプレイヤーであるし、mencoderはエンコーダーだ。 ニコニコ動画には、FLV形式の動画を直接アップロードできる。このとき、600kbpsで40MBの範囲に収まっていれば、再エンコードされずに、そのまま使われる。この制限は、かなり厳しい。

FLVというコンテナには、いくつかの動画形式を格納できるが、その中でも極めて、低ビットレートに置いても画質が優れているのが、On2 TecnologyのVP62だ。H263もそれなりにいいのだが、600kbps以下という厳しい制限では、VP62が圧勝してしまう。

さて、VP62にエンコードするには、ffmpegでエンコードするか、On2 Tecnologyのvfw(Video For Windows)コーデックである。vp6vfw.dllを使うしかない。ffmpegに実装されているエンコーダーはあまりよろしくないので、本家のvp6vfw.dllを使うことになる。mencoderは、それ自体で多数の動画形式へエンコードできるのだが、vfwコーデックを使うことも出来る。そのため、非常に使い勝手がいい。ちなみに、x86 Linuxで、Windowsのdllを使うために、非常に興味深いLoadLibraryの自前実装があるのだが、それはまた別の話。 それだけではない。mencoderは、その辺の安っぽい動画編集ソフトウェアよりも、よほど優れた動画編集能力を持っているのだ。まず、デコード、エンコードできる動画形式が多い。mpeg1/2/4はもちろんのこと、VOBなども問題ないし、ASF/WMA/WMV, QT/MOV/MP4, RealMedia, Matroska, NUT, NuppelVideo, FLI, YUV4MPEG, FILM, RoQ, PVAと、有名どころの形式は、余すところなくサポートしている。ffmepgに感謝すべきか。 また、基本的なフィルタも有しており、上下左右反転や回転はもちろんのこと、スケーリング、アスペクト比変更、ブラックバンドの追加、ノイズ除去、フレームレートの変更(単純な脱落から、フレームの合成まで)、テレシネ、逆テレシネ、シャープ、ブラー、インターレス解除ができる。とくにインターレス解除やスケーリングは、かなり多数のアルゴリズムを使うことが出来る。ロゴの削除なる機能もあるが、これをまともに使うのは難しそうだ。

と、ここまで説明すると、「おいおい、なぜCUIな貧弱ツールでフィルタなど使わなければならないんだ。この俺が使っているクールでイージーでGUIなツールでフィルタをかけたほうがいいじゃないか」と言う人がいるかもしれない。CUIであることの利点は、自分でコードを書いて、簡単にバッチ処理ができたりすることもあるのだが、なによりすばやいことだ。複雑なGUIでは、あるフィルタをかけるためには、メニューからフィルタの適用を選択し、ダイアログから目的のフィルタを選んで、パラメータを指定しなければならなかったりする。mencoderでは、-vfオプションを使うだけで、簡単に指定できる。たとえば、512x384にスケーリングしたければ、

mencoder -vf scale=512:384

とすれば良いし、400x300にスケーリングして、黒帯をいれて中央に表示し、512x384にしたい場合は、

mencoder -vf scale=400:300,expand=512:384

とすればよい。また、インターレスをLinear blendで解除しつつ、512x384にスケーリングするには、

mencoder -vf pp=li,scale=512:384

となる。非常に簡単だ。ちなみに、フィルタは並んでいる順番で適用される。インターレス解除は、一番最初に行っておかないと、泣きを見ることになる。

また、「俺のクールでイージーなGUIツールには、フィルタのプレビュー機能があるぜ」という人もいるかもしれない。この点も問題はない。なぜならば、mplayerとmencoderは一心同体、mencoderのフィルタは、mplayerでも同様に使える。だから、mplayerでリアルタイムにフィルタをかけつつ再生して、効果を確かめることもできる。 とはいっても、最高に高画質を目指す人から見れば、mencoderのフィルタは貧弱かもしれない。しかし、私のように、多数の動画にたいして、ある程度の画質を維持しつつ、寝ている間にエンコードしたいという人間には、最適なのだ。

次回は、ニコニコwikiで配布されている、mencoderを使うバッチファイルが何をしているかについて、解説する。タグ、mencoderで、一覧を見ることができる。

2007-05-08

what do we trust in the TBS

 時刻表示は信頼できるだろう。よほどのことがない限り、誤差はかなり低いと考えられる。  しかし、生放送を数分ずらしてリアルタイム編集しつつ放送とかやりそうだけど。

2007-05-04

プロセス終了時にメモリを解放すべからず

http://blogs.msdn.com/oldnewthing/archive/2007/05/03/2383346.aspx  よく、OSが解放してくれるから、プロセス終了時にはリソース解放などをしなくてもいいという意見に対して、「いや、できる限りすべきだ」という人が居るが、場合によりけりということらしい。いや、別にしてもいいのだけれど、DLL_PROCESS_DETACHの中でやるなということで。  プロセスが終了するとき、Windows XPがどのような処理をするか。ExitProcessが呼ばれたとき、ExitProcessを読んだスレッド以外のすべてのスレッドは、終了される。スレッドが何をしていようがお構いなしだ。つまりは、TerminateThreadに等しいということだ。MSDNではTerminateThreadは使うべきではないとしつこく警告されているが、一体何がまずいのか。実は、TerminateThreadとは、スレッドが何をしていようと、強制的に終了させるのだ。もし、強制終了されるスレッドが、クリティカルセクションに入っていた場合、そのクリティカルセクションはロックされたままになる。これの何がまずいのかというと、スレッド間で排他をとるヒープを使っていて、まさにヒープからメモリを確保、解放するときに終了されると、ヒープがロックされたままになる。  さて、ある「賢い」DLLは、DLL_PROCESS_DETACH通知が送られたときに、確保したリソースを解放しようとする。しかし、そのリソースに排他的にアクセス中のスレッドが強制終了された場合、リソースを解放しようとすると、例外を投げてこける。結果的にプロセスは終了するのだが、なんとも汚い終わり方になってしまう。  そこで、プロセス終了時のDLL_PROCESS_DETACHの中では、何もするな。何も「賢い」ことをするな。ただreturnせよ。リソースの解放はOSにまかせろ。  ただし、動的にDLLがアンロードされる場合は、この限りではない。まだプロセスは動き続けるのだから、リソースを解放しなければ、リソースリークになってしまう。なんともやっかいだ。

Time flies when you're enjoying yourself

 光陰矢のごとしとはよく言ったものだ。実際早い、早すぎる。私とて、もう二十歳なのだ。後せいぜい五十年ないしは六十年ぐらいしか生きられない定めなのだ。しかも50年とは、あくまで生存可能な時間であって、有意義に生きられる時間ではない。最新の技術にいつまでついていけるだろうか。あと20年、いや10年もないかも知れぬ。そう短い時間では、何も極めることができないだろう。  何ということだ。人間はたったの百年足らずしか生きられぬのか。いかに富や名声を得ようとも、歴史教科書の片隅に、「かくかくしかじかなる有名な男がいた」程度の扱いしかされぬのだ。今、各の如く、考え、悩み、先人のしたように、文に綴りてみんとするこの瞬間の思想は、決して伝えられないというのだろうか。

2007-05-03

High Quality Dressed Up Car

 車の免許を取るために、二段階技能で外を走っていたとき、ふと、前の車のリアウインドウにでかでかと張ってある、ステッカーが目に付いた。そこには、High Quality Dressed Up Car(超めかした車)と書いてあった。ああ、自画自賛ここにきわまれり。  あるいは、「大安売り」などと書いてあるTシャツを着ている外人と、似たような感覚なのだろうか。

2007-04-27

Boost 1.34.0 Beta was released

 Boostの1.34.0のベータ版が公開された。 http://lists.boost.org/Archives/boost/2007/04/120375.php  ダウンロードはここから http://sourceforge.net/project/showfiles.php?group_id=7586

車の話

 ようやく仮免を取り、何度か外を走ってみた。なかなか難しい。そういえば、車好きの友人が居たので聞いてみることに。  自分「いやぁ~、青信号で発進するとき、なかなかうまくいかないんだよね。ギアをトップまで持っていくのに10秒以上かかるし、すばやく加速もできない」  友人「は、俺なんかもっとかかるで。後ろからクラクション鳴らされるんやで」  自分「何と、そりゃまたどういうわけで。お前なら速攻で切り替えてさっさと行くものとばかり思っていたが」  友人「あのなぁ、ええか、急に加速したら、ガソリンを食う、タイヤが磨り減る、クラッチが痛む、環境にも悪い。まあ環境はともかく、何でそなことせなあかんねや。周りがいくら迷惑しようとも、俺はのんびりいくで。」  自分「ああ、そういえばお前はそういう奴だった……」  この友人は、現実で車をかっ飛ばすより、ゲーム中でかっ飛ばすのが好きなようだ。何しろ、ゲームではガソリン消費もタイヤの磨り減りも気にしなくていい。そういえば、レーシングゲームは数多くあれど、みなアクセルとブレーキ、ステアリングで操作するものになっている。何故だろう。MT車の方がいいと主張する車好きはたくさんいるし、クラッチ操作のあるゲームがあっても不思議はないのだが。  この疑問を友人にぶつけてみると、面白い答えが返ってきた。まず、ゲームパッドで操作しにくい。クラッチ操作というからには、ちゃんと半クラにしなければならないため、アナログ入力が必要である。しかし、Xbox360やPSのコントローラでは、クラッチを操作するのに必要なトリガーが足りない。左右に日本ついているだけだ。もし3本目のトリガーがあったとしても、一体どの指で操作するというのか。  また、かつてアーケードゲームで、クラッチペダルのあるゲームが存在したらしい。アーケードならば、現実に近いコントローラ、つまり本物のステアリングと、本物のペダルを用意できる。かのクラッチ操作を伴うゲームは、クラッチのアナログ入力や、回転数があっていなければエンストを起こすという本格仕様であったらしい。しかし流行らなかった。どうやら、ゲーマーというのは、そこまで極端に操作性の本物志向を求めないものらしい。そういう本物志向にこだわる人間は、本物の車に乗るものらしい。  ふーむ、そんなものなのかね。何はともかく、今のうちに車の免許は取っておかなければならない。どんな職に就くにせよ、働きながら免許を取るのはかなり面倒だからだ。

2007-04-21

酒を飲んだ話

 長い間バイトをしていた人がやめるというので、飲みに行くことのした。かなり人から好かれる性格をしている人だったので、最終的に15人もの人数になった。しかし、酒を飲んだときの、人の変わり様は極端すぎる。私が常々思っていることは、「京都の人は裏表ありすぎ」だ。酒が入ると、如実に現れる。私もだいぶ飲んで足がふらついていたが、宴会が終わる30分前から酒をやめて、酔いを醒ました。宴会が終わったのは、2時ごろであった。  その後、ある人の知り合いのスナックに行って、カラオケをした。皆まだ酔っているようだ。私はだいぶ醒めてしまった。ところで、私には歌える歌がない。あるにはあるが、マニアックすぎるものばかりだ。  酒は冷めていたが、たまたま入っていた歌が歌いたかったので、入れてみた。.hack//SIGNのObsessionである。案の定、誰も知らずに場がしらけた。おそらくは、私の他に歌える歌、真ゲッターのSTORMなども、しらけるのだろう。ところで、誰か創生のアクエリオンのShangri-Laを歌えるのだろうか。  3時半過ぎにスナックから出た。帰宅に際し、周りはタクシーの相乗りを勧めるが、まだ酒が抜けていそうにない二人と同乗するのは面倒だったので、徒歩にて帰ることのした。家に帰り、シャワーを浴びて就寝。  正午に起床する。かるい頭痛がしたが、いつものことだ。酒を飲んだ次の日は、必ず頭が痛くなる。不思議なことに、睡眠をとった後で痛くなるのだ。寝る前にも酒は抜けていたはずなのだが、どういうことなのだろう。まあ、3時間ぐらいで収まるので、問題はない。  昨日、アマゾンで注文したWindows Internalsの代金の支払いと、明日のひぐらしデイブレイク改のために、銀行から金を下ろしに行く。Windows Internalsは、かのMark Russinovich氏も書いている。これは読まねばならない。もっと早く気づくべきだった。  ついでに、コンビニで紙パックのジュースを買うことにした。そこのコンビニでは、一ヶ月ぐらいセールをやっていて、レモンティーは110円であった。ただし、もうセールが終わっていて、126円に戻っていたのだ。私は、頭痛と、Windows Internalsと、ひぐらしデイブレイク改と、ニコニコ動画に上げるゲーム動画の作成について、思いを巡らせていたので、店員の「126円になります」という声を聞き漏らした。つまり、まだ値段は110円であると思っていたのだ。財布の中の小銭を見ると、果たして500円玉がある。しかし100円玉はない。そこで私は、無意識に510円を出した。無論、100円玉4枚のお釣りをもらうためだ。しかし、実際の代金は126円であるため、これは誤りである。店員は一言も発せず、510円を受け取り、384円のお釣りを返してきた。  何かが間違っている気がする。10円玉の意味がない。

2007-04-16

チラシの裏

 South Parkの1106. D-Yikesだが、金の装身具を身につけた浅黒い人々はPersianだ。South Parkのスクリプトは、ここで見ることができる。  かねてから目をつけていた、ハッピーハッキングキーボードを買ってみた。なかなか使いやすい。今回は英語配列を買った。小さくて場所をとらないのがいい。  しかし、英語配列のキーボードはコードが書きやすい。なんといううらやましいことだ。問題は、日本語が入力しにくい。半角全角キーなどなく、IMEを有効にするには、歴史的なAlt+`を押し下げなければならない。しかし、一度に複数のキーボードを使うときは、キーボードごとに違ったレイアウトを使いたいものだ。何とかならないものか。  キャプチャデバイスについて一言、USBのものを買う場合、USBバスパワーだけで動作するものはお勧めしない。とくに、私が買ったものは酷かった。まず、ドライバが署名されていない。これだけでも酷いというのに、付属のソフトウェアも酷い。バッテリーで動作しているときは、キャプチャするときに確認を求めてくるのはいいのだが、何が酷いかといって、PCをスタンバイする際に、「PCがスタンバイされるが、よろしいか?」というダイアログを出す。もちろん、スタンバイを一時停止させてだ。これはひどい。普通のラップトップにとって、スタンバイするというのは、閉じた場合なのだ。すでに閉じているので、ダイアログが出ていることなど分かるわけもない。とうぜん、スタンバイはされず、バッテリーを消費しつくす。本当に腐ったソフトウェアだ。Vistaでは、もはやこのようなくだらないソフトウェアをわざわざ待ったりはしない。プログラムはスタンバイ通知から2秒間の猶予を与えられるのみである。OSは有無を言わさずスタンバイに取り掛かる。

2007-04-12

feed pigeons

 昨日、川辺でクラッカーを食べていたら、鳩がいたので、クラッカーを与えてみた。いったいどこにいたのか、見る間に数十羽も集まってきた。これには驚いた。そして、たまたまそこを通りがかった、散歩中の犬とも触れ合ってきた。なかなか癒された。

2007-04-06

定額定額定額

パケット定額です ただしPCのモデムとして使用した場合を除く  実際のカタログなどでは、もっとひどい記述になっている。モデムと書いてくれれば分かりやすいのに。「PCにケーブル接続して通信モードによってパケット通信をした場合は云々」などと、独自用語をふんだんに使って、実に分かりにくく解説している。しかも読むのにルーペが必要になるほど細かい字で書いてある。これを読んで理解するには、携帯をモデムとして使う際の説明を捜すという意図を持って、エスパー能力を駆使しつつ読み解かなければならない。  3年前から、各社ともこんな感じだ。はっきりいって、携帯は低機能過ぎる。まったく欲しいと思わない。PHSならば、少しは欲しいが。

2007-04-02

niconico video

 カノンをBGMにトレス疑惑の画像がいくつか流れたとおもったら、いきなりロック超になり、さまざまな似ている画像が表示される動画。これは笑わずにはいられない。それにしても、荒木先生と土方が似ていたとは。

2007-03-28

ネオジム磁石のブレスレット

先日紹介した、ネオジム磁石のブレスレットが、やっと届いた。さっそく装備する。

そういえば、昔は防具屋の近くに意味ありげなオヤジがいて、「ぼうぐは そうびしないと いみが ないぞ」などと教えてくれたものだ。近頃、こういう親切な人が耐えて久しい。

さて、今日はクエストがある。トム爺さんを押すのではなく、三流ホテルの皿洗いのクエストだ。さっそくいくと、パーティメンバーの、職業おばはんの人から、次のように言われた。

おばはん曰く、「へぇ~それ強い磁石なんだ。もぅ~すごい波動が出てるんじゃない」
我、答えて曰く、「科学の名において、有神論者に災いあれ」

まあ、つづめて言うと、ネオジム磁石の面白いブレスレットを身に付けてバイトに行くと、磁石が健康にいいと信じているおばはんが、波動がでていると宣ったわけだ。

一体波動とはなんだろうか。確かに間違いではない。電磁波(もちろん可視光も含む)を、一般に波動というのだろうが、このおばはんの口にする波動という言葉は、どこかオカルトじみていた。このおばはんは、本当にこの手の似非科学がすきなのだ。サプリメント愛用者であり、バイト中の水分補給に酸素水を愛飲している。サプリメントなんて、緊急に何かを摂取しないといけないときぐらいしか使う必要がないし、酸素水は愚の骨頂、そもそも酸素は水にほとんど溶けないのだ。ペットボトル一本飲み干しても、一呼吸分の酸素に相当するかどうかも怪しいものだ。第一、水に溶けた酸素をどうやって吸収するというのか? 我々は、何十平方メートルもある肺胞で酸素を取り入れるのだ。この面積はどうしても必要なのだ。皮膚呼吸などというものが、いかに馬鹿げているか分かるだろう。

本当に、「水商売」は昔からなくならない。

そして、磁石の健康への影響も、統計的には、存在しないと結論できる。しかし、何故人はこの手の似非科学に惹かれるのだろうか。

2007-03-27

what's wrong with Trackback

トラックバックという機能を知ったときは、面白いとは思ったが、さほど興味を抱かなかった。なにしろ私には、「どうぞ私にスパムを送りつけてください」と宣言しているように感じられたからだ。

こちらへリンクを自動的に貼ってもらうという仕組みは、当然スパムに利用されるに決まっている。案の定、もはやトラックバックはスパムだらけである。このスパムに対して、各社とも知恵を絞っている。単純な単語やIPなどのフィルタから、トラックバック元に、こちらへのリンクがなければ無効にするという機能、あるいは、同一のリモートホストから、自社のブログサービスへ、一度に大量のトラックバックが送られた場合、スパムとみなすなどである。これらの努力はすばらしいが、しかし、そこまでしてトラックバックを使いたいものかと疑問になる。

ところで、bloggerには、バックリンクという仕組みがある。これは、自分へリンクしている所へ、こちらからリンクをはる機能だ。そもそもトラックバックは、Movable Typeが始めたもので、ある記事にたいするリンクである。自分の記事にリンクしているサイトは、明らかに関連のある事柄を扱っているに違いない。では、こちらからもリンクしてやろうというわけだ。この仕組みは、なかなか面白い。このバックリンクへスパムを使用とするならば、Googleにクロールされる形で、スパム先へのリンクを提供し続けなければならないからだ。

とはいっても、バックリンクを提供できるのは、大手検索サイトぐらいなものだろう。特にGoogleだ。

2007-03-25

リアル砂の女(主人公は女)

http://www.h-keizai.com/article-2007-02/p078-kokuhaku.html 各種募集など http://ninaite.or.jp/osirase/061003_nikkapu.htm http://www.obira.on.arena.ne.jp/nougyou-iinkai/n-taiken/nougyou-taiken.html http://www.koukeisya-niikappu.jp/YOURYOU.htm http://www.ja-enyu.com/sub/sub05/sub05_2.htm http://www.ja-shinshinotsu.jp/taikensha/taikensha_2.htm http://ninaite.or.jp/osirase/060815_syari.htm http://www.ja-shari.or.jp/taisaku/INFO/info.htm  条件として目立つのが、「独身女性」だ。また、男女募集となっていても、選考段階で、「残念ながら」、男がはじかれるようになっている。まさか、阿部公房の砂の女が、この時代においても、リアルに存在するとは思わなかった。真実は小説より奇なりや?

2007-03-24

いい加減にしろ、黄昏フロンティア

http://www.tasofro.net/cgi-bin/cbbsD/cbbs.cgi?mode=al2&namber=1993&rev=0&no=0  >正式に対応を保障しているOSはWindowsXPと2000のみになります。  嘘をつけ嘘を。  対応しているのではなく、たまたま動いているように見えるだけだ。特に、最初は、デバッガでアタッチして起動させただけで例外を投げるという、すばらしいコードだったではないか。いまでも、Vistaの互換性検証ツールで起動させることすらできない。

2007-03-22

I don't like Automatic Transmission.

 AT車をはじめて動かしてみたが、どうも好きになれない。車の免許を取る前は、「もはやAT車全盛の世の中なのだから、MTなど一部の物好きに供されるものだ」と考えていたのだが、どういう風の吹き回しだろう。  アクセルを踏まなくても動き出すのがまず気に食わない。アクセルペダルを緩めても、あまり減速しないのも気に食わない。そういえば、MT車でブレーキペダルは、停止するときぐらいしか踏んでいなかった。  最も気に食わないのは、勝手にギア比が変わることだ。走っていると、ギア比が勝手に変わったことが察せられ、実に気色悪い。  まあ、親父も車やバイクが好きで、そのために転職までしたほどだから、ある意味、親父譲りってところなのだろうか。

2007-03-18

Does VC8 optimize quick sort?

バイナリサーチは末尾再帰で書けるので、最適化できる。では、末尾再帰ではない再帰は、どのようなコードが生成されるのか。たとえば、クイックソートだ。

template < typename Iterator >
void quick_sort(Iterator first, Iterator last)
{
    if ( std::distance(first, last) < 3 )
    { return ; } // 末尾

    Iterator left(first), right(last) ;
    ++left ;
    --right ;

    while ( left < right ) 
    {
        while ( left <= right && *left <= *first )
        { ++left ; }
        while ( left <= right && *right > *first )
        { --right ; }

        if (left < right )
        { std::iter_swap(left, right) ; }
    }

    std::iter_swap(first, right) ;

    quick_sort(first, right) ;
    quick_sort(++right, last) ; //末尾
}

どうもスマートに書くのは難しいが、とりあえず実験の用には足りるだろう。これはどう見ても末尾再帰ではない。これをVC8でコンパイルしてみると、二つ目の再帰呼び出しは、最適化されてループになっていた。なるほど、そういうこともできるのか。

2007-03-16

Does VC8 optimize Tail Recursion?

 末尾再帰というものがある。ある関数が、最後に自分自身を呼び出すように書かれている場合、もし分岐があるならば、それぞれの分岐の最後に、自分自身を呼び出すように書かれている場合、それをTail Recursion(末尾再帰)という。下に例を示す。
void print_hello(int const n) { if ( n == 0 ) { return ; } else { std::cout << "hello" << std::endl ; return print_hello(n - 1) ; } } double power( double const x, int const n ) { if ( n == 0 ) { return 1.0 ; } else { return x * power(x, n - 1) ; } }
 print_hello関数は、引数に与えられた数だけ、helloと出力する関数である。power関数は、xのn乗を計算する関数である。しかし、このように再帰的に記述するのは、C++らしくない。我々C++プログラマは、副作用がたっぷり詰まった、forやwhile文のループを好むものだ。なぜならば、たとえばMS-Windows X86の場合、関数を呼ぶというのは、それだけでスタックを消費するのだ。今の時代にC++を書く、根性のあるプログラマは、皆CPUのサイクル数や、数バイトのメモリ消費を気にするパフォーマンスの信奉者である。再帰のオーバーヘッドなど許されるはずがない。  しかし、ちょっと待って欲しい。次のような単純な変換を施すだけで、この糞みたいなオーバーヘッドを持つ関数は、単なるループに変わる。
void print_hello(int n) { LOOP : if ( n == 0 ) { return ; } else { std::cout << "hello" << std::endl ; --n ; goto LOOP ; } } double power( double x, int n ) { double tmp(x) ; LOOP : if ( n == 0 ) { return tmp ; } else { tmp *= x ; --n ; goto LOOP ; } }
 すばらしい。実に単純な変形だ。コンパイラにできないはずがない。  実際、主要なコンパイラは、末尾再帰を最適化できる。この末尾再帰という考え方は、副作用を忌み嫌う関数型言語の信者にとって、崇拝の対象である。特にLISP教徒は、再帰がなければまともにループを書くことができない。LISPの方言のひとつ、Schemeなどは、 「Thou shalt not waste stack by tail recursion. if thou defy god's will, thy are evil beast, slow belly, and pagan.」 「処理系は末尾再帰にてスタックの消費をしてはならぬ。もし我が意に沿わざれば、汝は悪しき獣、懶惰の腹、異教徒なり」  とまで、規格書の中で明言している。まあ、私にとって、Schemeが異教徒なのだが。  さて、関数型言語は異教徒ではあるかというと、最近のC++の動向を見るにつけ、そうもいえなくなっている。しかし、どの程度できるのだろうか。さっそく確かめてみよう。  確かめるからには、何か実用的なコードにしなければならない。バイナリサーチなどどうだろう。あれは、スタックを消費せずに、ループでも実装できる。あれを再帰で書いて、コンパイラが最適化できるか確かめてみよう。  まず、典型的なC++教徒の書くバイナリサーチを書いてみる。
template < typename Iterator, typename T > bool binary_search( Iterator first, Iterator last, T const & value ) { typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last) ; Iterator mid ; for ( ; n != 0 ; n = n / 2 ) { mid = first ; std::advance(mid, n / 2) ; if ( *mid < value ) { first = ++mid ; } else { last = ++mid ;} } return bool( *first == value ) ; }
 これはどうみても、典型的なC++のバイナリサーチだ。さて、早速再帰で書いてみよう。特に難しくはない。
namespace detail { template < typename Iterator, typename T > bool binary_search(Iterator first, Iterator last, T const & value , typename std::iterator_traits<Iterator>::difference_type const n) { if ( n == 0 ) { return bool( *first == value ) ; } Iterator mid(first) ; std::advance(mid, n / 2 ) ; if ( *mid < value ) { return binary_search(++mid, last, value, n / 2) ; } else { return binary_search(first, ++mid, value, n / 2) ; } } } // namespace detail template < typename Iterator, typename T > bool binary_search( Iterator first, Iterator last, T const & value ) { return detail::binary_search(first, last, value, std::distance(first, last) ) ; }
 私はまだ、C++への信心と修行が足りないし、ましてや異教徒の操る再帰は得意ではないが、こんなものだろう。さっそくこれを、VC8 SP1でコンパイルしてみる。VC8の最適化のほどを見せてもらおう。五千円だして買っただけの価値はあるのだろうか(学生というのはいい身分だ)  まず、これがC++版のbinary_searchだ。これを次のように呼ぶと。
binary_search<int *, int>(&v[0], &v[1000], 12700) ;
00401120 |> 99 /CDQ 00401121 |. 2BC2 |SUB EAX,EDX 00401123 |. D1F8 |SAR EAX,1 00401125 |. 813C81 9C310000 |CMP DWORD PTR DS:[ECX+EAX*4],319C 0040112C |. 7D 04 |JGE SHORT test.00401132 0040112E |. 8D4C81 04 |LEA ECX,DWORD PTR DS:[ECX+EAX*4+4] 00401132 |> 85C0 |TEST EAX,EAX 00401134 |.^75 EA \JNZ SHORT 00401120
 前後を省略するが、これがループである。binary_search関数は、呼び出したところでインライン展開された。ループ版のbinary_searchはこのようになる。再帰版のbinary_searchも、このようになることが理想だ。さて、どうなるだろう。早速比較しよう。
00401370 /$ 85C0 TEST EAX,EAX 00401372 |. 74 16 JE SHORT 0040138A 00401374 |. 56 PUSH ESI 00401375 |. 8B37 MOV ESI,DWORD PTR DS:[EDI] 00401377 |> 99 /CDQ 00401378 |. 2BC2 |SUB EAX,EDX 0040137A |. D1F8 |SAR EAX,1 0040137C |. 393481 |CMP DWORD PTR DS:[ECX+EAX*4],ESI 0040137F |. 7D 04 |JGE SHORT 00401385 00401381 |. 8D4C81 04 |LEA ECX,DWORD PTR DS:[ECX+EAX*4+4] 00401385 |> 85C0 |TEST EAX,EAX 00401387 |.^75 EE \JNZ SHORT 00401377 00401389 |. 5E POP ESI 0040138A |> 8B01 MOV EAX,DWORD PTR DS:[ECX] 0040138C |. 3B07 CMP EAX,DWORD PTR DS:[EDI] 0040138E |. 0F94C0 SETE AL 00401391 \. C3 RETN
 これが、再帰版のbinary_search関数である。呼び出したところにインライン展開はされなかったものの、再帰ではなくなっている。思うに、binary_search関数自体はインライン展開されているのだろう。detail::binary_search関数は、末尾再帰が最適化されて、ループに直されるものの、そのトップレベルの関数自体がインライン展開されることはないのだろう。これには何か、理由があると思われる。  さて、肝心のインストラクションコードはどうだろうか。00401377番地から始まるループを見て欲しい。すばらしい出来だ。関数自体がインライン展開されないので、0x319C(12700)は即値ではなくなっているものの、なんとレジスタである。そのほかはすべて、ループ版と同じだ。再起によるオーバーヘッドはなくなった。単なるループとまったく同じである。もちろん関数呼び出しにかかるコストはあるが、それは一回だけで、無料同然に安い。5千円の価値はあるといえよう。    しかし、ここまで分かりやすい結果になるとは思わなかった。  因云、VC8のイテレータは、デフォルトで範囲外チェックを行う。コンピュータがネットワークにつながることが当たり前になった今の時代、パフォーマンスよりもセキュリティの方が重要だと叫ばれている。セキュリティの確保にかかるコストは無料ではない。ヘビーなパイプラインを持つCPUにとって、条件分岐は禁忌だ。さて、VC8の、セキュアなイテレータは、どの程度パフォーマンスに影響を及ぼすのか。  先ほどの関数に、セキュアなイテレータを通してみると、恐ろしく長いコードが生成された。範囲外をチェックするコードは、恐ろしく頻出するので、インライン展開しないほうが良いと判断されたのか、関数になっている。山のようなpushとpopがある。汎用レジスタが、全然足りていないのだ。うーむ、セキュリティは無料ではないとはいえ、これはすこし、セキュアなイテレータの使用をためらってしまう。  恐らくは、大半の場合は、セキュアなイテレータを使うべきなのだ。それは分かっている。当然だ。しかし、この生成されるコードは……、いや、これは私が古いからなのだ。まったく。この業界は、どうかしている。経験に裏打ちされた熟練の技というものは存在しない。10年前、いや5年前の常識だって通用しないのだ。むしろ、そういう古い知識は、新しい技術習得の邪魔になる。やんぬるかな

2007-03-15

Why Japanese translation of south park is gay

 最近、South Parkというアニメに、クレイジーになっている。しかし、日本語吹き替えはゲイだ。何故だろう。  まず考えられる説として、声優の演技がケツの穴なのかもしれない。特に、OPの歌はひどい。しかしどうも、私はここに、英語と日本語の違いによるものがあるのではないかと思っている。日本語にはない独特の――うまく表現しがたいが――、リズムのようなものがあると考えている。たとえば、Full Metal Jacketの、冒頭から最初の六分ほどの、先任軍曹の語りだ。  英語が分からなかったとしても、この日本語にはないリズムは感じられるのではないだろうか。ただ、FMJの罵倒は、少々古臭いのだが。  もうひとつ思うことは、罵倒の文句だ。日本語には、文になっている罵倒が少ないのではないだろうか。バカ、アホ、マヌケなどが罵倒に際して、よく用いられるが、suck my bollocks とか、lick my ass あるいは、fuck yourself などといった罵倒が、日本語で使われることは無いように思われる。唯一思いつけた定型文での罵倒は、「お前の母ちゃんデベソ」だが、これはあまりにも幼稚すぎる。そもそも、今使われているのだろうか。他に何かあるだろうか。「チョーシ、コイてんじゃねーぞ」等だろうか。しかし、どうも迫力に欠ける。  あるいは、文化的なものなのだろうか。日本語訳には、英語にあるような毒が抜けている感がする。微妙なニュアンスが、訳せないのだろうか。この投稿にあたって、適当な既存のラベルがなかったので、新たなラベル:IMAOを使うことにした。これはそもそも、IMHO(In My Humble Opinion : 私の愚見では)という略語に対する、ネット上のスラングで、In My Arrogant Opinion(吾輩の思し召しは)である。これだけ長々と説明しないと、IMAOのもつニュアンスですら伝わらないのだから、無理もないのだろうか。   注釈: ゲイ(gay):くだらない、つまらない ケツの穴(asshole):ドアホ  私はgayという単語を注釈の意味で解釈している。実際、このように使われているからだ。しかし、いい加減に書くことはできないので、調べようとしたが、私の持っているジーニアス英和辞典やロングマン等には、こういう意味は載っていない。ホモとか、快活な、などと言う意味でのっている。Urban Dictionaryが、この手のスラングの用法についてくわしいようだ。often used to describe something stupid or unfortunateとある。私の解釈は間違っていなかったようだ。

2007-03-13

how to write Merge sort?

http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/index.htm  マージソートを実装した。
namespace hito { namespace detail { template < typename Iterator > void merge_sort( Iterator first, Iterator last , typename std::iterator_traits<Iterator>::difference_type const n , typename std::iterator_traits<Iterator>::value_type * buf ) { if (n < 4) { for ( ; first != last ; ++first) { Iterator iter = std::min_element(first, last) ; if (iter != first) std::iter_swap(first, iter) ; } return ; } Iterator mid(first) ; std::advance(mid, n / 2) ; merge_sort(first, mid, n / 2, buf) ; merge_sort(mid, last, n / 2, buf) ; std::copy(first, mid, buf) ; typename std::iterator_traits<Iterator>::value_type * const end(buf + n / 2) ; while ( buf != end && mid != last ) { if ( *buf < *mid ) { *first = *buf ; ++buf ; } else { *first = *mid ; ++mid ; } ++first ; } std::copy(buf, end, first) ; } } // namespace detail template < typename Iterator > void merge_sort( Iterator first, Iterator last ) { typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last) ; if ( n == 1 ) return ; // Done typedef typename std::iterator_traits<Iterator>::value_type type ; type * buf = new type[(n + 1) / 2] ; detail::merge_sort(first, last, n, buf) ; delete[] buf ; } } // namespace hito
 結局、どう実装するのが一番最適なのだろう。これはBidirectinalIteratorでもソート可能だ。しかし、RandomAccessIteratorの場合は、引数のnなどいらない。ランダムアクセスイテレータに対して、std::distanceはフリーだからだ。実際どうするべきなんだろう。  そしてふと、Nicolai JosuttisのSTL本を紐解くと、驚くべき事実が載っていた。stable_sortのイテレータはRandomAccessIteratorである。そんな馬鹿な。VC8のDinkumwareはBidirectionalIteratorでもソート可能だ。これは一体どういうことだ。規格を読むと、25.3.1.2に、確かにRandomAccessIteratorとある。しかし、実際にBidirectionalなlistのイテレータを渡しても、ソートできる(listはもっといいメンバ関数があるのだが) ヘルプや、Dinkumwareのソースでは、双方向イテレータになっている。ふーむ。VCの独自仕様なのだろう。実際、マージソートは、双方向イテレータでも、それほど問題はないと思われる。

insertion sort

 http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/index.htm  insertion sortを、C++的に実装した。
namespace hito { template < typename BidirectionalIterator > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last ) { BidirectionalIterator pos = first ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; BidirectionalIterator iter = pos, sorted_iter = pos ; for (--iter ; iter != first && key < *iter ; --iter, --sorted_iter) { *sorted_iter = *iter ; } if ( key < *iter ) // check first element { *sorted_iter = *iter ; --sorted_iter ; } *sorted_iter = key ; } } template < typename BidirectionalIterator, typename BinaryPredicate > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last, BinaryPredicate op ) { BidirectionalIterator pos = first ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; BidirectionalIterator iter = pos, sorted_iter = pos ; for (--iter ; iter != first && op(key, *iter) ; --iter, --sorted_iter) { *sorted_iter = *iter ; } if ( op(key, *iter) ) // check first element { *sorted_iter = *iter ; --sorted_iter ; } *sorted_iter = key ; } } } // namespace hito
 しかし、これはちょっと汚い。reverse_iteratorを使ってみると、こうなる。
namespace hito { template < typename BidirectionalIterator > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last ) { BidirectionalIterator pos = first ; std::reverse_iterator<BidirectionalIterator> const rend(first) ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; std::reverse_iterator<BidirectionalIterator> riter(pos), rsorted_iter(pos) ; for ( --rsorted_iter ; riter != rend && key < *riter ; ++riter, ++rsorted_iter) { *rsorted_iter = *riter ; } *rsorted_iter = key ; } } template < typename BidirectionalIterator, typename BinaryPredicate > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last, BinaryPredicate op ) { BidirectionalIterator pos = first ; std::reverse_iterator<BidirectionalIterator> const rend(first) ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; std::reverse_iterator<BidirectionalIterator> riter(pos), rsorted_iter(pos) ; for ( --rsorted_iter ; riter != rend && op(key, *riter) ; ++riter, ++rsorted_iter) { *rsorted_iter = *riter ; } *rsorted_iter = key ; } } } // namespace hito