2010-10-11

OldNewThing: Windows開発部と有名ゲーム

Wildly popular computer game? The Windows product team has you covered - The Old New Thing - Site Home - MSDN Blogs

Windows 95において、もっともよくテストされたゲームは、DOOMである。これは別に、テスターがテスト計画をよく練ったり、テストが自動化されていたためではない。そういうわけではないのだ。これはただ単に、Windows 95の開発部のメンバーに、DOOMで遊んでいた人間が多かったというだけの話である。

DOOMがついに、DOS窓で動いたことは、大いなる前進であった。わざわざMS-DOSモードで起動する必要がなくなったわけなのだから。つまり、他のプログラムを終了させずに、DOOMを起動できるようになったのである。

聞くところによると、Windows Vistaにおいては、もっともよくテストされたゲームは、World of Warcraftだったそうである。DirectXアプリケーションの互換性部門の人間の多くや、Windowsの他の部門の人間は、WoWプレイヤーであったからだ。

そんなわけで、パソコン用の有名なゲームを持っているとしたら、Windowsの各部門にも、所有者があふれかえっているだろうことは、容易に予測できる。「品質保持の観点からも、特に保証できる次第である」

関連:ネットワークカードがWindowsで正常に動作するかどうか確かめる方法

ちなみに、関連のリンク先は、Raymond Chenの著書にも載っている有名な話である。その内容とは、当時、自社製品のNICを負荷テストする最良の方法は、サンプルをMicrosoft社に送りつけることであった。なぜならば、まだインターネットが唯一の標準のネットワークプロトコルではなかった当時、もっともNICを酷使する環境にあった会社は、Microsoft社の社内ネットワークだったからだ。

興味深いSSDの耐久テスト

SSD耐久テスト

この人は、Windows Internalsを読むべきである。

$Bitmapとは、NTFSのメタデータである。一応、Windows Internalsによると、Windows XP以降ならば、NTFSはリードオンリーでマウントできると書いてある。

ただし、Windows Internalsの記述から判断するに、通常、WindowsがNTFSをマウントする際には、ディスクは書き込み可能でなければならない。NTFSはマウントの際にリカバリーを実行するし、マウント後も、5秒ごとにログファイルへの書き込みが発生する。

問題は、今手元にあるWindows Internals 4thの、NTFSのリードオンリーの記述が、限りなく短いことだ。リードオンリーなメディアをマウントできるとしか書いてない。Windowsは、ディスクをマウントするさいに、ディスクへの書き込みに失敗した場合、自動的にリードオンリーでマウントしてくれるのだろうか。あるいは、リードオンリーでマウントするためには、ディスクやそのドライバーが、このメディアはリードオンリーであると話さなければならないのだろうか。その辺の記述は見当たらないので、分からない。

5thでは、増補されているのだろうか。

2010-10-09

親知らず一週間目

抜糸を行った。最後までしぶとく残っていた痛みは、やはり糸のせいだったらしい。

昨日から、少し固形物が食べられるようになってきた。しかし、まだ完全とは言いがたい。

糸をとった後も、どうもまだ痛む。もうしばらくかかりそうだ。

アロケーターに最低限必要なもの

C++0xでは、std::allocator_traitsの導入によって、アロケーターに最低限必要なものが、かなり減った。これにより、アロケーター実装者の負担も減っている。メモ替わりに書いてみる。

以下は、std::allocator_traitsを通してアロケーターを使う場合に、最低限必要なものである。

// 必ずテンプレートパラメーターをひとつ取らなければならない
// T型のオブジェクトに対するアロケーター
template < typename T >
class allocator
{
public :
    // 最低限必要なnested type
    typedef T value_type ;

    // ストレージの確保用
    // n個のT型のオブジェクトを確保できるに足るだけのストレージを返す
    value_type * allocate( std::size_t n ) ;
    // ストレージの解放用
    // pが指すn個のストレージを解放する
    void deallocate( value_type * p, std::size_t n ) ;

    // DefaultConstructibleである必要はない

    // コピーできなければならない
    // 例外を投げてはならない
    allocator( allocator const & ) noexcept ;
    // ムーブできなければならない
    // 例外を投げてはならない
    // 必要に応じて、ムーブコンストラクターも追加

    // template argumentの違う他の型からの変換関数、コピーとムーブが両方可能であること
    // 例外を投げてはならない
    template <class U> allocator( allocator<U> const & ) noexcept ;

    // デストラクターは例外を投げてはならない
    // これは、STLの決まりごと
    ~allocator() noexcept ; 

    // 他のオブジェクトと比較できなければならない
    // template argumentの違う他の型とも、比較できなければならない
    // a == bにおいて、お互いのallocateで確保したストレージが、お互いのdeallocateで解放できる場合、trueを。
    // そうでない場合、falseを返す
    template < typename U > bool operator == ( allocator<U> const & ) ;

    // ==演算子の否定を返す
    template < typename U > bool operator != ( allocator<U> const & ) ;
} ;

この他のメンバー、たとえばconstructとかdestroyとか、細々としたnested typesなどは、std::allocator_traitsを通して使う場合、適当に補完される。実を言うと、allocateやdeallocateも補完されるのだが、通常のユーザーが、自前アロケーターを書く目的は、そこにはないだろう。

追記、value_typeという名前のnested typeが必要であった。

2010-10-08

ノーベル平和賞

今回、中国人がノーベル平和賞を受賞したというのは、非常にめでたいニュースだ。毎年、ノーベル賞受賞を夢見てきた中国にとって、さぞかし感無量であろう。

どうも不思議なthread_localの仕様

thread_local指定子は、クラスのメンバーの際には、static指定子と共に宣言しなければならない。

void f()
{
    thread_local int x ; // 暗黙のうちにstatic
}

struct S
{
    // 宣言、staticも必要
    static thread_local int x ; 
} ;

// 定義、staticを使ってはいけない
thread_local int S::x ;

ここで、S::xの定義には、staticは使えない。なぜならば、staticデータメンバーの定義は名前空間スコープに書くわけで、そこでのstatic指定子の意味は、staticストレージではなく、internal linkageだからだ。

何故このような制限があるのか分からない。メンバーの宣言にも、暗黙のstaticを認めてもいいと思うのだが。第一、thread_localによって宣言された変数は、thread storagedである。static storageではない。

