Fortranでオブジェクト指向(12)
今日のポイント 実数型と倍精度実数型の共存
数値解析は一般的に倍精度実数型変数で行うことが多く、
OpenGLなどのライブラリでは実数型が標準になっていることが多くあります。
この時、実数型と倍精度実数型の変換処理はシステムによっては
かなりのCPUリソースを消費するため、この二つの変換を極力
少なくするために明示的に別々の計算をしたい場合があります。
この時、interface文で多様性を利用して方法で実装することも出来ますが、
構造体の多様性を利用してシンプルに実装することもできます。
サンプルプログラム
以下のサンプルではif_normモジュールのrvec, dvecの定義がポイントです。
rvecは実数型でXYZベクトル成分を持ちます。またprocedure normをrnormに
割り当てることでrvec%norm()でその絶対値を求められます。
dvecは倍精度型で上記と同じ処理を行います。
両者ともに%norm()でnormが求められますが、内部の処理では単精度実数と
倍精度実数が明示的に区別されている点がポイントです。
勿論構造体を用いなくても明示的に型変換の発生しないプログラムを作成する
ことは難しくはありませんが、保守性は最悪です。
module if_norm
type rvec
real :: x, y, z
contains
procedure :: norm => rnorm
end type rvec
type dvec
double precision :: x, y, z
contains
procedure :: norm => dnorm
end type dvec
contains
real function rnorm(this)
class(rvec), INTENT(INOUT) :: this
rnorm = sqrt(this%x * this%x + this%y * this%y + this%z * this%z)
return
end function rnorm
double precision function dnorm(this)
class(dvec), INTENT(INOUT) :: this
dnorm = sqrt(this%x * this%x + this%y * this%y + this%z * this%z)
return
end function dnorm
end module if_norm
program main
use if_norm
implicit none
class(rvec), allocatable :: vec1(:)
class(dvec), allocatable :: vec2(:)
allocate(vec1(1), vec2(1))
vec1(1)%x = 1.0
vec1(1)%y = 2.0
vec1(1)%z = 2.0
vec2(1)%x = 1.0d0
vec2(1)%y = 2.0d0
vec2(1)%z = 2.0d0
write(6,*) vec1(1)%norm()
write(6,*) vec2(1)%norm()
read(5,*)
stop
end program main
実行結果
3.000000
3.0000000000000
因みに数値解析の結果をOpenGLで表示する場合には
・一度は型変換して単精度実数で処理する
・型変換せずにOpenGLの倍精度実数処理を利用する
のいずれかになります。
本日はこの辺で。