Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2ddce84

Browse files
committedDec 16, 2017
reset GLOBAL_RNG state in/out at-testset for reproducibility
This is a follow-up on the recently introduced `guardsrand` functionality, first suggested at #16940 (comment). Each `testset` block is now implicitly wrapped in a `guardsrand` block, which is more user-friendly and more systematic (only few users know about `guardsrand`). These are essentially two new features: 1) "in": in base, tests are run with the global RNG randomly seeded, but the seed is printed in case of failure to allow reproducing the failure; but even if the failure occurs after many tests, when they alter the global RNG state, one has to re-run the whole file, which can be time-consuming; with this change, at the beginning of each `testset`, the global RNG is re-seeded with its own seed: this allows to re-run only the failing `testset`, which can be done easily in the REPL (the seeding occurs for each loop in a `testset for`; this also allows to re-arrange `testset`s in arbitrary order w.r.t. the global RNG; 2) "out": a `testset` leaves no tracks of its use of `srand` or `rand` (this "feature" should be less and less needed/useful with the generalization of the use of `testset` blocks). Example: ``` @testset begin srand(123) rand() @testset for T in (Int, Float64) # here is an implicit srand(123), by 1) rand() end rand() # this value will not be affected if the sub-`testset` block # above is removed, or if another rand() call is added therein, by 2) end ``` Note that guardsrand can't be used directly, as then the testset's body is wrapped in a function, which causes problem with overwriting loop variable ("outer"), using `using`, defining new methods, etc. So we need to duplicate guardsrand's logic.
1 parent 378e102 commit 2ddce84

File tree

9 files changed

+551
-527
lines changed

9 files changed

+551
-527
lines changed
 

‎stdlib/IterativeEigensolvers/test/runtests.jl

+94-94
Original file line numberDiff line numberDiff line change
@@ -4,118 +4,118 @@ using IterativeEigensolvers
44
using Test
55

66
@testset "eigs" begin
7-
guardsrand(1234) do
8-
n = 10
9-
areal = sprandn(n,n,0.4)
10-
breal = sprandn(n,n,0.4)
11-
acmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4))
12-
bcmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4))
7+
srand(1234)
8+
n = 10
9+
areal = sprandn(n,n,0.4)
10+
breal = sprandn(n,n,0.4)
11+
acmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4))
12+
bcmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4))
1313

14-
testtol = 1e-6
14+
testtol = 1e-6
1515

16-
@testset for elty in (Float64, ComplexF64)
17-
if elty == ComplexF32 || elty == ComplexF64
18-
a = acmplx
19-
b = bcmplx
20-
else
21-
a = areal
22-
b = breal
23-
end
24-
a_evs = eigvals(Array(a))
25-
a = convert(SparseMatrixCSC{elty}, a)
26-
asym = a' + a # symmetric indefinite
27-
apd = a'*a # symmetric positive-definite
16+
@testset for elty in (Float64, ComplexF64)
17+
if elty == ComplexF32 || elty == ComplexF64
18+
a = acmplx
19+
b = bcmplx
20+
else
21+
a = areal
22+
b = breal
23+
end
24+
a_evs = eigvals(Array(a))
25+
a = convert(SparseMatrixCSC{elty}, a)
26+
asym = a' + a # symmetric indefinite
27+
apd = a'*a # symmetric positive-definite
2828

29-
b = convert(SparseMatrixCSC{elty}, b)
30-
bsym = b' + b
31-
bpd = b'*b
29+
b = convert(SparseMatrixCSC{elty}, b)
30+
bsym = b' + b
31+
bpd = b'*b
3232