何故このような制限があるの変わらかないと書いたが、全然思い当たらないでもない。結局、static storageとは別に、static data memberという概念があるために、こうなっているのだろう。全然別の事を、ひとつのキーワードで行わせるのは、混乱のもとだと思う。

standard-layout classのささいな条件

あるクラスがstandard-layout classの条件を満たしたときに保証される動作はいくつかあるが、その中でもとくに重要なものに、クラスのオブジェクトへのアドレスは、クラスの最初の非staticデータメンバーのサブオブジェクトへのアドレスに等しい。というものがある。

struct A
{
    int x ; int y ;
} ;

A a ;

A * a_ptr = &a ;
int * ptr = reinterpret_cast<int *>( a_ptr ) ;

この場合、ptrはa.xを指す。これは規格で保証されている。ちなみにこの時、++ptrがa.yを指す保証はない。なぜならば、実装はデータメンバーの間にpaddingを入れるかもしれないからだ。ともかく、このクラスのオブジェクトへのアドレスが、クラスの最初の非staticデータメンバーへのサブオブジェクトのアドレスに等しいというのは、重要な保証だ。

ところで、standard-layout classとなるためには、かなり厳しい条件を満たさなければならないわけだが、その中に、「最初の非staticデータメンバーと、基本クラスとで、同じ型を使わない」というものがある。

// standard-layout classではない例
struct A { } ;
struct B : A // 基本クラス
{
    A a ; // 最初の非staticデータメンバー
    int data ; // 二つ目の非staticデータメンバー
} ;

なぜかというと、基本クラスのサブオブジェクトと、データメンバーaは、別々のアドレスを割り当てられていなければ、困るからだ。

struct A { } ;
struct B : A { A a ; } ;

B obj ;

A * p1 = &obj ; // 基本クラスのサブオブジェクトへのアドレス
A * p2 = &obj.a ; // データメンバーへのアドレス

// p1 != p2が保証される

なぜならば、クラスBに、クラスAというサブオブジェクトは、二つあるからだ。p1 != p2を保証するためには、このようなクラスには、standard-layout classになってもらっては困る。

2010-10-07

電源ユニットのファンが壊れた

電源ユニットのファンが逝ってしまわれたらしい。急に再起動がかかって何事かと思ったら、電源ユニットが非常に熱くなっていた。GPUをフル稼働させていたのも、原因の一つかもしれない。

電源ユニットは、前のPCのものが余っているのだが、交換するのは面倒だ。ケースを開けて扇風機で風を送るか、GPUをフル稼働させなければ問題ないようだ。

2010-10-06

Foxit Reader

Adobe Readerにうんざりして、Foxit Readerをインストールしてみた。Adobe Readerと比べても、遜色ないようだ。

FSM教の教義による親知らずの意義

空飛ぶスパゲッティモンスター教(FSM教)では、人体の様々な、不要な部分の持つ真の役割を解説している。

これは預言者Bobby Hendersonによる福音書22ページから24ページにかけての記述に基づくものである。これは単なるセオリーであって、証明されてはいないが、否定されてもいないので、他の証明されていないセオリーである自然科学と対等に扱うべきセオリーである。特に、カンザス州では、全生徒に教育すべきことが望ましい。

自然科学によれば、親知らずとは、まだ我々の祖先が、粗野な食物を食べていたとき、多くの歯ですりつぶす必要があったために存在する歯のことである。

ところで、海賊は、現代人よりよほど粗野な食物を食べていた。また海賊は、喉の奥に剣を隠しておくという離れ業を、こともなくやってのける連中であった。よって、論理的に考えれば、より多くの歯を必要としたはずである。

その他にも、男性の乳首は、海賊が天候や風向きを判断するための計測装置であるし、鳥肌は、海賊が水中で浮力を得るための機能であるし、盲腸の虫垂は、海賊が金貨を隠すための便利な場所である。また、尾骨は、鹿の角と同じく、海賊の戦いのために用いられた。当時の海賊は、お互いに後ろ向きに向かい合い、ケツをふりあげて尾骨を角のように見立てて戦ったらしい。Bobby Hendersonは、この戦闘法を、尻戦(けっせん)(ass-fighting)と命名している。

なお、我々人間は、ビタミンCを合成する遺伝子を持っているが、この遺伝子は働かない。これはなぜかというと、我々の祖先である海賊は、南国にいてフルーツが豊富に得られたため、わざわざ遺伝子を働かす必要がなかったからである。

これらのセオリーは、明確に、我々の祖先が海賊であることをしめしている。当時の海賊は、現代の犯罪集団とは違い、祝福された存在であったのだ。無論、これらのセオリーは証明されたことがないが、否定するに足る証拠も見つかっていない。

親知らず5日目

もうほとんど痛みはないのだが、傷は治っていない。もう少しで顎を閉じられそうな気がするのだが、まだ痛む。顎の腫れも、まだ残っている。

ほとんど動かせるようになったのに、完全に歯を噛み合わせることができないというのは辛い。

喉の痛みも大方治まったようだ。水が普通に飲める。

しかし、抜歯によって傷付いたのは顎であるはずなのに、なぜ熱が出たり、喉が痛くなったりするのやら。熱はまだしも、喉はよく分からない。

どうもまだ少々の痛みがあるが、これは糸のせいではないかとおもう。

どうも今日は、やけに痛む。抜糸まであと三日。

これを電子メールでするんじゃない

If you do this in an email, I hate you - The Oatmeal

From: ビル ジマーズ
Subect: 至急、返信を乞う
Attached: UserAgreement.doc (12MB)

こんにちはマットさん。日頃お世話になっております。
さて、本メールに30ページのドキュメントを添付いたしました。
ダウンロードした上で印刷し、署名捺印の上、早急にFAXを願います。
よろしくお願い致します。ビルより

これは言ってみれば、以下のように言っているのと等しい。

From: 三位の中将ビル、インターネットの雲の上人
Subect: 至急、返り事を送られよかし
Attached: UserAgreement.doc (12MB)

やをれ、マット、確かに承れ。
和殿、必ずスペインまで船の旅にて上りて、これなる羊皮紙に羽ペンにて署名捺印し候へ。
我が都にはインターネットといふもの侍らず。
いやしくも女王より位階を賜わりし身としては、求めに応じて即座に都に上がりて、羊皮紙に署名することぞ、勤めなる。
武運を祈る。三位のビルより。

