Fortran/語言擴充套件
與其他幾種語言一樣,Fortran 90 及更高版本支援根據傳遞的引數從例程列表中選擇適當的例程。此選擇在編譯時完成,因此不受執行時效能損失的影響。此功能可以透過使用模組和介面塊來訪問。
在以下示例中,指定了一個模組,該模組包含一個介面函式 f,它可以處理各種型別的引數。
module extension_m
implicit none
private
public f ! Only the interface f is accessable outside the module.
interface f ! The overloaded function is called "f".
module procedure f_i ! "f(x)" for integer argument "x" will call "f_i"
module procedure f_r ! "f(x)" for real argument "x" will call "f_r"
module procedure f_z ! ... complex .... "f_z"
end interface
contains
integer function f_i(x) result (y)
integer, intent (in) :: x
y = x**2 - 1
end function
real function f_r(x) result(y)
real, intent (in) :: x
y = x**2 - 1.0
end function
complex function f_z(x) result(y)
complex, intent (in) :: x
y = x**2 - 1.0
end function
end module
現在,使用此模組的程式可以訪問單個介面函式 f,該函式接受整數、實數或複數型別的引數。函式的返回型別與輸入型別相同。這樣,該例程很像 Fortran 標準中定義的許多內在函式。下面給出一個示例程式
program main
use extension_m
implicit none
complex :: xz, yz
integer :: xi, yi
real :: xr, yr
xi = 2
xr = 2.0
xz = 2.0
yi = f(xi)
yr = f(xr)
yz = f(xz)
end program
可以擴充套件內在函式。這類似於過載運算子。
這裡我們將透過擴充套件 sqrt 函式來演示這一點。內在函式沒有為整數型別的引數實現。這是因為沒有明確的想法如何定義非整數型別的結果(例如 ,但如何定義 )。我們在這裡實現了一種方法,其中結果始終是最接近的整數。
module sqrt_int_m
implicit none
private
public sqrt
! use intrinsic sqrt for data types which are not overloaded
intrinsic :: sqrt
! extend sqrt for integers
interface sqrt
module procedure sqrt_int
end interface
contains
pure integer function sqrt_int(i)
integer, intent (in) :: i
sqrt_int = nint(sqrt(real(i)))
end function
end module
program main
use sqrt_int_m
implicit none
integer :: i
! sqrt can be called by real and integer arguments
do i = 1, 7
print *, "i, sqrt(i), sqrt(real(i))", i, sqrt(i), sqrt(real(i))
end do
end program
Fortran 90 及更高版本支援建立新的資料型別,這些資料型別是現有型別的組合。在某些方面,這類似於陣列,但元件不必全部是相同型別,並且它們是透過名稱而不是索引引用的。這種資料型別必須在該型別變數之前宣告,並且宣告必須在範圍內才能使用。下面給出了一個簡單二維向量型別的示例。
type :: vec_t
real :: x,y
end type
可以像宣告其他任何變數一樣宣告此型別的變數,包括變數特徵,如指標或維度。
type (vec_t) :: a,b
type (vec_t), dimension (10) :: vecs
使用派生資料型別,Fortran 語言可以擴充套件為表示比原始型別表示的更多樣化的資料型別。
運算子可以過載,以便派生資料型別支援標準操作,從而有可能擴充套件 Fortran 語言,使其具有行為類似於本機型別的新型別。
賦值運算子 = 可以過載。我們將透過以下示例來演示這一點。這裡,我們定義瞭如何在左側邏輯型別和右側整數之間執行賦值。
module overload_assignment_m
implicit none
private
public assignment (=)
interface assignment (=)
module procedure logical_gets_integer
end interface
contains
subroutine logical_gets_integer(tf, i)
logical, intent (out) :: tf
integer, intent (in) :: i
tf = (i == 0)
end subroutine
end module
program main
use overload_assignment_m
implicit none
logical :: tf
tf = 0
print *, "tf=0:", tf ! Yields: T
tf = 1
print *, "tf=1:", tf ! Yields: F
end program
可以過載內在運算子,如 +,-,*。
在以下示例中,我們將過載 * 運算子以用作邏輯 .and.。
module overload_asterisk_m
implicit none
private
public operator (*)
interface operator (*)
module procedure logical_and
end interface
contains
pure logical function logical_and(log1, log2)
logical, intent (in) :: log1, log2
logical_and = (log1 .and. log2)
end function
end module
program main
use overload_asterisk_m
implicit none
logical, parameter :: T = .true., F = .false.
print *, "T*T:", T*T ! Yields: T
print *, "T*F:", T*F ! Yields: F
print *, "F*T:", F*T ! Yields: F
print *, "F*F:", F*F ! Yields: F
end program
可以建立新的自建立運算子。
我們透過以下示例來演示這一點:我們建立了一個一元運算子 .even. <int>,它在給定的 integer 為偶數時輸出一個 logical,以及一個二元運算子 <reals> .cross. <reals>,它執行兩個 real 向量的標準叉積。
module new_operators_m
implicit none
private
public operator (.even.)
public operator (.cross.)
interface operator (.even.)
module procedure check_even
end interface
interface operator (.cross.)
module procedure cross_product
end interface
contains
pure logical function check_even(i)
integer, intent (in) :: i
check_even = (modulo(i, 2) == 0)
end function
function cross_product(x, y) result(z)
real, intent (in) :: x(3), y(3)
real :: z(3)
z(1) = x(2)*y(3) - x(3)*y(2)
z(2) = x(3)*y(1) - x(1)*y(3)
z(3) = x(1)*y(2) - x(2)*y(1)
end function
end module
program main
use new_operators_m
implicit none
integer :: i
real :: x(3), y(3)
do i = 1, 6
print *, "i:", i, "even?", .even. i
end do
print *
x = [ 1, 2, 3]
y = [-1, 2, -3]
print *, 'x', x
print *, 'y', y
print *, 'x cross_product y', x .cross. y
end program