7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FortranAdvent Calendar 2021

Day 6

Fortranの標準ライブラリstdlibの紹介(組込機能の代替・補足)

Last updated at Posted at 2021-12-06

概要

Fortran-langコミュニティが主導して開発しているFortraの標準ライブラリstdlibについて紹介します.紹介する内容は,stdlibの現行バージョン0.1.0に基づいています.

本記事では,組込機能の代替・補足として使える機能を紹介します.

  • stdlib_error
  • stdlib_kinds
  • stdlib_io
  • stdlib_optval

stdlib_error

stdlib_errorモジュールでは,エラー処理関わる手続を定義しています.モジュール内には,手続が二つ定義されています.

  • check
    条件式の結果を調べ,条件が成立していない場合にプログラムを停止する.
  • error_stop
    プログラムを停止する.

check

checkは,引数に論理値を取り,論理値が.false.の場合にプログラムを停止します.実用上は,論理値ではなく条件式を渡して条件成立の成否を確認する,assertionに用いられます.

サブルーチンであるため,call check(condition[, msg][, code][, warn])として呼び出します.引数はそれぞれ下記の意味があります.

引数名 用途
condition logical,intent(in) 条件式の結果
msg character(*),intent(in),optional 出力されるエラーメッセージ.標準値はCheck failed.
code integer,intent(in),optional 終了コード.標準値は1
warn logical,intent(in),optional プログラムを終了しない.標準値は.false.

使い方

  • 引数condition.false.のとき,Check failed.を出力し,終了コード1でプログラムを終了する.
call check(condition=.false.)
!  Check failed.
! ERROR STOP 1
  • 論理値ではなく条件式を渡して条件成立の成否を確認する.
integer :: a = 1

call check(a == 0)
!  Check failed.
! ERROR STOP 1
  • a==0.false.のとき,引数msgに渡した文字列を出力し,終了コード1でプログラムを終了する.
integer :: a = 1

call check(a == 0, msg="error: actual value of a is not equal to expected value 0")
!  error: actual value of a is not equal to expected value 0
! ERROR STOP 1
  • 条件式が.false.のとき,引数msgに渡した文字列を出力し,終了コード77でプログラムを終了する.
integer :: a = 1

call check(a == 0, "error: actual value of a is not equal to expected value 0", code=77)
!  error: actual value of a is not equal to expected value 0
! ERROR STOP 77
  • 引数warnに.true.を渡すと,プログラムは終了しない.
integer :: a = 1

call check(a == 0, "warning: actual value of a is not equal to expected value 0", warn=.true.)
!  warning: actual value of a is not equal to expected value 0

error_stop

error_stopは,エラーメッセージを表示して,非ゼロの終了コードでプログラムを終了します.Fortran 2018にerror stop文があり,それと機能は同じです.一方で,Fortran 2008のerror stop文は定数式を指定できますが,変数を指定できません.error_stopは,この機能不足を補い,Fortran 2008でも2018でも同じように書けるようにするために導入されています.

call error_stop(msg[, code])として呼び出します.引数はそれぞれ下記の意味があります.

引数名 用途
msg character(*),intent(in) 出力されるエラーメッセージ.
code integer,intent(in),optional 終了コード.標準値は1

使い方

  • 引数msgに渡した文字列を出力し,非ゼロの終了コードでプログラムを終了する.
call error_stop(msg="Fatal error")
!  Fatal error
! ERROR STOP
  • 引数に渡した文字列を出力し,終了コード999でプログラムを終了する.
call error_stop("Fatal error", code=999)
!  Fatal error
!  ERROR: code          999  was specified.
! ERROR STOP

stdlib_kinds

stdlib_kindsモジュールでは,Fortranのデータ型の種別kindを指定する定数が定義されています.

Fortran 2008で単精度および倍精度のkindを指定するパラメータreal32およびreal64が定められました.しかし,単精度のkindをsp,倍精度をdpとする習慣があったので,それを踏襲したのだと考えられます.

