Skip to content
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

@test a ≈ b atol=ε #19901

Merged
merged 5 commits into from
Jan 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1674,4 +1674,71 @@ iteratoreltype(::Type{Task}) = EltypeUnknown()

isempty(::Task) = error("isempty not defined for Tasks")

# BEGIN code from base/test.jl
approx_full(x::AbstractArray) = x
approx_full(x::Number) = x
approx_full(x) = full(x)

function test_approx_eq(va, vb, Eps, astr, bstr)
va = approx_full(va)
vb = approx_full(vb)
la, lb = length(linearindices(va)), length(linearindices(vb))
if la != lb
error("lengths of ", astr, " and ", bstr, " do not match: ",
"\n ", astr, " (length $la) = ", va,
"\n ", bstr, " (length $lb) = ", vb)
end
diff = real(zero(eltype(va)))
for (xa, xb) = zip(va, vb)
if isfinite(xa) && isfinite(xb)
diff = max(diff, abs(xa-xb))
elseif !isequal(xa,xb)
error("mismatch of non-finite elements: ",
"\n ", astr, " = ", va,
"\n ", bstr, " = ", vb)
end
end

if !isnan(Eps) && !(diff <= Eps)
sdiff = string("|", astr, " - ", bstr, "| <= ", Eps)
error("assertion failed: ", sdiff,
"\n ", astr, " = ", va,
"\n ", bstr, " = ", vb,
"\n difference = ", diff, " > ", Eps)
end
end

array_eps{T}(a::AbstractArray{Complex{T}}) = eps(float(maximum(x->(isfinite(x) ? abs(x) : T(NaN)), a)))
array_eps(a) = eps(float(maximum(x->(isfinite(x) ? abs(x) : oftype(x,NaN)), a)))

test_approx_eq(va, vb, astr, bstr) =
test_approx_eq(va, vb, 1E4*length(linearindices(va))*max(array_eps(va), array_eps(vb)), astr, bstr)

"""
@test_approx_eq_eps(a, b, tol)

Test two floating point numbers `a` and `b` for equality taking into account
a margin of tolerance given by `tol`.
"""
macro test_approx_eq_eps(a, b, c)
Base.depwarn(string("@test_approx_eq_eps is deprecated, use `@test ", a, " ≈ ", b, " atol=", c, "` instead"),
Symbol("@test_approx_eq_eps"))
:(test_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b))))
end
export @test_approx_eq_eps

"""
@test_approx_eq(a, b)

Deprecated. Test two floating point numbers `a` and `b` for equality taking into
account small numerical errors.
"""
macro test_approx_eq(a, b)
Base.depwarn(string("@test_approx_eq is deprecated, use `@test ", a, " ≈ ", b, "` instead"),
Symbol("@test_approx_eq"))
:(test_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b))))
end
export @test_approx_eq
# END code from base/test.jl

# End deprecations scheduled for 0.6
122 changes: 49 additions & 73 deletions base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Test
export @test, @test_throws, @test_broken, @test_skip, @test_warn, @test_nowarn
export @testset
# Legacy approximate testing functions, yet to be included
export @test_approx_eq_eps, @inferred
export @inferred
export detect_ambiguities
export GenericString

Expand Down Expand Up @@ -203,29 +203,65 @@ end

const comparison_prec = Base.operator_precedence(:(==))

"""
test_expr!(ex, kws...)

Preprocess test expressions of function calls with trailing keyword arguments
so that e.g. `@test a ≈ b atol=ε` means `@test ≈(a, b, atol=ε)`.
"""
test_expr!(m, ex) = ex

function test_expr!(m, ex, kws...)
ex isa Expr && ex.head == :call || @goto fail
for kw in kws
kw isa Expr && kw.head == :(=) || @goto fail
kw.head = :kw
push!(ex.args, kw)
end
return ex
@label fail
error("invalid test macro call: $m $ex $(join(kws," "))")
end

