1. 導入
数値計算の現場において、データセットに含まれるNaN(非数)や異常値の除去は、モデルの安定性を左右する重要な前処理です。ループ処理で一つずつ条件判定を行うのはコードが冗長になりがちで、計算効率も低下します。そこで活用したいのが、FortranのMERGE関数による「スカラー混合」というテクニックです。これを用いることで、配列の形状を維持したまま、特定の条件を満たす要素だけを瞬時に定数で置換することが可能になります。
2. 基礎知識
FortranのMERGE(TSOURCE, FSOURCE, MASK)関数は、マスク条件に基づいて二つのソースから値を選択する関数です。MASKが真(.true.)であればTSOURCEを、偽(.false.)であればFSOURCEを選択します。
ここで重要なのが「スカラー混合」の概念です。通常、MERGEの引数は配列同士であることが多いですが、一方がスカラー(単一の値)であっても、Fortranのコンパイラはそれを配列の形状に合わせて自動的にブロードキャスト(拡張)して処理します。これにより、メモリ効率と可読性を両立させたクリーンなコードが実現できます。
3. 実装/解決策
異常値を置換する際、最も単純な手法は「正常な値」のマスクを生成することです。例えば、NaNを判定する際には組み込み関数のIS_NAN(Fortran 2003以降)を使用します。
具体的には、”もし値がNaNでなければ元の値を維持し、NaNであれば0.0に置き換える”というロジックをMERGEで記述します。これにより、IF文を用いたループ処理を排除し、SIMD命令などを利用した高速な演算が可能となります。
4. サンプルプログラム
以下のコードは、配列内のNaNを0.0に置換する実用的なサンプルです。
program merge_example
implicit none
real, dimension(5) :: raw_data
real, dimension(5) :: clean_data
! サンプルデータの作成:NaNを含む配列
raw_data = [1.0, -999.0, 3.0, 4.0, 5.0]
! 便宜上、2番目の要素をNaNとみなす処理(実際にはieee_arithmeticモジュール等を利用)
raw_data(2) = 0.0 / 0.0
! MERGE関数によるクリーニング処理
! 条件式: .NOT. IS_NAN(raw_data) が真なら元の値、偽なら0.0を採用
clean_data = merge(raw_data, 0.0, .not. isnan(raw_data))
print , "元のデータ: ", raw_data
print , "変換後データ: ", clean_data
end program merge_example
5. 応用・注意点
この手法を用いる際に注意すべき点は、メモリの割り当てと型の一致です。MERGE関数は戻り値として新しい配列を生成するため、巨大な配列に対して頻繁に実行するとメモリ消費量が増大する可能性があります。計算資源が極めて限られている環境では、必要に応じて配列のスライシングを活用し、メモリ上の特定領域のみを更新する設計も検討してください。
また、比較対象がNaNである場合、単なる等号(==)ではなく、必ずIEEE_IS_NANなどの専用関数を用いて判定を行ってください。浮動小数点演算の性質上、NaN同士の比較は常に偽となるため、意図しないバグの温床となるリスクがあるためです。実務では、標準的なライブラリ関数を積極的に活用し、コードの堅牢性を確保することを推奨します。

コメント