概要

はじめに

MATH1(数学処理下位パッケージ)は, 地球流体電脳ライブラリ群のなかでも, もっとも基本的なサブルーチンおよび関数を集めたパッケージである.

MATH1 は,いくつかのサブパッケージからなる.

これらの中の多くのサブパッケージでは, 「欠損値の処理」や「実数の誤差を考慮した大小関係の判定」 ができるようになっている. なお,これらのサブパッケージの中でソースレベルでの機種依存性が あるのは OSLIB のみである. ( SYSLIB はシステムに依存する定数を管理している.)

以下本章では,MATH1 の特色である内部変数管理, 欠損値処理, 並びに,誤差を含めた判断について若干の解説をおこない,さらに,そのよ うなパッケージのよってきたる FORTRAN 77 の構造について説明を行なう ことにする.

内部変数

地球流体電脳ライブラリでは, MATH1/SYSLIB の GLpGET/GLpSETのような内部変数管理ルーチン が多く使われている. (ここで,pR/I/L/C のどれかで, それぞれ,実数,整数,論理変数,文字変数用である.) 内部変数管理ルーチン とは,設定された変数の値を保持し, 問い合わせに答えて値を返す機能を持ったルーチンで, 「掲示版」のような役目をするものである. この様なルーチンを使う理由は,

である.複数のサブルーチンで情報を共有するには, COMMON BLOCK を使うこともできるが, これを多用するとプログラムの可読性を落とすことにつながるので, 電脳ライブラリでは極力 COMMON BLOCK の使用を避けている. また,サブルーチンの引数を少くすると融通の効かないサブルーチンになって しまうが,かといって,むやみに引数の数を増やすとかえって使いにくくなっ てしまう. このような問題を解決するのが 内部変数管理ルーチン である. もともと「パッケージの内部で使われる変数」という意味で, 内部変数という言葉を使っているが, その変数はパッケージ外からも設定/参照できるので, その有効範囲からすると C 言語の「外部変数」に 似た性格を持つものである.

内部変数管理ルーチンは xxpGET xxpSETという名前 (xx は通常パッケージの先頭2文字) を持ち, あらかじめ,システムが用意した変数の値(システムデフォルト)を 保持している. この値は xxpGETによって参照, xxpSETによって変更することがでる. 電脳ライブラリの多くのルーチンでは, 必要なパラメタの多くを xxpGETによって取得しており, ユーザーが何も指定しなければシステムデフォルトを使い, xxpSETで値を指定すれば,その値を使うようになっている.

この内部変数は実行時オプションによって変更することもできる. 実行時オプションとは,プログラム実行時に外部環境と交信することによって 内部変数への介入を可能にするような指定である. 具体的には,外部ファイル,環境変数,コマンドライン引数など による交信手段を念頭においた概念であるが, それがどのように実現されているかは,システムに依存する. なお, 実行時オプションの効力は,システムデフォルトよりも強く, xxp SETの指定よりも弱い.

実行時オプションに比べて xxpSETによる設定は強力なので, その設定を実行時に変更することができないが, 実行時オプションより効力の弱い xxpSTXというルーチンも 用意されている. これを使えば, プログラム中でデフォルト値(ユーザーデフォルト)を設定し, 実行時に変更することが可能になる.

内部変数の設定手段を,その効力の強さの順に並べると,

                           
  1:   xxpSET              
                           
  2:   実行時オプション    
                           
  3:   xxpSTX              
                           
  4:   システムデフォルト  
                           

となる.

実行時オプションは,「オプション名」と「オプションの値」の組合せからなり, 複数個指定できる. オプション名は原則として,介入しようとする内部変数を 管理している xxpGET/xxpSET の最初の2文字 'xx' と 内部変数名 'PNAME' を組み合わせて xx:PNAME となる.

環境変数を通してオプションを指定する場合, 例えば UNIX の C シェル環境で GLpGET/GLpSETが 管理する内部変数 'MSGLEV' を 1 に変更したいときには,

    > setenv GL:MSGLEV 1

とする. このとき環境変数名はすべて大文字でなければならない.

また,コマンドライン引数を通してオプションを指定する場合は, 原則としてオプション名に - 記号を付け, さらにオプション名とオプションの値の間に '=' を入れて, -xx:PNAME=value という形式で指定する (環境変数名と違って大文字・小文字の区別はない). 例えば,sample というプログラム実行時に

    > sample -gl:msglev=1

とすると,上記の環境変数の場合と同じ結果が得られる. ここで,'=' 記号の前後に空白を入れてはいけない.

外部ファイルを通してオプションを指定する場合は,

gl:msglev  1
gl:lmiss .true.

のように(行のはじめの番号は便宜的につけてある), オプション名とオプションの値を並べて書いたファイルを, たとえば .dclrc として カレントディレクトリに用意してやればよい. ここで,オプション名は第1カラム目から書きはじめ, オプションの値との間は1個以上の空白によって 区切らなければならない(タブなどを入れてはいけない). 読み込むファイルを検索するルールについては, 第[here]節を参照のこと.

