Fortran 95 で初歩的なアルゴリズムを作成し、Richardson 外挿として知られる手順で補強された中心差分を使用して関数 (コードで規定されている例) の勾配を計算しました。
function f(n,x)
! The scalar multivariable function to be differentiated
integer :: n
real(kind = kind(1d0)) :: x(n), f
f = x(1)**5.d0 + cos(x(2)) + log(x(3)) - sqrt(x(4))
end function f
!=====!
!=====!
!=====!
program gradient
!==============================================================================!
! Calculates the gradient of the scalar function f at x=0using a finite !
! difference approximation, with a low order Richardson extrapolation. !
!==============================================================================!
parameter (n = 4, M = 25)
real(kind = kind(1d0)) :: x(n), xhup(n), xhdown(n), d(M), r(M), dfdxi, h0, h, gradf(n)
h0 = 1.d0
x = 3.d0
! Loop through each component of the vector x and calculate the appropriate
! derivative
do i = 1,n
! Reset step size
h = h0
! Carry out M successive central difference approximations of the derivative
do j = 1,M
xhup = x
xhdown = x
xhup(i) = xhup(i) + h
xhdown(i) = xhdown(i) - h
d(j) = ( f(n,xhup) - f(n,xhdown) ) / (2.d0*h)
h = h / 2.d0
end do
r = 0.d0
do k = 3,M r(k) = ( 64.d0*d(k) - 20.d0*d(k-1) + d(k-2) ) / 45.d0
if ( abs(r(k) - r(k-1)) < 0.0001d0 ) then
dfdxi = r(k)
exit
end if
end do
gradf(i) = dfdxi
end do
! Print out the gradient
write(*,*) " "
write(*,*) " Grad(f(x)) = "
write(*,*) " "
do i = 1,n
write(*,*) gradf(i)
end do
end program gradient
単精度では問題なく動作し、まともな結果が得られます。しかし、コードに示されているように倍精度に変更しようとすると、代入ステートメントを主張してコンパイルしようとするとエラーが発生します。
d(j) = ( f(n,xhup) - f(n,xhdown) ) / (2.d0*h)
型の不一致が発生していreal(4)/real(8)
ます。倍精度のいくつかの異なる宣言を試み、コード内のすべての適切な倍精度定数を で追加しましたが、d0
毎回同じエラーが発生します。f
関数がどのように単精度数を生成する可能性があるかについて、私は少し困惑しています。