lkは論理型変数のkindです.

定義されている定数

  • sp
    単精度浮動小数点数のkind(=real32).selected_real_kind(6)の戻り値.
  • dp
    倍精度浮動小数点数のkind(=real64).selected_real_kind(15)の戻り値.
  • xdp
    拡張倍精度浮動小数点数のkind.selected_real_kind(18)の戻り値.利用できない場合-1
  • qp
    4倍精度浮動小数点数のkind(=real128).selected_real_kind(33)の戻り値.利用できない場合-1
  • lk
    論理値のkind.

定義されている定数以外に,iso_fortran_envモジュールに定義されているint8, int16, int32, int64が読み込まれ,公開されています.同様に,iso_c_bindingモジュールに定義されているc_boolも公開されています.

stdlib-fpm

xdpおよびqpは,cmakeおよびfyppの機能を用いて値が定められます.fpmを用いてビルドする場合,プリプロセスができないため,xdp, qpともに-1となっています.

stdlib_kinds.f90
  !> Extended double precision real numbers
  integer, parameter :: xdp = -1

  !> Quadruple precision real numbers
  integer, parameter :: qp = -1

これらは,selected_real_kindを用いるように変更した方がよいでしょう.コンパイラが拡張倍精度や4倍精度浮動小数点数をサポートしていなければ,selected_real_kind-1を返します.

stdlib_kinds.f90
  !> Extended double precision real numbers
  integer, parameter :: xdp = selected_real_kind(18)

  !> Quadruple precision real numbers
  integer, parameter :: qp = selected_real_kind(33)

stdlib_io

stdlib_ioモジュールでは,入出力の利便性を改善する手続が定義されています.

  • open
    ファイルを開き,その装置番号を返す.
  • savetxt
    2次元配列をテキスト形式でファイルに書き出す.
  • loadtxt
    2次元配列をテキスト形式でファイルから読み込む.

open

open関数は,ファイルを開き,その装置番号を返します.

unit_number = open(filename[, mode][, iostat])として利用します.戻り値unit_numberintegerです.引数はそれぞれ下記の意味があります.

引数名 用途
filename character(*),intent(in) ファイル名.
mode character(*),intent(in),optional ファイルを開くモード.標準はrt
iostat integer,intent(out),optional open関数のエラー状態.エラーがなければ0

モード

モードは,テキストで指定します.

テキスト モード
"r" 読み取り専用として開く.(標準)
"w" 書き込み用に新規に開く.(既存ファイルの中は消去される)
"x" ファイルを新規作成する.ファイルが既に存在する場合は処理が失敗する.
"a" ファイルを追記するために開く.
"+" ファイル更新(読み取り,書き込み)用に開く
"b" バイナリモードで開く.
"t" テキストモードで開く(標準)

使い方

integer(int32) :: unit
character(128) :: str

! 書き込み+テキストモードで開く.
unit = open ("example_io.txt", "wt")
close (unit)

! 読み取り+テキストモードで開く
unit = open ("example_io.txt", "rt")

! 書き込みをしようとするとエラー.
! write (unit, '(A)') "append to example_io.txt"
close (unit)

! 追記モードで開く
unit = open ("example_io.txt", "a")
close (unit)

savetxt

サブルーチンsavetxtは,2次元配列をテキストモードでファイルに書き出します.

call savetxt(filename, array)として利用します.引数はそれぞれ下記の意味があります.

引数名 用途
filename character(*),intent(in) ファイル名.
array integer,dimension(:,:),intent(in) 出力する2次元配列
real,dimension(:,:),intent(in)
complex,dimension(:,:),intent(in)

使い方

use :: stdlib_math
use :: iso_c_binding

real(real32) :: array(16, 2)

enum, bind(c)
    enumerator :: x = 1
    enumerator :: f
