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