@@ -135,44 +135,41 @@ ProjectTo(::Real) = ProjectTo{Real}()
135135ProjectTo (:: Complex ) = ProjectTo {Complex} ()
136136ProjectTo (:: Number ) = ProjectTo {Number} ()
137137for T in (Float16, Float32, Float64, ComplexF16, ComplexF32, ComplexF64)
138- # Preserve low-precision floats as accidental promotion is a common perforance bug
138+ # Preserve low-precision floats as accidental promotion is a common performance bug
139139 @eval ProjectTo (:: $T ) = ProjectTo {$T} ()
140140end
141141ProjectTo (x:: Integer ) = ProjectTo (float (x))
142142ProjectTo (x:: Complex{<:Integer} ) = ProjectTo (float (x))
143143
144- # Preserve low-precision floats as accidental promotion is a common perforance bug
144+ # Preserve low-precision floats as accidental promotion is a common performance bug
145+ # In these cases we can just `convert` as we know we are dealing with plain and simple types
145146(:: ProjectTo{T} )(dx:: AbstractFloat ) where T<: AbstractFloat = convert (T, dx)
146- (:: ProjectTo{T} )(dx:: Integer ) where T<: AbstractFloat = convert (T, dx)
147-
147+ (:: ProjectTo{T} )(dx:: Integer ) where T<: AbstractFloat = convert (T, dx) # needed to avoid ambiguity
148148
149149# We asked for a number/real and they gave use one. We did ask for a particular concrete
150150# type, but that is just for the preserving low precision floats, which is handled above.
151151# Any Number/Real actually occupies the same subspace, so we can trust them.
152152# In particular, this makes weirder Real subtypes that are not simply the values like
153153# ForwardDiff.Dual and Symbolics.Sym work, because we stay out of their way.
154- (:: ProjectTo{<:Number} )(dx:: Number ) where {T<: Number } = dx
155- (:: ProjectTo{<:Real} )(dx:: Real ) = dx
154+ (:: ProjectTo{<:Number} )(dx:: Number ) = dx
155+ # If you remove the above julia sometimes can't find the (::ProjectTo{T})(::T) for complex T
156+ # Seems like it might be a julia bug?
156157
157- (:: ProjectTo{T } )(dx:: Complex ) where T <: Real = ProjectTo ( zero (T)) (real (dx))
158+ (project :: ProjectTo{<:Real } )(dx:: Complex ) = project (real (dx))
158159
159160# Complex
160- function (proj:: ProjectTo{<:Complex{<:AbstractFloat}} )(
161- dx:: Complex{<:Union{AbstractFloat,Integer}}
162- )
163- # in this case we can just convert as we know we are dealing with
164- # boring floating point types or integers
165- return convert (project_type (proj), dx)
166- end
167- # Pass though non-AbstractFloat to project each component
161+
162+ # Preserve low-precision floats as accidental promotion is a common performance bug
163+ # In these cases we can just `convert` as we know we are dealing with plain and simple types
164+ (:: ProjectTo{T} )(dx:: Complex{<:AbstractFloat} ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
165+ (:: ProjectTo{T} )(dx:: AbstractFloat ) where {T<: Complex{<:AbstractFloat} } = convert (T, dx)
166+
167+ # For on-AbstractFloat other types pass though to project each component
168168function (:: ProjectTo{<:Complex{T}} )(dx:: Complex ) where T
169169 project = ProjectTo (zero (T))
170170 return Complex (project (real (dx)), project (imag (dx)))
171171end
172- function (:: ProjectTo{<:Complex{T}} )(dx:: Real ) where T
173- project = ProjectTo (zero (T))
174- return Complex (project (dx), project (zero (dx)))
175- end
172+ (:: ProjectTo{<:Complex{T}} )(dx:: Real ) where T = Complex (ProjectTo (zero (T))(dx))
176173
177174# Arrays
178175# If we don't have a more specialized `ProjectTo` rule, we just assume that there is
0 commit comments