@@ -10,9 +10,9 @@ function GradientCache(
10
10
fx :: Union{Void,<:Number,AbstractArray{<:Number}} = nothing ,
11
11
c1 :: Union{Void,AbstractArray{<:Number}} = nothing ,
12
12
c2 :: Union{Void,AbstractArray{<:Number}} = nothing ,
13
- fdtype :: DataType = Val{:central },
14
- returntype :: DataType = eltype (x),
15
- inplace :: Bool = true )
13
+ fdtype :: Type{T1} = Val{:central },
14
+ returntype :: Type{T2} = eltype (x),
15
+ inplace :: Type{Val{T3}} = Val{ true }) where {T1,T2,T3}
16
16
17
17
if fdtype!= Val{:forward } && typeof (fx)!= Void
18
18
warn (" Pre-computed function values are only useful for fdtype == Val{:forward}." )
@@ -30,13 +30,10 @@ function GradientCache(
30
30
else
31
31
_c1 = c1
32
32
end
33
- epsilon_factor = compute_epsilon_factor (fdtype, real (eltype (x)))
34
- @. _c1 = compute_epsilon (fdtype, real (x), epsilon_factor)
35
-
36
33
if typeof (c2)!= typeof (x) || size (c2)!= size (x)
37
- _c2 = copy (x)
34
+ _c2 = similar (x)
38
35
else
39
- copy! ( _c2, x)
36
+ _c2 = c2
40
37
end
41
38
else
42
39
if ! (returntype<: Real )
@@ -76,16 +73,16 @@ function GradientCache(
76
73
GradientCache {typeof(_fx),typeof(_c1),typeof(_c2),fdtype,returntype,inplace} (_fx,_c1,_c2)
77
74
end
78
75
79
- function finite_difference_gradient (f, x, fdtype:: DataType = Val{:central },
80
- returntype:: DataType = eltype (x), inplace:: Bool = true ,
76
+ function finite_difference_gradient (f, x, fdtype:: Type{T1} = Val{:central },
77
+ returntype:: Type{T2} = eltype (x), inplace:: Type{Val{T3}} = Val{ true } ,
81
78
fx:: Union{Void,AbstractArray{<:Number}} = nothing ,
82
79
c1:: Union{Void,AbstractArray{<:Number}} = nothing ,
83
- c2:: Union{Void,AbstractArray{<:Number}} = nothing )
80
+ c2:: Union{Void,AbstractArray{<:Number}} = nothing ) where {T1,T2,T3}
84
81
85
82
if typeof (x) <: AbstractArray
86
83
df = zeros (returntype, size (x))
87
84
else
88
- if inplace
85
+ if inplace == Val{ true }
89
86
if typeof (fx)== Void && typeof (c1)== Void && typeof (c2)== Void
90
87
error (" In the scalar->vector in-place map case, at least one of fx, c1 or c2 must be provided, otherwise we cannot infer the return size." )
91
88
else
@@ -102,12 +99,12 @@ function finite_difference_gradient(f, x, fdtype::DataType=Val{:central},
102
99
finite_difference_gradient! (df,f,x,cache)
103
100
end
104
101
105
- function finite_difference_gradient! (df, f, x, fdtype:: DataType = Val{:central },
106
- returntype:: DataType = eltype (x), inplace:: Bool = true ,
102
+ function finite_difference_gradient! (df, f, x, fdtype:: Type{T1} = Val{:central },
103
+ returntype:: Type{T2} = eltype (x), inplace:: Type{Val{T3}} = Val{ true } ,
107
104
fx:: Union{Void,AbstractArray{<:Number}} = nothing ,
108
105
c1:: Union{Void,AbstractArray{<:Number}} = nothing ,
109
106
c2:: Union{Void,AbstractArray{<:Number}} = nothing ,
110
- )
107
+ ) where {T1,T2,T3}
111
108
112
109
cache = GradientCache (df,x,fx,c1,c2,fdtype,returntype,inplace)
113
110
finite_difference_gradient! (df,f,x,cache)
@@ -131,9 +128,13 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Abstract
131
128
cache:: GradientCache{T1,T2,T3,fdtype,returntype,inplace} ) where {T1,T2,T3,fdtype,returntype,inplace}
132
129
133
130
# NOTE: in this case epsilon is a vector, we need two arrays for epsilon and x1
134
- # c1 denotes epsilon (pre-computed by the cache constructor),
135
- # c2 is x1, pre-set to the values of x by the cache constructor
131
+ # c1 denotes epsilon, c2 is x1, pre-set to the values of x by the cache constructor
136
132
fx, c1, c2 = cache. fx, cache. c1, cache. c2
133
+ if fdtype != Val{:complex }
134
+ epsilon_factor = compute_epsilon_factor (fdtype, eltype (x))
135
+ @. c1 = compute_epsilon (fdtype, x, epsilon_factor)
136
+ copy! (c2,x)
137
+ end
137
138
if fdtype == Val{:forward }
138
139
@inbounds for i ∈ eachindex (x)
139
140
c2[i] += c1[i]
@@ -153,6 +154,7 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Abstract
153
154
x[i] += c1[i]
154
155
end
155
156
elseif fdtype == Val{:complex } && returntype <: Real
157
+ copy! (c1,x)
156
158
epsilon_complex = eps (real (eltype (x)))
157
159
# we use c1 here to avoid typing issues with x
158
160
@inbounds for i ∈ eachindex (x)
@@ -176,27 +178,27 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Number,
176
178
fx, c1, c2 = cache. fx, cache. c1, cache. c2
177
179
178
180
if fdtype == Val{:forward }
179
- epsilon_factor = compute_epsilon_factor (fdtype, real ( eltype (x) ))
180
- epsilon = compute_epsilon (Val{:forward }, real (x) , epsilon_factor)
181
- if inplace
181
+ epsilon_factor = compute_epsilon_factor (fdtype, eltype (x))
182
+ epsilon = compute_epsilon (Val{:forward }, x , epsilon_factor)
183
+ if inplace == Val{ true }
182
184
f (c1, x+ epsilon)
183
185
else
184
186
c1 .= f (x+ epsilon)
185
187
end
186
188
if typeof (fx) != Void
187
189
@. df = (c1 - fx) / epsilon
188
190
else
189
- if inplace
191
+ if inplace == Val{ true }
190
192
f (c2, x)
191
193
else
192
194
c2 .= f (x)
193
195
end
194
196
@. df = (c1 - c2) / epsilon
195
197
end
196
198
elseif fdtype == Val{:central }
197
- epsilon_factor = compute_epsilon_factor (fdtype, real ( eltype (x) ))
198
- epsilon = compute_epsilon (Val{:central }, real (x) , epsilon_factor)
199
- if inplace
199
+ epsilon_factor = compute_epsilon_factor (fdtype, eltype (x))
200
+ epsilon = compute_epsilon (Val{:central }, x , epsilon_factor)
201
+ if inplace == Val{ true }
200
202
f (c1, x+ epsilon)
201
203
f (c2, x- epsilon)
202
204
else
@@ -206,7 +208,7 @@ function finite_difference_gradient!(df::AbstractArray{<:Number}, f, x::Number,
206
208
@. df = (c1 - c2) / (2 * epsilon)
207
209
elseif fdtype == Val{:complex } && returntype <: Real
208
210
epsilon_complex = eps (real (eltype (x)))
209
- if inplace
211
+ if inplace == Val{ true }
210
212
f (c1, x+ im* epsilon_complex)
211
213
else
212
214
c1 .= f (x+ im* epsilon_complex)
0 commit comments