なんでわざわざ電子メールで紙の署名を求めるんだというお話。果たして、電子メールは紙の手紙に比べて、信頼性が低いのであろうか。例えば、電子メールのサーバーを第三者が運営していれば、確実に変更されない記録は残るはずだ。もちろん、変更することは、メールサーバーの管理者からすれば、技術的に可能であるが、メールを削除する以外のことは、ユーザーからはできない。

結局、何故我々が未だに紙の契約書を作り、はんこを使いたがるかというと、紙の方が歴史があるからにすぎないのだ。言うまでもなく、私は、紙が嫌いである。特に、はんこなどというものは、全く信用していない。はんこの複製は、現代では、ものすごく簡単なのだ。3Dプリンターが発明されてから何年経っていると思っているのか。

そういえば、これに近いことは、私にもたびたびあったような気がする。我々はさらなる文明の進歩のために、紙を捨て去る必要がある。

2010-10-05

親知らず4日目

熱はだいぶ下がったようだ。顎の腫れも、だいぶひいてきた。しかし、相変わらず歯を噛み合わせることができない。喉がまだ少し痛むのが気になる。

おかゆだけでは体に悪いだろうと、豆腐を食べることにした。液体ならば飲めるので、牛乳も買ってみた。そういえば、牛乳を飲むのは久しぶりかもしれない。

もうすこしで治りそうな気もするのだが、どうも痛みが取れない。とにかく、早く抜糸をしたい。

2010-10-04

噛みごたえは重要である

私は、あまり食に関心のない種類の人間である。私に取って食事というのは、生存に必要な栄養を得るための行為であった。私が食に関して気を付けていることは、「同じものを食べ続けない」ということだけである。

ところで、私はつい先日、親知らずを抜いたために、顎が使えず、噛まずに飲み込めるほど薄い粥をすすって生きている。もう三日になるが、これはなかなかに苦行だ。噛みごたえがない食事というのが、こんなに辛いものだとは思わなかった。

私は今まで、美味というものは、主に油と、舌鼻を刺激する物によって決まると思い込んでいた。ところが、実は噛みごたえというファクターがあるらしい。

私は粥に対して、様々な調味料の適用を試みた。しかし、塩を除いては、はかばかしい成功はしなかった。たとえ、ミキサーで焼き肉や焼き魚を粥に混ぜ入れたとしても、あまり良い食べ物にはならないだろう。

しかし、何と言っても私は、まだ粥をすすり始めて三日しか立っていないのだ。しかも希望がある。私の場合、せいぜい一、二週間もすれば、元通り咀嚼できるようになるだろう。それでもなお、粥をすすることにうんざりしている。これは恐るべきことである。世の中には、歯を全部なくしたり、顎を悪くしたりして、まともに咀嚼できない人間が大量にいると聞く。将来、そのような身になりたくはない。

親知らずを抜いて理解したこととは、歯と顎は大切にするべきである。咀嚼力は、スルメを食べる時以外にも発揮しなければならないのだ。

まあしかし、経口摂取できるのは、まだ幸せな方なのかもしれぬ。胃に直接流動食を流し込むよりはマシであろう。点滴は、言うまでもない。

C++0xの落とし穴を埋める改良

聡明なC++0xプログラマである読者諸君ならば、もう、以下のコードは、C++0xでは、疑いようもなくwell-formedであることを知っているだろう。

// C++03ではill-formed
// C++0xではwell-formed
vector<vector<int>> v ;

従来、連続した>は、>>演算子と、文法上曖昧であるので、かならず>>演算子だと解釈されるようになっていた。C++0xでは、このような場合、演算子と解釈されることはなくなった。もちろん、分かりやすさから言えば、空白文字を挟んだ方が分かりやすいだろう。

vector< vector< int > > v ;

何にしても、このようなちょっとした落とし穴は、初心者を無用に混乱させる。、C++0xでは、このようなちょっとした落とし穴がいくつも塞がれている。

さて、ここまでが前振りで、ここからが本番である。以下のコードは、C99では、ill-formedである。C++03ではundefined behaviorである。C++0xではwell-formedである。ただし、[EOF]は、ソースファイルの終りを表す。実際の文字ではない。

int main()
{

}[EOF]

何故か。C99は、空ではないソースファイルは、必ず改行文字で終わらなければならないと定めているからだ。C++03では、空ではないソースファイルが、改行文字で終わっていない場合は、挙動は未定義と定めているからだ。したがって、上記のコードは、C99やC++03といった、前時代の旧言語では、動かない。

しかし、この仕様は、ユーザーの立場になって考えると、馬鹿げている。ソースファイルの終りが改行でなければならないというのは、ユーザー側からすれば、意味が分からない。ユーザー側からすれば、ソースファイルはそこで終わっているのだから。C++0xでは、このような馬鹿げた制限を取り払った。C++0xでは、空ではないソースファイルが、改行文字で終わっていない場合は、改行文字が補われると定めている。したがって、上記のコードは、C++0xという最高にクールな新言語では、well-formedである。

実は、このC++0xの制限緩和は、実に最近の変更である。いつドラフトに入ったのかというと、FCDからである。何と、今年に入ってからの変更だ。

ちなみに、この制限に関する文面は、
C99(TC3)の5.1.1.2 Translation phases paragraph 1.2
C++03の2.1 Phases of translation paragraph 1.2
C++の最新ドラフトN3126の2.2 Phases of translation paragraph 1.2
に書いてある。

親知らず3日目

親知らずを抜いてから3日目。

やはり熱がある。顎が腫れている。顎を動かすと痛い。

今日も食事はおかゆになるだろう。

顎を動かさなければ、ほとんど痛みはない。しかし、顎を動かさないというのは辛い。物を噛めないし、発声も難しい。また、口を完全にとじることができないというのもつらい。

2010-10-03

親知らず2日目

聞説、親知らずは、問題になる人の割合の方が多いという。しかるに、Web上には、あまり親知らず治療中の情報がない。いつも読んでいるデイリーポータルZに、親知らず治療体験記を発見した。

@nifty:デイリーポータルZ:親知らずの抜歯手術レポート~歯茎の増殖過程を追え!

そこで、ないものは自分で書くことにした。この記事を読んで、まだ親知らずが問題になっていない人は、覚悟できるだろう。

そして
それこそ
『幸福』であるッ!

独りではなく全員が未来を
『覚悟』できるからだッ!
『覚悟した者』は
『幸福』であるッ!

悪い出来事の未来も
知る事は『絶望』と
思うだろうが