33-
(d,v) = eigs(a, nev=3)
34-
@test a*v[:,2] d[2]*v[:,2]
35-
@test norm(v) > testtol # eigenvectors cannot be null vectors
36-
(d,v) = eigs(a, I, nev=3) # test eigs(A, B; kwargs...)
37-
@test a*v[:,2] d[2]*v[:,2]
38-
@test norm(v) > testtol # eigenvectors cannot be null vectors
39-
@test_logs (:warn,"Use symbols instead of strings for specifying which eigenvalues to compute") eigs(a, which="LM")
40-
@test_logs (:warn,"Adjusting ncv from 1 to 4") eigs(a, ncv=1, nev=2)
41-
@test_logs (:warn,"Adjusting nev from $n to $(n-2)") eigs(a, nev=n)
42-
# (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet
43-
# @test a*v[:,2] ≈ d[2]*b*v[:,2] atol=testtol
44-
# @test norm(v) > testtol # eigenvectors cannot be null vectors
45-
if elty <: Base.LinAlg.BlasComplex
46-
sr_ind = indmin(real.(a_evs))
47-
(d, v) = eigs(a, nev=1, which=:SR)
48-
@test d[1] a_evs[sr_ind]
49-
si_ind = indmin(imag.(a_evs))
50-
(d, v) = eigs(a, nev=1, which=:SI)
51-
@test d[1] a_evs[si_ind]
52-
lr_ind = indmax(real.(a_evs))
53-
(d, v) = eigs(a, nev=1, which=:LR)
54-
@test d[1] a_evs[lr_ind]
55-
li_ind = indmax(imag.(a_evs))
56-
(d, v) = eigs(a, nev=1, which=:LI)
57-
@test d[1] a_evs[li_ind]
58-
end
33+
(d,v) = eigs(a, nev=3)
34+
@test a*v[:,2] d[2]*v[:,2]
35+
@test norm(v) > testtol # eigenvectors cannot be null vectors
36+
(d,v) = eigs(a, I, nev=3) # test eigs(A, B; kwargs...)
37+
@test a*v[:,2] d[2]*v[:,2]
38+
@test norm(v) > testtol # eigenvectors cannot be null vectors
39+
@test_logs (:warn,"Use symbols instead of strings for specifying which eigenvalues to compute") eigs(a, which="LM")
40+
@test_logs (:warn,"Adjusting ncv from 1 to 4") eigs(a, ncv=1, nev=2)
41+
@test_logs (:warn,"Adjusting nev from $n to $(n-2)") eigs(a, nev=n)
42+
# (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet
43+
# @test a*v[:,2] ≈ d[2]*b*v[:,2] atol=testtol
44+
# @test norm(v) > testtol # eigenvectors cannot be null vectors
45+
if elty <: Base.LinAlg.BlasComplex
46+
sr_ind = indmin(real.(a_evs))
47+
(d, v) = eigs(a, nev=1, which=:SR)
48+
@test d[1] a_evs[sr_ind]
49+
si_ind = indmin(imag.(a_evs))
50+
(d, v) = eigs(a, nev=1, which=:SI)
51+
@test d[1] a_evs[si_ind]
52+
lr_ind = indmax(real.(a_evs))
53+
(d, v) = eigs(a, nev=1, which=:LR)
54+
@test d[1] a_evs[lr_ind]
55+
li_ind = indmax(imag.(a_evs))
56+
(d, v) = eigs(a, nev=1, which=:LI)
57+
@test d[1] a_evs[li_ind]
58+
end
5959

60-
(d,v) = eigs(asym, nev=3)
61-
@test asym*v[:,1] d[1]*v[:,1]
62-
@test eigs(asym; nev=1, sigma=d[3])[1][1] d[3]
63-
@test norm(v) > testtol # eigenvectors cannot be null vectors
60+
(d,v) = eigs(asym, nev=3)
61+
@test asym*v[:,1] d[1]*v[:,1]
62+
@test eigs(asym; nev=1, sigma=d[3])[1][1] d[3]
63+
@test norm(v) > testtol # eigenvectors cannot be null vectors
6464

65-
(d,v) = eigs(apd, nev=3)
66-
@test apd*v[:,3] d[3]*v[:,3]
67-
@test eigs(apd; nev=1, sigma=d[3])[1][1] d[3]
65+
(d,v) = eigs(apd, nev=3)
66+
@test apd*v[:,3] d[3]*v[:,3]
67+
@test eigs(apd; nev=1, sigma=d[3])[1][1] d[3]
6868

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

73-
@testset "(shift-and-)invert mode" begin
74-
(d,v) = eigs(apd, nev=3, sigma=0)
75-
@test apd*v[:,3] d[3]*v[:,3]
76-
@test norm(v) > testtol # eigenvectors cannot be null vectors
73+
@testset "(shift-and-)invert mode" begin
74+
(d,v) = eigs(apd, nev=3, sigma=0)
75+
@test apd*v[:,3] d[3]*v[:,3]
76+
@test norm(v) > testtol # eigenvectors cannot be null vectors
7777

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

