10 組込み手続
Fortran には、Fortran 言語にあらかじめ組込まれた関数やサブルーチンが用意されています。 これらは組込み手続と呼ばれ、Fortran 90 では約 100 種類が提供されています。 以下に良く利用されるものを示します。
組込み手続 | 意味 |
abs(x) | 絶対値 |
acos(x) | 逆余弦 |
asin(x) | 逆正弦 |
atan(x) | 逆正接 |
atan2(y,x) | 逆正接(2つの値より) |
sin(x) | 正弦 |
cos(x) | 余弦 |
tan(x) | 正接 |
exp(x) | 指数 |
log(x) | 自然対数 |
int(a [,kind]) | 整数へ変換(切り捨て) |
nint(a [,kind]) | 整数へ変換(四捨五入) |
real(a [,kind]) | 実数へ変換 |
dble(a) | 倍精度実数への変換 real(a,kind(0d0)) と同じ |
cmplx(x [,y] [,kind]) | 複素数への変換 |
mod(a,p) | a÷p の余り |
sqrt(x) | 平方根 |
max(a1,a2[,a3,...]) | 最大値 |
min(a1,a2[,a3,...]) | 最小値 |
len(a) | 文字長 |
len_trim(a) | 後ろの空白を除いた文字長 |
achar(i) | i によって示される ASCII 文字 |
iachar(a) | a によって示される ASCII 文字のコード |
bit_size(i) | i のビット数 |
btest(i,pos) | i の pos+1 番目のビットが 1 かどうか |
iand(i,j) | i と j のビットごとの論理積 |
ior(i,j) | i と j のビットごとの論理和 |
ieor(i,j) | i と j のビットごとの排他的論理和 |
ibclr(i,pos) | i の pos+1 番目のビットを 0 に設定 |
ibset(i,pos) | i の pos+1 番目のビットを 1 に設定 |
not(i) | i の論理否定 |
以下に組込み関数の利用例を示します。
[
intrinsics.f90
] - 組込み関数を用いるサンプル
program intrinsic_sample implicit none integer :: i = 99 real :: a = 2.5 print *, "i=", i print *, "a=", a print *, "real(i)=", real(i) print *, "dble(i)=", dble(i) print *, "int(a)=", int(a) print *, "nint(a)=", nint(a) print *, "sin(0.5)=", sin(0.5) print *, "sin(0.5d0)=", sin(0.5d0) print *, "sqrt(10.0)=", sqrt(10.0) print *, "mod(10,3)=", mod(10,3) do i=iachar("A"), iachar("A")+4 print *, achar(i) end do end program intrinsic_sample 出力例: i= 99 a= 2.5000000 real(i)= 99.0000000 dble(i)= 99.0000000000000000 int(a)= 2 nint(a)= 3 sin(0.5)= 0.4794255 sin(0.5d0)= 0.4794255386042030 sqrt(10.0)= 3.1622777 mod(10,3)= 1 A B C D E
10.1 総称名と個別名について
組込み手続を呼び出した場合に与える引数の型により内部的に別の関数が呼び出される場合があります。 例えば、
a = sqrt(b)
と記述した場合に、b の型が倍精度実数であれば内部的に倍精度実数版の関数により計算が行われます。 またもし b の型が倍精度複素数であれば内部的に倍精度複素数版の関数により計算が行われます。
例: program generic_vs_specific implicit none double precision :: a = 2.0 complex(kind(0d0)) :: b = (2.0,1.0) print *, sqrt(a) print *, sqrt(b) end program generic_vs_specific 実行例: 1.4142135623730951 (1.4553466902253549,0.3435607497225124)
内部的に呼び出される関数は Fortran 標準で規定されているものとそうではないものが存在します。 例えば上記例において sqrt(倍精度実数) は内部的に dsqrt という関数を呼び出します。 dsqrt 関数は Fortran 標準でも規定されている関数で倍精度実数型の引数を取り倍精度実数型を返す関数です。 一方で sqrt(倍精度複素数) は内部的にまた別の関数を呼び出しますが、呼び出される関数の名前は Fortran 標準では規定されていません。
ここで sqrt(任意の実数型もしくは複素数型) は総称名と呼ばれ、dsqrt(倍精度実数) は個別名と呼ばれます。 総称名を利用することにより引数の型に基づき適切な内部関数が呼び出されることになります。 また総称名の代わりに個別名を利用するメリットはほぼ皆無に等しいこともあり、組込み手続の利用は総称名で行うことが強く推奨されています。
組込み関数の個別名には上記 dsqrt のように Fortran 標準で規定されているものの他に、様々なコンパイラメーカーが独自に拡張した非標準のものが存在します。 例えばあるコンパイラメーカーでは倍精度複素数の sqrt を zsqrt と呼び、また別のコンパイラメーカーでは cdsqrt 等と呼んでいます。 このような非標準の組込み関数はプログラムのポータビリティーを損ないますので利用せずに、その代りに総称名を利用することが強く推奨されています。
以下に Fortran 標準に含まれる個別名一覧及び対応する総称名を示します。
説明 | 総称名形式 | 個別名 | 引数型 | 関数型 |
整数への変換 | int(a) | int | 単精度実数 | 整数 |
ifix | 単精度実数 | 整数 | ||
idint | 倍精度実数 | 整数 | ||
実数への変換 | real(a) | real | 整数 | 単精度実数 |
float | 整数 | 単精度実数 | ||
sngl | 倍精度実数 | 単精度実数 | ||
最大値 | max(a1,a2,…) | max0 | 整数 | 整数 |
amax1 | 単精度実数 | 単精度実数 | ||
dmax1 | 倍精度実数 | 倍精度実数 | ||
amax0 | 整数 | 単精度実数 | ||
max1 | 単精度実数 | 整数 | ||
最小値 | min(a1,a2,…) | min0 | 整数 | 整数 |
amin1 | 単精度実数 | 単精度実数 | ||
dmin1 | 倍精度実数 | 倍精度実数 | ||
amin0 | 整数 | 単精度実数 | ||
min1 | 単精度実数 | 整数 | ||
s1 >= s2 | lge(s1,s2) | lge | 文字 | 論理 |
s1 > s2 | lgt(s1,s2) | lgt | 文字 | 論理 |
s1 <= s2 | lle(s1,s2) | lle | 文字 | 論理 |
s1 < s2 | llt(s1,s2) | llt | 文字 | 論理 |
a の絶対値 * b の符号 | sign(a,b) | isign | 整数 | 整数 |
sign | 単精度実数 | 単精度実数 | ||
dsign | 倍精度実数 | 倍精度実数 | ||
x-y と 0 の大きい方の値 | dim(x,y) | idim | 整数 | 整数 |
dim | 単精度実数 | 単精度実数 | ||
ddim | 倍精度実数 | 倍精度実数 | ||
x*y | dprod(x,y) | 単精度実数 | 倍精度実数 | |
小数点以下切り捨て | aint(a) | aint | 単精度実数 | 単精度実数 |
dint | 倍精度実数 | 倍精度実数 | ||
最近傍整数 | anint(a) | anint | 単精度実数 | 単精度実数 |
dnint | 倍精度実数 | 倍精度実数 | ||
最近傍整数への変換 | nint(a) | nint | 単精度実数 | 整数 |
idnint | 倍精度実数 | 整数 | ||
絶対値 | abs(a) | iabs | 整数 | 整数 |
abs | 単精度実数 | 単精度実数 | ||
dabs | 倍精度実数 | 倍精度実数 | ||
cabs | 単精度複素数 | 単精度実数 | ||
余り | mod(a,p) | mod | 整数 | 整数 |
amod | 単精度実数 | 単精度実数 | ||
dmod | 倍精度実数 | 倍精度実数 | ||
平方根 | sqrt(x) | sqrt | 単精度実数 | 単精度実数 |
dsqrt | 倍精度実数 | 倍精度実数 | ||
csqrt | 単精度複素数 | 単精度複素数 | ||
指数 | exp(x) | exp | 単精度実数 | 単精度実数 |
dexp | 倍精度実数 | 倍精度実数 | ||
cexp | 単精度複素数 | 単精度複素数 | ||
自然対数 | log(x) | alog | 単精度実数 | 単精度実数 |
dlog | 倍精度実数 | 倍精度実数 | ||
clog | 単精度複素数 | 単精度複素数 | ||
常用対数 | log10(x) | alog10 | 単精度実数 | 単精度実数 |
dlog10 | 倍精度実数 | 倍精度実数 | ||
正弦 | sin(x) | sin | 単精度実数 | 単精度実数 |
dsin | 倍精度実数 | 倍精度実数 | ||
csin | 単精度複素数 | 単精度複素数 | ||
余弦 | cos(x) | cos | 単精度実数 | 単精度実数 |
dcos | 倍精度実数 | 倍精度実数 | ||
ccos | 単精度複素数 | 単精度複素数 | ||
正接 | tan(x) | tan | 単精度実数 | 単精度実数 |
dtan | 倍精度実数 | 倍精度実数 | ||
逆正弦 | asin(x) | asin | 単精度実数 | 単精度実数 |
dasin | 倍精度実数 | 倍精度実数 | ||
逆余弦 | acos(x) | acos | 単精度実数 | 単精度実数 |
dacos | 倍精度実数 | 倍精度実数 | ||
逆正接 | atan(x) | atan | 単精度実数 | 単精度実数 |
datan | 倍精度実数 | 倍精度実数 | ||
逆正接(y/x) | atan2(y,x) | atan2 | 単精度実数 | 単精度実数 |
datan2 | 倍精度実数 | 倍精度実数 | ||
双曲線正弦 | sinh(x) | sinh | 単精度実数 | 単精度実数 |
dsinh | 倍精度実数 | 倍精度実数 | ||
双曲線余弦 | cosh(x) | cosh | 単精度実数 | 単精度実数 |
dcosh | 倍精度実数 | 倍精度実数 | ||
双曲線正接 | tanh(x) | tanh | 単精度実数 | 単精度実数 |
dtanh | 倍精度実数 | 倍精度実数 | ||
虚数部 | aimag(z) | aimag | 単精度複素数 | 単精度実数 |
複素共役 | conjg(z) | conjg | 単精度複素数 | 単精度複素数 |
文字長 | len(s) | len | 文字 | 整数 |
開始位置 | index(s,t) | index | 文字 | 整数 |
補足:
上記一覧にはコンパイラメーカーの独自の拡張である Fortran 言語非標準の個別名は含まれていません。
これらの非標準な個別名をリストアップすることは不可能ですが、一般的なルールとして例えば "xFUN" のような非標準個別名の代わりに総称名 "FUN" を使用してください。
(ここで "x" は1文字または複数文字の個別名の接頭辞、"FUN" は数学関数の名前です。)
(良く利用される)数学関数の名前:
ABS, ACOS, ASIN, ATAN, ATAN2, CONJG, COS, COSH, DIM, EXP, LOG, LOG10, MAX, MIN, SIGN, SIN, SINH, SQRT, TAN, TANH
(典型的な)個別名の接頭辞:
C, CD, CQ, D, DC, Q, Z
例えば、非標準個別名 CDEXP, DCEXP, QEXP, CQEXP, ZEXP はどれも総称名 EXP に置き換えて同じ結果を得ることができます。
10.2 余りを求める組込み関数について
割り算の余りを求めるためには mod() 組込み関数を用いることができます。print *, mod(10, 3) ! 10÷3 の余りを表示 出力例: 1
10.3 ビット操作を行う組込み関数
ビット操作を行う組込み関数も用意されています。 以下にサンプルを示します。[ bit-operations.f90 ] - ビット操作を行うサンプル
program bit_operations implicit none integer :: i = 0 call print_bits(i,"i=0") i = ibset(i,4) ! 5 番目のビットを設定 call print_bits(i,"ibset(i,4)") i = not(i) ! すべてのビットを反転 call print_bits(i,"i=not(i)") i = ibclr(i,2) ! 3 番目のビットをクリア call print_bits(i,"i=ibclr(i,2)") i = ishft(i,5) ! 5 ビット右へシフト call print_bits(i,"i=ishft(i,5)") i = ieor(i,i) ! 同じ値どうしの排他的論理和 call print_bits(i,"i=ieor(i,i)") contains subroutine print_bits( num, msg ) integer num, i character(*) msg character(bit_size(num)) a a = ""; do i=1, bit_size(num) if ( btest(num,i-1) ) then a = trim(a) // "1" else a = trim(a) // "0" end if end do print *, a, " : ", msg end subroutine print_bits end 出力例: 00000000000000000000000000000000 : i=0 00001000000000000000000000000000 : ibset(i,4) 11110111111111111111111111111111 : i=not(i) 11010111111111111111111111111111 : i=ibclr(i,2) 00000110101111111111111111111111 : i=ishft(i,5) 00000000000000000000000000000000 : i=ieor(i,i)
10.4 ★ 練習課題:素数を求める
入力した値以下の素数をすべて出力するプログラムを作成して下さい。処理手順例
-
変数を宣言する
例)
integer i, j, n
logical sosu_desu - N を入力してほしい旨を画面に出力する(print 文)
- N をキーボードから入力する(read 文)
-
2 から n までについて調べるために反復(do)文を記述する
例)
do i=2,n -
素数であるかどうかのフラグを真に設定しておく
例)
sosu_desu = .true. -
2 から i-1 までについて(int(sqrt(dble(i))) まで調べるだけでも良い)、割り切れるかどうか調べるために反復する
例)
do j=2,i-1 -
割り切れるかどうかによりフラグを設定する
例)
if ( mod(i,j) == 0 ) sosu_desu = .false. ! 割り切れるので素数ではない - 内側のループ終了後に sosu_desu フラグが真であれば i を出力する
- 外側のループ終了
実行例: Please enter N: 29 2 3 5 7 11 13 17 19 23 29[ kadai-sosu.f90 ] - 素数を求めるプログラム例
前へ 上へ 次へ