逆だッ!

明日『死ぬ』と
わかっていても
『覚悟』があるから
幸福なんだ!

『覚悟』は『絶望』を
吹き飛ばすからだッ!
人類はこれで変わるッ!
これが わたしの求めたものッ!
『メイド・イン・ヘブン』だッ!

出典:ジョジョの奇妙な冒険 80巻  メイド・イン・ヘブン その⑨

痛みであまり眠れずに朝を迎える。体調は悪い。明らかに熱があり、体がだるい。右の顎が腫れている。顎が動かせない。喉が痛い。

何か食べなければならない。ここしばらく、一日一食ぐらいしか食べていない。これは、参考書を執筆するのに、集中する必要があるが、満腹では集中できないからだ。したがって、必然的に食事の量は減っていた。そこへきて親知らずだ。私は何も考えずに、土曜日でも、普段行っている歯医者が空いていてよかったと、朝一番、食事もせずに治療に出かけた。思えば、これが失敗だった。何か食べておくべきであった。親知らずを抜いた後は、しばらくまともに物が食べられなくなるのだから。今、おかゆすら食べられなくなっている。

これを読んでいるもので、親知らずの疑いが出てきたものは、まずしっかりと食事をとってから歯医者に行くべきである。少なくとも、抜く前ならば、おかゆぐらいは食べられるであろうから。

それはさておき、このままではまずい。私は一日四回も化膿止めを飲まなければならないのに、何も食べないのは確実にまずい。しかし、おかゆすら食べられないのにどうする。ぼんやりする頭で思案したところ、ウイダーinゼリーが思いついた。あのゼリー状の液体ならば、流しこむことができるのではないか。

さっそく買ってきたところ、どうやら食べられるようだ。

今は、より十倍以上の水でおかゆを作っている。これが食べられるといいのだが。

ちなみに、私の親知らずを抜くのは、だいぶ手間がかかったようだ。一時間以上かかったし、何回も切り分けて取っていたし、歯医者は、「久しぶりやわ、骨とくっついている」などという言葉を漏らしていた。

どうやら、今度は食べられるおかゆを作ることに成功したようだ。野菜などの具が入れられず、なんとも寂しいおかゆだ。卵ぐらいなら入れられるかもしれぬ。

ハリウッドが忠臣蔵を作ったら

  • 日本と中国と韓国を混ぜあわせたような不思議な着物
  • 建物があきらかに中国風
  • 男はみな辮髪。女は纏足
  • 文字が楷書でかな交じり(最近の日本の時代劇もそうだが)
  • お歯黒を付けない既婚女性(最近の日本の時代劇もそうだが)
  • なぜか皆筋骨隆々としており、平均身長は六尺
  • 何故か意味もなく出てくる忍者
  • 刀は片手で振り回す
  • 家に上がるときは履物を脱ぐが、足は拭わない
  • からくりじかけの怪しげな装置
  • なぜか最後は素手による格闘で決着を付ける
  • 終りに切腹しないで生き残る

2010-10-02

親知らず

今日、朝起きてみると、どうも口の中がおかしい。何やら、右下の奥の歯肉が、盛り上がっているように思われる。虫歯かと鏡を確認したが、どうもそれらしき歯はない。歯は痛くない。単に腫れているのだろうか。しかし、最近口の中を怪我した覚えはない。

まさか、親知らずだろうか。いやそんなまさか。

ともかく、このままでは食事も満足にできないので、歯医者に行った。歯医者は、口の中を見て一瞬で、レントゲンを取ると言った。現像された写真を見ると、見事に歯が横向きに生えている。親知らずだった。

歯医者「親知らずですねぇ。どうしますか? 抜きますか?」
私「抜く以外の選択はあるんですか?」
歯医者「ありません」

その後、多量の麻酔をかけた後、一時間かけて親知らずを抜いた。そして、口の中を縫った。

そして、帰宅してこれを書いているのだが、徐々に麻酔が切れてきている。だいぶ痛む。やれやれ、親知らずだけはどうにもならん。

ちなみに、左下顎にも、見事に横向に生えている親知らずがあったが、これはまだ問題になっていないので、放置していてもいいらしい。問題にならなければいいのだが。親知らずはもう二度と御免だ。何故あんなに親知らずが忌み嫌われているか、今日はじめて理解した。

追記:麻酔が切れてきた。ものすごく痛む。痛み止めを飲む。実は、まだわずかに血が出ているようだ。

追記2: そろそろ昼飯を食べたいのだが、痛みと出血で食欲が無い。歯医者に行く前に、何か食べておけばよかった。失敗した。

追記3:痛みはだいぶマシになり、出血も治まったようだが、顎を動かすと痛む。また、喉が痛い。何か食べなければならないが、食欲が無い。

2010-10-01

Dark_Shikari、WebPについて語る

Diary Of An x264 Developer » H.264 and VP8 for still image coding: WebP?

H.264のエンコーダー、x264の開発者の一人である、Dark_Shikari氏が、WebPについて語っている。基本的に、WebP規格自体は悪くないのだが、公式のエンコーダーであるlibvpxがクソすぎる。

Dark_Shikari本人曰く、まだ追記するかもしれないとのこと。今は完全に一致しているが、念のためリンク先の翻訳元(英語)を参照することをおすすめする。

JPEGはかなり昔の圧縮フォーマットで、あまりよろしくない。実際のところ、MPEG-2時代の動画フォーマットですら、JPEGには勝てる。なぜ皆が移行しないのかというのは、単純だ。特に利点がないからだ。たとえJPEGより2倍すぐれていたとしても、全世界に対して、20年間使い慣れた画像フォーマットを変更するように強いるのは、不可能だ。さらに、JPEGは高速で、簡単で、事実上、特許やロイヤリティなどがフリーである。JPEGの代替は、かつて何度も試みられた。まず、JPEG-2000、次にMicrosoftのJPEG XR。どちらも、JPEGを王座から引きずり下ろすことを試みた。どちらも、まったく歯が立たなかったのだが。

さて、Googleがまた性懲りもなく新しい画像フォーマットをだしてきたわけだ。"WebP"とかいう、いや待てよ。単なるVP8のイントラフレームじゃないか。この新しい画像フォーマットがJPEGより劣る理由が、すぐに挙げられる。JPEGの全機能をサポートしていないからだ。アルファチャンネル、ロスレスといった機能がサポートされていない。4:2:0 chroma subsamplingしかサポートしていないのだ。JPEGなら4:2:2や4:4:4までもサポートしているというのに。そもそも、Googleはこれらの機能を付け加えることに興味を示していないようである。