# @test - check if the expression evaluates to true
"""
@test ex
@test f(args...) key=val ...

Tests that the expression `ex` evaluates to `true`.
Returns a `Pass` `Result` if it does, a `Fail` `Result` if it is
`false`, and an `Error` `Result` if it could not be evaluated.

The `@test f(args...) key=val...` form is equivalent to writing
`@test f(args..., key=val...)` which can be useful when the expression
is a call using infix syntax such as approximate comparisons:

@test a ≈ b atol=ε

This is equivalent to the uglier test `@test ≈(a, b, atol=ε)`.
It is an error to supply more than one expression unless the first
is a call expression and the rest are assignments (`k=v`).
"""
macro test(ex)
macro test(ex, kws...)
test_expr!("@test", ex, kws...)
orig_ex = Expr(:inert, ex)
result = get_test_result(ex)
:(do_test($result, $orig_ex))
end

"""
@test_broken ex
@test_broken f(args...) key=val ...

Indicates a test that should pass but currently consistently fails.
Tests that the expression `ex` evaluates to `false` or causes an
exception. Returns a `Broken` `Result` if it does, or an `Error` `Result`
if the expression evaluates to `true`.

The `@test_broken f(args...) key=val...` form works as for the `@test` macro.
"""
macro test_broken(ex)
macro test_broken(ex, kws...)
test_expr!("@test_broken", ex, kws...)
orig_ex = Expr(:inert, ex)
result = get_test_result(ex)
# code to call do_test with execution result and original expr
Expand All @@ -234,12 +270,16 @@ end

"""
@test_skip ex
@test_skip f(args...) key=val ...

Marks a test that should not be executed but should be included in test
summary reporting as `Broken`. This can be useful for tests that intermittently
fail, or tests of not-yet-implemented functionality.

The `@test_skip f(args...) key=val...` form works as for the `@test` macro.
"""
macro test_skip(ex)
macro test_skip(ex, kws...)
test_expr!("@test_skip", ex, kws...)
orig_ex = Expr(:inert, ex)
testres = :(Broken(:skipped, $orig_ex))
:(record(get_testset(), $testres))
Expand Down Expand Up @@ -326,6 +366,7 @@ end
@test_throws extype ex

Tests that the expression `ex` throws an exception of type `extype`.
Note that `@test_throws` does not support a trailing keyword form.
"""
macro test_throws(extype, ex)
orig_ex = Expr(:inert, ex)
Expand Down Expand Up @@ -960,71 +1001,6 @@ function get_testset_depth()
return length(testsets)
end

#-----------------------------------------------------------------------
# Legacy approximate testing functions, yet to be included

approx_full(x::AbstractArray) = x
approx_full(x::Number) = x
approx_full(x) = full(x)

function test_approx_eq(va, vb, Eps, astr, bstr)
va = approx_full(va)
vb = approx_full(vb)
la, lb = length(linearindices(va)), length(linearindices(vb))
if la != lb
error("lengths of ", astr, " and ", bstr, " do not match: ",
"\n ", astr, " (length $la) = ", va,
"\n ", bstr, " (length $lb) = ", vb)
end
diff = real(zero(eltype(va)))
for (xa, xb) = zip(va, vb)
if isfinite(xa) && isfinite(xb)
diff = max(diff, abs(xa-xb))
elseif !isequal(xa,xb)
error("mismatch of non-finite elements: ",
"\n ", astr, " = ", va,
"\n ", bstr, " = ", vb)
end
end

if !isnan(Eps) && !(diff <= Eps)
sdiff = string("|", astr, " - ", bstr, "| <= ", Eps)
error("assertion failed: ", sdiff,
"\n ", astr, " = ", va,
"\n ", bstr, " = ", vb,
"\n difference = ", diff, " > ", Eps)
end
end

array_eps{T}(a::AbstractArray{Complex{T}}) = eps(float(maximum(x->(isfinite(x) ? abs(x) : T(NaN)), a)))
array_eps(a) = eps(float(maximum(x->(isfinite(x) ? abs(x) : oftype(x,NaN)), a)))

test_approx_eq(va, vb, astr, bstr) =
test_approx_eq(va, vb, 1E4*length(linearindices(va))*max(array_eps(va), array_eps(vb)), astr, bstr)

"""
@test_approx_eq_eps(a, b, tol)

