fortran66のブログ

fortran について書きます。

【メモ帳】精度毎のルーチンで楽したい

generic の代用

薬局でもジェネリックを勧められても拒否するし、Fortran 文法でもジェネリクス導入を拒否しますw

そもそも単精度では精度を保つため、積の結果だけ倍精度使うとか、完全に同じソースではすまないことがあります。

とはいえ、ジェネリクスのように同じコードの繰り返しを1回で済ませられなくても、実装部は同じ内容のコピペを繰り返して、インターフェース前後だけ最小限いじってすませられないか、少し考えてみました。

submodule を使うと、定義の向きなどが素直でいいのですが、名前の重複に工夫が必要です。ここでは module のみで考えてみることにします。

 Fortran

単精度・倍精度・四倍精度の module を三つそれぞれに対して用意しますが、モジュール名と定数以外は共通とします。それらを親モジュールに集めて、名前のダブりを use 文で回避して、総称名にします。

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

 module mod00
    implicit none
    integer, parameter :: ks = kind(1.0e0)
    integer, parameter :: kd = kind(1.0d0)
    integer, parameter :: kq = kind(1.0q0)
end module mod00

module mods
    use mod00
    implicit none
    integer, parameter :: kn = ks
contains
    real(kn) function fun(x) result(res)
        real(kn), intent(in):: x
        res=x
    end  
end  

module modd
    use mod00
    implicit none
    integer, parameter :: kn = kd
contains
    real(kn) function fun(x) result(res)
       real(kn), intent(in):: x
       res=x
    end    
end  

module modq
    use mod00
    implicit none
    integer, parameter :: kn = kq
contains
    real(kn) function fun(x) result(res)
       real(kn), intent(in):: x
       res=x
    end    
end  


module mod
    use mods, only: fun_s=>fun 
    use modd, only: fun_d=>fun
    use modq, only: fun_q=>fun
    interface fun
        procedure :: fun_s, fun_d, fun_q
    end interface
end module mod

    
program test
    use mod
    implicit none
    print *, fun(1.0e0)
    print *, fun(1.0d0)
    print *, fun(1.0q0)
end program

実行結果

   1.000000
   1.00000000000000
   1.00000000000000000000000000000000