まあ、ともかく、これらのエンコーダーが、静止画に対してどれだけ圧縮できるかを試してみよう。すでに説明したように、VP8はH.264とほぼ同じ優秀なイントラ予測(intra prediction)を備えている。すでに説明した理由によって、H.264のイントラ圧縮(intra compression)は、非常に優れているのだ。VP8はi4x4とi16x16モードしかなく、i8x8を持たないので、H.264ほどではないが、ほぼ同じ性能である。

訳注:ここでDark_Shikariが行っているテストとは、H.264とVP8で、1フレームだけエンコードすることによって、静止画圧縮を実現している。これは、H.264とVP8のイントラフレームの性能を比較しているのに等しい。イントラフレームは、単体でデコードできるため、静止画の圧縮フォーマットとしても流用可能である。WebPも、VP8のイントラフーレムを使っているに過ぎない。また、x264とはH.264のエンコーダー、libvpxとはGoogleによるVP8のエンコーダーである。jpgcrushとは、すでにエンコードされたjpegファイル自体を最適化するperlスクリプトである。これは、x264の開発者の一人である、Loren Merrittによって書かれた。最適化はロスレスで行われる。基本的な仕組みとしては、ある状態をjpegフォーマットでコードする方法は複数あり、そのうち最適なものを複数回の試行により選ぶものである。だからロスレスで最適化できる。

テストファイルは、すべて155KB程度である。ダウンロードして確かめるとよい。どのファイルに対しても、私はファイルサイズをほぼ同じにするためのクオリティレベルを。バイナリサーチして弾きだした。x264では、--tune stillimage --preset placeboでエンコードした。livpxでは、--bestでエンコードした。JPEGには、ffmpegを使い、さらにjpgcrushという、ロスレスのjpeg圧縮ツールを用いた。ひょっとしたら、ffmpegより優れたJPEGエンコーダーがあるかもしれない。もし読者が聡明にも、より優れたエンコーダーを知っていたならば、どうぞ自分でも試してもらいたい。画像のソースは、Xiph.org :: Test Mediaによる、Parkjoyの200フーレム目である。

ファイル:x264[154KB]、VP8[155KB]、jpg[156KB]

訳注:このファイルは、H.264とVP8のRaw streamである。このファイルをデコードして見るためには、ffmpegやmplayerなどを使うといい。

結果(デコードしてPNGに圧縮):x264VP8jpg

訳注:このファイルは、エンコードされたファイルを一度デコードして、PNGに圧縮しなおしたものである。PNGはロスレス圧縮なので、単に画質を目で比較したい場合は、こちらをダウンロードするとよい。

これを見るとどうも、libvpxは赤面ものの結果になっている。主観的に思うに、VP8は最悪である。JPEGはブロッキングノイズがあるとはいえ、VP8よりマシである。何故こうなったのか? VP8には、JPEGよりはるかに優れたエントロピーコーディング(entropy coding)があるというのに。VP8には、より優れたイントラ予測(intra prediction)があるというのに。JPEGにあるのはDC予測(DC prediction)だけだ。なぜVP8がこんなにも劣って見えるのか? 分析してみよう。

VP8は4×4変換(4×4 transform)を使っている。これは一般に、JPEGの8×8変換(8×8 transform)より、ブラーがかかり、細部が失われてしまう。しかし、それだけではここまで酷い違いにはならないはずだ。私の仮説では、おそらく問題は、libvpxの画像のエンコードでは、PSNRに最適化されていて、人間の目とっての高画質を無視しているのだ。ここで、x264を、--tune psnr --preset placeboでエンコードしてみよう、つまり、psy optimizationを無効にするのだ。

訳注:PSNRは、二つの画像を比較して、どのくらい違っているかを図るための、計算方法である。つまり、PSNRを計算することは、エンコードにより画像がどのくらい変化したかという、劣化具合を計算することができる。しかし、PSNRで高得点を得たからといって、必ずしも人間の目にとって、高画質であるとは限らない。x264には、psy optimizationという名称の、より人間的な画質の劣化具合を計算するための比較方法が実装されている。

ファイル:x264、PSNR最適化[154KB]、ちなみに、adaptive quantizationが無効になっているため、ファイルサイズを合わせるために、CQMを使った。

結果(デコードしてPNG圧縮):x264、PSNR最適化

何というブラーだ! VP8より多少はマシなだけである。JPEGより遥かに悪い。これが同じエンコーダーに、同じ品質の解析をさせた結果である。ただ唯一の違いは、psy optimizationを無効にしているだけである。

さて、ここで当然の疑問が沸き起こる。Googleはアホなのか? JPEGより優れているのならば、WebPとやらをプッシュするのも分かる。もちろん、技術的に、ファイルフォーマットとしては、優れている。フォーマットに基づくエンコーダーも、JPEGより優れたものを出力できるであろう。ただし、「できるであろう」ということに注意しなければならない。なぜlibvpxが、未だにクソエンコーダーであるこの時期に発表するんだ? こんなブラーだらけのクソでJPEGを置き換えるというのか?

全世界よりGoogleに告ぐ:まず、てめぇのエンコーダーをまともにしやがれ。代替案として宣伝するのはその後だ。順番が逆ではダメだ。

追記:
maikmertenがtheoraによる比較をしてくれた。PNGソース。何と、Theora 1.2 (Ptalarbvorm) がVP8を打ち負かしているではないか。生き恥もいいところだな。Ptalarbvormの謳い文句の新機能とは何か。psy optimizationだよ。

ちなみに、以前にも、Dark_Shikari氏と、H.264のイントラフレームを、静止画のフォーマットとして流用することの如何をチャットしたことがある。H.264のイントラフレームを静止画のフォーマットとして使うにあたって、技術的な障害は何もないのだが、やはりすでに普及しているJPEGの牙城を崩すことは難しいだろう。現代では、画像程度のファイルサイズを、あまり気にしないという問題もある。画質はそのままで圧縮率が二倍になったとしても、テラバイトの3.5インチHDDが民生品として売っている現状では、あまり利点はない。

また、WebPは、weppy(ウェッピー)と読むらしい。bが無声音になるらしい。しかもy音が追加される。ふしぎふしぎ。最初、読み方はWeb-Pee(Web小便)かと思った。

