@@ -46,16 +46,25 @@ function GradientCache(
46
46
end
47
47
48
48
else # the f:R->R^n case
49
- # need cache arrays for fx1 and fx2
50
- if typeof (c1) != typeof (df) || size (c1) != size (df)
51
- _c1 = similar (df)
52
- else
53
- _c1 = c1
54
- end
55
- if typeof (c2) != typeof (df) || size (c2) != size (df)
56
- _c2 = similar (df)
49
+ # need cache arrays for fx1 and fx2, except in complex mode
50
+ if fdtype != Val{:complex }
51
+ if typeof (c1) != typeof (df) || size (c1) != size (df)
52
+ _c1 = similar (df)
53
+ else
54
+ _c1 = c1
55
+ end
56
+ if fdtype == Val{:forward } && typeof (fx) != Void
57
+ _c2 = nothing
58
+ else
59
+ if typeof (c2) != typeof (df) || size (c2) != size (df)
60
+ _c2 = similar (df)
61
+ else
62
+ _c2 = c2
63
+ end
64
+ end
57
65
else
58
- _c2 = c2
66
+ _c1 = nothing
67
+ _c2 = nothing
59
68
end
60
69
end
61
70
GradientCache {typeof(_fx),typeof(_c1),typeof(_c2),fdtype,RealOrComplex} (_fx,_c1,_c2)
@@ -144,16 +153,26 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Number,
144
153
# c1 denotes fx1, c2 is fx2, sizes guaranteed by the cache constructor
145
154
fx, c1, c2 = cache. fx, cache. c1, cache. c2
146
155
156
+ epsilon_elemtype = compute_epsilon_elemtype (nothing , x)
147
157
if fdtype == Val{:forward }
148
- # TODO
158
+ epsilon_factor = compute_epsilon_factor (fdtype, real (eltype (x)))
159
+ epsilon = compute_epsilon (Val{:forward }, real (x), epsilon_factor)
160
+ c1 .= f (x+ epsilon)
161
+ if typeof (fx) != Void
162
+ @. df = (c1 - fx) / epsilon
163
+ else
164
+ c2 .= f (x)
165
+ @. df = (c1 - c2) / epsilon
166
+ end
149
167
elseif fdtype == Val{:central }
168
+ epsilon_factor = compute_epsilon_factor (fdtype, real (eltype (x)))
169
+ epsilon = compute_epsilon (Val{:central }, real (x), epsilon_factor)
150
170
c1 .= f (x+ epsilon)
151
171
c2 .= f (x- epsilon)
152
- @inbounds for i ∈ 1 : length (fx)
153
- df[i] = (f (x+ epsilon)[1 ] - f (x- epsilon)[1 ]) / (2 * epsilon)
154
- end
172
+ @. df = (c1 - c2) / (2 * epsilon)
155
173
elseif fdtype == Val{:complex }
156
- # TODO
174
+ epsilon_complex = eps (epsilon_elemtype)
175
+ df .= imag .(f (x+ im* epsilon_complex)) ./ epsilon_complex
157
176
end
158
177
df
159
178
end
@@ -162,13 +181,13 @@ end
162
181
function finite_difference_gradient! (df:: AbstractArray{<:Number} , f, x:: AbstractArray{<:Number} ,
163
182
cache:: GradientCache{T1,T2,T3,fdtype,Val{:Complex}} ) where {T1,T2,T3,fdtype}
164
183
165
- # TODO
184
+ error ( " Not implemented yet. " )
166
185
df
167
186
end
168
187
169
188
function finite_difference_gradient! (df:: AbstractArray{<:Number} , f, x:: Number ,
170
189
cache:: GradientCache{T1,T2,T3,fdtype,Val{:Complex}} ) where {T1,T2,T3,fdtype}
171
190
172
- # TODO
191
+ error ( " Not implemented yet. " )
173
192
df
174
193
end
0 commit comments