なお,環境変数,コマンドライン引数,外部ファイルを通して 同じオプションを指定した場合には, 原則としてその優先順位はコマンドライン引数, 環境変数,外部ファイルを通して指定したもの順になる. (コマンドライン引数による指定が一番強い.)

欠損値処理

自然を相手に観測などする場合, 観測機器の不調等により正常にデータが取れない場合がある. そのような場合,本来データを書くべきところに, 特定のある数値(例えば999.) を書いて, 正常にデータが取れていないことを示すことがある. この「正常なデータでない」ことを意味する数値が欠損値である. 地球流体電脳ライブラリの多くのパッケージでは, このような欠損値を含むデータを直接扱うことができる.

例えば, 次のようなデータがあったとしよう.

+----------------------+------+------+------+--------+------+------+--------+
| 日最高気温の月平均値 |      |      |      |        |      |      |        |
|----------------------|------|------|------|--------|------|------|--------|
| 月観測点             | 札幌 | 仙台 | 東京 | 名古屋 | 京都 | 福岡 | 鹿児島 |
|----------------------|------|------|------|--------|------|------|--------|
| 1月                  | -1.  | 5.0  | 9.5  | 8.4    | 999. | 9.3  | 12.2   |
|                      | 1    |      |      |        |      |      |        |
|----------------------|------|------|------|--------|------|------|--------|
| 7月                  | 24.  | 25.  | 28.  | 999.   | 999. | 30.  | 31.4   |
|                      | 8    | 6    | 8    |        |      | 6    |        |
+----------------------+------+------+------+--------+------+------+--------+

1月の京都,7月の名古屋,京都の 999. は データが正常に得られなかったことを示している. 1月,7月それぞれの月のデータを配列T1, T7に読み込んで 平均値を算出するとき, 999. まで有効なデータとして扱ってしまうと, とんでもない値が算出されてしまう. そこで,以下のように GLpGET/GLpSETが管理する内部変数'LMISS'.TRUE.として(初期値は.FALSE.) RFALIBのRAVEを用いれば, 999. を除いた平均値が算出できる.

      CALL GLLSET('LMISS', .TRUE.)
      TAVE1 = RAVE(T1, 7, 1)
      TAVE7 = RAVE(T7, 7, 1)

なお,欠損値処理をおこなうことができる関数では, すべての配列要素が欠損値のときは欠損値が返される.

また,VRBLIBのVRADDを用いて 配列T1T7の和をTXとして求めるときは,

      CALL GLLSET('LMISS', .TRUE.)
      CALL VRADD(T1, T7, TX, 7, 1, 1, 1)

としてやればよい. 'LMISS'.TRUE.としたとき, VRADDT1およびT7の配列要素の少なくとも どちらかが欠損値ならば欠損値を返すようになっているので, この場合,名古屋,京都に対応するTXの配列要素は 欠損値となる.

欠損値は GLpGET/GLpSETが管理する内部変数 'RMISS'で指定され,初期値は 999. である. 999. という値は,気温としては本来ありえない値なので, 気温データなどの場合には問題はないが, この値がデータの範囲に入ってしまうような場合には, 'RMISS'の値を変更しておく必要がある.

誤差を含めた判断

計算機内部で実数値は近似的に扱われるため, どうしても誤差を含んでしまう. 例えば,

      LOGICAL LEQ

X = 1. Y = X/3. LEQ = X .EQ. (Y*3.)

というプログラムではLEQ.TRUE.にならない. しかし,もともとXYは近似値なのであるから, それらを比較するときも近似的に比較するのが合理的であり, 実際そのような比較をしたい場合も多い. すなわち,XY*3.が正確に一致するかどうかではなく, 近似的に一致するかどうか調べたい場合も多い.

そのような場合のために,LRLLIB が用意されている. 例えば,

      LOGICAL LEQ, LREQ

X = 1. Y = X/3. CALL GLLSET('LEPSL', .TRUE.) LEQ = LREQ(X, Y*3.)

とすると, 近似的な比較が可能になる. LREQ は LRLLIBの関数で, 2つの値が計算機の精度内で近似的に一致するかどうか調べるものである. ここでいう計算機の精度とは GLpGET/GLpSETの管理する内部変数'REPSL''RFACT'をかけた値である. 'REPSL'には, 実際の実数の内部表現の精度に安全率として10倍をかけた値が設定されており, 'RFACT'には初期値として1が設定されている. 'REPSL'はライブラリのインストール時に決るもので, この値をプログラムの中で変更することはできないが, 計算精度が悪くて, この値よりもラフな比較をしたい時には, 内部変数 'RFACT'に1以上の数値を指定すればよい.

LRLLIBだけでなく,MATH1のいくつかのサブパッケージには同様の機能がある.


Back to Main


Latex Source


地球流体電脳倶楽部 : 95/6/9 (Version 5.0)

NUMAGUTI Atusi <a1n@gfdl.gov>
Last Modified: Thu Aug 31 13:00:46 EDT 1995