14
14
eps_cbrt * max (one (T), abs (x))
15
15
end
16
16
17
- @inline function compute_epsilon {T<:Real} (:: Type{Val{:complex}} , x:: T , :: Union{Void,T} = nothing )
18
- eps (x)
19
- end
20
-
21
17
@inline function compute_epsilon_factor {T<:Real} (fdtype:: DataType , :: Type{T} )
22
18
if fdtype== Val{:forward }
23
19
return sqrt (eps (T))
@@ -40,48 +36,41 @@ function finite_difference{T<:Real}(f, x::AbstractArray{T}, fdtype::DataType, fx
40
36
end
41
37
42
38
function finite_difference! {T<:Real} (df:: AbstractArray{T} , f, x:: AbstractArray{T} , fdtype:: DataType , fx:: Union{Void,AbstractArray{T}} , :: Type{Val{:Default}} )
43
- epsilon_factor = compute_epsilon_factor (fdtype, T)
44
- @. epsilon = compute_epsilon (fdtype, x, epsilon_factor)
45
39
if fdtype == Val{:forward }
40
+ epsilon_factor = compute_epsilon_factor (fdtype, T)
41
+ @. epsilon = compute_epsilon (fdtype, x, epsilon_factor)
46
42
if typeof (fx) == Void
47
43
@. df = (f (x+ epsilon) - f (x)) / epsilon
48
44
else
49
45
@. df = (f (x+ epsilon) - fx) / epsilon
50
46
end
51
47
elseif fdtype == Val{:central }
48
+ epsilon_factor = compute_epsilon_factor (fdtype, T)
49
+ @. epsilon = compute_epsilon (fdtype, x, epsilon_factor)
52
50
@. df = (f (x+ epsilon) - f (x- epsilon)) / (2 * epsilon)
53
- end
54
- df
55
- end
56
-
57
- function finite_difference! {T<:Real} (df:: AbstractArray{T} , f, x:: AbstractArray{T} , fdtype:: DataType , fx:: Union{Void,AbstractArray{T}} , :: Type{Val{:DiffEqDerivativeWrapper}} )
58
- epsilon_factor = compute_epsilon_factor (fdtype, T)
59
- @. epsilon = compute_epsilon (fdtype, x, epsilon_factor)
60
- error (" Not implemented yet." )
61
-
62
- if fdtype == Val{:forward }
63
- if typeof (fx) == Void
64
-
65
- else
66
-
67
- end
68
- elseif fdtype == Val{:central }
69
-
51
+ elseif fdtype == Val{:complex }
52
+ epsilon = eps (T)
53
+ @. df = imag (f (x+ im* epsilon)) / epsilon
70
54
end
71
55
df
72
56
end
73
57
74
58
function finite_difference! {T<:Real} (df:: AbstractArray{T} , f, x:: T , fdtype:: DataType , fx:: AbstractArray{T} , :: Type{Val{:DiffEqDerivativeWrapper}} )
75
- epsilon = compute_epsilon (fdtype, x)
76
59
fx1 = f. fx1
77
60
if fdtype == Val{:forward }
61
+ epsilon = compute_epsilon (fdtype, x)
78
62
f (fx, x)
79
63
f (fx1, x+ epsilon)
80
64
@. df = (fx1 - fx) / epsilon
81
65
elseif fdtype == Val{:central }
66
+ epsilon = compute_epsilon (fdtype, x)
82
67
f (fx, x- epsilon)
83
68
f (fx1, x+ epsilon)
84
69
@. df = (fx1 - fx) / (2 * epsilon)
70
+ elseif fdtype == Val{:complex }
71
+ epsilon = eps (T)
72
+ f (fx, f (x+ im* epsilon))
73
+ @. df = imag (fx) / epsilon
85
74
end
86
75
df
87
76
end
@@ -128,8 +117,13 @@ Compute the derivative df of a real-valued callable f on a collection of points
128
117
Single point implementations.
129
118
=#
130
119
function finite_difference {T<:Real} (f, x:: T , fdtype:: DataType , f_x:: Union{Void,T} = nothing )
131
- epsilon = compute_epsilon (fdtype, x)
132
- finite_difference_kernel (f, x, fdtype, epsilon, f_x)
120
+ if fdtype == Val{:complex }
121
+ epsilon = eps (T)
122
+ return imag (f (x+ im* epsilon)) / epsilon
123
+ else
124
+ epsilon = compute_epsilon (fdtype, x)
125
+ return finite_difference_kernel (f, x, fdtype, epsilon, f_x)
126
+ end
133
127
end
134
128
135
129
@inline function finite_difference_kernel {T<:Real} (f, x:: T , :: Type{Val{:forward}} , epsilon:: T , fx:: Union{Void,T} )
@@ -154,7 +148,7 @@ function finite_difference_jacobian{T<:Real}(f, x::AbstractArray{T}, fdtype::Dat
154
148
if funtype== Val{:Default }
155
149
fx = f .(x)
156
150
elseif funtype== Val{:DiffEqJacobianWrapper }
157
- f (fx, x)
151
+ fx = f ( x)
158
152
else
159
153
error (" Unrecognized funtype: must be Val{:Default} or Val{:DiffEqJacobianWrapper}." )
160
154
end
@@ -225,6 +219,22 @@ function finite_difference_jacobian!{T<:Real}(J::StridedArray{T}, f, x::StridedA
225
219
J
226
220
end
227
221
222
+ function finite_difference_jacobian! {T<:Real} (J:: StridedArray{T} , f, x:: StridedArray{T} , :: Type{Val{:complex}} , fx:: StridedArray{T} , :: Type{Val{:Default}} )
223
+ m, n = size (J)
224
+ epsilon = eps (T)
225
+ epsilon_inv = one (T) / epsilon
226
+ @inbounds for i in 1 : n
227
+ for j in 1 : m
228
+ if i== j
229
+ J[j,i] = imag (f (x[j]+ im* epsilon)) * epsilon_inv
230
+ else
231
+ J[j,i] = zero (T)
232
+ end
233
+ end
234
+ end
235
+ J
236
+ end
237
+
228
238
# efficient implementations for OrdinaryDiffEq Jacobian wrappers, assuming the system function supplies StridedArrays
229
239
function finite_difference_jacobian! {T<:Real} (J:: StridedArray{T} , f, x:: StridedArray{T} , :: Type{Val{:forward}} , fx:: StridedArray{T} , :: Type{Val{:JacobianWrapper}} )
230
240
m, n = size (J)
0 commit comments