83-
@testset "ArgumentErrors" begin
84-
@test_throws ArgumentError eigs(rand(elty,2,2))
85-
@test_throws ArgumentError eigs(a, nev=-1)
86-
@test_throws ArgumentError eigs(a, which=:Z)
87-
@test_throws ArgumentError eigs(a, which=:BE)
88-
@test_throws DimensionMismatch eigs(a, v0=zeros(elty,n+2))
89-
@test_throws ArgumentError eigs(a, v0=zeros(Int,n))
90-
if elty == Float64
91-
@test_throws ArgumentError eigs(a+a.',which=:SI)
92-
@test_throws ArgumentError eigs(a+a.',which=:LI)
93-
@test_throws ArgumentError eigs(a,sigma=rand(ComplexF32))
94-
end
83+
@testset "ArgumentErrors" begin
84+
@test_throws ArgumentError eigs(rand(elty,2,2))
85+
@test_throws ArgumentError eigs(a, nev=-1)
86+
@test_throws ArgumentError eigs(a, which=:Z)
87+
@test_throws ArgumentError eigs(a, which=:BE)
88+
@test_throws DimensionMismatch eigs(a, v0=zeros(elty,n+2))
89+
@test_throws ArgumentError eigs(a, v0=zeros(Int,n))
90+
if elty == Float64
91+
@test_throws ArgumentError eigs(a+a.',which=:SI)
92+
@test_throws ArgumentError eigs(a+a.',which=:LI)
93+
@test_throws ArgumentError eigs(a,sigma=rand(ComplexF32))
9594
end
9695
end
96+
end
9797

98-
@testset "Symmetric generalized with singular B" begin
99-
n = 10
100-
k = 3
101-
A = randn(n,n); A = A'A
102-
B = randn(n,k); B = B*B'
103-
@test sort(eigs(A, B, nev = k, sigma = 1.0)[1]) sort(eigvals(A, B)[1:k])
104-
end
98+
@testset "Symmetric generalized with singular B" begin
99+
srand(124)
100+
n = 10
101+
k = 3
102+
A = randn(n,n); A = A'A
103+
B = randn(n,k); B = B*B'
104+
@test sort(eigs(A, B, nev = k, sigma = 1.0)[1]) sort(eigvals(A, B)[1:k])
105105
end
106106
end
107107

108108
# Problematic example from #6965A
109109
let A6965 = [
110-
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
111-
-1.0 2.0 0.0 0.0 0.0 0.0 0.0 1.0
112-
-1.0 0.0 3.0 0.0 0.0 0.0 0.0 1.0
113-
-1.0 0.0 0.0 4.0 0.0 0.0 0.0 1.0
114-
-1.0 0.0 0.0 0.0 5.0 0.0 0.0 1.0
115-
-1.0 0.0 0.0 0.0 0.0 6.0 0.0 1.0
116-
-1.0 0.0 0.0 0.0 0.0 0.0 7.0 1.0
117-
-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 8.0
118-
]
110+
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
111+
-1.0 2.0 0.0 0.0 0.0 0.0 0.0 1.0
112+
-1.0 0.0 3.0 0.0 0.0 0.0 0.0 1.0
113+
-1.0 0.0 0.0 4.0 0.0 0.0 0.0 1.0
114+
-1.0 0.0 0.0 0.0 5.0 0.0 0.0 1.0
115+
-1.0 0.0 0.0 0.0 0.0 6.0 0.0 1.0
116+
-1.0 0.0 0.0 0.0 0.0 0.0 7.0 1.0
117+
-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 8.0
118+
]
119119
d, = eigs(A6965,which=:SM,nev=2,ncv=4,tol=eps())
120120
@test d[1] 2.5346936860350002
121121
@test real(d[2]) 2.6159972444834976

‎stdlib/Test/src/Test.jl

+13-1
Original file line numberDiff line numberDiff line change
@@ -964,12 +964,20 @@ function testset_beginend(args, tests, source)
964964
# which is needed for backtrace scrubbing to work correctly.
965965
while false; end
966966
push_testset(ts)
967+
# we reproduce the logic of guardsrand, but this function
968+
# cannot be used as it changes slightly the semantic of @testset,
969+
# by wrapping the body in a function
970+
oldrng = copy(Base.GLOBAL_RNG)
967971
try
972+
# GLOBAL_RNG is re-seeded with its own seed to ease reproduce a failed test
973+
srand(Base.GLOBAL_RNG.seed)
968974
$(esc(tests))
969975
catch err
970976
# something in the test block threw an error. Count that as an
971977
# error in this test set
972978
record(ts, Error(:nontest_error, :(), err, catch_backtrace(), $(QuoteNode(source))))
979+
finally
980+
copy!(Base.GLOBAL_RNG, oldrng)
973981
end
974982
pop_testset()
975983
finish(ts)
@@ -1030,12 +1038,16 @@ function testset_forloop(args, testloop, source)
10301038
ts = $(testsettype)($desc; $options...)
10311039
push_testset(ts)
10321040
first_iteration = false
1041+
oldrng = copy(Base.GLOBAL_RNG)
10331042
try
1043+
srand(Base.GLOBAL_RNG.seed)
10341044
$(esc(tests))
10351045
catch err
10361046
# Something in the test block threw an error. Count that as an
10371047
# error in this test set
10381048
record(ts, Error(:nontest_error, :(), err, catch_backtrace(), $(QuoteNode(source))))
1049+
finally
1050+
copy!(Base.GLOBAL_RNG, oldrng)
10391051
end
10401052
end
10411053
quote
@@ -1477,7 +1489,7 @@ end
14771489

14781490
"`guardsrand(f, seed)` is equivalent to running `srand(seed); f()` and
14791491
then restoring the state of the global RNG as it was before."
1480-
guardsrand(f::Function, seed::Integer) = guardsrand() do
1492+
guardsrand(f::Function, seed::Union{Vector{UInt32},Integer}) = guardsrand() do
14811493
srand(seed)
14821494
f()
14831495
end

‎stdlib/Test/test/runtests.jl

+21-4
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,8 @@ end
287287
end
288288
end
289289
@testset "some loops fail" begin
290-
guardsrand(123) do
291-
@testset for i in 1:5
292-
@test i <= rand(1:10)
293-
end
290+
@testset for i in 1:5
291+
@test i <= 4
294292
end
295293
# should add 3 errors and 3 passing tests
296294
@testset for i in 1:6
@@ -739,3 +737,22 @@ end
739737
be tested in --depwarn=error mode"""
740738
end
741739
end
740+
741+
@testset "@testset preserves GLOBAL_RNG's state, and re-seeds it" begin
742+
# i.e. it behaves as if it was wrapped in a `guardsrand(GLOBAL_RNG.seed)` block
743+
seed = rand(UInt128)
744+
srand(seed)
745+
a = rand()
746+
@testset begin
747+
# global RNG must re-seeded at the beginning of @testset
748+
@test a == rand()
749+
end
750+
@testset for i=1:3
751+
@test a == rand()
752+
end
753+
# the @testset's above must have no consequence for rand() below
754+
b = rand()
755+
srand(seed)
756+
@test a == rand()
757+
@test b == rand()
758+
end

‎test/linalg/lapack.jl

+45-49
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,24 @@ import Base.LinAlg.BlasInt
1010
@test_throws ArgumentError Base.LinAlg.LAPACK.chktrans('Z')
1111

1212
@testset "syevr" begin
13-
guardsrand(123) do
14-
Ainit = randn(5,5)
15-
@testset for elty in (Float32, Float64, ComplexF32, ComplexF64)
16-
if elty == ComplexF32 || elty == ComplexF64
17-
A = complex.(Ainit, Ainit)
18-
else
19-
A = Ainit
20-
end
21-
A = convert(Array{elty, 2}, A)
22-
Asym = A'A
23-
vals, Z = LAPACK.syevr!('V', copy(Asym))
24-
@test Z*(Diagonal(vals)*Z') Asym
25-
@test all(vals .> 0.0)
26-
@test LAPACK.syevr!('N','V','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[vals .< 1.0]
27-
@test LAPACK.syevr!('N','I','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[4:5]
28-
@test vals LAPACK.syev!('N','U',copy(Asym))
29-
30-
@test_throws DimensionMismatch LAPACK.sygvd!(1,'V','U',copy(Asym),ones(elty,6,6))
13+
srand(123)
14+
Ainit = randn(5,5)
15+
@testset for elty in (Float32, Float64, ComplexF32, ComplexF64)
16+
if elty == ComplexF32 || elty == ComplexF64
17+
A = complex.(Ainit, Ainit)
18+
else
19+
A = Ainit
3120
end
21+
A = convert(Array{elty, 2}, A)
22+
Asym = A'A
23+
vals, Z = LAPACK.syevr!('V', copy(Asym))
24+
@test Z*(Diagonal(vals)*Z') Asym
25+
@test all(vals .> 0.0)
26+
@test LAPACK.syevr!('N','V','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[vals .< 1.0]
27+
@test LAPACK.syevr!('N','I','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[4:5]
28+
@test vals LAPACK.syev!('N','U',copy(Asym))
29+
30+
@test_throws DimensionMismatch LAPACK.sygvd!(1,'V','U',copy(Asym),ones(elty,6,6))
3231
end
3332
end
3433

@@ -207,12 +206,11 @@ end
207206

208207
@testset "gels" begin
209208
@testset for elty in (Float32, Float64, ComplexF32, ComplexF64)
210-
guardsrand(913) do
211-
A = rand(elty,10,10)
212-
X = rand(elty,10)
213-
B,Y,z = LAPACK.gels!('N',copy(A),copy(X))
214-
@test A\X Y
215-
end
209+
srand(913)
210+
A = rand(elty,10,10)
211+
X = rand(elty,10)
212+
B,Y,z = LAPACK.gels!('N',copy(A),copy(X))
213+
@test A\X Y
216214
end
217215
end
218216

@@ -435,36 +433,34 @@ end
435433

436434
@testset "sysv" begin
437435
@testset for elty in (Float32, Float64, ComplexF32, ComplexF64)
438-
guardsrand(123) do
439-
A = rand(elty,10,10)
440-
A = A + A.' #symmetric!
441-
b = rand(elty,10)
442-
c = A \ b
443-
b,A = LAPACK.sysv!('U',A,b)
444-
@test b c
445-
@test_throws DimensionMismatch LAPACK.sysv!('U',A,rand(elty,11))
446-
end
436+
srand(123)
437+
A = rand(elty,10,10)
438+
A = A + A.' #symmetric!
439+
b = rand(elty,10)
440+
c = A \ b
441+
b,A = LAPACK.sysv!('U',A,b)
442+
@test b c
443+
@test_throws DimensionMismatch LAPACK.sysv!('U',A,rand(elty,11))
447444
end
448445
end
449446

450447
@testset "hesv" begin
451448
@testset for elty in (ComplexF32, ComplexF64)
452-
guardsrand(935) do
453-
A = rand(elty,10,10)
454-
A = A + A' #hermitian!
455-
b = rand(elty,10)
456-
c = A \ b
457-
b,A = LAPACK.hesv!('U',A,b)
458-
@test b c
459-
@test_throws DimensionMismatch LAPACK.hesv!('U',A,rand(elty,11))
460-
A = rand(elty,10,10)
461-
A = A + A' #hermitian!
462-
b = rand(elty,10)
463-
c = A \ b
464-
b,A = LAPACK.hesv_rook!('U',A,b)
465-
@test b c
466-
@test_throws DimensionMismatch LAPACK.hesv_rook!('U',A,rand(elty,11))
467-
end
449+
srand(935)
450+
A = rand(elty,10,10)
451+
A = A + A' #hermitian!
452+
b = rand(elty,10)
453+
c = A \ b
454+
b,A = LAPACK.hesv!('U',A,b)
455+
@test b c
456+
@test_throws DimensionMismatch LAPACK.hesv!('U',A,rand(elty,11))
457+
A = rand(elty,10,10)
458+
A = A + A' #hermitian!
459+
b = rand(elty,10)
460+
c = A \ b
461+
b,A = LAPACK.hesv_rook!('U',A,b)
462+
@test b c
463+
@test_throws DimensionMismatch LAPACK.hesv_rook!('U',A,rand(elty,11))
468464
end
469465
end
470466

‎test/linalg/lu.jl

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ dimg = randn(n)/2
195195
end
196196

197197
@testset "conversion" begin
198+
srand(3)
198199
a = Tridiagonal(rand(9),rand(10),rand(9))
199200
fa = Array(a)
200201
falu = lufact(fa)

‎test/linalg/tridiag.jl

+280-280
Large diffs are not rendered by default.

‎test/random.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ using Main.TestHelpers.OAs
55

66
using Base.Random: Sampler, SamplerRangeFast, SamplerRangeInt
77

8-
# Issue #6573
9-
guardsrand(0) do
8+
@testset "Issue #6573" begin
9+
srand(0)
1010
rand()
1111
x = rand(384)
1212
@test find(x .== rand()) == []

‎test/sorting.jl

+59-59
Original file line numberDiff line numberDiff line change
@@ -226,73 +226,73 @@ function randn_with_nans(n,p)
226226
end
227227

228228
@testset "advanced sorting" begin
229-
guardsrand(0xdeadbeef) do
230-
for n in [0:10; 100; 101; 1000; 1001]
231-
local r
232-
r = -5:5
233-
v = rand(r,n)
234-
h = [sum(v .== x) for x in r]
235-
236-
for rev in [false,true]
237-
# insertion sort (stable) as reference
238-
pi = sortperm(v, alg=InsertionSort, rev=rev)
239-
@test pi == sortperm(float(v), alg=InsertionSort, rev=rev)
240-
@test isperm(pi)
241-
si = v[pi]
242-
@test [sum(si .== x) for x in r] == h
243-
@test issorted(si, rev=rev)
244-
@test all(issorted,[pi[si.==x] for x in r])
245-
c = copy(v)
246-
permute!(c, pi)
247-
@test c == si
248-
ipermute!(c, pi)
249-
@test c == v
250-
251-
# stable algorithms
252-
for alg in [MergeSort]
253-
p = sortperm(v, alg=alg, rev=rev)
254-
@test p == sortperm(float(v), alg=alg, rev=rev)
255-
@test p == pi
256-
s = copy(v)
257-
permute!(s, p)
258-
@test s == si
259-
ipermute!(s, p)
260-
@test s == v
261-
end
262-
263-
# unstable algorithms
264-
for alg in [QuickSort, PartialQuickSort(n)]
265-
p = sortperm(v, alg=alg, rev=rev)
266-
@test p == sortperm(float(v), alg=alg, rev=rev)
267-
@test isperm(p)
268-
@test v[p] == si
269-
s = copy(v)
270-
permute!(s, p)
271-
@test s == si
272-
ipermute!(s, p)
273-
@test s == v
274-
end
229+
srand(0xdeadbeef)
230+
for n in [0:10; 100; 101; 1000; 1001]
231+
local r
232+
r = -5:5
233+
v = rand(r,n)
234+
h = [sum(v .== x) for x in r]
235+
236+
for rev in [false,true]
237+
# insertion sort (stable) as reference
238+
pi = sortperm(v, alg=InsertionSort, rev=rev)
239+
@test pi == sortperm(float(v), alg=InsertionSort, rev=rev)
240+
@test isperm(pi)
241+
si = v[pi]
242+
@test [sum(si .== x) for x in r] == h
243+
@test issorted(si, rev=rev)
244+
@test all(issorted,[pi[si.==x] for x in r])
245+
c = copy(v)
246+
permute!(c, pi)
247+
@test c == si
248+
ipermute!(c, pi)
249+
@test c == v
250+
251+
# stable algorithms
252+
for alg in [MergeSort]
253+
p = sortperm(v, alg=alg, rev=rev)
254+
@test p == sortperm(float(v), alg=alg, rev=rev)
255+
@test p == pi
256+
s = copy(v)
257+
permute!(s, p)
258+
@test s == si
259+
ipermute!(s, p)
260+
@test s == v
275261
end
276262

277-
v = randn_with_nans(n,0.1)
278-
# TODO: alg = PartialQuickSort(n) fails here
279-
for alg in [InsertionSort, QuickSort, MergeSort],
280-
rev in [false,true]
281-
# test float sorting with NaNs
282-
s = sort(v, alg=alg, rev=rev)
283-
@test issorted(s, rev=rev)
284-
@test reinterpret(UInt64,v[isnan.(v)]) == reinterpret(UInt64,s[isnan.(s)])
285-
286-
# test float permutation with NaNs
263+
# unstable algorithms
264+
for alg in [QuickSort, PartialQuickSort(n)]
287265
p = sortperm(v, alg=alg, rev=rev)
266+
@test p == sortperm(float(v), alg=alg, rev=rev)
288267
@test isperm(p)
289-
vp = v[p]
290-
@test isequal(vp,s)
291-
@test reinterpret(UInt64,vp) == reinterpret(UInt64,s)
268+
@test v[p] == si
269+
s = copy(v)
270+
permute!(s, p)
271+
@test s == si
272+
ipermute!(s, p)
273+
@test s == v
292274
end
293275
end
276+
277+
v = randn_with_nans(n,0.1)
278+
# TODO: alg = PartialQuickSort(n) fails here
279+
for alg in [InsertionSort, QuickSort, MergeSort],
280+
rev in [false,true]
281+
# test float sorting with NaNs
282+
s = sort(v, alg=alg, rev=rev)
283+
@test issorted(s, rev=rev)
284+
@test reinterpret(UInt64,v[isnan.(v)]) == reinterpret(UInt64,s[isnan.(s)])
285+
286+
# test float permutation with NaNs
287+
p = sortperm(v, alg=alg, rev=rev)
288+
@test isperm(p)
289+
vp = v[p]
290+
@test isequal(vp,s)
291+
@test reinterpret(UInt64,vp) == reinterpret(UInt64,s)
292+
end
294293
end
295294
end
295+
296296
@testset "sortperm" begin
297297
inds = [
298298
1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,

‎test/sparse/sparse.jl

+36-38
Original file line numberDiff line numberDiff line change
@@ -1691,21 +1691,20 @@ end
16911691
end
16921692

16931693
@testset "sparse matrix normestinv" begin
1694-
guardsrand(1234) do
1695-
Ac = sprandn(20,20,.5) + im* sprandn(20,20,.5)
1696-
Aci = ceil.(Int64, 100*sprand(20,20,.5)) + im*ceil.(Int64, sprand(20,20,.5))
1697-
Ar = sprandn(20,20,.5)
1698-
Ari = ceil.(Int64, 100*Ar)
1699-
if Base.USE_GPL_LIBS
1700-
# NOTE: normestinv is probabilistic, so must be included in the guardsrand block
1701-
@test Base.SparseArrays.normestinv(Ac,3) norm(inv(Array(Ac)),1) atol=1e-4
1702-
@test Base.SparseArrays.normestinv(Aci,3) norm(inv(Array(Aci)),1) atol=1e-4
1703-
@test Base.SparseArrays.normestinv(Ar) norm(inv(Array(Ar)),1) atol=1e-4
1704-
@test_throws ArgumentError Base.SparseArrays.normestinv(Ac,0)
1705-
@test_throws ArgumentError Base.SparseArrays.normestinv(Ac,21)
1706-
end
1707-
@test_throws DimensionMismatch Base.SparseArrays.normestinv(sprand(3,5,.9))
1694+
srand(1234)
1695+
Ac = sprandn(20,20,.5) + im* sprandn(20,20,.5)
1696+
Aci = ceil.(Int64, 100*sprand(20,20,.5)) + im*ceil.(Int64, sprand(20,20,.5))
1697+
Ar = sprandn(20,20,.5)
1698+
Ari = ceil.(Int64, 100*Ar)
1699+
if Base.USE_GPL_LIBS
1700+
# NOTE: normestinv is probabilistic, so requires a fixed seed (set above in srand(1234))
1701+
@test Base.SparseArrays.normestinv(Ac,3) norm(inv(Array(Ac)),1) atol=1e-4
1702+
@test Base.SparseArrays.normestinv(Aci,3) norm(inv(Array(Aci)),1) atol=1e-4
1703+
@test Base.SparseArrays.normestinv(Ar) norm(inv(Array(Ar)),1) atol=1e-4
1704+
@test_throws ArgumentError Base.SparseArrays.normestinv(Ac,0)
1705+
@test_throws ArgumentError Base.SparseArrays.normestinv(Ac,21)
17081706
end
1707+
@test_throws DimensionMismatch Base.SparseArrays.normestinv(sprand(3,5,.9))
17091708
end
17101709

17111710
@testset "issue #13008" begin
@@ -1745,30 +1744,29 @@ end
17451744
end
17461745

17471746
@testset "factorization" begin
1748-
guardsrand(123) do
1749-
local A
1750-
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2) + im*sprandn(5, 5, 0.2)
1751-
A = A + A'
1752-
@test !Base.USE_GPL_LIBS || abs(det(factorize(Hermitian(A)))) abs(det(factorize(Array(A))))
1753-
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2) + im*sprandn(5, 5, 0.2)
1754-
A = A*A'
1755-
@test !Base.USE_GPL_LIBS || abs(det(factorize(Hermitian(A)))) abs(det(factorize(Array(A))))
1756-
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2)
1757-
A = A + A.'
1758-
@test !Base.USE_GPL_LIBS || abs(det(factorize(Symmetric(A)))) abs(det(factorize(Array(A))))
1759-
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2)
1760-
A = A*A.'
1761-
@test !Base.USE_GPL_LIBS || abs(det(factorize(Symmetric(A)))) abs(det(factorize(Array(A))))
1762-
@test factorize(triu(A)) == triu(A)
1763-
@test isa(factorize(triu(A)), UpperTriangular{Float64, SparseMatrixCSC{Float64, Int}})
1764-
@test factorize(tril(A)) == tril(A)
1765-
@test isa(factorize(tril(A)), LowerTriangular{Float64, SparseMatrixCSC{Float64, Int}})
1766-
@test !Base.USE_GPL_LIBS || factorize(A[:, 1:4])\ones(size(A, 1)) Array(A[:, 1:4])\ones(size(A, 1))
1767-
@test_throws ErrorException chol(A)
1768-
@test_throws ErrorException lu(A)
1769-
@test_throws ErrorException eig(A)
1770-
@test_throws ErrorException inv(A)
1771-
end
1747+
srand(123)
1748+
local A
1749+
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2) + im*sprandn(5, 5, 0.2)
1750+
A = A + A'
1751+
@test !Base.USE_GPL_LIBS || abs(det(factorize(Hermitian(A)))) abs(det(factorize(Array(A))))
1752+
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2) + im*sprandn(5, 5, 0.2)
1753+
A = A*A'
1754+
@test !Base.USE_GPL_LIBS || abs(det(factorize(Hermitian(A)))) abs(det(factorize(Array(A))))
1755+
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2)
1756+
A = A + A.'
1757+
@test !Base.USE_GPL_LIBS || abs(det(factorize(Symmetric(A)))) abs(det(factorize(Array(A))))
1758+
A = sparse(Diagonal(rand(5))) + sprandn(5, 5, 0.2)
1759+
A = A*A.'
1760+
@test !Base.USE_GPL_LIBS || abs(det(factorize(Symmetric(A)))) abs(det(factorize(Array(A))))
1761+
@test factorize(triu(A)) == triu(A)
1762+
@test isa(factorize(triu(A)), UpperTriangular{Float64, SparseMatrixCSC{Float64, Int}})
1763+
@test factorize(tril(A)) == tril(A)
1764+
@test isa(factorize(tril(A)), LowerTriangular{Float64, SparseMatrixCSC{Float64, Int}})
1765+
@test !Base.USE_GPL_LIBS || factorize(A[:, 1:4])\ones(size(A, 1)) Array(A[:, 1:4])\ones(size(A, 1))
1766+
@test_throws ErrorException chol(A)
1767+
@test_throws ErrorException lu(A)
1768+
@test_throws ErrorException eig(A)
1769+
@test_throws ErrorException inv(A)
17721770
end
17731771

17741772
@testset "issue #13792, use sparse triangular solvers for sparse triangular solves" begin

0 commit comments

Comments
 (0)
Please sign in to comment.