-
-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add modphase keyword for isapprox, deprecate @test_approx_eq_modphase
#393
Comments
It should probably be just |
So would it make sense to implement this as something like
Or do you think it simply shouldn't be part of |
Something like that seems fine to me. I would tend to fixphase(bdota::Real) = sign(bdota)
fixphase(bdota) = cis(angle(bdota)) in order to avoid unnecessarily complexifying real vectors. |
I assume you mean the |
In particular, I think the scalar and vector cases should look like this: # given bdota = dot(b,a), return the phase factor eⁱᵠ that minimizes
# the L2 norm |b - a|. For real vectors, this is just a ± sign,
# and we special-case bdota::Real to avoid complexifying real vectors.
fixphase(bdota::Real) = bdota < 0 ? -one(bdota) : +one(bdota)
fixphase(bdota) = isfinite(bdota) ? cis(angle(bdota)) : complex(float(fixphase(real(bdota))))
function isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0,
nans::Bool=false, ignorephase::Bool=false)
ignorephase && return isapprox(a,b*fixphase(b⋅a); rtol=rtol, atol=atol, nans=nans)
x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) || (nans && isnan(x) && isnan(y))
end
function isapprox{T,S}(x::AbstractArray{T}, y::AbstractArray{S};
rtol::Real=Base.rtoldefault(promote_leaf_eltypes(x),promote_leaf_eltypes(y)),
atol::Real=0, nans::Bool=false, ignorephase::Bool=false,
norm::Function=vecnorm)
if ignorephase
ydotx = y⋅x
if isnan(ydotx) && nans
# Re-compute dot products ignoring nans, since NaN*phase is a NaN.
# (We can use reduce(op, itr) because x & y must be nonempty here.)
ydotx = reduce(ab -> let adotb = ab[1]⋅ab[2]
isnan(adotb) ? zero(adotb) : adotb
end, zip(y, x))
end
return isapprox(x,y*Base.fixphase(ydotx); rtol=rtol, atol=atol, nans=nans, norm=norm)
end
d = norm(x - y)
if isfinite(d)
return d <= atol + rtol*max(norm(x), norm(y))
else
# Fall back to a component-wise approximate comparison
return all(ab -> isapprox(ab[1], ab[2]; rtol=rtol, atol=atol, nans=nans), zip(x, y))
end
end
function test_approx_eq_modphase{S,T}(a::AbstractVector{S}, b::AbstractVector{T},
err = length(indices(a,1))^3*(eps(S)+eps(T)))
@test a ≈ b atol=err ignorephase=true
end
function test_approx_eq_modphase{S,T}(A::AbstractMatrix{S}, B::AbstractMatrix{T},
err = length(indices(a,1))^3*(eps(S)+eps(T)))
@test all(i -> isapprox(A[:,i], B[:,i], atol=err, ignorephase=true), i in size(A,2))
end However, the |
Couldn't the |
It could, but then the |
I have no idea, I don't really understand what this function does or why it exists, which is why I want to deleted it. I feel like you (@stevengj), @andreasnoack and @jiahao need to figure this one out. |
The reason it exists is for testing things like eigensolvers, which return a matrix whose columns are the eigenvectors, but each eigenvector has a "random" phase. |
Would a function to "standardize" the phase of certain slices of an array allow this to be expressed more concisely? |
I think this is too specific to linear algebra to be part of _make_first_row_positive(A) = A*Diagonal(conj.(sign.(A[1,:])))
@test _make_first_row_positive(V1) ≈ _make_first_row_positive(V2) or simply @test V1 ≈ V2 .* cis.(angle.(sum(conj.(V2) .* V1, 1))) in the few cases where it is needed. |
I removed this in secret in JuliaLang/julia#25571 |
Since it seems that both Base and some packages use the horrifically named
@test_approx_eq_modphase
macro, perhaps it would be useful for amodphase
keyword to be introduced for theisapprox
function at which point@test_approx_eq_modphase a b
could be cleanly deprecated in favor of@test a ≈ b modphase=true
instead of simply deleting the macro or copy-pasta-ing everywhere. I, however, do not feel that I have the expertise to correctly implement such a keyword argument for the function, so if someone who understands what this macro is for could implement it, that would be greatly appreciated. cc: @andreasnoack, @jiahao, @stevengjThe text was updated successfully, but these errors were encountered: