@@ -135,13 +135,44 @@ ProjectTo(::Real) = ProjectTo{Real}()
135
135
ProjectTo (:: Complex ) = ProjectTo {Complex} ()
136
136
ProjectTo (:: Number ) = ProjectTo {Number} ()
137
137
for 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 perforance bug
139
139
@eval ProjectTo (:: $T ) = ProjectTo {$T} ()
140
140
end
141
141
ProjectTo (x:: Integer ) = ProjectTo (float (x))
142
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))
143
+
144
+ # Preserve low-precision floats as accidental promotion is a common perforance bug
145
+ (:: ProjectTo{T} )(dx:: AbstractFloat ) where T<: AbstractFloat = convert (T, dx)
146
+ (:: ProjectTo{T} )(dx:: Integer ) where T<: AbstractFloat = convert (T, dx)
147
+
148
+
149
+ # We asked for a number/real and they gave use one. We did ask for a particular concrete
150
+ # type, but that is just for the preserving low precision floats, which is handled above.
151
+ # Any Number/Real actually occupies the same subspace, so we can trust them.
152
+ # In particular, this makes weirder Real subtypes that are not simply the values like
153
+ # 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
156
+
157
+ (:: ProjectTo{T} )(dx:: Complex ) where T<: Real = ProjectTo (zero (T))(real (dx))
158
+
159
+ # 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
168
+ function (:: ProjectTo{<:Complex{T}} )(dx:: Complex ) where T
169
+ project = ProjectTo (zero (T))
170
+ return Complex (project (real (dx)), project (imag (dx)))
171
+ end
172
+ function (:: ProjectTo{<:Complex{T}} )(dx:: Real ) where T
173
+ project = ProjectTo (zero (T))
174
+ return Complex (project (dx), project (zero (dx)))
175
+ end
145
176
146
177
# Arrays
147
178
# If we don't have a more specialized `ProjectTo` rule, we just assume that there is
0 commit comments