@@ -195,6 +195,38 @@ macro define_ternary_dual_op(f, xyz_body, xy_body, xz_body, yz_body, x_body, y_b
195
195
return esc (defs)
196
196
end
197
197
198
+ # Support complex-valued functions such as `hankelh1`
199
+ function dual_definition_retval (:: Val{T} , val:: Real , deriv:: Real , partial:: Partials ) where {T}
200
+ return Dual {T} (val, deriv * partial)
201
+ end
202
+ function dual_definition_retval (:: Val{T} , val:: Real , deriv1:: Real , partial1:: Partials , deriv2:: Real , partial2:: Partials ) where {T}
203
+ return Dual {T} (val, _mul_partials (partial1, partial2, deriv1, deriv2))
204
+ end
205
+ function dual_definition_retval (:: Val{T} , val:: Complex , deriv:: Union{Real,Complex} , partial:: Partials ) where {T}
206
+ reval, imval = reim (val)
207
+ if deriv isa Real
208
+ p = deriv * partial
209
+ return Complex (Dual {T} (reval, p), Dual {T} (imval, zero (p)))
210
+ else
211
+ rederiv, imderiv = reim (deriv)
212
+ return Complex (Dual {T} (reval, rederiv * partial), Dual {T} (imval, imderiv * partial))
213
+ end
214
+ end
215
+ function dual_definition_retval (:: Val{T} , val:: Complex , deriv1:: Union{Real,Complex} , partial1:: Partials , deriv2:: Union{Real,Complex} , partial2:: Partials ) where {T}
216
+ reval, imval = reim (val)
217
+ if deriv1 isa Real && deriv2 isa Real
218
+ p = _mul_partials (partial1, partial2, deriv1, deriv2)
219
+ return Complex (Dual {T} (reval, p), Dual {T} (imval, zero (p)))
220
+ else
221
+ rederiv1, imderiv1 = reim (deriv1)
222
+ rederiv2, imderiv2 = reim (deriv2)
223
+ return Complex (
224
+ Dual {T} (reval, _mul_partials (partial1, partial2, rederiv1, rederiv2)),
225
+ Dual {T} (imval, _mul_partials (partial1, partial2, imderiv1, imderiv2)),
226
+ )
227
+ end
228
+ end
229
+
198
230
function unary_dual_definition (M, f)
199
231
FD = ForwardDiff
200
232
Mf = M == :Base ? f : :($ M.$ f)
@@ -206,7 +238,7 @@ function unary_dual_definition(M, f)
206
238
@inline function $M. $f (d:: $FD.Dual{T} ) where T
207
239
x = $ FD. value (d)
208
240
$ work
209
- return $ FD. Dual {T} (val, deriv * $ FD. partials (d))
241
+ return $ FD. dual_definition_retval ( Val {T} (), val, deriv, $ FD. partials (d))
210
242
end
211
243
end
212
244
end
@@ -236,17 +268,17 @@ function binary_dual_definition(M, f)
236
268
begin
237
269
vx, vy = $ FD. value (x), $ FD. value (y)
238
270
$ xy_work
239
- return $ FD. Dual {Txy} (val, $ FD. _mul_partials ( $ FD . partials (x), $ FD. partials (y), dvx, dvy ))
271
+ return $ FD. dual_definition_retval ( Val {Txy} (), val, dvx, $ FD. partials (x), dvy, $ FD. partials (y))
240
272
end ,
241
273
begin
242
274
vx = $ FD. value (x)
243
275
$ x_work
244
- return $ FD. Dual {Tx} (val, dvx * $ FD. partials (x))
276
+ return $ FD. dual_definition_retval ( Val {Tx} (), val, dvx, $ FD. partials (x))
245
277
end ,
246
278
begin
247
279
vy = $ FD. value (y)
248
280
$ y_work
249
- return $ FD. Dual {Ty} (val, dvy * $ FD. partials (y))
281
+ return $ FD. dual_definition_retval ( Val {Ty} (), val, dvy, $ FD. partials (y))
250
282
end
251
283
)
252
284
end
0 commit comments