@@ -11,7 +11,7 @@ function GradientCache(
11
11
c1 :: Union{Void,AbstractArray{<:Number}} = nothing ,
12
12
c2 :: Union{Void,AbstractArray{<:Number}} = nothing ,
13
13
fdtype :: Type{T1} = Val{:central },
14
- returntype :: Type{T2} = eltype (x ),
14
+ returntype :: Type{T2} = eltype (df ),
15
15
inplace :: Type{Val{T3}} = Val{true }) where {T1,T2,T3}
16
16
17
17
if fdtype!= Val{:forward } && typeof (fx)!= Void
@@ -26,10 +26,15 @@ function GradientCache(
26
26
# need cache arrays for x1 (c1) and epsilon (c2) (both only if non-StridedArray)
27
27
if fdtype!= Val{:complex } # complex-mode FD only needs one cache, for x+eps*im
28
28
if typeof (x)<: StridedVector
29
- _c1 = nothing
30
- _c2 = nothing
31
- if typeof (c1)!= Void || typeof (c2)!= Void
32
- warn (" For StridedVectors, neither c1 nor c2 are necessary." )
29
+ if eltype (df)<: Complex && ! (eltype (x)<: Complex )
30
+ _c1 = zeros (Complex{eltype (x)}, size (x))
31
+ _c2 = nothing
32
+ else
33
+ _c1 = nothing
34
+ _c2 = nothing
35
+ if typeof (c1)!= Void || typeof (c2)!= Void
36
+ warn (" For StridedVectors, neither c1 nor c2 are necessary." )
37
+ end
33
38
end
34
39
else
35
40
if typeof (c1)!= typeof (x) || size (c1)!= size (x)
@@ -108,7 +113,7 @@ function finite_difference_gradient(f, x, fdtype::Type{T1}=Val{:central},
108
113
end
109
114
110
115
function finite_difference_gradient! (df, f, x, fdtype:: Type{T1} = Val{:central },
111
- returntype:: Type{T2} = eltype (x ), inplace:: Type{Val{T3}} = Val{true },
116
+ returntype:: Type{T2} = eltype (df ), inplace:: Type{Val{T3}} = Val{true },
112
117
fx:: Union{Void,AbstractArray{<:Number}} = nothing ,
113
118
c1:: Union{Void,AbstractArray{<:Number}} = nothing ,
114
119
c2:: Union{Void,AbstractArray{<:Number}} = nothing ,
@@ -130,25 +135,6 @@ function finite_difference_gradient(f,x,
130
135
df
131
136
end
132
137
133
- #=
134
- function f1(df,f,x,epsilon)
135
- for i in eachindex(x)
136
- x0=x[i]
137
- x[i]+=epsilon
138
- dfi=f(x)
139
- x[i]=x0
140
- dfi-=f(x)
141
- df[i]=real(dfi/epsilon)
142
- x[i]+=im*epsilon
143
- dfi=f(x)
144
- x[i]=x0
145
- dfi-=f(x)
146
- df[i]+=im*imag(dfi/(im*epsilon))
147
- end
148
- df
149
- end
150
- =#
151
-
152
138
# vector of derivatives of a vector->scalar map by each component of a vector x
153
139
# this ignores the value of "inplace", because it doesn't make much sense
154
140
function finite_difference_gradient! (df:: AbstractArray{<:Number} , f, x:: AbstractArray{<:Number} ,
@@ -163,19 +149,19 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Abstract
163
149
copy! (c1,x)
164
150
end
165
151
if fdtype == Val{:forward }
166
- if eltype (df) <: Complex || returntype <: Complex || eltype (x)<: Complex
167
- for i ∈ eachindex (x)
168
- epsilon = c2 [i]
169
- c1_old = c1[i]
170
- c1[i] += epsilon
171
- if typeof ( fx) != Void
172
- dfi = ( f (c1) - fx) / epsilon
173
- else
174
- fx0 = f (x)
175
- dfi = ( f (c1) - fx0) / epsilon
176
- end
177
- df [i] = real (dfi)
178
- c1[i] = c1_old
152
+ @inbounds for i ∈ eachindex (x)
153
+ epsilon = c2[i]
154
+ c1_old = c1 [i]
155
+ c1[i] += epsilon
156
+ if typeof (fx) != Void
157
+ dfi = ( f (c1) - fx) / epsilon
158
+ else
159
+ fx0 = f (x)
160
+ dfi = ( f (c1) - fx0) / epsilon
161
+ end
162
+ df[i] = real (dfi)
163
+ c1 [i] = c1_old
164
+ if eltype (df) <: Complex
179
165
c1[i] += im * epsilon
180
166
if typeof (fx) != Void
181
167
dfi = (f (c1) - fx) / (im* epsilon)
@@ -185,18 +171,6 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Abstract
185
171
c1[i] = c1_old
186
172
df[i] += im * imag (dfi)
187
173
end
188
- else
189
- @inbounds for i ∈ eachindex (x)
190
- epsilon = c2[i]
191
- c1_old = c1[i]
192
- c1[i] += epsilon
193
- if typeof (fx) != Void
194
- df[i] = (f (c1) - fx) / epsilon
195
- else
196
- df[i] = (f (c1) - f (x)) / epsilon
197
- end
198
- c1[i] = c1_old
199
- end
200
174
end
201
175
elseif fdtype == Val{:central }
202
176
@inbounds for i ∈ eachindex (x)
@@ -205,9 +179,16 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Abstract
205
179
c1[i] += epsilon
206
180
x_old = x[i]
207
181
x[i] -= epsilon
208
- df[i] = ( f (c1) - f (x)) / (2 * epsilon)
182
+ df[i] = real (( f (c1) - f (x)) / (2 * epsilon) )
209
183
c1[i] = c1_old
210
184
x[i] = x_old
185
+ if eltype (df)<: Complex
186
+ c1[i] += im* epsilon
187
+ x[i] -= im* epsilon
188
+ df[i] += im* imag ( (f (c1) - f (x)) / (2 * im* epsilon) )
189
+ c1[i] = c1_old
190
+ x[i] = x_old
191
+ end
211
192
end
212
193
elseif fdtype == Val{:complex } && returntype <: Real
213
194
copy! (c1,x)
@@ -228,80 +209,77 @@ end
228
209
function finite_difference_gradient! (df:: StridedVector{<:Number} , f, x:: StridedVector{<:Number} ,
229
210
cache:: GradientCache{T1,T2,T3,fdtype,returntype,inplace} ) where {T1,T2,T3,fdtype,returntype,inplace}
230
211
231
- # c1 is x1, c2 shouldn't exist in this case
212
+ # c1 is x1 if we need a complex copy of x, otherwise Void
213
+ # c2 is Void
232
214
fx, c1, c2 = cache. fx, cache. c1, cache. c2
233
215
if fdtype != Val{:complex }
234
216
epsilon_factor = compute_epsilon_factor (fdtype, eltype (x))
217
+ if eltype (df)<: Complex && ! (eltype (x)<: Complex )
218
+ copy! (c1,x)
219
+ end
235
220
end
236
221
if fdtype == Val{:forward }
237
- if eltype (df)<: Complex || returntype<: Complex || eltype (x)<: Complex
238
- for i ∈ eachindex (x)
239
- epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
240
- x_old = x[i]
241
- if typeof (fx) != Void
242
- x[i] += epsilon
243
- dfi = (f (x) - fx) / epsilon
244
- x[i] = x_old
245
- else
246
- fx0 = f (x)
247
- x[i] += epsilon
248
- dfi = (f (x) - fx0) / epsilon
249
- x[i] = x_old
250
- end
251
- df[i] = real (dfi)
252
- x[i] += im * epsilon
253
- if typeof (fx) != Void
254
- dfi = (f (x) - fx) / (im* epsilon)
255
- else
256
- dfi = (f (x) - fx0) / (im* epsilon)
257
- end
222
+ for i ∈ eachindex (x)
223
+ epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
224
+ x_old = x[i]
225
+ if typeof (fx) != Void
226
+ x[i] += epsilon
227
+ dfi = (f (x) - fx) / epsilon
258
228
x[i] = x_old
259
- df[i] += im * imag (dfi)
260
- end
261
- else
262
- @inbounds for i ∈ eachindex (x)
263
- epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
264
- x_old = x[i]
229
+ else
230
+ fx0 = f (x)
265
231
x[i] += epsilon
266
- dfi = f (x)
232
+ dfi = ( f (x) - fx0) / epsilon
267
233
x[i] = x_old
268
- if typeof (fx) != Void
269
- dfi -= fx
234
+ end
235
+ df[i] = real (dfi)
236
+ if eltype (df)<: Complex
237
+ if eltype (x)<: Complex
238
+ x[i] += im * epsilon
239
+ if typeof (fx) != Void
240
+ dfi = (f (x) - fx) / (im* epsilon)
241
+ else
242
+ dfi = (f (x) - fx0) / (im* epsilon)
243
+ end
244
+ x[i] = x_old
270
245
else
271
- dfi -= f (x)
246
+ c1[i] += im * epsilon
247
+ if typeof (fx) != Void
248
+ dfi = (f (c1) - fx) / (im* epsilon)
249
+ else
250
+ dfi = (f (c1) - fx0) / (im* epsilon)
251
+ end
252
+ c1[i] = x_old
272
253
end
273
- df[i] = dfi / epsilon
254
+ df[i] += im * imag (dfi)
274
255
end
275
256
end
276
257
elseif fdtype == Val{:central }
277
- if eltype (df)<: Complex || returntype<: Complex || eltype (x)<: Complex
278
- @inbounds for i ∈ eachindex (x)
279
- epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
280
- x_old = x[i]
281
- x[i] += epsilon
282
- dfi = f (x)
283
- x[i] = x_old - epsilon
284
- dfi -= f (x)
285
- x[i] = x_old
286
- df[i] = real (dfi / (2 * epsilon))
287
- x[i] += im* epsilon
288
- dfi = f (x)
289
- x[i] = x_old - im* epsilon
290
- dfi -= f (x)
291
- x[i] = x_old
258
+ @inbounds for i ∈ eachindex (x)
259
+ epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
260
+ x_old = x[i]
261
+ x[i] += epsilon
262
+ dfi = f (x)
263
+ x[i] = x_old - epsilon
264
+ dfi -= f (x)
265
+ x[i] = x_old
266
+ df[i] = real (dfi / (2 * epsilon))
267
+ if eltype (df)<: Complex
268
+ if eltype (x)<: Complex
269
+ x[i] += im* epsilon
270
+ dfi = f (x)
271
+ x[i] = x_old - im* epsilon
272
+ dfi -= f (x)
273
+ x[i] = x_old
274
+ else
275
+ c1[i] += im* epsilon
276
+ dfi = f (c1)
277
+ c1[i] = x_old - im* epsilon
278
+ dfi -= f (c1)
279
+ c1[i] = x_old
280
+ end
292
281
df[i] += im* imag (dfi / (2 * im* epsilon))
293
282
end
294
- else
295
- @inbounds for i ∈ eachindex (x)
296
- epsilon = compute_epsilon (fdtype, x[i], epsilon_factor)
297
- x_old = x[i]
298
- x[i] += epsilon
299
- dfi = f (x)
300
- x[i] = x_old - epsilon
301
- dfi -= f (x)
302
- x[i] = x_old
303
- df[i] = dfi / (2 * epsilon)
304
- end
305
283
end
306
284
elseif fdtype== Val{:complex } && returntype<: Real && eltype (df)<: Real && eltype (x)<: Real
307
285
copy! (c1,x)
0 commit comments