2012-11-30

FortranからCを呼ぶときの諸問題 @uwabami さんへ

https://twitter.com/uwabami/statuses/274207773250691072 というtwを受信したので、Fortran から C を呼ぼうとした場合の諸問題について知るところをまとめておく。

1.問題の解剖

・データ型の対応
・名前の対応
・引数順序の対応
・ランタイムがらみの話

2.データ型の対応

ちょっと考えでは無保証の荒野に放り出されるようであるが、意外とパズルの解は少ない。

Fortran には「INTEGER型とREAL型の幅が同じでなければならず、DOUBLE PRECISIONはその二倍でなければならない」という制約がある。そして、Fortranが実装されるような機械ではCコンパイラであってもIEEE 754のbinary32および
binary64型はどうせ実装されざるを得ないので、結局次の関係ができる。

REAL = binary32 = float
DOUBLE PRECISION = binary64 = double
符号付き32ビット整数 = INTEGER = int32_t ≒ int

反例は知らない。

int32_t は C99 でしか使えないので、実際には int を使うことになる。一見おっかないようだが、昔懐かし 16 ビットコンピュータか、ILP64 モデルでない限り int が 32 ビッ
トとみなして外れることはない。怖かったら typedef でもしよう。

3.名前の対応

実はこれが一番いやらしい。Fortranの名前が Cでどう見えるかには次の4通りが知られている。

: gfortran
全て小文字にして "_" を後置する。ただし、元の名前に "_" が含まれる場合は
"__" を後置する。
: Intel Fortran
全て小文字にして "_" を後置する。
: IBM XL Fortran
全て小文字にする。
: 旧Visual Fortran
全て大文字にする。

これを configure で判定するのがわりと常道だが、判定が外れるとリンクできないというリスクがあり、しかもどういうわけだかうまくいかないことが多い。個人的な趣味は、4種類のラッパーを作って .lib を作ってしまうこ
とである。

ところで、上記知見の重要な系:

Cで書かれたライブラリで、API関数名が全て小文字であるばあい、まったく同じ名前をFortranバインディングのAPIとすることは禁忌である。あなたはAIXの前で泣くか、かわいそうな犠牲者に石を投げられることになる。NetCDF がバージョン3で関
数名を変えたのも、NuSDaS の C API がすべて NuSDaS_ で始まるのもこのせいである。


4.引数順序の対応

Fortran の文字型引数は、データとともに長さも渡される。さてどうやって?
これは今日的には問題ではないかもしれないが、cfortran.h などのツールが第一に取り組もうとした課題である。

現在知られている Fortran 処理系では、文字型の引数を渡すにあたって、文字列の先頭へのポインタの次に文字列長を与える int の2つの引数を渡す。

SUBROUTINE SUB(I1, C, I2)
INTEGER:: I1, I2
CHARACTER(*):: C

というのがあったら

void sub_(int *i1, char *c, int c_len, int *i2);

になるというわけだ。しかし、文字列長引数を全ての引数の最後にまとめて置くという流儀があり、MS Fortran PowerStation ではこれがデフォルトだった。

void SUB(int *i1, char *c, int *i2, int c_len);

になるというわけだ。

5.ランタイムまわり

Fortran コードを書くならば、どうせメインは Fortran にする羽目になるものだ。

つまり、Fortran ライブラリ(文字列コピーや数学関数などの実体)だけでなく
Fortran ランタイム、すなわち main() としてコマンドラインや環境変数を受け取り、ファイル番号 5, 6 を開き、主プログラム(PROGRAM ... END)を呼び出すルーチンに依
存している機能が多いので、ランタイムをリンクしたくなるものである。

それはそれでいいが、メインを取られているということは、コマンドラインへのアクセスは Fortran の方法によらざるを得ないということだ。C から Fortran を呼ばねばならなくなるとリンケージ問題(上記3.)を必ず解決せねばならないし、文字列長が不明になるのは誠に腹立たしい。が、ま、しかたがない。