end enum

! stdlib_mathで定義されているlinspaceを利用してx = [0, 2π]を設定し,sin(x)を計算.
array(:, x) = linspace(0., 2.*acos(-1.), 16)
array(:, f) = sin(array(:, x))

! 2次元配列をテキストモードで出力する.
call savetxt("sin.txt", array)
sin.txt
0.00000000E+00  0.00000000E+00
4.18879032E-01  4.06736642E-01
8.37758064E-01  7.43144870E-01
1.25663710E+00  9.51056540E-01
1.67551613E+00  9.94521916E-01
2.09439516E+00  8.66025388E-01
2.51327419E+00  5.87785184E-01
2.93215322E+00  2.07911611E-01
3.35103226E+00 -2.07911789E-01
3.76991129E+00 -5.87785363E-01
4.18879032E+00 -8.66025448E-01
4.60766935E+00 -9.94521916E-01
5.02654839E+00 -9.51056480E-01
5.44542742E+00 -7.43144751E-01
5.86430645E+00 -4.06736493E-01
6.28318548E+00  1.74845553E-07

loadtxt

サブルーチンloadtxtは,テキストファイルから2次元配列を読み取ります.

call savetxt(filename, array)として利用します.引数はそれぞれ下記の意味があります.

引数名 用途
filename character(*),intent(in) ファイル名.
array integer,dimension(:,:),allocatable,intent(out) 読み取ったファイル内容を保持する2次元配列
real,dimension(:,:),allocatable,intent(in)
complex,dimension(:,:),allocatable,intent(in)

使い方

real(real32), allocatable :: array(:, :)

! テキストファイルから2次元配列を読み取る.
call loadtxt("sin.txt", array)
print *, array(:, 1)
print *, array(:, 2)
!   0.00000000      0.418879032      0.837758064       1.25663710       1.67551613       2.09439516       2.51327419       2.93215322       3.35103226       3.76991129       4.18879032       4.60766935       5.02654839       5.44542742       5.86430645       6.28318548
!   0.00000000      0.406736642      0.743144870      0.951056540      0.994521916      0.866025388      0.587785184      0.207911611     -0.207911789     -0.587785363     -0.866025448     -0.994521916     -0.951056480     -0.743144751     -0.406736493       1.74845553E-07

stdlib_optval

stdlib_optvalモジュールでは,optional引数の取り扱いを改善する手続optvalを定義しています.

optval

optvalは,optional引数が存在しない場合に標準値を定めるための関数です.

result = optval([x,] default)として呼び出します.引数はそれぞれ下記の意味があります.

引数名 用途
x integer,intent(in),optional optional引数
real,intent(in),optional
complex,intent(in),optional
logical,intent(in),optional
character,intent(in),optional
default xと同じ xが存在しない場合の標準値

使い方

  • 整数
print *, optval(1, default=0), optval(default=0)
! 1 0
  • 単精度実数
print *, optval(1., default=0.), optval(default=0.)
! 1.00000000 0.00000000
  • 倍精度実数
print *, optval(1d0, default=0d0), optval(default=0d0)
! 1.0000000000000000 0.0000000000000000
  • 論理値
print *, optval(.true., default=.false.), optval(default=.false.)
! T F
  • 複素数
print *, optval((1., 2.), default=(0., 0.)), optval(default=(0., 0.))
! (1.00000000,2.00000000) (0.00000000,0.00000000)
  • xのn乗根を計算する関数root.nの標準値は2
real(real64) :: x = 64.

print *, root(x), root(x, 3)
! 8.0000000000000000 3.9999999999999996

contains

!| xのn乗根を計算する.
real(real64) function root(x, n)
    implicit none
    real(real64), intent(in) :: x !! 被開平数
    integer(int32), intent(in), optional :: n !! 指数

    root = x**(1d0/optval(n, 2)) ! nが無いときは2が使われる
end function root
7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?