追記:Chromium Blog: WebP, a new image format for the Webによれば、将来的にアルファチャンネルをサポートする意思はあるらしい。

画像による広告は逆効果ではないか

本の虫: pixivreaderがすばらしいを書いていて、ふと閃いたことがある。Web上で、画像による広告は逆効果ではないか、ということだ。

Web上では、実に多くの広告を見る。テキスト、画像、動画、音声。甚だしきはFlash。これらの広告は、あまり見たいとは思わない、むしろ邪魔なものである。

ところで、もしFirefoxかChromeを使っているならば、当然、Adblockを使っているだろう。これは、ドメインとCSSセレクターのマッチによって、広告を消し去ってくれる便利なエクステンションである。元はといえば、Firefoxのエクステンションであったが、Chromeにも移植されている。

しかし、このエクステンションは万能ではない。このエクステンションを使ったとしても、多くのWebサイトは、いまだに広告を見せ続ける。これは畢竟、我々があらゆる広告にマッチして、誤爆を一切しないCSSセレクターを書くことができないからである。ちなみに、あらゆるコンテンツにマッチするAdblockのフィルターなら、以下のように記述できる。

##*

冗談はさておき、標準のフィルターでブロックできない広告をブロックしたい場合、自分でフィルターを書かなければならない。これを本格的に行うには、CSSセレクターの知識が必要になる。これは、特に難しいということはないが、少なくとも数分の手間がかかる。CSSセレクターの知識がなくても、最近のAdblockには、大抵クリックした場所を公告とみなして隠す機能があるが、大抵、あまりうまくいかないし、おそらくもっと時間がかかるであろう。

Webサイトをどのように描画するかというとこは、完全にUAの自由であり、広告主は当然、UAはこのような便利な機能を有していることを認識すべきである。

しかし、Adblockのユーザーが、ありとあらゆる広告を隠すことはない。そんなことをしていては、時間の無駄だからだ。Adblockユーザーは、極端に目につく広告だけを隠すはずである。どうも、既存の広告は、目立つということだけを考えていて、Adblockの的になるということは、あまり考えていないようである。

そういう時、どのような広告が目につくのか。

まず、Flashを使っている広告は一発で消されるだろう。もっとも私は、Flash自体を、必要な場合にしか有効にしないので、Flashによる広告を見ることはない。そのようなExtensionがあるからだ。

次に、video要素やaudio要素を使った広告もすぐに消されるだろう。現在のところ、これらの要素を使った広告は、あまり見たことがないが、あのIEですら、IE9でサポートするので、すぐに増えてくるだろう。

上記の広告が消されるのは、当然である。清少納言の言葉を借りれば、すさまじきものだからだ。では、画像はどうか。画像も、否応にも目立つ。広告としては、目立つほどいいのかもしれないが、Web広告に取っては、目立つということは、すなわちAdblockで消されるということである。

では、テキストによる広告はどうか。不思議なことに、私はテキストによる広告をブロックするためにフィルターを書いたことは、ただの一度もない。もちろん、有名所の広告は、すでにAdblock標準のフィルターで消えているというのもあるのであろうが、自分からテキスト広告を消したことはない。すると、テキストによる広告は、一番狙われにくいのではないだろうか。

目立が消される広告と、目立たないが消されない広告、どちらがいいかは自明である。

pixivreaderがすばらしい

pixivreader - by edvakf in hatena

これは便利だ。

しかし、こんなextensionを使わなければまともに見ることの出来ないPixivの悲しさよ。まあ、色々な都合があって(見かけ上のPVでも稼ぎたいんだろうか)、わざとああいう使いづらいデザインにしているのだろうが、何とも悲惨だ。

Pixivのデザインの悪さは、意図的なものである。例えば、連中は、広告をわざとNext/Prevの近くに配置することによって、誤クリックによるセコイ広告誘導を狙っている。もちろん、そんな広告は、遠慮無くAdBlockのフィルターを記述して消している。

私はあまり、広告の削除というのはやらないのだ。なぜならば、DOMツリーから該当の要素を見つけ、フィルターを書くには、いくらChromeがすばらしいDOM Inspectorを提供してくれているとはいえ、数分かかる。広告だけに正しくマッチするフィルターのルールを考えなければならないからだ。

それでもやる時というのは、Pixivのように、あまりにも露骨な広告の配置をしている時だけだ。結局、クライアント側が、サイトをどのように描画するかは、クライアント側の意のままであるのだから、サーバー側のこのようなセコイ広告配置は、逆効果である。私のように少しでもCSSをかじっている人間は、容易にAdBlockのフィルターを書く事ができるのだから。

私は、このブログでは、できるだけ本来のコンテンツと広告は、明確に違いがわかるようにしている。何、それでも邪魔だと言うのか? 私も同意する。遠慮無くAdBlockのフィルターを記述して消せばよい。私もそうしている。このようなPV数の低いブログでは、全く儲からないので、そろそろ広告を消すことも考えている。

このように動的に画像を追加する考えを推し進めて、動的に過去の記事を追加するブログというアイディアを思いついたが、それはすでにGoogle Readerがやっているので、わざわざブログ単位でやるまでもないだろう。私は、人のブログは大抵、Google Reader経由で読んでいる。たまに、フィードで全文を配信していないブログがあるが、そういうブログは、大抵読む価値がない(少なくとも、ブログ主はフィードの何たるかを解していないので、価値観が合わない)ので、問題はない。

フィードは、単なる更新を告げるだけであり、全文を含むものではないという思想も、過去にはあったらしいが、フィードリーダーから内容を読むということが一般的になり、また、検索エンジンも、フィードの内容を確認している今となっては、古臭い思想と言わざるをえない。フィードは全文を含むべきである。

2010-09-30

プログラマーが読んで楽しめる本

全プログラマーが読んで楽しめる本とは何か。最良の本ということになれば、これは、そのプログラマーの信仰する言語によって、異なるであろう。

例えば、C言語厨はK&Rとか言う古書を聖書と定めている。LISP信者は全員、SICPという魔法の経文を所有しており、毎日欠かさずに読経するそうである。また、各人が確実にSICPを読んだことを確認しあう意図なのであろう。LISP信者同士の挨拶は、"Have you read your SICP today?"である。C++信者にとっては、ISOの規格書が最良の本だろう。コンパイラ屋は、銘の刻まれた剣と盾と鎧を装備した騎士が、ドラゴンと向かうあう本を、座右に置いているらしい。これにはどういう言われがあるのか分からないが、たぶんゲームの攻略本か何かであろう。