Test two floating point numbers `a` and `b` for equality taking into account
a margin of tolerance given by `tol`.
"""
macro test_approx_eq_eps(a, b, c)
:(test_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b))))
end

"""
@test_approx_eq(a, b)

Deprecated. Test two floating point numbers `a` and `b` for equality taking into
account small numerical errors.
"""
macro test_approx_eq(a, b)
Base.depwarn(string("@test_approx_eq is deprecated, use `@test ", a, " ≈ ", b, "` instead"),
Symbol("@test_approx_eq"))
:(test_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b))))
end
export @test_approx_eq

_args_and_call(args...; kwargs...) = (args[1:end-1], kwargs, args[end](args[1:end-1]...; kwargs...))
"""
@inferred f(x)
Expand Down Expand Up @@ -1119,13 +1095,13 @@ end
# Raises an error if any columnwise vector norm exceeds err. Otherwise, returns
# nothing.
function test_approx_eq_modphase{S<:Real,T<:Real}(
a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, err=nothing)
a::StridedVecOrMat{S}, b::StridedVecOrMat{T},
err = length(indices(a,1))^3*(eps(S)+eps(T))
)
@test indices(a,1) == indices(b,1) && indices(a,2) == indices(b,2)
m = length(indices(a,1))
err === nothing && (err=m^3*(eps(S)+eps(T)))
for i in indices(a,2)
v1, v2 = a[:, i], b[:, i]
@test_approx_eq_eps min(abs(norm(v1-v2)), abs(norm(v1+v2))) 0.0 err
@test min(abs(norm(v1-v2)),abs(norm(v1+v2))) 0.0 atol=err
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ end
@test exp(x) ≈ exp(big(x))
@test exp10(x) ≈ exp10(big(x))
@test exp2(x) ≈ exp2(big(x))
@test_approx_eq_eps expm1(x) expm1(big(x)) eps(T)
@test expm1(x) expm1(big(x)) atol=eps(T)
@test log(x) ≈ log(big(x))
@test log10(x) ≈ log10(big(x))
@test log1p(x) ≈ log1p(big(x))
Expand Down
8 changes: 4 additions & 4 deletions test/linalg/arnoldi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ using Base.Test
@test a*v[:,2] ≈ d[2]*v[:,2]
@test norm(v) > testtol # eigenvectors cannot be null vectors
# (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet
# @test_approx_eq_eps a*v[:,2] d[2]*b*v[:,2] testtol
# @test a*v[:,2] d[2]*b*v[:,2] atol=testtol
# @test norm(v) > testtol # eigenvectors cannot be null vectors

(d,v) = eigs(asym, nev=3)
Expand All @@ -47,7 +47,7 @@ using Base.Test
@test eigs(apd; nev=1, sigma=d[3])[1][1] ≈ d[3]

(d,v) = eigs(apd, bpd, nev=3, tol=1e-8)
@test_approx_eq_eps apd*v[:,2] d[2]*bpd*v[:,2] testtol
@test apd*v[:,2] d[2]*bpd*v[:,2] atol=testtol
@test norm(v) > testtol # eigenvectors cannot be null vectors

@testset "(shift-and-)invert mode" begin
Expand All @@ -56,7 +56,7 @@ using Base.Test
@test norm(v) > testtol # eigenvectors cannot be null vectors

(d,v) = eigs(apd, bpd, nev=3, sigma=0, tol=1e-8)
@test_approx_eq_eps apd*v[:,1] d[1]*bpd*v[:,1] testtol
@test apd*v[:,1] d[1]*bpd*v[:,1] atol=testtol
@test norm(v) > testtol # eigenvectors cannot be null vectors
end

