【入門編】SQRT関数の浮動小数点演算ユニット(FPU)利用 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!IBMメインフレームの世界へようこそ。
JavaやCOBOLでの開発経験をお持ちの方なら、「よし、新しい言語を覚えるぞ!」というワクワク感と同時に、「レガシーシステムって、なんだか要塞みたいで近寄りがたいな……」という少しの緊張感をお持ちかもしれませんね。

大丈夫です、怖くないですよ。一つずつ紐解けば、PL/I(ピーエルアイ)も他の言語と本質は変わりません。むしろ、非常に表現力が豊かで、ハードウェアの性能を極限まで引き出せる面白い言語なんです。

今回は、数あるPL/Iの機能の中でも、「ハードウェアの力をダイレクトに借りる計算処理」、具体的には組み込み関数である `SQRT`(平方根)と、それを取り巻くちょっとユニークなデータ規則についてお話ししていきますね。

—

1. 他の言語とはちょっと違う?PL/Iの「予約語」の秘密

JavaやCOBOLを触ってきた方だと、「えっ、この単語って変数名に使えないんだっけ?」とコンパイラに怒られて頭を悩ませた経験、ありませんか? 例えば、`VALUE` や `DATA` なんて、ごく普通の英単語なのに予約語だったりしますよね。

ところが、PL/Iの非常にユニークな(そして初学者が最初に驚く)特徴として、「PL/Iには厳密な意味での『予約語』が存在しない」という仕様があります。

どういうことかと言うと、極端な話、システムが標準で提供している機能の名前(例えば今回の主役である `SQRT` や、入出力の `READ` など)でさえ、あなたが変数名として使えてしまうのです。

1
/ こんな変態的な(笑)宣言も、PL/Iの文法上はエラーになりません /
DCL SQRT FLOAT(53); — SQRTという名前の浮動小数点数型の変数
DCL READ FIXED BIN(31); — READという名前の整数型の変数

「えっ、じゃあコンパイラはどうやってそれが『関数』なのか『変数』なのか見分けているの?」って思いますよね。
PL/Iは、「文脈(コンテキスト)」でそれを判断します。後ろにカッコ `( )` が続いて値を受け渡していれば関数、単独で置いてあれば変数、といった具合に、前後の文脈から空気を読んで解釈してくれるのです。

……とはいえ、実務の現場で `SQRT` という名前の変数を作るのは、将来のメンテナンス担当者(あるいは未来のあなた自身)を絶望の淵に追い込むテロ行為なので絶対にやめましょうね! ルール上は自由度が高くても、良識あるプログラミングを心がけましょう。

—

2. メインフレームの心臓部を叩く:SQRT関数とFPU(浮動小数点演算ユニット)

さて、基幹システムで金利計算や科学技術計算、あるいは複雑な統計処理を行う際、平方根(スクートルート)を計算するシーンは意外と多いものです。

PL/Iで平方根を求めるには、組み込み関数の `SQRT` を使います。
Javaの `Math.sqrt()` や、COBOLの関数と同じ感覚ですね。

1
Dcl MY_VALUE FLOAT(53) INIT(144.0);
Dcl RESULT FLOAT(53);

/ 平方根を計算する /
RESULT = SQRT(MY_VALUE);

ここで注目してほしいのは、このコードがIBMメインフレーム( z/Architecture )の上で実行されるとき、裏側で何が起きているかです。
PL/Iコンパイラは、この `SQRT` という記述を見つけると、ソフトウェアでちまちま計算するようなまどろっこしいコードは吐き出しません。メインフレームのハードウェアが持つ、専用の浮動小数点演算ユニット(FPU)の高速なハードウェア命令(平方根を求めるマシン語命令)を直接呼び出すように翻訳します。

これにより、何百万件という膨大なバッチ処理の中でも、瞬時に、かつ正確に計算結果を得ることができるのです。メインフレームの圧倒的なパワーを体感できる瞬間ですね。

—

3. 「負の数」をぶっ込んだらどうなる?例外処理との連携

ここで一つ、実務で絶対に知っておかなければならないトラップ(というか仕様)のお話です。

数学の授業を思い出してください。実数の範囲において、マイナスの数字の平方根(例: $\sqrt{-9}$)は存在しませんよね?
もし、バッチプログラムの不具合や予期せぬ入力データのエラーによって、この `SQRT` 関数にマイナスの値を渡してしまったら、ハードウェアやプログラムは一体どうなるでしょうか?

「そんなの、即座に異常終了(ABEND)してジョブが落ちるに決まってる!」と思いますよね。
Javaなら `ArithmeticException` や `NaN (Not a Number)` が返ってくるでしょうか。

PL/Iの懐の深い(あるいは恐ろしい)ところは、これを「条件(Condition)」という仕組みでプログラマがハンドリングできるようにしている点です。
ハードウェアレベルで「おい、マイナスの平方根なんて計算できねぇよ!」というシグナル(浮動小数点例外)が上がると、PL/Iのランタイム環境はそれをキャッチし、プログラム内の特定のルーチンに処理を飛ばすことができます。

これが、PL/Iの「ON条件(ON-condition)制御」です。

1
/ 浮動小数点エラー(FIXEDOVERFLOWやZERODIVIDE、INVALIDOPなど)を捕捉する準備 /
ON ERROR
BEGIN;
DISPLAY(‘【警告】計算処理においてハードウェア例外または無効な引数が検出されました!’);
/ ここにログ出力や異常終了を回避するリカバリ処理を書くことができます /
GOTO CALC_ERROR_ROUTINE;
END;

/ 実際に計算を行うロジック /
DCL INPUT_DATA FLOAT(53) INIT(-16.0); / うっかりマイナス値が入ってきた想定 /
DCL ANS FLOAT(53);

ANS = SQRT(INPUT_DATA); / ここでハードウェアのFPUが「おや?」と検知する /

RETURN;

CALC_ERROR_ROUTINE:
/ 異常時のフェイルセーフ処理 /
ANS = 0.0;
DISPLAY(‘処理を安全なデフォルト値(0.0)で継続します。’);

このように、PL/Iではハードウェアが発する悲鳴(例外)を、高級言語の構文で優しく包み込んでコントロールできるようになっています。
「プログラムがいきなりシステム基盤ごとブッ飛ぶ(ABENDする)」のを防ぎ、安全にエラー処理に誘導するための、レガシーシステムならではの知恵と頑健性がここに詰まっているわけですね。

—

まとめ

いかがでしたでしょうか?

  • PL/Iには厳密な予約語がないため、文脈で解釈される(でも変数名に紛らわしい名前は使わない!)
  • `SQRT` 関数は、単なるライブラリ関数ではなく、メインフレームのハードウェア(FPU)の命令を直接叩く超高速な仕組みである
  • 万が一、マイナス値のような無効な引数を渡してしまっても、`ON条件` を使ってハードウェア例外と連携し、プログラムを優しく守ることができる

メインフレームやPL/Iの世界は、一見すると古めかしく難解に見えますが、その実体は「ハードウェアの性能を極限まで引き出しつつ、システムを絶対に止ませないための工夫」の塊です。

「レガシーだけど、なんだか理にかなっていて面白いかも」
そう思っていただけたら、システムアーキテクトとしてこれほど嬉しいことはありません。

それでは、次回のメインフレーム・アドベンチャーでお会いしましょう!

タイトルとURLをコピーしました