話がそれた。ここでは、プログラマーの宗教、もとい言語や専門分野に関わらず、一般に楽しめる本を紹介する。

G Pascal Zachary著:Showstopper! the Breakneck Race to Create Windows Nt and the Next Generation at Microsoft
邦訳:闘うプログラマー ビル・ゲイツの野望を担った男達

Windows NTの開発秘話。NTカーネルの設計者であるDave Cutler様を主人公にして話が展開される。

Clifford Stoll著The Cuckoo's Egg: Tracking a Spy Through the Maze of Computer Espionage
邦訳:カッコウはコンピュータに卵を産む〈上〉カッコウはコンピュータに卵を産む〈下〉

伝説のハッカーの一人、Clifford Stallの自著による、不正アクセスの発見と監視の記録。

長谷川 裕行著:ソフトウェアの20世紀―ヒトとコンピュータの対話の歴史

コンピューター史をひと通り、画像付きで解説している歴史書。

とりあえず、自分の読んだ中で、特に面白いと思ったものを挙げた。他にも、90年代前半までのコンピューターウイルスの歴史を解説した良書があったはずだが、本の題名を忘れた。

他にも、マイ・コンピュータをつくる―組み立てのテクニックという、ブルーバックスシリーズの本があるのだが、これは少し、人を選ぶかもしれない。内容は、8086を使った自作コンピューターの作り方を説明する本である。とはいっても、今となってはそれほど役には立たないだろうし、電子工作が好きな人向けか、当時の組み立て済みではない自作マイコンの歴史的資料を探している人向けだろうか。

10代で読んでも理解出来ない書物

10代で読んでいないと恥ずかしい必読書 - その1 - PictorialConnect

思うに、これらの書物は、哲学である。数学や物理学や機械工学などではない。してみれば、これらの書物は、原文で読まなければ、真に「読んだ」とは言えぬのではなかろうか。なぜならば、数学などの学問は、どの言語で定義しているかということは、問題にならないはずである。しかし、思想は、言語の影響を受ける。しかも、これらは口頭で語られたものではなく、文章である。中には、スピーチを文章に落とし込んだものもあるが、結局、文章であり、聞くのでなく、読むことを前提にしていることには変りない。

しかし、このリンク先の人物は、古ギリシャ語やラテン語に加えて、当時の(現代語とは多少異なる)ドイツ語、フランス語、デンマーク語、英語、イタリア語を、すべて読むことができるのであろうか。ザメンホフや柳沼重剛のような言語オタクならともかく、果たして本当にそのような言語オタクなのだろうか。もしそうでなく、どれか一冊でも翻訳で読んでいるのであれば、彼は自分の発言を恥づべきである。

むしろ逆に、10代では読んでも理解出来ない書物を挙げたほうが役に立つのではないか。

たとえば、芥川龍之介だ。彼の文章を真に理解するためには、今昔物語集を読破しなければならない。私も、今昔物語集を、最近になって読み終えて、始めて彼の文章の真の素晴らしさが分かった。しかし、現代人は、10代のうちに今昔物語集を読破するのは難しい。

高山樗牛もすばらしい小説をひとつだけ書いたが、あの文章が以下にすばらしいかを理解するためには、源平盛衰記を読破しなければならない。これも、10代では、難しいだろう。

古文や漢文も、10代の頃から読んではいたが、当時は、本当の面白さを理解してないなかった。もっとも、私のことだから、30代になれば、「20代の頃は、古文漢文の本当の本当の面白さを理解していなかった」などと思うのであろう。

これを思うに、結局、時間が足りないということだろうか。

では逆に、10代のうちから楽しめる書物は何か。私の経験では、太宰治、中島敦、吉川英治である。彼らの書く文章は独特の勢いがあり、特に難しいことを考えなくても読める。ただし、20代になると、もう楽しむことはできない。というのも、彼らの小説は、筋書きが違うだけで、後はすべて同じだからだ。太宰治は、陰鬱な文章ばかり書いているし、中島敦は、人より優れていながら、何らかの理由によって成り上がれないでいる主人公の話ばかりだ。これは、作者の性格と環境が影響しているのであろう。吉川英治は、王道とも言うべき大筋を、どの小説に対しても適用する。特に不自由せず暮らしていた人物が、ある問題を発端として、これまでの人生を否定せねばならず、その結果として放浪の旅があり、最後には問題を円満に解決するといったものだ。

2010-09-28

NINTENDO64は64だった!


Digg - Nintendo 64 coincidence? (PIC)

あのNINTENDO64のロゴは、頂点数もポリゴン数も、ちょうど64個で構成されていたらしい。実際に自分でダンプして確かめたわけではないので、真偽は分からないが、任天堂ならば、さもありなんと思える遊び心だ。

2010-09-26

国勢調査

風邪を引いたらしく、朝から寝ていた。三時頃に、チャイムの音で起こされた。出てみると、国勢調査らしい。用紙を渡された。

前に、日本のプログラマーの人口を推定するという話で、国勢調査があるということを知った。その時の調べで、今年の10月だと知っていたので、そろそろだとは思っていたが、すっかり忘れていた。ともかく、これで、2010年のプログラマー人口を推定できるかもしれない。楽しみだ。

しかし、私の仕事はプログラマーと言えるかは疑問だ。早く参考書を書き終えなければ。

起きて数十分ぐらいは、だいぶ風邪も治ったかと思ったが、一時間経つと、明らかに体調が悪くなってきた。残念ながら、風邪が治るには、まだもうしばらくかかりそうだ。それにしても、こう季節の変わり目ごとに、風邪をひいていては、キリがない。毎年毎年、夏から冬にかけてと、冬から春にかけてと、気候が急激に変わるときに、体調を崩しているのだ。親は決まって、不養生と生活環境とを挙げるが、どうもこれは、体質なのではないかと思う。

しかし、今回の風邪は、比較的マシな方だと思う。鼻水と喉が痛いだけで、頭痛や、気だるさなどは、常よりは少ない。少なくとも、横になっていれば、ほとんど頭痛や体のだるさはない。

ちなみに、今昔物語集では、(かぜ)という表記で、ちらほら出てくる。

2010-09-25

std::initializer_listはどのように実装されるのか

初期化リストを使うにあたって、初心者が信じてしまうかもしれないと懸念される問題は、std::initializer_listは、通常の配列に比べて、遅いのではないかという迷信だ。規格によれば、std::initializer_listは、通常の配列をautomatic storage、もしくはstatic storage上に構築し、その配列へのポインターを格納するのと、何ら変わることはない。

例えば、以下のようなコードは、

void f() 
{
    for ( auto i : { 1, 2, 3 } )
    {
        std::cout << i << std::endl ; 
    }
}

最終的に、以下のように置き換えることができる。

void f()
{
    int a[3] = { 1, 2, 3 } ;
    int * iter = a ;
    int * last = a + 3 ;
    for ( ; iter != last ; ++iter )
    {
        auto i = *iter ;
        std::cout << i << std::endl ;
    }
}

もちろん、細部をどのように実装するかについては、実装により異なる。しかし、初期化リストの各要素を格納するオブジェクトは、automatic storageかstatic storage上に構築可能である。

これを考えれば、std::minとstd::maxを、initializer_listで実装するか、Variadic Templatesで実装するかというのは、パフォーマンスを考えて見れば、ささいな違いではないかと思う。

したがって、std::initializer_listのパフォーマンスを心配するのは、「static変数やローカル変数、関数の実引数や戻り値のオブジェクトは、実装によってどこかよく分からないストレージ上に構築されるので信用ならん」と言うのに等しい。

いや、メモリーじゃなくてストレージという言葉が出てくる時点で、こう考えることはあり得ないか。

風邪

どうやら、風邪をひいたらしい。季節の変わり目になるといつもこうだ。

2010-09-23

ささやかな楽しみ

コンパイラの規格違反を発見するのが、私のささやかな楽しみとなっている。もちろん、VC10では、規格通りの解釈されるコードを探すほうが難しいので、まったくもってやりがいがない。gccには、なかなかそういうことがないので、規格違反を発見したときは、実にいい気分になる。たいてい、数ヶ月に一度ぐらいしか、規格違反は見つけられないのが困りものだが。

このたび、面白いバグを発見した。ひょっとしたら、まだどのコンパイラも正しく実装していないだけなのかもしれないが、バグには違いない。

メンバーテンプレート関数は、クラスの「コピー」のために、インスタンス化されることはない。

struct S
{
    S() = default ;
    template < typename T >
    S( T && ) { std::cout << "bad copy constructor" << std::endl ; }

    template < typename T >
    S & operator = ( T && ){ std::cout << "bad copy assignment operator" << std::endl ; return *this ; }
} ;

int main()
{
    S a ;
    S b = a ; // use trivial copy constructor
    b = a ; // use trivial copy assignment operator
}

このコードは、コピーのために、trivialなコピーコンストラクターとコピー代入演算子を使う。メンバーテンプレート関数はインスタンス化されない。したがって、このコードを実行しても、何も出力されない。

ところが、関数の仮引数がrvalueリファレンスの場合、VC10は、テンプレートなコンストラクターを呼び出してしまった。gccに至っては、コンストラクターに加えて、代入演算子も呼び出してしまっている。これは誤りである。

何故、コンパイラは、こんな単純な間違いを犯したのか。それは、インスタンス化されないのは、あくまで「コピー」に対しての話だからである。ムーブに対しては、問題なくインスタンス化される。

// 上記のクラス定義を使う

int main()
{
    S a ;
    S b = std::move(a) ; // use member template function
}

このコードは、テンプレート版の代入演算子をインスタンス化して、ムーブのために使う。その結果、bad copy assignment operatorと出力される。この挙動は正しい。

また、テンプレートパラメータへのrvalueリファレンスを、関数の仮引数にすると、argument deductionで、lvalueリファレンスにもなりうるという仕様がある。

template < typename T > void f( T && ) ;

int main()
{
    int object ;
    f( object ) ; // Tはint &
    f ( std::move( object ) ) ; // Tはint &&
}

このため、単にメンバーテンプレート関数であればインスタンス化を禁止するというだけではだめで、コピーかムーブかという違いを、コンパイラがしっかり認識していなければならない。コンパイラの実装には詳しくないが、まあ、ちょっと仕様が複雑だというのは理解できる。

ムーブが言語機能に取り入れられたのは、かなり最近の話だが、それだったら軒並みインスタンス化されなくてもいいものを、何でインスタンス化してしまうのか。まあ、軒並み禁止してしまったら、まともにrvalueリファレンスが使えなくなるので、ムーブを言語に取り入れていなかった規格の問題だったというべきなのかもしれない。

Google日本語入力の開発版が更新された

Google Japan Blog: Google 日本語入力の開発版をアップデートしました。(0.13.481.10x)

どうやら今回は、開発版ユーザーの中でも、一部だけにアップデートがかかるらしい。そしてどうやら、私はその一部の開発ユーザーになったらしく、アップデートされた。

Windows版のIMEのAPIが、TSFからIMMに退化(?)したのはどういう理由があるのだろう。

今回は、辞書の更新も入っているらしく、当て字が大幅に強化されたらしい。また、開発者は、Twitterでこんなことを言っている。

Twitter / Taku Kudo:

当て字が大幅にサポートされました。超電磁砲とか、約束された勝利の剣(えくすかりばー)なんてのも変換できます。信頼性の高い当て字をウェブからマイニングしています。

Twitter / Taku Kudo:

超電磁砲は、「れーるがん」で変換することができた。約束された勝利の剣には、どのような由来があるのやら。ググッたところ、有名な同人ゲーム、Fate/stay nightに由来するようだが。

追記:Fateは同人ゲームではないというツッコミを受けたので訂正。調べたところ、Fateの販売元であるTYPE-MOONは、昔は同人サークルであったが、いまは同人を卒業して、商業でやっているらしい。商業ベースで出した一作目が、Fateなのだとか。

参考:
Fate/stay night - Wikipedia
TYPE-MOON - Wikipedia

また、前回の開発版には、Windows版がなかったが、今回からは、辞書に顔文字も入っているようだ。「かおもじ」で変換したところ、548件の顔文字候補がでてきた。

せっかくなので、当て字の変換をさせて遊ぼうかと思ったが、ふと気がついてみれば、もうかれこれ五年以上、マンガもアニメもゲームもラノベも読んでいないのである。中二病全開の当て字はさっぱり分からない。

ともかく、あとは、古語と旧仮名遣いがあらまほしきかな。