Expand Down Expand Up @@ -99,7 +99,7 @@ let A6965 = [
# 0.8 0.1 0.1
# 0.7 0.1 0.2 ]
#d,v,nconv = eigs(T6965,nev=1,which=:LM)
#@test_approx_eq_eps T6965*v d[1]*v 1e-6
# @test T6965*v d[1]*v atol=1e-6
end

# Example from Quantum Information Theory
Expand Down
2 changes: 1 addition & 1 deletion test/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ srand(1)
Test.test_approx_eq_modphase(u1, u2)
Test.test_approx_eq_modphase(v1, v2)
end
@test_approx_eq_eps 0 vecnorm(u2*diagm(d2)*v2'-Tfull) n*max(n^2*eps(relty), vecnorm(u1*diagm(d1)*v1' - Tfull))
@test 0 vecnorm(u2*diagm(d2)*v2'-Tfull) atol=n*max(n^2*eps(relty),vecnorm(u1*diagm(d1)*v1'-Tfull))
@inferred svdvals(T)
@inferred svd(T)
end
Expand Down
4 changes: 2 additions & 2 deletions test/linalg/bunchkaufman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ bimg = randn(n,2)/2
@test logabsdet(bc1)[2] ≈ sign(det(bc1))
end
@test inv(bc1)*asym ≈ eye(n)
@test_approx_eq_eps asym*(bc1\b) b 1000ε
@test asym*(bc1\b) ≈ b atol=1000ε
@testset for rook in (false, true)
@test inv(bkfact(a.'+a, :U, true, rook))*(a.'+a) ≈ eye(n)
@test size(bc1) == size(bc1.LD)
Expand All @@ -76,7 +76,7 @@ bimg = randn(n,2)/2
@test logabsdet(bc2)[1] ≈ log(abs(det(bc2)))
@test logabsdet(bc2)[2] == sign(det(bc2))
@test inv(bc2)*apd ≈ eye(n)
@test_approx_eq_eps apd * (bc2\b) b 150000ε
@test apd*(bc2\b) ≈ b atol=150000ε
@test ishermitian(bc2) == !issymmetric(bc2)
end
end
Expand Down
12 changes: 6 additions & 6 deletions test/linalg/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ for elty in (Float32, Float64, Complex64, Complex128)
a = view(ainit, 1:n, 1:n)
end
# cond
@test_approx_eq_eps cond(a, 1) 4.837320054554436e+02 0.01
@test_approx_eq_eps cond(a, 2) 1.960057871514615e+02 0.01
@test_approx_eq_eps cond(a, Inf) 3.757017682707787e+02 0.01
@test_approx_eq_eps cond(a[:,1:5]) 10.233059337453463 0.01
@test cond(a,1) 4.837320054554436e+02 atol=0.01
@test cond(a,2) 1.960057871514615e+02 atol=0.01
@test cond(a,Inf) 3.757017682707787e+02 atol=0.01
@test cond(a[:,1:5]) 10.233059337453463 atol=0.01
@test_throws ArgumentError cond(a,3)
end
end
Expand Down Expand Up @@ -75,8 +75,8 @@ debug && println("Solve square general system of equations")
debug && println("Test nullspace")
a15null = nullspace(a[:,1:n1]')
@test rank([a[:,1:n1] a15null]) == 10
@test_approx_eq_eps norm(a[:,1:n1]'a15null, Inf) zero(eltya) 300ε
@test_approx_eq_eps norm(a15null'a[:,1:n1], Inf) zero(eltya) 400ε
@test norm(a[:,1:n1]'a15null,Inf) zero(eltya) atol=300ε
@test norm(a15null'a[:,1:n1],Inf) zero(eltya) atol=400ε
@test size(nullspace(b), 2) == 0
@test nullspace(zeros(eltya,n)) == eye(eltya,1)
end
Expand Down
Loading