環境変数については getenv(3) が使えなくなる Fortran 処理系があるかどうか知見がない。たぶんないと思う。

もうちょっと嫌らしいのは、たいていの Fortran ランタイムはシグナルハンドラをフックするとか、OpenMPするとSIGFPEがマスクされる処理系があるとか、浮動小数点の丸めモードがある設定でないと動作保証しないFortranライブラリがあるとか、等々といった怪しいリソースだ。まあ、これらも知っていさえすればいいのだが。

2012-11-14

色覚についてのメモその4:NWSの配色

前項の続き。まずは準備、第三異常の混同色軌跡を描いてみる。
第三異常の混同色軌跡(カラーサークル視点)
(放射状というよりは平行な線に近いのに驚く。これは、RGB空間が人間の視覚の限界の実に狭い一部しか表現していないことを意味している)
つぎにこれがなるべく点に近くみえるようにRGB立方体を回転してみる。

2012-11-13

色覚についてのメモその3:資料追加、NWSサイトでみかけた配色

1.資料補遺。

混同色軌跡についてもうすこし資料的なページを見つけた。
http://www.med.teikyo-u.ac.jp/~ortho/med/pat/color.htm

第二異常の混同色軌跡の集積点はもうすこし正確に言うと x, y = 1.1, -0.07 付近のようだ。
(前稿の大勢に影響はないとおもうが)

また、第三異常の混同色軌跡の集積点は 400 nm 単色光付近にあるらしい。
(400 nm なら x, y = 0.1733, 0.0048)

2.気がついたこと

先日、元ハリケーン・サンディの関係で降水量の図を紹介した。
http://www.hpc.ncep.noaa.gov/qpf/zoom/Rainfall_Day_1.gif
かなり日本では見ない配色になっていて、いったいどういうセンスなんだろうと思っていた。

が、しかしこれはものすごく考えられているのではないかという気がしてきた。

いちど検算しないうちに図を示すのはためらわれるが、どうやらこの配色、三色視・第1異常〜第3異常のすべてにとって、それなりに弁別性がよいようなのだ。

誰も切り捨てまいとする態度に感服するとともに、おのが感覚を恥じる。

色覚についてのメモ2:色立体図

RGB 色空間は R, G, B それぞれに 0 から 255 までの数値の3つ組で、立方体型で描くことができる。どういう向きに描いてもいいのだが、三色視の人向けのデザインに有用なのは黒(0, 0, 0)と白(255, 255, 255)を重ねて置いて、周縁に飽和度の最も高い色、いわゆるカラーサークルが来るように置くことだ。
RGB色空間(カラーサークル視点)

 前回の理屈で、混同色軌跡を描いてみるとこうなる(ただしY=1は大きすぎるのでY=0.33にした)。

2012-11-12

色覚についてのメモ:混同色軌跡

CIE xy 色度図上の混同色軌跡の図がある。(図4-4)
http://www.shikikaku.jp/explan/b-2.html

第一異常の場合は約 700nm単色光の位置から放射状に、
第二異常の場合はほぼ (x=1, y=0) の位置から放射状に線が延びている。
後者は X 等色関数が赤錐体の感度曲線に近いという散文的記述に対応する(資料は知らないが整合的である)。
前者はちょっとよくわからない。

参考:理科年表によると 700nm 単色光の色度は (0.7347, 0.2653, 0.0000)

いずれにしてもこれら集積点を通る直線を何本か引いて、x+y+z=1の関係とY=1で規格化して XYZ が得られたら、次のように線形変換をすることでこれをリニアRGBに、
ついで Adobe RGB のような実用RGB値に変換することができるはずである。
http://w3.kcua.ac.jp/~fujiwara/infosci/colorspace/colorspace1.html

そうしたら、併用してはならない色の対が RGB で得られる。

とりあえず理屈だけ。