@@ -245,29 +245,40 @@ Base.:/(z::Number, w::Dual) = Dual(z/value(w), -z*epsilon(w)/value(w)^2)
245245Base.:/ (z:: Dual , x:: Number ) = Dual (value (z)/ x, epsilon (z)/ x)
246246
247247for f in [:(Base.:^ ), :(NaNMath. pow)]
248- @eval function ($ f)(z:: Dual , w:: Dual )
249- if epsilon (w) == 0.0
250- return $ f (z, value (w))
251- end
248+ @eval function ($ f)(z:: Dual{T1} , w:: Dual{T2} ) where {T1, T2}
249+ T = promote_type (T1, T2) # for type stability in ? : statements
252250 val = $ f (value (z), value (w))
253251
254- du = epsilon (z) * value (w) * $ f (value (z), value (w) - 1 ) +
255- epsilon (w) * $ f (value (z), value (w)) * log (value (z))
252+ ezvw = epsilon (z) * value (w) # for using in ? : statement
253+ du1 = iszero (ezvw) ? zero (T) : ezvw * $ f (value (z), value (w) - 1 )
254+ ew = epsilon (w) # for using in ? : statement
255+ # the float is for type stability because log promotes to floats
256+ du2 = iszero (ew) ? zero (float (T)) : ew * val * log (value (z))
257+ du = du1 + du2
256258
257259 Dual (val, du)
258260 end
259261end
260262
261263Base. mod (z:: Dual , n:: Number ) = Dual (mod (value (z), n), epsilon (z))
262264
263- # these two definitions are needed to fix ambiguity warnings
264- Base.:^ (z:: Dual , n:: Unsigned ) = z^ Signed (n)
265- Base.:^ (z:: Dual , n:: Integer ) = Dual (value (z)^ n, epsilon (z)* n* value (z)^ (n- 1 ))
266- Base.:^ (z:: Dual , n:: Rational ) = Dual (value (z)^ n, epsilon (z)* n* value (z)^ (n- 1 ))
265+ # introduce a boolean !iszero(n) for hard zero behaviour to combat NaNs
266+ function pow (z:: Dual , n:: AbstractFloat )
267+ return Dual (value (z)^ n, ! iszero (n) * (epsilon (z) * n * value (z)^ (n - 1 )))
268+ end
269+ function pow (z:: Dual{T} , n:: Integer ) where T
270+ iszero (n) && return Dual (one (T), zero (T)) # avoid DomainError Int^(negative Int)
271+ isone (z) && return Dual (one (T), epsilon (z) * n)
272+ return Dual (value (z)^ n, epsilon (z) * n * value (z)^ (n - 1 ))
273+ end
274+ # these first two definitions are needed to fix ambiguity warnings
275+ for T1 ∈ (:Integer , :Rational , :Number )
276+ @eval Base.:^ (z:: Dual{T} , n:: $T1 ) where T = pow (z, n)
277+ end
278+
267279
268- Base.:^ (z:: Dual , n:: Number ) = Dual (value (z)^ n, epsilon (z)* n* value (z)^ (n- 1 ))
269- NaNMath. pow (z:: Dual , n:: Number ) = Dual (NaNMath. pow (value (z),n), epsilon (z)* n* NaNMath. pow (value (z),n- 1 ))
270- NaNMath. pow (z:: Number , w:: Dual ) = Dual (NaNMath. pow (z,value (w)), epsilon (w)* NaNMath. pow (z,value (w))* log (z))
280+ NaNMath. pow (z:: Dual{T} , n:: Number ) where T = Dual (NaNMath. pow (value (z),n), epsilon (z)* n* NaNMath. pow (value (z),n- 1 ))
281+ NaNMath. pow (z:: Number , w:: Dual{T} ) where T = Dual (NaNMath. pow (z,value (w)), epsilon (w)* NaNMath. pow (z,value (w))* log (z))
271282
272283Base. inv (z:: Dual ) = dual (inv (value (z)),- epsilon (z)/ value (z)^ 2 )
273284
0 commit comments