レガシーコードを gfortran でコンパイルして蹴られたところのメモ。
負の冪乗
Error: Raising a negative REAL at (1) to a REAL power is prohibited
負値を実数で冪乗することは禁止だと言っています。
(以前ここに余計なことを書いたが訂正。少なくとも Fortran 2003 には禁止規定があります(§7.1.8)。 )
ケースでは、(-12.0)**X
というようなコードがあって、X
は実数型とはいえ整数値の定数がありました。他で X
が使われていない保証ができれば整数型に変えるのですが、面倒だったので、-(12.0**X)
に置き換えました。
1行が長過ぎる
Error: Symbol 'x' at (1) has no IMPLICIT type
読んでみると x
などという変数はないのですが、 x
で始まる変数がありました。よく見ると1行が132文字(F95§3.3.1)を超えていて、先頭1文字だけが認識されていたのです。&
を使って行を折り返して解決。
エラー: Unterminated character constant beginning at (1)
文字列が途中で切れている場合はこうなります。
DATA 文の初期値と配列長が不整合
Error: DATA statement at (1) has more variables than values
DATA 文の変数(初期化項目並び)と値(初期値表現並び)の数は同じでなければなりません(F95§5.2.9に明示規定あり)。大きな配列を宣言して、DATA 文で与える値が少ないと上のメッセージが出ます(gfortran以外の大抵のコンパイラでは不足する配列要素が不定値になるようです)。逆に値が多すぎると「more values than variables」というメッセージが出ます。
「more variables than values」の場合は、DATA文にダミーの初期値を書き込むか、配列を小さくすることで解決できます。配列の大きさを無闇に変えるとメモリレイアウトの変化などによる問題が評価しきれないので、ダミーの初期値を埋め込むほうが無難でしょう。
REAL ARY(100)
DATA ARY/0., 1., 2., 3./
とあったら(たとえばダミー値 999.
を追加するなら)
REAL ARY(100)
DATA ARY/0., 1., 2., 3., 96*999./
のようにすれば解決です。値を数えるのが面倒だったら、1*999.
から増やしていってメッセージが変わったところで止めればよいです。
ちょっとやっかいなのが、配列 ARY
が EQUIVALENCE 文や COMMON ブロックなどを使って他の配列とオーバーラップしている場合です。この場合はオーバーラップ先で DATA 文を使っていると衝突してしまいます(gfortran はエラーにしてくれるのでエライです)。仕方がないので数を数えて必要なだけダミー値を設定します。
REAL ARY(100), OTHER(100)
EQUIVALENCE(ARY(51), OTHER(1))
DATA ARY/0., 1., 2., 3., 46*999./
整数型変数に文字を代入
KSY= 'X'
1
Error: Can't convert CHARACTER(1) to INTEGER(4) at (1)
整数型変数 KSY
はこの直後でサブルーチン引数としてだけ使われます。おそらくかつてはホレリス定数 1HX
をサブルーチン引数に使っていたのを書き換えたのでしょう。
Intel Fortran では字数が4の倍数ではない文字型値を整数変数に代入すると、あたかも4文字の文字型変数に代入したかのように右に空白を補ってからtransferしたかのように挙動します。つまり
KSY=TRANSFER('X ', KSY)
とすれば、gfortran でも通るし、Intel Fortran でも従来通りの挙動になります。
NAMELISTを実行文の間に書く
やりたいたいことはわかるのです。NAMELIST は所詮 READ 文の入出力対象を列挙しているだけなので、当該 READ 文の近くにあった方が読みやすい。が、 gfortran では蹴られます。
対処は簡単で NAMELIST 文を最初の実行文の前に移すだけです。
警告だから放置したもの
整数と実数を同一視する警告がほうぼうに見られました。
- DO ループの端を実数にしてはいけません
- 配列添字を実数にしてはいけません
- 実数型引数に整数を与えてはいけません
最後のはヤバイはずですが、どう変えるべきかは慎重に読む必要があります。