@@ -134,14 +134,32 @@ ProjectTo(::Bool) = ProjectTo{NoTangent}() # same projector as ProjectTo(::Abst
134134ProjectTo (:: Real ) = ProjectTo {Real} ()
135135ProjectTo (:: Complex ) = ProjectTo {Complex} ()
136136ProjectTo (:: Number ) = ProjectTo {Number} ()
137+
138+ ProjectTo (x:: Integer ) = ProjectTo (float (x))
139+ ProjectTo (x:: Complex{<:Integer} ) = ProjectTo (float (x))
140+
141+ # Preserve low-precision floats as accidental promotion is a common performance bug
137142for T in (Float16, Float32, Float64, ComplexF16, ComplexF32, ComplexF64)
138- # Preserve low-precision floats as accidental promotion is a common perforance bug
139143 @eval ProjectTo (:: $T ) = ProjectTo {$T} ()
140144end
141- ProjectTo (x:: Integer ) = ProjectTo (float (x))
142- ProjectTo (x:: Complex{<:Integer} ) = ProjectTo (float (x))
143- (:: ProjectTo{T} )(dx:: Number ) where {T<: Number } = convert (T, dx)
144- (:: ProjectTo{T} )(dx:: Number ) where {T<: Real } = convert (T, real (dx))
145+
146+ # In these cases we can just `convert` as we know we are dealing with plain and simple types
147+ (:: ProjectTo{T} )(dx:: AbstractFloat ) where T<: AbstractFloat = convert (T, dx)
148+ (:: ProjectTo{T} )(dx:: Integer ) where T<: AbstractFloat = convert (T, dx) # needed to avoid ambiguity
149+ # simple Complex{<:AbstractFloat}} cases
150+ (:: ProjectTo{T} )(dx:: Complex{<:AbstractFloat} ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
151+ (:: ProjectTo{T} )(dx:: AbstractFloat ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
152+ (:: ProjectTo{T} )(dx:: Complex{<:Integer} ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
153+ (:: ProjectTo{T} )(dx:: Integer ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
154+
155+ # Other numbers, including e.g. ForwardDiff.Dual and Symbolics.Sym, should pass through.
156+ # We assume (lacking evidence to the contrary) that it is the right subspace of numebers
157+ # The (::ProjectTo{T})(::T) method doesn't work because we are allowing a different
158+ # Number type that might not be a subtype of the `project_type`.
159+ (:: ProjectTo{<:Number} )(dx:: Number ) = dx
160+
161+ (project:: ProjectTo{<:Real} )(dx:: Complex ) = project (real (dx))
162+ (project:: ProjectTo{<:Complex} )(dx:: Real ) = project (complex (dx))
145163
146164# Arrays
147165# If we don't have a more specialized `ProjectTo` rule, we just assume that there is
0 commit comments