From e55ee1daaa4d2ae8c8d6092ea6917f1b0ffcb2d4 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 11 Jan 2021 07:10:35 +0100 Subject: [PATCH 001/439] Fix a type-instability in sparse `findmin`/`findmax` The helper function `_findr` would usually return a `Vector` as first argument, but would use a `SparseMatrixCSC` in the empty case. Fix by always using `Vector`. --- stdlib/SparseArrays/src/sparsematrix.jl | 2 +- stdlib/SparseArrays/test/sparse.jl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index db2a06361642f..a60cbec3f33ec 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -2043,7 +2043,7 @@ function _findr(op, A, region, Tv) throw(ArgumentError("array slices must be non-empty")) else ri = Base.reduced_indices0(A, region) - return (similar(A, ri), zeros(Ti, ri)) + return (zeros(Tv, ri), zeros(Ti, ri)) end end diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 488769c9f1158..1d74b3e3feed5 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1305,10 +1305,10 @@ end @testset "argmax, argmin, findmax, findmin" begin S = sprand(100,80, 0.5) A = Array(S) - @test argmax(S) == argmax(A) - @test argmin(S) == argmin(A) - @test findmin(S) == findmin(A) - @test findmax(S) == findmax(A) + @test @inferred(argmax(S)) == argmax(A) + @test @inferred(argmin(S)) == argmin(A) + @test @inferred(findmin(S)) == findmin(A) + @test @inferred(findmax(S)) == findmax(A) for region in [(1,), (2,), (1,2)], m in [findmax, findmin] @test m(S, dims=region) == m(A, dims=region) end From 1a302b9c3d1ddf519a860a20b57e1d1bde7d8347 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 11 Jan 2021 17:31:35 +0100 Subject: [PATCH 002/439] Make sparse `hvcat` inferable This also requires making sparse `vcat` and `hcat` inferable in the vararg case which in turn requires a different way to determine the resulting index type, now implemented similar to `promote_eltype`. --- stdlib/SparseArrays/src/sparsematrix.jl | 8 ++++++-- stdlib/SparseArrays/src/sparsevector.jl | 17 ++++++++--------- stdlib/SparseArrays/test/sparse.jl | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index a60cbec3f33ec..4f1f4dd60b20b 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -3272,6 +3272,10 @@ dropstored!(A::AbstractSparseMatrixCSC, ::Colon) = dropstored!(A, :, :) # Sparse concatenation +promote_idxtype(::AbstractSparseMatrixCSC{<:Any, Ti}) where {Ti} = Ti +promote_idxtype(::AbstractSparseMatrixCSC{<:Any, Ti}, X::AbstractSparseMatrixCSC...) where {Ti} = + promote_type(Ti, promote_idxtype(X...)) + function vcat(X::AbstractSparseMatrixCSC...) num = length(X) mX = Int[ size(x, 1) for x in X ] @@ -3286,7 +3290,7 @@ function vcat(X::AbstractSparseMatrixCSC...) end Tv = promote_eltype(X...) - Ti = promote_eltype(map(x->rowvals(x), X)...) + Ti = promote_idxtype(X...) nnzX = Int[ nnz(x) for x in X ] nnz_res = sum(nnzX) @@ -3338,7 +3342,7 @@ function hcat(X::AbstractSparseMatrixCSC...) n = sum(nX) Tv = promote_eltype(X...) - Ti = promote_eltype(map(x->rowvals(x), X)...) + Ti = promote_idxtype(X...) colptr = Vector{Ti}(undef, n+1) nnzX = Int[ nnz(x) for x in X ] diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 777be897ea7df..30747ffda82e7 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -1091,17 +1091,16 @@ function vcat(Xin::_SparseConcatGroup...) X = map(x -> SparseMatrixCSC(issparse(x) ? x : sparse(x)), Xin) vcat(X...) end -function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) - nbr = length(rows) # number of block rows - - tmp_rows = Vector{SparseMatrixCSC}(undef, nbr) - k = 0 - @inbounds for i = 1 : nbr - tmp_rows[i] = hcat(X[(1 : rows[i]) .+ k]...) - k += rows[i] +hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) = + vcat(_hvcat_rows(rows, X...)...) +function _hvcat_rows((row1, rows...)::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) + if row1 ≤ 0 + throw(ArgumentError("length of block row must be positive, got $row1")) end - vcat(tmp_rows...) + # provide X[1] separately to convince inference that we don't call hcat() without arguments + return (hcat(X[1], X[2 : row1]...), _hvcat_rows(rows, X[row1+1:end]...)...) end +_hvcat_rows(::Tuple{}, X::_SparseConcatGroup...) = () # make sure UniformScaling objects are converted to sparse matrices for concatenation promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = SparseMatrixCSC diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 1d74b3e3feed5..1f38f3023dda3 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -162,7 +162,7 @@ end sz34 = spzeros(3, 4) se77 = sparse(1.0I, 7, 7) @testset "h+v concatenation" begin - @test [se44 sz42 sz41; sz34 se33] == se77 + @test @inferred(hvcat((3, 2), se44, sz42, sz41, sz34, se33)) == se77 # [se44 sz42 sz41; sz34 se33] @test length(nonzeros([sp33 0I; 1I 0I])) == 6 end @@ -2168,7 +2168,7 @@ end # Test that concatenations of pairs of sparse matrices yield sparse arrays @test issparse(vcat(spmat, spmat)) @test issparse(hcat(spmat, spmat)) - @test issparse(hvcat((2,), spmat, spmat)) + @test issparse(@inferred(hvcat((2,), spmat, spmat))) @test issparse(cat(spmat, spmat; dims=(1,2))) # Test that concatenations of a sparse matrice with a dense matrix/vector yield sparse arrays @test issparse(vcat(spmat, densemat)) From 3555c329e00883286af071584406b729518a4c52 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 22 Jan 2021 12:45:14 -0500 Subject: [PATCH 003/439] make printing of typealias env shorter Inspired by #35710 Co-authored-by: Stephan Hilb --- base/show.jl | 98 +++++++++++++++++------- doc/src/manual/types.md | 2 +- stdlib/InteractiveUtils/test/runtests.jl | 2 +- test/errorshow.jl | 2 +- test/reflection.jl | 2 +- test/show.jl | 76 +++++++++++++++--- 6 files changed, 139 insertions(+), 43 deletions(-) diff --git a/base/show.jl b/base/show.jl index 278a5c96df615..8107dda015b9a 100644 --- a/base/show.jl +++ b/base/show.jl @@ -583,6 +583,56 @@ function make_typealias(@nospecialize(x::Type)) end end +function show_can_elide(p::TypeVar, wheres::Vector, elide::Int, env::SimpleVector, skip::Int) + elide == 0 && return false + wheres[elide] === p || return false + for i = (elide + 1):length(wheres) + v = wheres[i]::TypeVar + has_typevar(v.lb, p) && return false + has_typevar(v.ub, p) && return false + end + for i = 1:length(env) + i == skip && continue + has_typevar(env[i], p) && return false + end + return true +end + +function show_typeparams(io::IO, env::SimpleVector, wheres::Vector) + n = length(env) + print(io, "{") + elide = length(wheres) + for i = n:-1:1 + p = env[i] + if p isa TypeVar + if p.lb === Union{} && show_can_elide(p, wheres, elide, env, i) + elide -= 1 + elseif p.ub === Any && show_can_elide(p, wheres, elide, env, i) + elide -= 1 + end + end + end + for i = 1:n + p = env[i] + if p isa TypeVar + if p.lb === Union{} && something(findfirst(w -> w === p, wheres), 0) > elide + print(io, "<:") + show(io, p.ub) + elseif p.ub === Any && something(findfirst(w -> w === p, wheres), 0) > elide + print(io, ">:") + show(io, p.lb) + else + show(io, p) + end + else + show(io, p) + end + i < n && print(io, ", ") + end + print(io, "}") + return elide +end + function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, wheres::Vector) if !(get(io, :compact, false)::Bool) # Print module prefix unless alias is visible from module passed to @@ -595,21 +645,14 @@ function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, whe end end print(io, name.name) - n = length(env) - n == 0 && return - - print(io, "{") - param_io = IOContext(io) - for i = 1:length(wheres) - p = wheres[i]::TypeVar - param_io = IOContext(param_io, :unionall_env => p) - end - for i = 1:n - p = env[i] - show(param_io, p) - i < n && print(io, ", ") + isempty(env) && return + io = IOContext(io) + for p in wheres + io = IOContext(io, :unionall_env => p) end - print(io, "}") + elide = show_typeparams(io, env, wheres) + resize!(wheres, elide) + nothing end function make_wheres(io::IO, env::SimpleVector, @nospecialize(x::Type)) @@ -642,12 +685,12 @@ function make_wheres(io::IO, env::SimpleVector, @nospecialize(x::Type)) return wheres end -function show_wheres(io::IO, env::Vector) - isempty(env) && return +function show_wheres(io::IO, wheres::Vector) + isempty(wheres) && return io = IOContext(io) - n = length(env) + n = length(wheres) for i = 1:n - p = env[i]::TypeVar + p = wheres[i]::TypeVar print(io, n == 1 ? " where " : i == 1 ? " where {" : ", ") show(io, p) io = IOContext(io, :unionall_env => p) @@ -857,7 +900,11 @@ function _show_type(io::IO, @nospecialize(x::Type)) push!(wheres, var) io = IOContext(io, :unionall_env => var) end - show(io, x) + if x isa DataType + show_datatype(io, x, wheres) + else + show(io, x) + end end show_wheres(io, wheres) end @@ -919,13 +966,13 @@ function show_type_name(io::IO, tn::Core.TypeName) nothing end -function show_datatype(io::IO, @nospecialize(x::DataType)) +function show_datatype(io::IO, @nospecialize(x::DataType), wheres::Vector=TypeVar[]) parameters = x.parameters::SimpleVector istuple = x.name === Tuple.name n = length(parameters) # Print homogeneous tuples with more than 3 elements compactly as NTuple{N, T} - if istuple && n > 3 && all(i -> (parameters[1] === i), parameters) + if istuple && n > 3 && all(@nospecialize(i) -> (parameters[1] === i), parameters) print(io, "NTuple{", n, ", ", parameters[1], "}") else show_type_name(io, x.name) @@ -934,13 +981,8 @@ function show_datatype(io::IO, @nospecialize(x::DataType)) # printing a method signature or type parameter. # Always print the type parameter if we are printing the type directly # since this information is still useful. - print(io, '{') - for i = 1:n - p = parameters[i] - show(io, p) - i < n && print(io, ", ") - end - print(io, '}') + elide = show_typeparams(io, parameters, wheres) + resize!(wheres, elide) end end end diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 31ae3d7f26fe6..384e6dbcc694c 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1034,7 +1034,7 @@ consider the two types created by the following declarations: ```jldoctest julia> const T1 = Array{Array{T,1} where T, 1} -Vector{Vector{T} where T} (alias for Array{Array{T, 1} where T, 1}) +Vector{Vector{<:Any}} (alias for Array{Array{T, 1} where T, 1}) julia> const T2 = Array{Array{T, 1}, 1} where T Array{Vector{T}, 1} where T diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index b272f46f14794..09ed361af0774 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -60,7 +60,7 @@ end Base.getindex(A::Stable, i) = A.A[i] Base.getindex(A::Unstable, i) = A.A[i] -tag = "ARRAY{FLOAT64, N}" +tag = "ARRAY{FLOAT64, <:ANY}" @test warntype_hastag(getindex, Tuple{Unstable{Float64},Int}, tag) @test !warntype_hastag(getindex, Tuple{Stable{Float64,2},Int}, tag) @test warntype_hastag(getindex, Tuple{Stable{Float64},Int}, tag) diff --git a/test/errorshow.jl b/test/errorshow.jl index 736e68dee1ef0..83899aa4fff71 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -432,7 +432,7 @@ let err_str, @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))), - "($(curmod_prefix)StructWithUnionAllMethodDefs{T} where T<:Integer)(x)") + "($(curmod_prefix)StructWithUnionAllMethodDefs{<:Integer})(x)") @test repr("text/plain", FunctionLike()) == "(::$(curmod_prefix)FunctionLike) (generic function with 1 method)" @test repr("text/plain", Core.arraysize) == "arraysize (built-in function)" diff --git a/test/reflection.jl b/test/reflection.jl index 63101796804bb..45cef576b59b9 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -224,7 +224,7 @@ let ex = :(a + b) end foo13825(::Array{T, N}, ::Array, ::Vector) where {T, N} = nothing @test startswith(string(first(methods(foo13825))), - "foo13825(::Array{T, N}, ::Array, ::Vector{T} where T)") + "foo13825(::Array{T, N}, ::Array, ::Vector{<:Any}) where {T, N} in") mutable struct TLayout x::Int8 diff --git a/test/show.jl b/test/show.jl index c2db37493ab05..b6ce2ee267d73 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1569,12 +1569,64 @@ end end let x = TypeVar(:_), y = TypeVar(:_) - @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{_1, _2} where {_1, _2}" - @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{_1} where _1, _1} where _1" + @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{<:Any, <:Any}" + @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Any, _1} where _1" + @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{<:Any}, <:Any}" + @test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1, _2}" x = TypeVar(:a) y = TypeVar(:a) z = TypeVar(:a) - @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{a1, a2, a} where {a, a1, a2}" + @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{<:Any, <:Any, a} where a" + @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{z,y,x})))) == "Tuple{a, <:Any, a1} where {a, a1}" +end + +is_juliarepr(x) = eval(Meta.parse(repr(x))) == x +@testset "unionall types" begin + X = TypeVar(gensym()) + Y = TypeVar(gensym(), Ref, Ref) + x, y, z = TypeVar(:a), TypeVar(:a), TypeVar(:a) + struct TestTVUpper{A<:Integer} end + + # named typevars + @test is_juliarepr(Ref{A} where A) + @test is_juliarepr(Ref{A} where A>:Ref) + @test is_juliarepr(Ref{A} where A<:Ref) + @test is_juliarepr(Ref{A} where Ref<:A<:Ref) + @test is_juliarepr(TestTVUpper{<:Real}) + @test is_juliarepr(TestTVUpper{<:Integer}) + @test is_juliarepr(TestTVUpper{<:Signed}) + + # typearg order + @test is_juliarepr(UnionAll(X, Pair{X,<:Any})) + @test is_juliarepr(UnionAll(X, Pair{<:Any,X})) + + # duplicates + @test is_juliarepr(UnionAll(X, Pair{X,X})) + + # nesting + @test is_juliarepr(UnionAll(X, Ref{Ref{X}})) + @test is_juliarepr(Union{T, Int} where T) + @test is_juliarepr(Pair{A, <:A} where A) + + # renumbered typevars with same names + @test is_juliarepr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) + + # shortened typevar printing + @test repr(Ref{<:Any}) == "Ref{<:Any}" # improve? + @test repr(Pair{1, <:Any}) == "Pair{1, <:Any}" # improve? + @test repr(Ref{<:Ref}) == "Ref{<:Ref}" + @test repr(Ref{>:Ref}) == "Ref{>:Ref}" + @test repr(Pair{<:Any, 1}) == "Pair{<:Any, 1}" + yname = sprint(Base.show_unquoted, Y.name) + @test repr(UnionAll(Y, Ref{Y})) == "Ref{$yname} where Ref<:$yname<:Ref" + @test endswith(repr(TestTVUpper{<:Real}), "TestTVUpper{<:Real}") + @test endswith(repr(TestTVUpper{<:Integer}), "TestTVUpper{<:Integer}") # improve? + @test endswith(repr(TestTVUpper{<:Signed}), "TestTVUpper{<:Signed}") + + # exception for tuples + @test is_juliarepr(Tuple) + @test is_juliarepr(Tuple{}) + @test is_juliarepr(Tuple{<:Any}) end @testset "showarg" begin @@ -1659,7 +1711,7 @@ end @test showstr([Float16(1)]) == "Float16[1.0]" @test showstr([[Float16(1)]]) == "Vector{Float16}[[1.0]]" @test replstr(Real[Float16(1)]) == "1-element Vector{Real}:\n Float16(1.0)" - @test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real, N} where N}:\n [1]" + @test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real, <:Any}}:\n [1]" # printing tuples (Issue #25042) @test replstr(fill((Int64(1), zeros(Float16, 3)), 1)) == "1-element Vector{Tuple{Int64, Vector{Float16}}}:\n (1, [0.0, 0.0, 0.0])" @@ -1706,9 +1758,9 @@ end @test replstr([[1.0]=>1.0]) == "1-element Vector{Pair{Vector{Float64}, Float64}}:\n [1.0] => 1.0" # issue #28159 - @test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{names, Tuple{$Int, $Int}} where names}:\n (a = 1, b = 2)\n (a = 3, c = 4)" + @test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{<:Any, Tuple{$Int, $Int}}}:\n (a = 1, b = 2)\n (a = 3, c = 4)" - @test replstr(Vector[Any[1]]) == "1-element Vector{Vector{T} where T}:\n Any[1]" + @test replstr(Vector[Any[1]]) == "1-element Vector{Vector{<:Any}}:\n Any[1]" @test replstr(AbstractDict{Integer,Integer}[Dict{Integer,Integer}(1=>2)]) == "1-element Vector{AbstractDict{Integer, Integer}}:\n Dict(1 => 2)" @@ -1929,7 +1981,7 @@ end @testset """printing "Any" is not skipped with nested arrays""" begin @test replstr(Union{X28004,Vector}[X28004(Any[X28004(1)])], :compact => true) == - "1-element Vector{Union{X28004, Vector{T} where T}}:\n X(Any[X(1)])" + "1-element Vector{Union{X28004, Vector{<:Any}}}:\n X(Any[X(1)])" end # Issue 25589 - Underlines in cmd printing @@ -2096,11 +2148,13 @@ end @test Base.make_typealias(M37012.AStruct{1}) === nothing @test isempty(Base.make_typealiases(M37012.AStruct{1})[1]) @test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}" -@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{T} where T}" -@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{T} where T}" +@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{<:Any}}" +@test string(Union{Nothing, Number, Vector{<:Integer}}) == "Union{Nothing, Number, Vector{<:Integer}}" +@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{<:Any}}" +@test string(Union{Nothing, AbstractVecOrMat{<:Integer}}) == "Union{Nothing, AbstractVecOrMat{<:Integer}}" @test string(M37012.BStruct{T, T} where T) == "$(curmod_prefix)M37012.B2{T, T} where T" -@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Unsigned, S<:Signed}" -@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Signed, S<:T}" +@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{<:Signed, T} where T<:Unsigned" +@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{<:T, T} where T<:Signed" @test string(Union{M37012.SimpleU, Nothing}) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU}" @test string(Union{M37012.SimpleU, Nothing, T} where T) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU, T} where T" @test string(Union{AbstractVector{T}, T} where T) == "Union{AbstractVector{T}, T} where T" From 9472ed9be7e780120db647dc6e424addc6063b1a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 22 Jan 2021 18:36:05 -0500 Subject: [PATCH 004/439] additionally drop trailing env, if unneeded --- base/show.jl | 73 ++++++++++++++---------- doc/src/manual/types.md | 4 +- stdlib/InteractiveUtils/test/runtests.jl | 2 +- stdlib/REPL/src/docview.jl | 2 +- test/docs.jl | 22 +++---- test/reflection.jl | 2 +- test/show.jl | 39 ++++++++----- 7 files changed, 86 insertions(+), 58 deletions(-) diff --git a/base/show.jl b/base/show.jl index 8107dda015b9a..dc283002bc751 100644 --- a/base/show.jl +++ b/base/show.jl @@ -598,39 +598,50 @@ function show_can_elide(p::TypeVar, wheres::Vector, elide::Int, env::SimpleVecto return true end -function show_typeparams(io::IO, env::SimpleVector, wheres::Vector) +function show_typeparams(io::IO, env::SimpleVector, orig::SimpleVector, wheres::Vector) n = length(env) - print(io, "{") elide = length(wheres) + function egal_var(p::TypeVar, @nospecialize o) + return o isa TypeVar && + ccall(:jl_types_egal, Cint, (Any, Any), p.ub, o.ub) != 0 && + ccall(:jl_types_egal, Cint, (Any, Any), p.lb, o.lb) != 0 + end for i = n:-1:1 p = env[i] if p isa TypeVar - if p.lb === Union{} && show_can_elide(p, wheres, elide, env, i) + if i == n && egal_var(p, orig[i]) && show_can_elide(p, wheres, elide, env, i) + n -= 1 + elide -= 1 + elseif p.lb === Union{} && show_can_elide(p, wheres, elide, env, i) elide -= 1 elseif p.ub === Any && show_can_elide(p, wheres, elide, env, i) elide -= 1 end end end - for i = 1:n - p = env[i] - if p isa TypeVar - if p.lb === Union{} && something(findfirst(w -> w === p, wheres), 0) > elide - print(io, "<:") - show(io, p.ub) - elseif p.ub === Any && something(findfirst(w -> w === p, wheres), 0) > elide - print(io, ">:") - show(io, p.lb) + if n > 0 + print(io, "{") + for i = 1:n + p = env[i] + if p isa TypeVar + if p.lb === Union{} && something(findfirst(w -> w === p, wheres), 0) > elide + print(io, "<:") + show(io, p.ub) + elseif p.ub === Any && something(findfirst(w -> w === p, wheres), 0) > elide + print(io, ">:") + show(io, p.lb) + else + show(io, p) + end else show(io, p) end - else - show(io, p) + i < n && print(io, ", ") end - i < n && print(io, ", ") + print(io, "}") end - print(io, "}") - return elide + resize!(wheres, elide) + nothing end function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, wheres::Vector) @@ -650,8 +661,13 @@ function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, whe for p in wheres io = IOContext(io, :unionall_env => p) end - elide = show_typeparams(io, env, wheres) - resize!(wheres, elide) + orig = getfield(name.mod, name.name) + vars = TypeVar[] + while orig isa UnionAll + push!(vars, orig.var) + orig = orig.body + end + show_typeparams(io, env, Core.svec(vars...), wheres) nothing end @@ -972,18 +988,17 @@ function show_datatype(io::IO, @nospecialize(x::DataType), wheres::Vector=TypeVa n = length(parameters) # Print homogeneous tuples with more than 3 elements compactly as NTuple{N, T} - if istuple && n > 3 && all(@nospecialize(i) -> (parameters[1] === i), parameters) - print(io, "NTuple{", n, ", ", parameters[1], "}") + if istuple + if n > 3 && all(@nospecialize(i) -> (parameters[1] === i), parameters) + print(io, "NTuple{", n, ", ", parameters[1], "}") + else + print(io, "Tuple{") + join(io, parameters, ", ") + print(io, "}") + end else show_type_name(io, x.name) - if (n > 0 || istuple) && x !== Tuple - # Do not print the type parameters for the primary type if we are - # printing a method signature or type parameter. - # Always print the type parameter if we are printing the type directly - # since this information is still useful. - elide = show_typeparams(io, parameters, wheres) - resize!(wheres, elide) - end + show_typeparams(io, parameters, unwrap_unionall(x.name.wrapper).parameters, wheres) end end diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 384e6dbcc694c..009313545e216 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1033,8 +1033,8 @@ The `where` keyword itself can be nested inside a more complex declaration. For consider the two types created by the following declarations: ```jldoctest -julia> const T1 = Array{Array{T,1} where T, 1} -Vector{Vector{<:Any}} (alias for Array{Array{T, 1} where T, 1}) +julia> const T1 = Array{Array{T, 1} where T, 1} +Vector{Vector} (alias for Array{Array{<:Any, 1}, 1}) julia> const T2 = Array{Array{T, 1}, 1} where T Array{Vector{T}, 1} where T diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index 09ed361af0774..046d5d7bc85f5 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -60,7 +60,7 @@ end Base.getindex(A::Stable, i) = A.A[i] Base.getindex(A::Unstable, i) = A.A[i] -tag = "ARRAY{FLOAT64, <:ANY}" +tag = "ARRAY" @test warntype_hastag(getindex, Tuple{Unstable{Float64},Int}, tag) @test !warntype_hastag(getindex, Tuple{Stable{Float64,2},Int}, tag) @test warntype_hastag(getindex, Tuple{Stable{Float64},Int}, tag) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 9f36cadd0b868..0e45d5a89345f 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -291,7 +291,7 @@ function summarize(io::IO, TT::Type, binding::Binding) println(io, "# Subtypes") println(io, "```") for t in subt - println(io, t) + println(io, Base.unwrap_unionall(t)) end println(io, "```") end diff --git a/test/docs.jl b/test/docs.jl index fbe24da9be873..a8a7c6960aee6 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -965,10 +965,10 @@ abstract type $(curmod_prefix)Undocumented.at0{T<:Number, N} # Subtypes ``` -$(curmod_prefix)Undocumented.at1{T, N} where {Integer<:T<:Number, N} -$(curmod_prefix)Undocumented.pt2 -$(curmod_prefix)Undocumented.st3 -$(curmod_prefix)Undocumented.st4{T, N} where {T<:Number, N} +$(curmod_prefix)Undocumented.at1{Integer<:T<:Number, N} +$(curmod_prefix)Undocumented.pt2{T<:Number, N, A>:Integer} +$(curmod_prefix)Undocumented.st3{T<:Integer, N} +$(curmod_prefix)Undocumented.st4{T<:Number, N} ``` """) @test docstrings_equal(@doc(Undocumented.at0), doc"$doc_str") @@ -985,7 +985,7 @@ abstract type $(curmod_prefix)Undocumented.at1{T>:Integer, N} # Subtypes ``` -$(curmod_prefix)Undocumented.mt6{Integer, N} where N +$(curmod_prefix)Undocumented.mt6{Integer, N} ``` # Supertype Hierarchy @@ -1007,9 +1007,9 @@ abstract type $(curmod_prefix)Undocumented.at0{Int64, N} # Subtypes ``` -$(curmod_prefix)Undocumented.pt2{Int64, N, A} where {N, A>:Integer} -$(curmod_prefix)Undocumented.st3{Int64, N} where N -$(curmod_prefix)Undocumented.st4{Int64, N} where N +$(curmod_prefix)Undocumented.pt2{Int64, N, A>:Integer} +$(curmod_prefix)Undocumented.st3{Int64, N} +$(curmod_prefix)Undocumented.st4{Int64, N} ``` """) @test docstrings_equal(@doc(Undocumented.at_), doc"$doc_str") @@ -1157,9 +1157,9 @@ No documentation found. # Union Composed of Types - - `$(curmod_prefix)Undocumented.at1{T, N} where {T, N}` - - `$(curmod_prefix)Undocumented.pt2{T, N, A} where {T, N, A>:Integer}` - - `$(curmod_prefix)Undocumented.st3{T, N} where {T, N}` + - `$(curmod_prefix)Undocumented.at1{<:Any}` + - `$(curmod_prefix)Undocumented.pt2{<:Any}` + - `$(curmod_prefix)Undocumented.st3{<:Any}` - `$(curmod_prefix)Undocumented.st4` """) @test docstrings_equal(@doc(Undocumented.ut9), doc"$doc_str") diff --git a/test/reflection.jl b/test/reflection.jl index 45cef576b59b9..be0a53beae61f 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -224,7 +224,7 @@ let ex = :(a + b) end foo13825(::Array{T, N}, ::Array, ::Vector) where {T, N} = nothing @test startswith(string(first(methods(foo13825))), - "foo13825(::Array{T, N}, ::Array, ::Vector{<:Any}) where {T, N} in") + "foo13825(::Array{T, N}, ::Array, ::Vector) where {T, N} in") mutable struct TLayout x::Int8 diff --git a/test/show.jl b/test/show.jl index b6ce2ee267d73..d8ed9022f30a4 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1569,17 +1569,28 @@ end end let x = TypeVar(:_), y = TypeVar(:_) - @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{<:Any, <:Any}" + @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair" @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Any, _1} where _1" - @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{<:Any}, <:Any}" + @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref}" @test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1, _2}" +end + +let x, y, x x = TypeVar(:a) y = TypeVar(:a) z = TypeVar(:a) - @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{<:Any, <:Any, a} where a" - @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{z,y,x})))) == "Tuple{a, <:Any, a1} where {a, a1}" + @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{a1, a2, a} where {a, a1, a2}" + @test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{z,y,x})))) == "Tuple{a, a2, a1} where {a, a1, a2}" end +let x = TypeVar(:_, Number), y = TypeVar(:_, Number) + @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{<:Number, <:Number}" + @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Number, _1} where _1<:Number" + @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{<:Number}, <:Number}" + @test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1<:Number, _2<:Number}" +end + + is_juliarepr(x) = eval(Meta.parse(repr(x))) == x @testset "unionall types" begin X = TypeVar(gensym()) @@ -1612,15 +1623,17 @@ is_juliarepr(x) = eval(Meta.parse(repr(x))) == x @test is_juliarepr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) # shortened typevar printing - @test repr(Ref{<:Any}) == "Ref{<:Any}" # improve? - @test repr(Pair{1, <:Any}) == "Pair{1, <:Any}" # improve? + @test repr(Ref{<:Any}) == "Ref" + @test repr(Pair{1, <:Any}) == "Pair{1}" + @test repr(Ref{<:Number}) == "Ref{<:Number}" + @test repr(Pair{1, <:Number}) == "Pair{1, <:Number}" @test repr(Ref{<:Ref}) == "Ref{<:Ref}" @test repr(Ref{>:Ref}) == "Ref{>:Ref}" @test repr(Pair{<:Any, 1}) == "Pair{<:Any, 1}" yname = sprint(Base.show_unquoted, Y.name) @test repr(UnionAll(Y, Ref{Y})) == "Ref{$yname} where Ref<:$yname<:Ref" @test endswith(repr(TestTVUpper{<:Real}), "TestTVUpper{<:Real}") - @test endswith(repr(TestTVUpper{<:Integer}), "TestTVUpper{<:Integer}") # improve? + @test endswith(repr(TestTVUpper), "TestTVUpper") @test endswith(repr(TestTVUpper{<:Signed}), "TestTVUpper{<:Signed}") # exception for tuples @@ -1711,7 +1724,7 @@ end @test showstr([Float16(1)]) == "Float16[1.0]" @test showstr([[Float16(1)]]) == "Vector{Float16}[[1.0]]" @test replstr(Real[Float16(1)]) == "1-element Vector{Real}:\n Float16(1.0)" - @test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real, <:Any}}:\n [1]" + @test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real}}:\n [1]" # printing tuples (Issue #25042) @test replstr(fill((Int64(1), zeros(Float16, 3)), 1)) == "1-element Vector{Tuple{Int64, Vector{Float16}}}:\n (1, [0.0, 0.0, 0.0])" @@ -1760,7 +1773,7 @@ end # issue #28159 @test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{<:Any, Tuple{$Int, $Int}}}:\n (a = 1, b = 2)\n (a = 3, c = 4)" - @test replstr(Vector[Any[1]]) == "1-element Vector{Vector{<:Any}}:\n Any[1]" + @test replstr(Vector[Any[1]]) == "1-element Vector{Vector}:\n Any[1]" @test replstr(AbstractDict{Integer,Integer}[Dict{Integer,Integer}(1=>2)]) == "1-element Vector{AbstractDict{Integer, Integer}}:\n Dict(1 => 2)" @@ -1981,7 +1994,7 @@ end @testset """printing "Any" is not skipped with nested arrays""" begin @test replstr(Union{X28004,Vector}[X28004(Any[X28004(1)])], :compact => true) == - "1-element Vector{Union{X28004, Vector{<:Any}}}:\n X(Any[X(1)])" + "1-element Vector{Union{X28004, Vector}}:\n X(Any[X(1)])" end # Issue 25589 - Underlines in cmd printing @@ -2148,9 +2161,9 @@ end @test Base.make_typealias(M37012.AStruct{1}) === nothing @test isempty(Base.make_typealiases(M37012.AStruct{1})[1]) @test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}" -@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{<:Any}}" +@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector}" @test string(Union{Nothing, Number, Vector{<:Integer}}) == "Union{Nothing, Number, Vector{<:Integer}}" -@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{<:Any}}" +@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat}" @test string(Union{Nothing, AbstractVecOrMat{<:Integer}}) == "Union{Nothing, AbstractVecOrMat{<:Integer}}" @test string(M37012.BStruct{T, T} where T) == "$(curmod_prefix)M37012.B2{T, T} where T" @test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{<:Signed, T} where T<:Unsigned" @@ -2158,7 +2171,7 @@ end @test string(Union{M37012.SimpleU, Nothing}) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU}" @test string(Union{M37012.SimpleU, Nothing, T} where T) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU, T} where T" @test string(Union{AbstractVector{T}, T} where T) == "Union{AbstractVector{T}, T} where T" -@test string(Union{AbstractVector, T} where T) == "Union{AbstractVector{T} where T, T} where T" +@test string(Union{AbstractVector, T} where T) == "Union{AbstractVector, T} where T" @test sprint(show, :(./)) == ":((./))" @test sprint(show, :((.|).(.&, b))) == ":((.|).((.&), b))" From aa4bf234f6e318e4a997a1f4784155f43af4ada4 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 3 Feb 2021 22:44:39 -0500 Subject: [PATCH 005/439] Add detach(::Task) method to monitor for Task failures This adds a convenience method to be able to essentially wrap an arbitrary task in a try/catch/log block conveniently. --- base/exports.jl | 3 ++- base/task.jl | 37 +++++++++++++++++++++++++++++++++++++ doc/src/base/parallel.md | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/base/exports.jl b/base/exports.jl index adfb1772600d3..8842b45e49229 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -682,6 +682,7 @@ export timedwait, asyncmap, asyncmap!, + errormonitor, # channels take!, @@ -912,7 +913,7 @@ export uperm, walkdir, -# external processes ## TODO: whittle down these exports. +# external processes detach, getpid, ignorestatus, diff --git a/base/task.jl b/base/task.jl index 8c9516fb39766..f817fdaae9cae 100644 --- a/base/task.jl +++ b/base/task.jl @@ -417,6 +417,43 @@ macro async(expr) end end +""" + errormonitor(t::Task) + +Print an error log to `stderr` if task `t` fails. +""" +function errormonitor(t::Task) + t2 = Task() do + if istaskfailed(t) + local errs = stderr + try # try to display the failure atomically + errio = IOContext(PipeBuffer(), errs::IO) + emphasize(errio, "Unhandled Task ") + display_error(errio, catch_stack(t)) + write(errs, errio) + catch + try # try to display the secondary error atomically + errio = IOContext(PipeBuffer(), errs::IO) + print(errio, "\nSYSTEM: caught exception while trying to print a failed Task notice: ") + display_error(errio, catch_stack()) + write(errs, errio) + flush(errs) + # and then the actual error, as best we can + Core.print(Core.stderr, "while handling: ") + Core.println(Core.stderr, catch_stack(t)[end][1]) + catch e + # give up + Core.print(Core.stderr, "\nSYSTEM: caught exception of type ", typeof(e).name.name, + " while trying to print a failed Task notice; giving up\n") + end + end + end + nothing + end + _wait2(t, t2) + return t +end + # Capture interpolated variables in $() and move them to let-block function _lift_one_interp!(e) letargs = Any[] # store the new gensymed arguments diff --git a/doc/src/base/parallel.md b/doc/src/base/parallel.md index ce8e25107ab51..a508603a2d220 100644 --- a/doc/src/base/parallel.md +++ b/doc/src/base/parallel.md @@ -27,6 +27,7 @@ Base.schedule ## [Synchronization](@id lib-task-sync) ```@docs +Base.errormonitor Base.@sync Base.wait Base.fetch(t::Task) From d1d37f790a79f05591d5347a45036ce43d37cc07 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 3 Feb 2021 22:52:00 -0500 Subject: [PATCH 006/439] Add a monitor to some detached Tasks --- doc/src/manual/asynchronous-programming.md | 10 +++++--- doc/src/manual/distributed-computing.md | 2 +- doc/src/manual/networking-and-streams.md | 12 +++++----- doc/src/manual/running-external-programs.md | 2 ++ stdlib/Distributed/src/cluster.jl | 12 ++++++---- stdlib/Distributed/src/macros.jl | 3 ++- stdlib/Distributed/src/managers.jl | 19 +++++---------- stdlib/Distributed/src/process_messages.jl | 26 ++++++++++----------- stdlib/Distributed/src/remotecall.jl | 6 ++--- stdlib/REPL/src/LineEdit.jl | 6 ++--- stdlib/REPL/src/REPL.jl | 2 ++ stdlib/REPL/test/repl.jl | 5 ++-- 12 files changed, 53 insertions(+), 52 deletions(-) diff --git a/doc/src/manual/asynchronous-programming.md b/doc/src/manual/asynchronous-programming.md index 1791d4b0e40f7..c0181e775bd05 100644 --- a/doc/src/manual/asynchronous-programming.md +++ b/doc/src/manual/asynchronous-programming.md @@ -186,7 +186,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and a read end : # we can schedule `n` instances of `foo` to be active concurrently. for _ in 1:n - @async foo() + errormonitor(@async foo()) end ``` * Channels are created via the `Channel{T}(sz)` constructor. The channel will only hold objects @@ -263,10 +263,10 @@ julia> function make_jobs(n) julia> n = 12; -julia> @async make_jobs(n); # feed the jobs channel with "n" jobs +julia> errormonitor(@async make_jobs(n)); # feed the jobs channel with "n" jobs julia> for i in 1:4 # start 4 tasks to process requests in parallel - @async do_work() + errormonitor(@async do_work()) end julia> @elapsed while n > 0 # print out results @@ -289,6 +289,10 @@ julia> @elapsed while n > 0 # print out results 0.029772311 ``` +Instead of `errormonitor(t)`, a more robust solution may be use use `bind(results, t)`, as that will +not only log any unexpected failures, but also force the associated resources to close and propagate +the exception everywhere. + ## More task operations Task operations are built on a low-level primitive called [`yieldto`](@ref). diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index e5b6e78cae981..6e3231a76ed1a 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -580,7 +580,7 @@ julia> function make_jobs(n) julia> n = 12; -julia> @async make_jobs(n); # feed the jobs channel with "n" jobs +julia> errormonitor(@async make_jobs(n)); # feed the jobs channel with "n" jobs julia> for p in workers() # start tasks on the workers to process requests in parallel remote_do(do_work, p, jobs, results) diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index 163716c583804..0bdef1b338925 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -193,13 +193,13 @@ Let's first create a simple server: ```julia-repl julia> using Sockets -julia> @async begin +julia> errormonitor(@async begin server = listen(2000) while true sock = accept(server) println("Hello World\n") end - end + end) Task (runnable) @0x00007fd31dc11ae0 ``` @@ -265,7 +265,7 @@ printed the message and waited for the next client. Reading and writing works in To see this, consider the following simple echo server: ```julia-repl -julia> @async begin +julia> errormonitor(@async begin server = listen(2001) while true sock = accept(server) @@ -273,15 +273,15 @@ julia> @async begin write(sock, readline(sock, keep=true)) end end - end + end) Task (runnable) @0x00007fd31dc12e60 julia> clientside = connect(2001) TCPSocket(RawFD(28) open, 0 bytes waiting) -julia> @async while isopen(clientside) +julia> errormonitor(@async while isopen(clientside) write(stdout, readline(clientside, keep=true)) - end + end) Task (runnable) @0x00007fd31dc11870 julia> println(clientside,"Hello World from the Echo Server") diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index a00050ffb5149..8fb59b8f7152a 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -327,6 +327,8 @@ wait(writer) fetch(reader) ``` +(commonly also, reader is not a separate task, since we immediately `fetch` it anyways). + ### Complex Example The combination of a high-level programming language, a first-class command abstraction, and automatic diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 7329e1b91d37b..482e7da44390d 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -160,11 +160,12 @@ function check_worker_state(w::Worker) else w.ct_time = time() if myid() > w.id - @async exec_conn_func(w) + t = @async exec_conn_func(w) else # route request via node 1 - @async remotecall_fetch((p,to_id) -> remotecall_fetch(exec_conn_func, p, to_id), 1, w.id, myid()) + t = @async remotecall_fetch((p,to_id) -> remotecall_fetch(exec_conn_func, p, to_id), 1, w.id, myid()) end + errormonitor(t) wait_for_conn(w) end end @@ -242,10 +243,10 @@ function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_std else sock = listen(interface, LPROC.bind_port) end - @async while isopen(sock) + errormonitor(@async while isopen(sock) client = accept(sock) process_messages(client, client, true) - end + end) print(out, "julia_worker:") # print header print(out, "$(string(LPROC.bind_port))#") # print port print(out, LPROC.bind_addr) @@ -274,7 +275,7 @@ end function redirect_worker_output(ident, stream) - @async while !eof(stream) + t = @async while !eof(stream) line = readline(stream) if startswith(line, " From worker ") # stdout's of "additional" workers started from an initial worker on a host are not available @@ -284,6 +285,7 @@ function redirect_worker_output(ident, stream) println(" From worker $(ident):\t$line") end end + errormonitor(t) end struct LaunchWorkerError <: Exception diff --git a/stdlib/Distributed/src/macros.jl b/stdlib/Distributed/src/macros.jl index b53890017d4de..6603d627c3409 100644 --- a/stdlib/Distributed/src/macros.jl +++ b/stdlib/Distributed/src/macros.jl @@ -279,9 +279,10 @@ function preduce(reducer, f, R) end function pfor(f, R) - @async @sync for c in splitrange(Int(firstindex(R)), Int(lastindex(R)), nworkers()) + t = @async @sync for c in splitrange(Int(firstindex(R)), Int(lastindex(R)), nworkers()) @spawnat :any f(R, first(c), last(c)) end + errormonitor(t) end function make_preduce_body(var, body) diff --git a/stdlib/Distributed/src/managers.jl b/stdlib/Distributed/src/managers.jl index 3519259190fbc..ce99d85801e17 100644 --- a/stdlib/Distributed/src/managers.jl +++ b/stdlib/Distributed/src/managers.jl @@ -158,22 +158,15 @@ default_addprocs_params(::SSHManager) = function launch(manager::SSHManager, params::Dict, launched::Array, launch_ntfy::Condition) # Launch one worker on each unique host in parallel. Additional workers are launched later. # Wait for all launches to complete. - launch_tasks = Vector{Any}(undef, length(manager.machines)) - - for (i, (machine, cnt)) in enumerate(manager.machines) + @sync for (i, (machine, cnt)) in enumerate(manager.machines) let machine=machine, cnt=cnt - launch_tasks[i] = @async try - launch_on_machine(manager, machine, cnt, params, launched, launch_ntfy) - catch e - print(stderr, "exception launching on machine $(machine) : $(e)\n") - end + @async try + launch_on_machine(manager, $machine, $cnt, params, launched, launch_ntfy) + catch e + print(stderr, "exception launching on machine $(machine) : $(e)\n") + end end end - - for t in launch_tasks - wait(t::Task) - end - notify(launch_ntfy) end diff --git a/stdlib/Distributed/src/process_messages.jl b/stdlib/Distributed/src/process_messages.jl index 3216a4e1c73c6..8d5dac5af571e 100644 --- a/stdlib/Distributed/src/process_messages.jl +++ b/stdlib/Distributed/src/process_messages.jl @@ -78,7 +78,7 @@ function schedule_call(rid, thunk) rv = RemoteValue(def_rv_channel()) (PGRP::ProcessGroup).refs[rid] = rv push!(rv.clientset, rid.whence) - @async run_work_thunk(rv, thunk) + errormonitor(@async run_work_thunk(rv, thunk)) return rv end end @@ -111,7 +111,7 @@ end ## message event handlers ## function process_messages(r_stream::TCPSocket, w_stream::TCPSocket, incoming::Bool=true) - @async process_tcp_streams(r_stream, w_stream, incoming) + errormonitor(@async process_tcp_streams(r_stream, w_stream, incoming)) end function process_tcp_streams(r_stream::TCPSocket, w_stream::TCPSocket, incoming::Bool) @@ -141,7 +141,7 @@ Julia version number to perform the authentication handshake. See also [`cluster_cookie`](@ref). """ function process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true) - @async message_handler_loop(r_stream, w_stream, incoming) + errormonitor(@async message_handler_loop(r_stream, w_stream, incoming)) end function message_handler_loop(r_stream::IO, w_stream::IO, incoming::Bool) @@ -274,7 +274,7 @@ function handle_msg(msg::CallMsg{:call}, header, r_stream, w_stream, version) schedule_call(header.response_oid, ()->msg.f(msg.args...; msg.kwargs...)) end function handle_msg(msg::CallMsg{:call_fetch}, header, r_stream, w_stream, version) - @async begin + errormonitor(@async begin v = run_work_thunk(()->msg.f(msg.args...; msg.kwargs...), false) if isa(v, SyncTake) try @@ -285,18 +285,20 @@ function handle_msg(msg::CallMsg{:call_fetch}, header, r_stream, w_stream, versi else deliver_result(w_stream, :call_fetch, header.notify_oid, v) end - end + nothing + end) end function handle_msg(msg::CallWaitMsg, header, r_stream, w_stream, version) - @async begin + errormonitor(@async begin rv = schedule_call(header.response_oid, ()->msg.f(msg.args...; msg.kwargs...)) deliver_result(w_stream, :call_wait, header.notify_oid, fetch(rv.c)) - end + nothing + end) end function handle_msg(msg::RemoteDoMsg, header, r_stream, w_stream, version) - @async run_work_thunk(()->msg.f(msg.args...; msg.kwargs...), true) + errormonitor(@async run_work_thunk(()->msg.f(msg.args...; msg.kwargs...), true)) end function handle_msg(msg::ResultMsg, header, r_stream, w_stream, version) @@ -330,8 +332,7 @@ function handle_msg(msg::JoinPGRPMsg, header, r_stream, w_stream, version) lazy = msg.lazy PGRP.lazy = lazy - wait_tasks = Task[] - for (connect_at, rpid) in msg.other_workers + @sync for (connect_at, rpid) in msg.other_workers wconfig = WorkerConfig() wconfig.connect_at = connect_at @@ -340,14 +341,11 @@ function handle_msg(msg::JoinPGRPMsg, header, r_stream, w_stream, version) # The constructor registers the object with a global registry. Worker(rpid, ()->connect_to_peer(cluster_manager, rpid, wconfig)) else - t = @async connect_to_peer(cluster_manager, rpid, wconfig) - push!(wait_tasks, t) + @async connect_to_peer(cluster_manager, rpid, wconfig) end end end - for wt in wait_tasks; Base.wait(wt); end - send_connection_hdr(controller, false) send_msg_now(controller, MsgHeader(RRID(0,0), header.notify_oid), JoinCompleteMsg(Sys.CPU_THREADS, getpid())) end diff --git a/stdlib/Distributed/src/remotecall.jl b/stdlib/Distributed/src/remotecall.jl index f4845221a611a..9b2127d4f499a 100644 --- a/stdlib/Distributed/src/remotecall.jl +++ b/stdlib/Distributed/src/remotecall.jl @@ -192,7 +192,7 @@ or to use a local [`Channel`](@ref) as a proxy: ```julia p = 1 f = Future(p) -@async put!(f, remotecall_fetch(long_computation, p)) +errormonitor(@async put!(f, remotecall_fetch(long_computation, p))) isready(f) # will not block ``` """ @@ -249,10 +249,10 @@ end const any_gc_flag = Condition() function start_gc_msgs_task() - @async while true + errormonitor(@async while true wait(any_gc_flag) flush_gc_msgs() - end + end) end function send_del_client(rr) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 718cd02e6eb98..a8a1f5ef03912 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -182,7 +182,7 @@ function beep(s::PromptState, duration::Real=options(s).beep_duration, isinteractive() || return # some tests fail on some platforms s.beeping = min(s.beeping + duration, maxduration) let colors = Base.copymutable(colors) - @async begin + errormonitor(@async begin trylock(s.refresh_lock) || return try orig_prefix = s.p.prompt_prefix @@ -198,12 +198,10 @@ function beep(s::PromptState, duration::Real=options(s).beep_duration, s.p.prompt_prefix = orig_prefix refresh_multi_line(s, beeping=true) s.beeping = 0.0 - catch e - Base.showerror(stdout, e, catch_backtrace()) finally unlock(s.refresh_lock) end - end + end) end nothing end diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 68f157322facc..d17482ec453cb 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -313,10 +313,12 @@ function run_repl(repl::AbstractREPL, @nospecialize(consumer = x -> nothing); ba end if backend_on_current_task t = @async run_frontend(repl, backend_ref) + errormonitor(t) Base._wait2(t, cleanup) start_repl_backend(backend, consumer) else t = @async start_repl_backend(backend, consumer) + errormonitor(t) Base._wait2(t, cleanup) run_frontend(repl, backend_ref) end diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 577dfda1a811b..40c8617ce655d 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -453,7 +453,8 @@ for prompt = ["TestΠ", () -> randstring(rand(1:10))] # In the future if we want we can add a test that the right object # gets displayed by intercepting the display repl.specialdisplay = REPL.REPLDisplay(repl) - @async write(devnull, stdout_read) # redirect stdout to devnull so we drain the output pipe + + errormonitor(@async write(devnull, stdout_read)) # redirect stdout to devnull so we drain the output pipe repl.interface = REPL.setup_interface(repl) repl_mode = repl.interface.modes[1] @@ -1252,7 +1253,7 @@ end # AST transformations (softscope, Revise, OhMyREPL, etc.) @testset "AST Transformation" begin backend = REPL.REPLBackend() - @async REPL.start_repl_backend(backend) + errormonitor(@async REPL.start_repl_backend(backend)) put!(backend.repl_channel, (:(1+1), false)) reply = take!(backend.response_channel) @test reply == Pair{Any, Bool}(2, false) From e593839560c1aea5108a284b809f2eb23f297531 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 Mar 2021 15:23:38 -0400 Subject: [PATCH 007/439] restrict shorter printing of wheres to gensym names --- base/show.jl | 10 ++++++---- doc/src/manual/types.md | 2 +- test/docs.jl | 6 +++--- test/errorshow.jl | 2 +- test/show.jl | 14 +++++++------- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/base/show.jl b/base/show.jl index dc283002bc751..b45da56baa499 100644 --- a/base/show.jl +++ b/base/show.jl @@ -583,6 +583,8 @@ function make_typealias(@nospecialize(x::Type)) end end +isgensym(s::Symbol) = '#' in string(s) + function show_can_elide(p::TypeVar, wheres::Vector, elide::Int, env::SimpleVector, skip::Int) elide == 0 && return false wheres[elide] === p || return false @@ -612,9 +614,9 @@ function show_typeparams(io::IO, env::SimpleVector, orig::SimpleVector, wheres:: if i == n && egal_var(p, orig[i]) && show_can_elide(p, wheres, elide, env, i) n -= 1 elide -= 1 - elseif p.lb === Union{} && show_can_elide(p, wheres, elide, env, i) + elseif p.lb === Union{} && isgensym(p.name) && show_can_elide(p, wheres, elide, env, i) elide -= 1 - elseif p.ub === Any && show_can_elide(p, wheres, elide, env, i) + elseif p.ub === Any && isgensym(p.name) && show_can_elide(p, wheres, elide, env, i) elide -= 1 end end @@ -624,10 +626,10 @@ function show_typeparams(io::IO, env::SimpleVector, orig::SimpleVector, wheres:: for i = 1:n p = env[i] if p isa TypeVar - if p.lb === Union{} && something(findfirst(w -> w === p, wheres), 0) > elide + if p.lb === Union{} && something(findfirst(@nospecialize(w) -> w === p, wheres), 0) > elide print(io, "<:") show(io, p.ub) - elseif p.ub === Any && something(findfirst(w -> w === p, wheres), 0) > elide + elseif p.ub === Any && something(findfirst(@nospecialize(w) -> w === p, wheres), 0) > elide print(io, ">:") show(io, p.lb) else diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 009313545e216..0be372d4fa612 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1034,7 +1034,7 @@ consider the two types created by the following declarations: ```jldoctest julia> const T1 = Array{Array{T, 1} where T, 1} -Vector{Vector} (alias for Array{Array{<:Any, 1}, 1}) +Vector{Vector} (alias for Array{Array{T, 1} where T, 1}) julia> const T2 = Array{Array{T, 1}, 1} where T Array{Vector{T}, 1} where T diff --git a/test/docs.jl b/test/docs.jl index a8a7c6960aee6..da7a6f01f03e0 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -1157,9 +1157,9 @@ No documentation found. # Union Composed of Types - - `$(curmod_prefix)Undocumented.at1{<:Any}` - - `$(curmod_prefix)Undocumented.pt2{<:Any}` - - `$(curmod_prefix)Undocumented.st3{<:Any}` + - `$(curmod_prefix)Undocumented.at1{T} where T` + - `$(curmod_prefix)Undocumented.pt2{T} where T` + - `$(curmod_prefix)Undocumented.st3{T} where T` - `$(curmod_prefix)Undocumented.st4` """) @test docstrings_equal(@doc(Undocumented.ut9), doc"$doc_str") diff --git a/test/errorshow.jl b/test/errorshow.jl index 83899aa4fff71..736e68dee1ef0 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -432,7 +432,7 @@ let err_str, @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))), - "($(curmod_prefix)StructWithUnionAllMethodDefs{<:Integer})(x)") + "($(curmod_prefix)StructWithUnionAllMethodDefs{T} where T<:Integer)(x)") @test repr("text/plain", FunctionLike()) == "(::$(curmod_prefix)FunctionLike) (generic function with 1 method)" @test repr("text/plain", Core.arraysize) == "arraysize (built-in function)" diff --git a/test/show.jl b/test/show.jl index d8ed9022f30a4..734ab84a7e01b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1570,7 +1570,7 @@ end let x = TypeVar(:_), y = TypeVar(:_) @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair" - @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Any, _1} where _1" + @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{_2, _1} where {_1, _2}" @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref}" @test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1, _2}" end @@ -1584,9 +1584,9 @@ let x, y, x end let x = TypeVar(:_, Number), y = TypeVar(:_, Number) - @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{<:Number, <:Number}" - @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Number, _1} where _1<:Number" - @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{<:Number}, <:Number}" + @test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{_1, _2} where {_1<:Number, _2<:Number}" + @test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{_2, _1} where {_1<:Number, _2<:Number}" + @test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{_1} where _1<:Number, _1} where _1<:Number" @test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1<:Number, _2<:Number}" end @@ -1771,7 +1771,7 @@ end @test replstr([[1.0]=>1.0]) == "1-element Vector{Pair{Vector{Float64}, Float64}}:\n [1.0] => 1.0" # issue #28159 - @test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{<:Any, Tuple{$Int, $Int}}}:\n (a = 1, b = 2)\n (a = 3, c = 4)" + @test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{names, Tuple{$Int, $Int}} where names}:\n (a = 1, b = 2)\n (a = 3, c = 4)" @test replstr(Vector[Any[1]]) == "1-element Vector{Vector}:\n Any[1]" @test replstr(AbstractDict{Integer,Integer}[Dict{Integer,Integer}(1=>2)]) == @@ -2166,8 +2166,8 @@ end @test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat}" @test string(Union{Nothing, AbstractVecOrMat{<:Integer}}) == "Union{Nothing, AbstractVecOrMat{<:Integer}}" @test string(M37012.BStruct{T, T} where T) == "$(curmod_prefix)M37012.B2{T, T} where T" -@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{<:Signed, T} where T<:Unsigned" -@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{<:T, T} where T<:Signed" +@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Unsigned, S<:Signed}" +@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Signed, S<:T}" @test string(Union{M37012.SimpleU, Nothing}) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU}" @test string(Union{M37012.SimpleU, Nothing, T} where T) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU, T} where T" @test string(Union{AbstractVector{T}, T} where T) == "Union{AbstractVector{T}, T} where T" From 762d65963b372e7d70333d9512b4789b1b03bc36 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Sun, 21 Mar 2021 11:39:18 +0100 Subject: [PATCH 008/439] Normalize indices in promote_shape error messages. Seeing implementation like `Base.OneTo` in error messages may be confusing to some users (cf discussion in #39242, [discourse](https://discourse.julialang.org/t/promote-shape-dimension-mismatch/57529/)). This PR turns ```julia julia> ones(2, 3) + ones(3, 2) ERROR: DimensionMismatch("dimensions must match: a has dims (Base.OneTo(2), Base.OneTo(3)), b has dims (Base.OneTo(3), Base.OneTo(2)), mismatch at 1") ``` into ```julia julia> ones(2, 3) + ones(3, 2) ERROR: DimensionMismatch("dimensions must match: a has axes (1:2, 1:3), b has axes (1:3, 1:2), mismatch at 1") ``` Fixes #40118. Acked-by: Tamas K. Papp --- base/indices.jl | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 462e62c6d8883..085491a63e73f 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -106,26 +106,34 @@ IndexStyle(::IndexStyle, ::IndexStyle) = IndexCartesian() promote_shape(::Tuple{}, ::Tuple{}) = () -function promote_shape(a::Tuple{Int,}, b::Tuple{Int,}) - if a[1] != b[1] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) +# Consistent error message for promote_shape mismatch, hiding implementation details like +# OneTo. When b ≡ nothing, it is omitted; i can be supplied for an index. +function throw_promote_shape_mismatch(a, b, i = nothing) + _normalize(d) = map(x -> x isa AbstractUnitRange ? (firstindex(x):lastindex(x)) : x, d) + msg = "dimensions must match: a has dims $(_normalize(a))" + if b ≢ nothing + msg *= ", b has dims $(_normalize(b))" + end + if i ≢ nothing + msg *= ", mismatch at $(i)" end + throw(DimensionMismatch(msg)) +end + +function promote_shape(a::Tuple{Int,}, b::Tuple{Int,}) + a[1] != b[1] && throw_promote_shape_mismatch(a, b) return a end function promote_shape(a::Tuple{Int,Int}, b::Tuple{Int,}) - if a[1] != b[1] || a[2] != 1 - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) - end + (a[1] != b[1] || a[2] != 1) && throw_promote_shape_mismatch(a, b) return a end promote_shape(a::Tuple{Int,}, b::Tuple{Int,Int}) = promote_shape(b, a) function promote_shape(a::Tuple{Int, Int}, b::Tuple{Int, Int}) - if a[1] != b[1] || a[2] != b[2] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) - end + (a[1] != b[1] || a[2] != b[2]) && throw_promote_shape_mismatch(a, b) return a end @@ -153,14 +161,10 @@ function promote_shape(a::Dims, b::Dims) return promote_shape(b, a) end for i=1:length(b) - if a[i] != b[i] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b, mismatch at $i")) - end + a[i] != b[i] && throw_promote_shape_mismatch(a, b, i) end for i=length(b)+1:length(a) - if a[i] != 1 - throw(DimensionMismatch("dimensions must match: a has dims $a, must have singleton at dim $i")) - end + a[i] != 1 && throw_promote_shape_mismatch(a, nothing, i) end return a end @@ -174,14 +178,10 @@ function promote_shape(a::Indices, b::Indices) return promote_shape(b, a) end for i=1:length(b) - if a[i] != b[i] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b, mismatch at $i")) - end + a[i] != b[i] && throw_promote_shape_mismatch(a, b, i) end for i=length(b)+1:length(a) - if a[i] != 1:1 - throw(DimensionMismatch("dimensions must match: a has dims $a, must have singleton at dim $i")) - end + a[i] != 1:1 && throw_promote_shape_mismatch(a, nothing, i) end return a end From 7d117dceb0f791e9ab9a7d5864e32809c3ce16c0 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sun, 21 Mar 2021 08:56:45 -0400 Subject: [PATCH 009/439] document thread safety for RNGs (#40109) --- stdlib/Random/docs/src/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index 4e8ace596543a..ca86de44ecce4 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -13,7 +13,9 @@ type, which is a wrapper over the OS provided entropy. Most functions related to random generation accept an optional `AbstractRNG` object as first argument, which defaults to the global one if not provided. Moreover, some of them accept optionally dimension specifications `dims...` (which can be given as a tuple) to generate arrays of random -values. +values. In a multi-threaded program, you should generally use different RNG objects from different threads +in order to be thread-safe. However, the default global RNG is thread-safe as of Julia 1.3 (because +it internally corresponds to a per-thread RNG). A `MersenneTwister` or `RandomDevice` RNG can generate uniformly random numbers of the following types: [`Float16`](@ref), [`Float32`](@ref), [`Float64`](@ref), [`BigFloat`](@ref), [`Bool`](@ref), From 72c8a9f5242f47efd1fa431276282dc269ce7fcd Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Mon, 22 Mar 2021 15:33:31 +0100 Subject: [PATCH 010/439] customize error message based on types --- base/indices.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 085491a63e73f..50498a53615c0 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -108,11 +108,15 @@ promote_shape(::Tuple{}, ::Tuple{}) = () # Consistent error message for promote_shape mismatch, hiding implementation details like # OneTo. When b ≡ nothing, it is omitted; i can be supplied for an index. -function throw_promote_shape_mismatch(a, b, i = nothing) - _normalize(d) = map(x -> x isa AbstractUnitRange ? (firstindex(x):lastindex(x)) : x, d) - msg = "dimensions must match: a has dims $(_normalize(a))" +function throw_promote_shape_mismatch(a::Tuple{Vararg{T}}, + b::Union{Nothing,Tuple{Vararg{T}}}, + i = nothing) where {T} + _has_axes = T <: AbstractUnitRange + _normalize(d) = map(x -> _has_axes ? (firstindex(x):lastindex(x)) : x, d) + _things = _has_axes ? "axes" : "size" + msg = "dimensions must match: a has $(_things) $(_normalize(a))" if b ≢ nothing - msg *= ", b has dims $(_normalize(b))" + msg *= ", b has $(_things) $(_normalize(b))" end if i ≢ nothing msg *= ", mismatch at $(i)" From 5e5484cd2e96fba9b128ccbad2570863ddff4317 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Mon, 22 Mar 2021 21:39:12 +0100 Subject: [PATCH 011/439] mention use of underscore for private fields in manual (#40131) * Update variables.md * Update style-guide.md * Apply suggestions from code review --- doc/src/manual/style-guide.md | 4 ++++ doc/src/manual/variables.md | 2 ++ 2 files changed, 6 insertions(+) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index c62ad6a8a8848..10f4b8ea54878 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -141,6 +141,10 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. words squashed together ([`isequal`](@ref), [`haskey`](@ref)). When necessary, use underscores as word separators. Underscores are also used to indicate a combination of concepts ([`remotecall_fetch`](@ref) as a more efficient implementation of `fetch(remotecall(...))`) or as modifiers. + * functions mutating at least one of their arguments end in `!`. + * use identifiers starting with `_` to + denote functions, macros or variables that should be considered private and not part of a package's + public API. * conciseness is valued, but avoid abbreviation ([`indexin`](@ref) rather than `indxin`) as it becomes difficult to remember whether and how particular words are abbreviated. diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index c68fbd304d33a..65619dd02430d 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -141,5 +141,7 @@ conventions: * Functions that write to their arguments have names that end in `!`. These are sometimes called "mutating" or "in-place" functions because they are intended to produce changes in their arguments after the function is called, not just return a value. + * Names starting with an underscore denote functions, macros or variables that are only used internally + by a package and are not part of its public API. For more information about stylistic conventions, see the [Style Guide](@ref). From b1e56ab80a302acd2fffbee1276810e753ff5a5a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 22 Mar 2021 22:55:39 +0100 Subject: [PATCH 012/439] remove unclear docs for pure macro (#40092) --- base/expr.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/base/expr.jl b/base/expr.jl index 38a1c4e7089cb..4d6401b002a76 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -230,12 +230,6 @@ end `@pure` gives the compiler a hint for the definition of a pure function, helping for type inference. -A pure function can only depend on immutable information. -This also means a `@pure` function cannot use any global mutable state, including -generic functions. Calls to generic functions depend on method tables which are -mutable global state. -Use with caution, incorrect `@pure` annotation of a function may introduce -hard to identify bugs. Double check for calls to generic functions. This macro is intended for internal compiler use and may be subject to changes. """ macro pure(ex) From 7fbba2a3c3b976ce4da1d6d2d7936d0d5b338a7a Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Tue, 23 Mar 2021 10:12:51 +0900 Subject: [PATCH 013/439] fix a typo on the arithmetic and the logical shift --- doc/src/manual/noteworthy-differences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index e3279819ce204..ad1727ec6d1c0 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -310,7 +310,7 @@ For users coming to Julia from R, these are some noteworthy differences: parenthesis may be required. * Julia's [`^`](@ref) is exponentiation (pow), not bitwise XOR as in C/C++ (use [`⊻`](@ref xor), or [`xor`](@ref), in Julia) - * Julia has two right-shift operators, `>>` and `>>>`. `>>>` performs an arithmetic shift, `>>` + * Julia has two right-shift operators, `>>` and `>>>`. `>>` performs an arithmetic shift, `>>>` always performs a logical shift, unlike C/C++, where the meaning of `>>` depends on the type of the value being shifted. * Julia's `->` creates an anonymous function, it does not access a member via a pointer. From 2b6c7549915a04cc25847e620784be3bb24da1b9 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 22 Mar 2021 21:20:14 -0400 Subject: [PATCH 014/439] Fix #40100, doc for inbounds use each index (#40102) ... deja vu (#39369) --- doc/src/devdocs/boundscheck.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/devdocs/boundscheck.md b/doc/src/devdocs/boundscheck.md index fbd4fa6a6bb59..300d7f8b72993 100644 --- a/doc/src/devdocs/boundscheck.md +++ b/doc/src/devdocs/boundscheck.md @@ -18,7 +18,7 @@ For example, you might write the method `sum` as: ```julia function sum(A::AbstractArray) r = zero(eltype(A)) - for i = 1:length(A) + for i in eachindex(A) @inbounds r += A[i] end return r From a134facc415f1b7d81f2b572e43617627742e0f6 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Tue, 23 Mar 2021 08:50:28 +0100 Subject: [PATCH 015/439] Remove Base.getproperty docstrings in stdlibs (#40135) --- stdlib/LinearAlgebra/src/bunchkaufman.jl | 66 ++++-------------------- stdlib/SuiteSparse/src/spqr.jl | 42 --------------- 2 files changed, 10 insertions(+), 98 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index ead62ab0bc528..63254308799e1 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -167,6 +167,11 @@ julia> d, u, p = S; # destructuring via iteration julia> d == S.D && u == S.U && p == S.p true +julia> S.U*S.D*S.U' - S.P*A*S.P' +2×2 Matrix{Float64}: + 0.0 0.0 + 0.0 0.0 + julia> S = bunchkaufman(Symmetric(A, :L)) BunchKaufman{Float64, Matrix{Float64}} D factor: @@ -181,6 +186,11 @@ permutation: 2-element Vector{Int64}: 2 1 + +julia> S.L*S.D*S.L' - A[S.p, S.p] +2×2 Matrix{Float64}: + 0.0 0.0 + 0.0 0.0 ``` """ bunchkaufman(A::AbstractMatrix{T}, rook::Bool=false; check::Bool = true) where {T} = @@ -226,62 +236,6 @@ function _ipiv2perm_bk(v::AbstractVector{T}, maxi::Integer, uplo::AbstractChar, return p end -""" - getproperty(B::BunchKaufman, d::Symbol) - -Extract the factors of the Bunch-Kaufman factorization `B`. The factorization can take the -two forms `P'*L*D*L'*P` or `P'*U*D*U'*P` (or `L*D*transpose(L)` in the complex symmetric case) -where `P` is a (symmetric) permutation matrix, `L` is a [`UnitLowerTriangular`](@ref) matrix, `U` is a -[`UnitUpperTriangular`](@ref), and `D` is a block diagonal symmetric or Hermitian matrix with -1x1 or 2x2 blocks. The argument `d` can be - -- `:D`: the block diagonal matrix -- `:U`: the upper triangular factor (if factorization is `U*D*U'`) -- `:L`: the lower triangular factor (if factorization is `L*D*L'`) -- `:p`: permutation vector -- `:P`: permutation matrix - -# Examples -```jldoctest -julia> A = [1 2 3; 2 1 2; 3 2 1] -3×3 Matrix{Int64}: - 1 2 3 - 2 1 2 - 3 2 1 - -julia> F = bunchkaufman(Symmetric(A, :L)) -BunchKaufman{Float64, Matrix{Float64}} -D factor: -3×3 Tridiagonal{Float64, Vector{Float64}}: - 1.0 3.0 ⋅ - 3.0 1.0 0.0 - ⋅ 0.0 -1.0 -L factor: -3×3 UnitLowerTriangular{Float64, Matrix{Float64}}: - 1.0 ⋅ ⋅ - 0.0 1.0 ⋅ - 0.5 0.5 1.0 -permutation: -3-element Vector{Int64}: - 1 - 3 - 2 - -julia> F.L*F.D*F.L' - A[F.p, F.p] -3×3 Matrix{Float64}: - 0.0 0.0 0.0 - 0.0 0.0 0.0 - 0.0 0.0 0.0 - -julia> F = bunchkaufman(Symmetric(A)); - -julia> F.U*F.D*F.U' - F.P*A*F.P' -3×3 Matrix{Float64}: - 0.0 0.0 0.0 - 0.0 0.0 0.0 - 0.0 0.0 0.0 -``` -""" function getproperty(B::BunchKaufman{T}, d::Symbol) where {T<:BlasFloat} n = size(B, 1) if d === :p diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl index 79897b6c0de76..e94fa73994d03 100644 --- a/stdlib/SuiteSparse/src/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -288,48 +288,6 @@ function LinearAlgebra.rmul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRSparseQ}) return A end -""" - getproperty(F::QRSparse, d::Symbol) - -Extract factors of a QRSparse factorization. Possible values of `d` are -- `Q` : `QRSparseQ` matrix of the ``Q`` factor in Householder form -- `R` : `UpperTriangular` ``R`` factor -- `prow` : Vector of the row permutations applied to the factorized matrix -- `pcol` : Vector of the column permutations applied to the factorized matrix - -# Examples -```jldoctest -julia> F = qr(sparse([1,3,2,3,4], [1,1,2,3,4], [1.0,2.0,3.0,4.0,5.0])); - -julia> F.Q -4×4 SuiteSparse.SPQR.QRSparseQ{Float64, Int64}: - 1.0 0.0 0.0 0.0 - 0.0 1.0 0.0 0.0 - 0.0 0.0 1.0 0.0 - 0.0 0.0 0.0 1.0 - -julia> F.R -4×4 SparseMatrixCSC{Float64, Int64} with 5 stored entries: - 3.0 ⋅ ⋅ ⋅ - ⋅ 4.0 ⋅ 2.0 - ⋅ ⋅ 5.0 ⋅ - ⋅ ⋅ ⋅ 1.0 - -julia> F.prow -4-element Vector{Int64}: - 2 - 3 - 4 - 1 - -julia> F.pcol -4-element Vector{Int64}: - 2 - 3 - 4 - 1 -``` -""" @inline function Base.getproperty(F::QRSparse, d::Symbol) if d === :Q return QRSparseQ(F.factors, F.τ, size(F, 2)) From 3071f34b16059ea7279c2af5694f902155d0806e Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Tue, 23 Mar 2021 08:53:54 +0100 Subject: [PATCH 016/439] Preserve `Symmetric`/`Hermitian` shape in more cases (#40126) --- stdlib/LinearAlgebra/src/symmetric.jl | 4 ++++ stdlib/LinearAlgebra/test/symmetric.jl | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 8f1073817b71d..e206cfe7178d3 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -482,6 +482,10 @@ for f in (:+, :-) @eval begin $f(A::Hermitian, B::Symmetric{<:Real}) = $f(A, Hermitian(parent(B), sym_uplo(B.uplo))) $f(A::Symmetric{<:Real}, B::Hermitian) = $f(Hermitian(parent(A), sym_uplo(A.uplo)), B) + $f(A::SymTridiagonal, B::Symmetric) = Symmetric($f(A, B.data), sym_uplo(B.uplo)) + $f(A::Symmetric, B::SymTridiagonal) = Symmetric($f(A.data, B), sym_uplo(A.uplo)) + $f(A::SymTridiagonal{<:Real}, B::Hermitian) = Hermitian($f(A, B.data), sym_uplo(B.uplo)) + $f(A::Hermitian, B::SymTridiagonal{<:Real}) = Hermitian($f(A.data, B), sym_uplo(A.uplo)) end end diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index 7d99dd32889fd..d23eecb5be46e 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -727,4 +727,29 @@ end end end +@testset "Addition/subtraction with SymTridiagonal" begin + TR = SymTridiagonal(randn(Float64,5), randn(Float64,4)) + TC = SymTridiagonal(randn(ComplexF64,5), randn(ComplexF64,4)) + SR = Symmetric(randn(Float64,5,5)) + SC = Symmetric(randn(ComplexF64,5,5)) + HR = Hermitian(randn(Float64,5,5)) + HC = Hermitian(randn(ComplexF64,5,5)) + for op = (+,-) + for T = (TR, TC), S = (SR, SC) + @test op(T, S) == op(Array(T), S) + @test op(S, T) == op(S, Array(T)) + @test op(T, S) isa Symmetric + @test op(S, T) isa Symmetric + end + for H = (HR, HC) + for T = (TR, TC) + @test op(T, H) == op(Array(T), H) + @test op(H, T) == op(H, Array(T)) + end + @test op(TR, H) isa Hermitian + @test op(H, TR) isa Hermitian + end + end +end + end # module TestSymmetric From e3dffb9da5e2af961ccebf3d82de138bbda46d4d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 23 Mar 2021 11:43:32 -0400 Subject: [PATCH 017/439] fix #40050, handling fields that are pointers due to subtype circularity (#40095) --- src/cgutils.cpp | 5 ++++- test/core.jl | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 04522edd9c31c..bb0e15ed7363c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -608,7 +608,10 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ size_t fsz = 0, al = 0; bool isptr = !jl_islayout_inline(ty, &fsz, &al); if (jst->layout) { - assert(isptr == jl_field_isptr(jst, i)); + // NOTE: jl_field_isptr can disagree with jl_islayout_inline here if the + // struct decided this field must be a pointer due to a type circularity. + // Example from issue #40050: `struct B <: Ref{Tuple{B}}; end` + isptr = jl_field_isptr(jst, i); assert((isptr ? sizeof(void*) : fsz + jl_is_uniontype(ty)) == jl_field_size(jst, i)); } Type *lty; diff --git a/test/core.jl b/test/core.jl index c360dc6ba5b13..1053b8dffcf80 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7227,6 +7227,11 @@ end @test_broken isbitstype(Tuple{B33954}) @test_broken isbitstype(B33954) +struct B40050 <: Ref{Tuple{B40050}} +end +@test string((B40050(),)) == "($B40050(),)" +@test_broken isbitstype(Tuple{B40050}) + # Issue #34206/34207 function mre34206(a, n) va = view(a, :) From cc639ec7eadf3c8db1c6ae01ad0edbfdece1bc32 Mon Sep 17 00:00:00 2001 From: Jeffrey Lin Date: Tue, 23 Mar 2021 17:05:13 +0000 Subject: [PATCH 018/439] Markdown: prevent display() error with empty list item (#40122) --- stdlib/Markdown/src/render/terminal/formatting.jl | 1 + stdlib/Markdown/test/runtests.jl | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/stdlib/Markdown/src/render/terminal/formatting.jl b/stdlib/Markdown/src/render/terminal/formatting.jl index 4fd1cccedf7fb..bacd82f7ed021 100644 --- a/stdlib/Markdown/src/render/terminal/formatting.jl +++ b/stdlib/Markdown/src/render/terminal/formatting.jl @@ -42,6 +42,7 @@ wrapped_lines(io::IO, f::Function, args...; width = 80, i = 0) = function print_wrapped(io::IO, s...; width = 80, pre = "", i = 0) lines = wrapped_lines(io, s..., width = width, i = i) + isempty(lines) && return 0, 0 print(io, lines[1]) for line in lines[2:end] print(io, '\n', pre, line) diff --git a/stdlib/Markdown/test/runtests.jl b/stdlib/Markdown/test/runtests.jl index 286004707b8bd..f9983d10089f9 100644 --- a/stdlib/Markdown/test/runtests.jl +++ b/stdlib/Markdown/test/runtests.jl @@ -1213,3 +1213,12 @@ end | $x | """) end + +@testset "issue 40080: empty list item breaks display()" begin + d = TextDisplay(devnull) + display(d, md""" + 1. hello + 2. + """) +end + From 10ab32f57cfc7b1a5139582bb0ea867dd73a5df9 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Wed, 24 Mar 2021 19:42:47 +0100 Subject: [PATCH 019/439] Support shared named environments during startup (#40025) * Support shared named envs during startup * Improved handling of named envs during startup Co-authored-by: Jameson Nash * Improve tests for --project and JULIA_PROJECT * Add news item about shared env support at startup Co-authored-by: Jameson Nash --- NEWS.md | 2 ++ base/initdefs.jl | 2 +- test/cmdlineargs.jl | 13 ++++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index e0885b713f7ae..0cf30ffdd0e2e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,8 @@ Compiler/Runtime improvements Command-line option changes --------------------------- +* The Julia `--project` option and the `JULIA_PROJECT` environment variable now support selecting shared environments like `.julia/environments/myenv` the same way the package management console does: use `julia --project=@myenv` resp. `export JULIA_PROJECT="@myenv"` ([#40025]). + Multi-threading changes ----------------------- diff --git a/base/initdefs.jl b/base/initdefs.jl index 6e4a4a593b446..a61373c394eec 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -235,7 +235,7 @@ function init_active_project() ACTIVE_PROJECT[] = project === nothing ? nothing : project == "" ? nothing : - project == "@." ? current_project() : abspath(expanduser(project)) + startswith(project, "@") ? load_path_expand(project) : abspath(expanduser(project)) end ## load path expansion: turn LOAD_PATH entries into concrete paths ## diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index fdc4ecd528389..92d6ac9b1ee22 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -110,9 +110,16 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` # ~ expansion in --project and JULIA_PROJECT if !Sys.iswindows() - expanded = abspath(expanduser("~/foo")) - @test occursin(expanded, readchomp(`$exename --project='~/foo' -E 'Base.active_project()'`)) - @test occursin(expanded, readchomp(setenv(`$exename -E 'Base.active_project()'`, "JULIA_PROJECT" => "~/foo", "HOME" => homedir()))) + let expanded = abspath(expanduser("~/foo/Project.toml")) + @test expanded == readchomp(`$exename --project='~/foo' -e 'println(Base.active_project())'`) + @test expanded == readchomp(setenv(`$exename -e 'println(Base.active_project())'`, "JULIA_PROJECT" => "~/foo", "HOME" => homedir())) + end + end + + # handling of @projectname in --project and JULIA_PROJECT + let expanded = abspath(Base.load_path_expand("@foo")) + @test expanded == readchomp(`$exename --project='@foo' -e 'println(Base.active_project())'`) + @test expanded == readchomp(setenv(`$exename -e 'println(Base.active_project())'`, "JULIA_PROJECT" => "@foo", "HOME" => homedir())) end # --quiet, --banner From 61bec3faaacf119b828d389c404bf81878888dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 24 Mar 2021 20:17:05 +0100 Subject: [PATCH 020/439] add < to NamedTuple (#40147) --- base/namedtuple.jl | 2 +- base/operators.jl | 4 +++- test/namedtuple.jl | 11 ++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 07c4735f08b28..ff554cae39336 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -194,8 +194,8 @@ _nt_names(::Type{T}) where {names,T<:NamedTuple{names}} = names hash(x::NamedTuple, h::UInt) = xor(objectid(_nt_names(x)), hash(Tuple(x), h)) +(<)(a::NamedTuple{n}, b::NamedTuple{n}) where {n} = Tuple(a) < Tuple(b) isless(a::NamedTuple{n}, b::NamedTuple{n}) where {n} = isless(Tuple(a), Tuple(b)) -# TODO: case where one argument's names are a prefix of the other's same_names(::NamedTuple{names}...) where {names} = true same_names(::NamedTuple...) = false diff --git a/base/operators.jl b/base/operators.jl index 010f5793fba06..8b91657fda201 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -79,6 +79,9 @@ handle comparison to other types via promotion rules where possible. [`isequal`](@ref) falls back to `==`, so new methods of `==` will be used by the [`Dict`](@ref) type to compare keys. If your type will be used as a dictionary key, it should therefore also implement [`hash`](@ref). + +If some type defines `==`, [`isequal`](@ref), and [`isless`](@ref) then it should +also implement [`<`](@ref) to ensure consistency of comparisons. """ == @@ -319,7 +322,6 @@ a partial order. New numeric types with a canonical partial order should implement this function for two arguments of the new type. Types with a canonical total order should implement [`isless`](@ref) instead. -(x < y) | (x == y) # Examples ```jldoctest diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 128cff5f53731..82bbc26349a7a 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -90,11 +90,20 @@ end @test Tuple((a=1, b=2, c=3)) == (1, 2, 3) @test isless((a=1,b=2), (a=1,b=3)) -@test_broken isless((a=1,), (a=1,b=2)) +@test_throws MethodError isless((a=1,), (a=1,b=2)) @test !isless((a=1,b=2), (a=1,b=2)) @test !isless((a=2,b=1), (a=1,b=2)) @test_throws MethodError isless((a=1,), (x=2,)) +@test (a=1,b=2) < (a=1,b=3) +@test_throws MethodError (a=1,) < (a=1,b=2) +@test !((a=1,b=2) < (a=1,b=2)) +@test !((a=2,b=1) < (a=1,b=2)) +@test_throws MethodError (a=1,) < (x=2,) +@test !((a=-0.0,) < (a=0.0,)) +@test ismissing((a=missing,) < (a=1,)) +@test ismissing((a=missing,) < (a=missing,)) + @test map(-, (x=1, y=2)) == (x=-1, y=-2) @test map(+, (x=1, y=2), (x=10, y=20)) == (x=11, y=22) @test_throws ArgumentError map(+, (x=1, y=2), (y=10, x=20)) From d93fa40cefee6fc6e4bd87d261b4b83ed2a27178 Mon Sep 17 00:00:00 2001 From: adomasbaliuka <52975890+adomasbaliuka@users.noreply.github.com> Date: Wed, 24 Mar 2021 20:19:21 +0100 Subject: [PATCH 021/439] Fix manual claim that `run` returns `nothing` (#40155) --- doc/src/manual/running-external-programs.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index a00050ffb5149..0f1b7d255835d 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -40,9 +40,8 @@ julia> run(mycommand); hello ``` -The `hello` is the output of the `echo` command, sent to [`stdout`](@ref). The run method itself -returns `nothing`, and throws an [`ErrorException`](@ref) if the external command fails to run -successfully. +The `hello` is the output of the `echo` command, sent to [`stdout`](@ref). If the external command fails to run +successfully, the run method throws an [`ErrorException`](@ref). If you want to read the output of the external command, [`read`](@ref) or [`readchomp`](@ref) can be used instead: From f023677ce8b22a266b520b5b660114ccfce655e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bia=C5=82as?= Date: Thu, 25 Mar 2021 06:52:34 +0100 Subject: [PATCH 022/439] Fix #38491: fix an abspath() edge case on Windows (#38981) * Fix #38491: fix an abspath() edge case on Windows * Update base/path.jl Co-authored-by: Jameson Nash * Update base/path.jl * Update test/path.jl Co-authored-by: Jameson Nash Co-authored-by: Mustafa M Co-authored-by: Jameson Nash --- base/path.jl | 14 +++++++++++++- test/path.jl | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/base/path.jl b/base/path.jl index 1a7c2dc55018d..449085c00f26d 100644 --- a/base/path.jl +++ b/base/path.jl @@ -390,7 +390,19 @@ normpath(a::AbstractString, b::AbstractString...) = normpath(joinpath(a,b...)) Convert a path to an absolute path by adding the current directory if necessary. Also normalizes the path as in [`normpath`](@ref). """ -abspath(a::String) = normpath(isabspath(a) ? a : joinpath(pwd(),a)) +function abspath(a::String)::String + if !isabspath(a) + cwd = pwd() + a_drive, a_nodrive = splitdrive(a) + if a_drive != "" && lowercase(splitdrive(cwd)[1]) != lowercase(a_drive) + cwd = a_drive * path_separator + a = joinpath(cwd, a_nodrive) + else + a = joinpath(cwd, a) + end + end + return normpath(a) +end """ abspath(path::AbstractString, paths::AbstractString...) -> String diff --git a/test/path.jl b/test/path.jl index bbd9159c59295..ca772e24d41de 100644 --- a/test/path.jl +++ b/test/path.jl @@ -9,6 +9,23 @@ @test isabspath(S(homedir())) @test !isabspath(S("foo")) end + if Sys.iswindows() + @testset "issue #38491" begin + pwd_drive = uppercase(splitdrive(pwd())[1]) + drive = (pwd_drive == "X:") ? "Y:" : "X:" + @test abspath("$(lowercase(drive))a\\b\\c") == "$(lowercase(drive))\\a\\b\\c" + @test abspath("$(uppercase(drive))a\\b\\c") == "$(uppercase(drive))\\a\\b\\c" + @test abspath("$(lowercase(drive))a") == "$(lowercase(drive))\\a" + @test abspath("$(uppercase(drive))a") == "$(uppercase(drive))\\a" + @test abspath(lowercase(drive)) == "$(lowercase(drive))\\" + @test abspath(uppercase(drive)) == "$(uppercase(drive))\\" + + @test lowercase(abspath("$(pwd_drive)a\\b\\c")) == lowercase(joinpath(pwd(), "a\\b\\c")) + @test lowercase(abspath("$(pwd_drive)a")) == lowercase(joinpath(pwd(), "a")) + @test lowercase(abspath(lowercase(pwd_drive))) == lowercase("$(pwd())\\") + @test lowercase(abspath(uppercase(pwd_drive))) == lowercase("$(pwd())\\") + end + end @test basename(S("foo$(sep)bar")) == "bar" @test dirname(S("foo$(sep)bar")) == "foo" From e2f5f26aec6e0a3e239d3382aa7007c3caf85f5e Mon Sep 17 00:00:00 2001 From: jaakkor2 Date: Thu, 25 Mar 2021 07:52:59 +0200 Subject: [PATCH 023/439] Have different Windows uninstall keys for different Julia versions (#40163) * Have different Windows uninstall keys for different Julia versions Should fix #40004. Have the uninstall key to be "{#AppNameLong}_is1" where AppNameLong contains the Julia version to prevent Windows from overwriting the uninstall information for different Julia versions. Inno Setup documentation about the AppId https://jrsoftware.org/ishelp/topic_setup_appid.htm copied here for convenience ``` [Setup]: AppId Default value: AppName Description: The value of AppId is stored inside uninstall log files (unins???.dat), and is checked by subsequent installations to determine whether it may append to a particular existing uninstall log. Setup will only append to an uninstall log if the AppId of the existing uninstall log is the same as the current installation's AppId. For a practical example, say you have two installations -- one entitled My Program and the other entitled My Program 1.1 Update. To get My Program 1.1 Update to append to My Program's uninstall log, you would have to set AppId to the same value in both installations. AppId also determines the actual name of the Uninstall registry key, to which Inno Setup tacks on "_is1" at the end. (Therefore, if AppId is "MyProgram", the key will be named "MyProgram_is1".) Pre-1.3 versions of Inno Setup based the key name on the value of AppVerName. AppId is a not used for display anywhere, so feel free to make it as cryptic as you desire. The value may include constants. If you use a {code:..} constant to allow your user to customize AppId, you do not need to return the real value until just before the installation starts: if necessary you may return an empty or generic value at earlier times. If not empty, this value will only be used to attempt to restore previous install settings (like the settings stored by [Setup] section directive UsePreviousAppDir). If empty, it isn't used for anything. The length of AppId with all constants evaluated should never exceed 127 characters. Example: AppId=MyProgram ``` * Use DirName as AppId Co-authored-by: Mustafa M * remove unneeded code Co-authored-by: Mustafa M --- contrib/windows/build-installer.iss | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/contrib/windows/build-installer.iss b/contrib/windows/build-installer.iss index 576f834bc3c91..6648d9e1f528a 100644 --- a/contrib/windows/build-installer.iss +++ b/contrib/windows/build-installer.iss @@ -2,10 +2,6 @@ #define AppName "Julia" #endif -#ifndef AppId -#define AppId "{{054B4BC6-BD30-45C8-A623-8F5BA6EBD55D}" -#endif - #ifndef DirName #define DirName AppName + "-" + AppVersion #endif @@ -14,6 +10,9 @@ #define AppMainExeName "bin\julia.exe" #define CurrentYear GetDateTimeString('yyyy', '', '') +#ifndef AppId +#define AppId DirName +#endif [LangOptions] @@ -61,7 +60,7 @@ AppName={#AppName} AppVersion={#AppVersion} AppPublisher=Julia Language AppPublisherURL=https://julialang.org -AppCopyright=Copyright 2009-{#CurrentYear}; Julia Langage +AppCopyright=Copyright 2009-{#CurrentYear}; Julia Language VersionInfoDescription=Julia Installer PrivilegesRequiredOverridesAllowed=commandline WizardStyle=modern From c6d5c406974268c6f402ce036da4c0d70b849fd0 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 25 Mar 2021 12:35:02 +0100 Subject: [PATCH 024/439] README: git checkout 1.6.0 in the instructions. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca913ec539b48..f158ab22f7973 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Julia. However, most users should use the most recent stable version of Julia. You can get this version by changing to the Julia directory and running: - git checkout v1.5.3 + git checkout v1.6.0 Now run `make` to build the `julia` executable. From 65e134859cf27e2268782fe4b2113d0b395e3b69 Mon Sep 17 00:00:00 2001 From: Lea Kapelevich Date: Thu, 25 Mar 2021 10:38:03 -0400 Subject: [PATCH 025/439] [LinearAlgebra] Correct `liblapack` binding (#40170) * [LinearAlgebra] Correct binding * fix English * bring liblapack back into BLAS module --- stdlib/LinearAlgebra/src/lapack.jl | 5 +++++ stdlib/LinearAlgebra/test/blas.jl | 4 ++++ stdlib/LinearAlgebra/test/lapack.jl | 3 +++ 3 files changed, 12 insertions(+) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 3d02f3b058884..e0d86c67de31e 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -7,6 +7,11 @@ Interfaces to LAPACK subroutines. const libblastrampoline = "libblastrampoline" +# Legacy binding maintained for backwards-compatibility but new packages +# should not look at this, instead preferring to parse the output +# of BLAS.get_config() +const liblapack = libblastrampoline + import ..LinearAlgebra.BLAS.@blasfunc import ..LinearAlgebra: BlasFloat, BlasInt, LAPACKException, diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 6c2b27f9a53a5..be325617acb53 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -600,4 +600,8 @@ end @test BLAS.get_num_threads() === default end +# https://github.com/JuliaLang/julia/pull/39845 +@test LinearAlgebra.BLAS.libblas == "libblastrampoline" +@test LinearAlgebra.BLAS.liblapack == "libblastrampoline" + end # module TestBLAS diff --git a/stdlib/LinearAlgebra/test/lapack.jl b/stdlib/LinearAlgebra/test/lapack.jl index e335fdc30ee31..ccf8cf980f1c1 100644 --- a/stdlib/LinearAlgebra/test/lapack.jl +++ b/stdlib/LinearAlgebra/test/lapack.jl @@ -702,4 +702,7 @@ let A = [NaN NaN; NaN NaN] @test_throws ArgumentError eigen(A) end +# # https://github.com/JuliaLang/julia/pull/39845 +@test LinearAlgebra.LAPACK.liblapack == "libblastrampoline" + end # module TestLAPACK From 9ba867eca9815a7aff3657fffc3d83eb37ab65e8 Mon Sep 17 00:00:00 2001 From: Rik Huijzer Date: Thu, 25 Mar 2021 16:10:30 +0100 Subject: [PATCH 026/439] Update index.md --- stdlib/Dates/docs/src/index.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index c34be7b9ebef4..c6768bb1e41c9 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -128,9 +128,15 @@ julia> dt2 = Date("2015-01-02",df) You can also use the `dateformat""` string macro. This macro creates the `DateFormat` object once when the macro is expanded and uses the same `DateFormat` object even if a code snippet is run multiple times. ```jldoctest -julia> for i = 1:10^5 - Date("2015-01-01", dateformat"y-m-d") - end +julia> years = string.(2000:10000); + +julia> dates = Date.(years, dateformat"yyyy"); + +julia> dates[1:3] +3-element Vector{Date}: + 2000-01-01 + 2001-01-01 + 2002-01-01 ``` As well as via the constructors, a `Date` or `DateTime` can be constructed from From cad20ead3245ec7314172618a28ee5dc8d2df5e7 Mon Sep 17 00:00:00 2001 From: Rik Huijzer Date: Thu, 25 Mar 2021 18:41:18 +0100 Subject: [PATCH 027/439] Update index.md --- stdlib/Dates/docs/src/index.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index c6768bb1e41c9..c423b85ef4aba 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -125,18 +125,23 @@ julia> dt2 = Date("2015-01-02",df) 2015-01-02 ``` -You can also use the `dateformat""` string macro. This macro creates the `DateFormat` object once when the macro is expanded and uses the same `DateFormat` object even if a code snippet is run multiple times. +Alternatively, use broadcasting: ```jldoctest -julia> years = string.(2000:10000); +julia> years = ["2015", "2016"]; + +julia> Date.(years, DateFormat("yyyy")) +2-element Vector{Date}: + 2015-01-01 + 2016-01-01 +``` -julia> dates = Date.(years, dateformat"yyyy"); +You can also use the `dateformat""` string macro. This macro creates the `DateFormat` object once when the macro is expanded and uses the same `DateFormat` object even if a code snippet is run multiple times. -julia> dates[1:3] -3-element Vector{Date}: - 2000-01-01 - 2001-01-01 - 2002-01-01 +```jldoctest +julia> for i = 1:10^5 + Date("2015-01-01", dateformat"y-m-d") + end ``` As well as via the constructors, a `Date` or `DateTime` can be constructed from From 1897e08ff54eb8c91b806e20bbfecbe7b2d4f9f7 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 25 Mar 2021 12:51:27 -0700 Subject: [PATCH 028/439] Fix armv7l trampoline (#40176) We copy-pasted the wrong macro here, should have used `CNAMEADDR()` not `CNAME()`. This causes segfaults on armv7l processors by trying to read from an incorrect address when loading the trampoline target address value. --- cli/trampolines/trampolines_arm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/trampolines/trampolines_arm.S b/cli/trampolines/trampolines_arm.S index 1bb924168525b..f99b7820360b2 100644 --- a/cli/trampolines/trampolines_arm.S +++ b/cli/trampolines/trampolines_arm.S @@ -5,7 +5,7 @@ .global CNAME(name); \ .cfi_startproc; \ CNAME(name)##:; \ - ldr ip, CONCAT(.L,CNAME(name)); \ + ldr ip, CONCAT(.L,CNAMEADDR(name)); \ CONCAT(.L,CNAME(name)): ;\ add ip, pc, ip; \ ldr pc, [ip]; \ From 4f5044a86b92b008708096918c6309e4503e8437 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 25 Mar 2021 19:18:08 -0700 Subject: [PATCH 029/439] Allow startup despite p7zip not being found (#40049) Without this, a failure to find a usable `p7zip` will cause an error at startup. With this, we will at least attempt to invoke `p7zip` and fail at runtime, instead of failing at init time. --- stdlib/p7zip_jll/src/p7zip_jll.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/p7zip_jll/src/p7zip_jll.jl b/stdlib/p7zip_jll/src/p7zip_jll.jl index e1c94eb8d84be..99b346017ad97 100644 --- a/stdlib/p7zip_jll/src/p7zip_jll.jl +++ b/stdlib/p7zip_jll/src/p7zip_jll.jl @@ -77,7 +77,7 @@ function init_p7zip_path() return end end - global p7zip_path = Sys.which(p7zip_exe) + global p7zip_path = something(Sys.which(p7zip_exe), p7zip_exe) end function __init__() From d92b0d8aeaff8940aaf52ea5fba354de314b6d58 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Fri, 26 Mar 2021 18:07:38 +0900 Subject: [PATCH 030/439] Fix typo in messages.jl (#40205) bounday -> boundary --- stdlib/Distributed/src/messages.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Distributed/src/messages.jl b/stdlib/Distributed/src/messages.jl index 1424855ec1995..bfff8a4d5d1a7 100644 --- a/stdlib/Distributed/src/messages.jl +++ b/stdlib/Distributed/src/messages.jl @@ -8,7 +8,7 @@ abstract type AbstractMsg end # Each message has three parts, which are written in order to the worker's stream. # 1) A header of type MsgHeader is serialized to the stream (via `serialize`). # 2) A message of type AbstractMsg is then serialized. -# 3) Finally, a fixed bounday of 10 bytes is written. +# 3) Finally, a fixed boundary of 10 bytes is written. # Message header stored separately from body to be able to send back errors if # a deserialization error occurs when reading the message body. From beeb6d776678000c32cd3992d0bc4a65fe1aa5e3 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Fri, 26 Mar 2021 09:25:45 +0000 Subject: [PATCH 031/439] Remove eltype assumption from ldiv!(LowerTriangular(SparseMatrixCSC{Tv,Ti), ...) (#40174) --- stdlib/SparseArrays/src/linalg.jl | 4 ++-- stdlib/SparseArrays/test/sparsevector.jl | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index c6852382b5406..0ac2806b77a04 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -646,7 +646,7 @@ function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) for k = 1:ncolB for j = 1:nrowB i1 = ia[j] - i2 = ia[j + 1] - 1 + i2 = ia[j + 1] - one(eltype(ia)) # find diagonal element ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) @@ -688,7 +688,7 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) for k = 1:ncolB for j = nrowB:-1:1 i1 = ia[j] - i2 = ia[j + 1] - 1 + i2 = ia[j + 1] - one(eltype(ia)) # find diagonal element ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 602818678908b..79c952620050c 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -1050,6 +1050,10 @@ end @test y == Af'x2f end end + @testset "ldiv with different element types (#40171)" begin + sA = sparse(Int16.(1:4), Int16.(1:4), ones(4)) + @test all(ldiv!(LowerTriangular(sA), ones(4)) .≈ 1.) + end @testset "ldiv ops with triangular matrices and sparse vecs (#14005)" begin m = 10 sparsefloatvecs = SparseVector[sprand(m, 0.4) for k in 1:3] From 91c297b6c983aed2828600bcd9b8ba6494f747b6 Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" <37125+schneiderfelipe@users.noreply.github.com> Date: Fri, 26 Mar 2021 06:29:26 -0300 Subject: [PATCH 032/439] Support for using matrices of different types in generalized eigendecomposition (#39301) --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 1 + stdlib/LinearAlgebra/src/symmetric.jl | 168 ------------- stdlib/LinearAlgebra/src/symmetriceigen.jl | 271 +++++++++++++++++++++ stdlib/LinearAlgebra/test/eigen.jl | 27 +- 4 files changed, 298 insertions(+), 169 deletions(-) create mode 100644 stdlib/LinearAlgebra/src/symmetriceigen.jl diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 8f3e5c10663db..855e49265af2d 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -374,6 +374,7 @@ include("cholesky.jl") include("lu.jl") include("bunchkaufman.jl") include("diagonal.jl") +include("symmetriceigen.jl") include("bidiag.jl") include("uniformscaling.jl") include("hessenberg.jl") diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index e206cfe7178d3..ab031b4d30c43 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -676,174 +676,6 @@ end inv(A::Hermitian{<:Any,<:StridedMatrix}) = Hermitian(_inv(A), sym_uplo(A.uplo)) inv(A::Symmetric{<:Any,<:StridedMatrix}) = Symmetric(_inv(A), sym_uplo(A.uplo)) -eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) = Eigen(sorteig!(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)..., sortby)...) - -function eigen(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), sortby=sortby) -end - -eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = Eigen(LAPACK.syevr!('V', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)...) - -""" - eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen - -Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F` -which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the -matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) - -Iterating the decomposition produces the components `F.values` and `F.vectors`. - -The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref). - -The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to search for. - -!!! note - If `irange` is not `1:n`, where `n` is the dimension of `A`, then the returned factorization - will be a *truncated* factorization. -""" -function eigen(A::RealHermSymComplexHerm, irange::UnitRange) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) -end - -eigen!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = - Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...) - -""" - eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen - -Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F` -which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the -matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) - -Iterating the decomposition produces the components `F.values` and `F.vectors`. - -The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref). - -`vl` is the lower bound of the window of eigenvalues to search for, and `vu` is the upper bound. - -!!! note - If [`vl`, `vu`] does not contain all eigenvalues of `A`, then the returned factorization - will be a *truncated* factorization. -""" -function eigen(A::RealHermSymComplexHerm, vl::Real, vh::Real) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) -end - -eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = - LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1] - -function eigvals(A::RealHermSymComplexHerm) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A)) -end - -""" - eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values - -Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. -`irange` is a range of eigenvalue *indices* to search for - for instance, the 2nd to 8th eigenvalues. -""" -eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = - LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1] - -""" - eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values - -Returns the eigenvalues of `A`. It is possible to calculate only a subset of the -eigenvalues by specifying a [`UnitRange`](@ref) `irange` covering indices of the sorted eigenvalues, -e.g. the 2nd to 8th eigenvalues. - -# Examples -```jldoctest -julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) -3×3 SymTridiagonal{Float64, Vector{Float64}}: - 1.0 2.0 ⋅ - 2.0 2.0 3.0 - ⋅ 3.0 1.0 - -julia> eigvals(A, 2:2) -1-element Vector{Float64}: - 0.9999999999999996 - -julia> eigvals(A) -3-element Vector{Float64}: - -2.1400549446402604 - 1.0000000000000002 - 5.140054944640259 -``` -""" -function eigvals(A::RealHermSymComplexHerm, irange::UnitRange) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) -end - -""" - eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values - -Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. -`vl` is the lower bound of the interval to search for eigenvalues, and `vu` is the upper bound. -""" -eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = - LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1] - -""" - eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values - -Returns the eigenvalues of `A`. It is possible to calculate only a subset of the eigenvalues -by specifying a pair `vl` and `vu` for the lower and upper boundaries of the eigenvalues. - -# Examples -```jldoctest -julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) -3×3 SymTridiagonal{Float64, Vector{Float64}}: - 1.0 2.0 ⋅ - 2.0 2.0 3.0 - ⋅ 3.0 1.0 - -julia> eigvals(A, -1, 2) -1-element Vector{Float64}: - 1.0000000000000009 - -julia> eigvals(A) -3-element Vector{Float64}: - -2.1400549446402604 - 1.0000000000000002 - 5.140054944640259 -``` -""" -function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) -end - -eigmax(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, size(A, 1):size(A, 1))[1] -eigmin(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, 1:1)[1] - -function eigen!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix} - vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data')) - GeneralizedEigen(sorteig!(vals, vecs, sortby)...) -end -function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasComplex,S<:StridedMatrix} - vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data')) - GeneralizedEigen(sorteig!(vals, vecs, sortby)...) -end - -eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix} = - LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1] -eigvals!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix} = - LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1] - -eigvecs(A::HermOrSym) = eigvecs(eigen(A)) - function svd(A::RealHermSymComplexHerm, full::Bool=false) vals, vecs = eigen(A) I = sortperm(vals; by=abs, rev=true) diff --git a/stdlib/LinearAlgebra/src/symmetriceigen.jl b/stdlib/LinearAlgebra/src/symmetriceigen.jl new file mode 100644 index 0000000000000..0f18d290b4d62 --- /dev/null +++ b/stdlib/LinearAlgebra/src/symmetriceigen.jl @@ -0,0 +1,271 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +# Eigensolvers for symmetric and Hermitian matrices +eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) = Eigen(sorteig!(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)..., sortby)...) + +function eigen(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing) + T = eltype(A) + S = eigtype(T) + eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), sortby=sortby) +end + +eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = Eigen(LAPACK.syevr!('V', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)...) + +""" + eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen + +Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F` +which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the +matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) + +Iterating the decomposition produces the components `F.values` and `F.vectors`. + +The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref). + +The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to search for. + +!!! note + If `irange` is not `1:n`, where `n` is the dimension of `A`, then the returned factorization + will be a *truncated* factorization. +""" +function eigen(A::RealHermSymComplexHerm, irange::UnitRange) + T = eltype(A) + S = eigtype(T) + eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) +end + +eigen!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = + Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...) + +""" + eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen + +Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F` +which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the +matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) + +Iterating the decomposition produces the components `F.values` and `F.vectors`. + +The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref). + +`vl` is the lower bound of the window of eigenvalues to search for, and `vu` is the upper bound. + +!!! note + If [`vl`, `vu`] does not contain all eigenvalues of `A`, then the returned factorization + will be a *truncated* factorization. +""" +function eigen(A::RealHermSymComplexHerm, vl::Real, vh::Real) + T = eltype(A) + S = eigtype(T) + eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) +end + +eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = + LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1] + +function eigvals(A::RealHermSymComplexHerm) + T = eltype(A) + S = eigtype(T) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A)) +end + +""" + eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values + +Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. +`irange` is a range of eigenvalue *indices* to search for - for instance, the 2nd to 8th eigenvalues. +""" +eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = + LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1] + +""" + eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values + +Returns the eigenvalues of `A`. It is possible to calculate only a subset of the +eigenvalues by specifying a [`UnitRange`](@ref) `irange` covering indices of the sorted eigenvalues, +e.g. the 2nd to 8th eigenvalues. + +# Examples +```jldoctest +julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) +3×3 SymTridiagonal{Float64, Vector{Float64}}: + 1.0 2.0 ⋅ + 2.0 2.0 3.0 + ⋅ 3.0 1.0 + +julia> eigvals(A, 2:2) +1-element Vector{Float64}: + 0.9999999999999996 + +julia> eigvals(A) +3-element Vector{Float64}: + -2.1400549446402604 + 1.0000000000000002 + 5.140054944640259 +``` +""" +function eigvals(A::RealHermSymComplexHerm, irange::UnitRange) + T = eltype(A) + S = eigtype(T) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) +end + +""" + eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values + +Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. +`vl` is the lower bound of the interval to search for eigenvalues, and `vu` is the upper bound. +""" +eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = + LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1] + +""" + eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values + +Returns the eigenvalues of `A`. It is possible to calculate only a subset of the eigenvalues +by specifying a pair `vl` and `vu` for the lower and upper boundaries of the eigenvalues. + +# Examples +```jldoctest +julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) +3×3 SymTridiagonal{Float64, Vector{Float64}}: + 1.0 2.0 ⋅ + 2.0 2.0 3.0 + ⋅ 3.0 1.0 + +julia> eigvals(A, -1, 2) +1-element Vector{Float64}: + 1.0000000000000009 + +julia> eigvals(A) +3-element Vector{Float64}: + -2.1400549446402604 + 1.0000000000000002 + 5.140054944640259 +``` +""" +function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real) + T = eltype(A) + S = eigtype(T) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) +end + +eigmax(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, size(A, 1):size(A, 1))[1] +eigmin(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, 1:1)[1] + +function eigen!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix} + vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data')) + GeneralizedEigen(sorteig!(vals, vecs, sortby)...) +end +function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasComplex,S<:StridedMatrix} + vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data')) + GeneralizedEigen(sorteig!(vals, vecs, sortby)...) +end + +function eigen!(A::RealHermSymComplexHerm{T,S}, B::AbstractMatrix{T}; sortby::Union{Function,Nothing}=nothing) where {T<:Number,S<:StridedMatrix} + U = cholesky(B).U + vals, w = eigen!(UtiAUi!(A, U)) + vecs = U \ w + GeneralizedEigen(sorteig!(vals, vecs, sortby)...) +end + +# Perform U' \ A / U in-place. +UtiAUi!(As::Symmetric, Utr::UpperTriangular) = Symmetric(_UtiAsymUi!(As.uplo, parent(As), parent(Utr)), sym_uplo(As.uplo)) +UtiAUi!(As::Hermitian, Utr::UpperTriangular) = Hermitian(_UtiAsymUi!(As.uplo, parent(As), parent(Utr)), sym_uplo(As.uplo)) +UtiAUi!(As::Symmetric, Udi::Diagonal) = Symmetric(_UtiAsymUi_diag!(As.uplo, parent(As), Udi), sym_uplo(As.uplo)) +UtiAUi!(As::Hermitian, Udi::Diagonal) = Hermitian(_UtiAsymUi_diag!(As.uplo, parent(As), Udi), sym_uplo(As.uplo)) + +# U is upper triangular +function _UtiAsymUi!(uplo, A, U) + n = size(A, 1) + μ⁻¹ = 1 / U[1, 1] + αμ⁻² = A[1, 1] * μ⁻¹' * μ⁻¹ + + # Update (1, 1) element + A[1, 1] = αμ⁻² + if n > 1 + Unext = view(U, 2:n, 2:n) + + if uplo === 'U' + # Update submatrix + for j in 2:n, i in 2:j + A[i, j] = ( + A[i, j] + - μ⁻¹' * U[1, j] * A[1, i]' + - μ⁻¹ * A[1, j] * U[1, i]' + + αμ⁻² * U[1, j] * U[1, i]' + ) + end + + # Update vector + for j in 2:n + A[1, j] = A[1, j] * μ⁻¹' - U[1, j] * αμ⁻² + end + ldiv!(view(A', 2:n, 1), UpperTriangular(Unext)', view(A', 2:n, 1)) + else + # Update submatrix + for j in 2:n, i in 2:j + A[j, i] = ( + A[j, i] + - μ⁻¹ * A[i, 1]' * U[1, j]' + - μ⁻¹' * U[1, i] * A[j, 1] + + αμ⁻² * U[1, i] * U[1, j]' + ) + end + + # Update vector + for j in 2:n + A[j, 1] = A[j, 1] * μ⁻¹ - U[1, j]' * αμ⁻² + end + ldiv!(view(A, 2:n, 1), UpperTriangular(Unext)', view(A, 2:n, 1)) + end + + # Recurse + _UtiAsymUi!(uplo, view(A, 2:n, 2:n), Unext) + end + + return A +end + +# U is diagonal +function _UtiAsymUi_diag!(uplo, A, U) + n = size(A, 1) + μ⁻¹ = 1 / U[1, 1] + αμ⁻² = A[1, 1] * μ⁻¹' * μ⁻¹ + + # Update (1, 1) element + A[1, 1] = αμ⁻² + if n > 1 + Unext = view(U, 2:n, 2:n) + + if uplo === 'U' + # No need to update any submatrix when U is diagonal + + # Update vector + for j in 2:n + A[1, j] = A[1, j] * μ⁻¹' + end + ldiv!(view(A', 2:n, 1), Diagonal(Unext)', view(A', 2:n, 1)) + else + # No need to update any submatrix when U is diagonal + + # Update vector + for j in 2:n + A[j, 1] = A[j, 1] * μ⁻¹ + end + ldiv!(view(A, 2:n, 1), Diagonal(Unext)', view(A, 2:n, 1)) + end + + # Recurse + _UtiAsymUi!(uplo, view(A, 2:n, 2:n), Unext) + end + + return A +end + +eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix} = + LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1] +eigvals!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix} = + LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1] + +eigvecs(A::HermOrSym) = eigvecs(eigen(A)) diff --git a/stdlib/LinearAlgebra/test/eigen.jl b/stdlib/LinearAlgebra/test/eigen.jl index 16b47221a8333..fd9f7dfba92ee 100644 --- a/stdlib/LinearAlgebra/test/eigen.jl +++ b/stdlib/LinearAlgebra/test/eigen.jl @@ -3,7 +3,7 @@ module TestEigen using Test, LinearAlgebra, Random -using LinearAlgebra: BlasComplex, BlasFloat, BlasReal, QRPivoted +using LinearAlgebra: BlasComplex, BlasFloat, BlasReal, QRPivoted, UtiAUi! n = 10 @@ -73,6 +73,31 @@ aimg = randn(n,n)/2 d,v = eigen(asym_sg, a_sg'a_sg) @test d == f.values @test v == f.vectors + + # solver for in-place U' \ A / U (#14896) + if !(eltya <: Integer) + for atyp in (eltya <: Real ? (Symmetric, Hermitian) : (Hermitian,)) + for utyp in (UpperTriangular, Diagonal) + A = atyp(asym_sg) + U = utyp(a_sg'a_sg) + @test UtiAUi!(copy(A), U) ≈ U' \ A / U + end + end + end + + # matrices of different types (#14896) + if eltya <: Real + fs = eigen(Symmetric(asym_sg), a_sg'a_sg) + @test fs.values ≈ f.values + @test abs.(fs.vectors) ≈ abs.(f.vectors) # may change sign + gs = eigen(Symmetric(asym_sg), Diagonal(a_sg'a_sg)) + @test Symmetric(asym_sg)*gs.vectors ≈ (Diagonal(a_sg'a_sg)*gs.vectors) * Diagonal(gs.values) + end + fh = eigen(Hermitian(asym_sg), a_sg'a_sg) + @test fh.values ≈ f.values + @test abs.(fh.vectors) ≈ abs.(f.vectors) # may change sign + gh = eigen(Hermitian(asym_sg), Diagonal(a_sg'a_sg)) + @test Hermitian(asym_sg)*gh.vectors ≈ (Diagonal(a_sg'a_sg)*gh.vectors) * Diagonal(gh.values) end @testset "Non-symmetric generalized eigenproblem" begin if isa(a, Array) From 514426d3fd2723c6ddfc33444bfc23891c55454d Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Fri, 26 Mar 2021 10:01:42 -0700 Subject: [PATCH 033/439] [Libdl] Use RTLD_NOLOAD when calling dlpath(::String) (#39676) This should make it faster and have fewer side-effects to look up the absolute path of libraries. --- base/libdl.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base/libdl.jl b/base/libdl.jl index 4f29260bb24f8..9f37eb2034007 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -237,10 +237,9 @@ julia> dlpath("libjulia") ``` """ function dlpath(libname::Union{AbstractString, Symbol}) - handle = dlopen(libname) - path = dlpath(handle) - dlclose(handle) - return path + dlopen(libname, RTLD_NOLOAD) do handle + return dlpath(handle) + end end if Sys.isapple() From 712abb09c84c45906b60d1c2ded740f442788c88 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 26 Mar 2021 15:39:13 -0400 Subject: [PATCH 034/439] build: hotfix for #39956 (#40218) This was removed from libjulia.dll during the PR process, but got overlooked for libjulia-debug.dll, breaking that build. --- cli/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/Makefile b/cli/Makefile index e289ffc82aaa6..03261c386d2d0 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -121,13 +121,12 @@ ifeq ($(OS), WINNT) endif $(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_DOBJS) | $(build_shlibdir) $(build_libdir) - @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -DLIBRARY_EXPORTS -shared $(DEBUGFLAGS) $(LIB_DOBJS) -o $@.tmp \ + @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -DLIBRARY_EXPORTS -shared $(DEBUGFLAGS) $(LIB_DOBJS) -o $@ \ $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(RPATH_LIB) $(call SONAME_FLAGS,libjulia-debug.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-debug.$(SHLIB_EXT) $@.tmp ifeq ($(OS), WINNT) @$(call PRINT_ANALYZE, $(OBJCOPY) $(build_libdir)/$(notdir $@).tmp.a $(STRIP_EXPORTED_FUNCS) $(build_libdir)/$(notdir $@).a && rm $(build_libdir)/$(notdir $@).tmp.a) endif - @mv $@.tmp $@ ifneq ($(OS), WINNT) $(build_shlibdir)/libjulia.$(JL_MAJOR_SHLIB_EXT) $(build_shlibdir)/libjulia-debug.$(JL_MAJOR_SHLIB_EXT): $(build_shlibdir)/libjulia%.$(JL_MAJOR_SHLIB_EXT): \ From 40267bb03d9a6fa3406d84ed3a932e1f55b3cb4d Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Sun, 28 Mar 2021 06:42:48 +0200 Subject: [PATCH 035/439] fix IRCode show_ir with verbose linetable (#40240) fix block number printing with verbose linfo --- base/compiler/ssair/show.jl | 5 +++-- test/show.jl | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index c1f4e0f25f506..851cc46def6ea 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -555,6 +555,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print else bb_guard_rail = bb_guard_rail_cont end + floop = true # Print linetable information if verbose_linetable stack = compute_loc_stack(code.linetable, stmt[:line]) @@ -568,10 +569,11 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) print(io, bb_guard_rail) ssa_guard = " "^(maxlength_idx + 4 + (i - 1)) - entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry[:line]) " + entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) " hline = string("─"^(start_column-length(entry_label)-length(bb_guard_rail)+max_depth-i), "┐") printstyled(io, string(entry_label, hline), "\n"; color=:light_black) bb_guard_rail = bb_guard_rail_cont + floop = false end end printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) @@ -602,7 +604,6 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print if idx == last(bbrange) print_sep = true end - floop = true # print new nodes first in the right position while perm_idx <= length(new_nodes_perm) node_idx = new_nodes_perm[perm_idx] diff --git a/test/show.jl b/test/show.jl index c2db37493ab05..51e6abca85f9b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1890,6 +1890,12 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] @test pop!(lines2) == " │ \$(QuoteNode(4))" @test pop!(lines2) == "17 │ \$(QuoteNode(3))" # TODO: this should print after the next statement @test lines1 == lines2 + + # verbose linetable + io = IOBuffer() + Base.IRShow.show_ir(io, ir; verbose_linetable=true) + seekstart(io) + @test count(contains(r"my_fun28173 at none:\d+"), eachline(io)) == 9 end # Verify that extra instructions at the end of the IR From 323b5b4dfa912cde8b80f684bd0af0e2d2358220 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sun, 28 Mar 2021 02:34:01 -0500 Subject: [PATCH 036/439] Make `Float16(::BigFloat)` go through `Float64` Doesn't fix double rounding issues, but makes them occur 2^29 times less frequently. Should have minimal performance effects. --- base/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index c85531856f5c9..cffad32e50ea0 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -339,7 +339,7 @@ Float32(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = Float32(x::BigFloat, r::RoundingMode) = Float32(x, convert(MPFRRoundingMode, r)) # TODO: avoid double rounding -Float16(x::BigFloat) = Float16(Float32(x)) +Float16(x::BigFloat) = Float16(Float64(x)) promote_rule(::Type{BigFloat}, ::Type{<:Real}) = BigFloat promote_rule(::Type{BigInt}, ::Type{<:AbstractFloat}) = BigFloat From d0ab30b78a2c551f033e3eefc1ada6169b985297 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Mon, 29 Mar 2021 14:42:00 +0200 Subject: [PATCH 037/439] Reinstate support for merging modules with non-const globals. --- src/jitlayers.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 3ac092d53fbc6..77ce3c93eadd3 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -944,8 +944,7 @@ void jl_merge_module(Module *dest, std::unique_ptr src) // continue; //} else { - assert(dG->isDeclaration() || (dG->getInitializer() == sG->getInitializer() && - dG->isConstant() && sG->isConstant())); + assert(dG->isDeclaration() || dG->getInitializer() == sG->getInitializer()); dG->replaceAllUsesWith(sG); dG->eraseFromParent(); } From 2ec75d65ce13651f42f59456568aefe30901b9c6 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 29 Mar 2021 16:29:47 +0200 Subject: [PATCH 038/439] Fix a small bug in the TOML parser and add an example of printing to a file (#40208) fix the TOML parser to parse 0e-3 and add an example of writing to a file --- base/toml_parser.jl | 2 -- stdlib/TOML/docs/src/index.md | 13 +++++++++++-- stdlib/TOML/test/values.jl | 5 +++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/base/toml_parser.jl b/base/toml_parser.jl index c69096504df0b..956c62196d6b8 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -821,8 +821,6 @@ function parse_number_or_date_start(l::Parser) ate && return parse_int(l, contains_underscore) elseif accept(l, isdigit) return parse_local_time(l) - elseif peek(l) !== '.' - return ParserError(ErrLeadingZeroNotAllowedInteger) end end diff --git a/stdlib/TOML/docs/src/index.md b/stdlib/TOML/docs/src/index.md index e34bb8d85f2f1..36e8ec6248108 100644 --- a/stdlib/TOML/docs/src/index.md +++ b/stdlib/TOML/docs/src/index.md @@ -65,8 +65,6 @@ format. ```jldoctest julia> using TOML -julia> fname = tempname(); - julia> data = Dict( "names" => ["Julia", "Julio"], "age" => [10, 20], @@ -75,6 +73,17 @@ julia> data = Dict( julia> TOML.print(data) names = ["Julia", "Julio"] age = [10, 20] + +julia> fname = tempname(); + +julia> open(fname, "w") do io + TOML.print(io, data) + end + +julia> TOML.parsefile(fname) +Dict{String, Any} with 2 entries: + "names" => ["Julia", "Julio"] + "age" => [10, 20] ``` Keys can be sorted according to some value diff --git a/stdlib/TOML/test/values.jl b/stdlib/TOML/test/values.jl index 9f09e26b01cda..8337bb5a54714 100644 --- a/stdlib/TOML/test/values.jl +++ b/stdlib/TOML/test/values.jl @@ -39,6 +39,7 @@ end @test testval("1.0e0" , 1.0) @test testval("1.0e+0" , 1.0) @test testval("1.0e-0" , 1.0) + @test testval("0e-3" , 0.0) @test testval("1.001e-0" , 1.001) @test testval("2e10" , 2e10) @test testval("2e+10" , 2e10) @@ -53,8 +54,8 @@ end @test testval("+1_000" , 1000 |> Int64) @test testval("-1_000" , -1000 |> Int64) - @test failval("0_" , Internals.ErrLeadingZeroNotAllowedInteger) - @test failval("0__0" , Internals.ErrLeadingZeroNotAllowedInteger) + @test failval("0_" , Internals.ErrUnderscoreNotSurroundedByDigits) + @test failval("0__0" , Internals.ErrUnderscoreNotSurroundedByDigits) @test failval("__0" , Internals.ErrUnexpectedStartOfValue) @test failval("1_0_" , Internals.ErrTrailingUnderscoreNumber) @test failval("1_0__0" , Internals.ErrUnderscoreNotSurroundedByDigits) From 02249d5075535f95278af963867c0e7f62c9bc65 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 26 Mar 2021 16:15:25 -0400 Subject: [PATCH 039/439] add FZ16 to fpcr_fz_mask for aarch64 --- src/processor_arm.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index f15f205118773..9bbd540fa233f 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -1810,6 +1810,8 @@ extern "C" int jl_test_cpu_feature(jl_cpu_feature_t feature) #ifdef _CPU_AARCH64_ // FPCR FZ, bit [24] static constexpr uint32_t fpcr_fz_mask = 1 << 24; +// FPCR FZ16, bit [19] +static constexpr uint32_t fpcr_fz16_mask = 1 << 19; // FPCR DN, bit [25] static constexpr uint32_t fpcr_dn_mask = 1 << 25; @@ -1833,7 +1835,8 @@ extern "C" JL_DLLEXPORT int32_t jl_get_zero_subnormals(void) extern "C" JL_DLLEXPORT int32_t jl_set_zero_subnormals(int8_t isZero) { uint32_t fpcr = get_fpcr_aarch64(); - fpcr = isZero ? (fpcr | fpcr_fz_mask) : (fpcr & ~fpcr_fz_mask); + static uint32_t mask = fpcr_fz_mask | (jl_test_cpu_feature(JL_AArch64_fullfp16) ? fpcr_fz16_mask : 0); + fpcr = isZero ? (fpcr | mask) : (fpcr & ~mask); set_fpcr_aarch64(fpcr); return 0; } From 59f1534c19c749411db18c92e15955487bb9d5ca Mon Sep 17 00:00:00 2001 From: "McCoy R. Becker" <34410036+femtomc@users.noreply.github.com> Date: Mon, 29 Mar 2021 13:36:53 -0400 Subject: [PATCH 040/439] Changed realloc to calloc to avoid issues with non-initialization. (#40225) --- src/threading.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/threading.c b/src/threading.c index 01fe98e041a87..bffc1b02d909a 100644 --- a/src/threading.c +++ b/src/threading.c @@ -398,8 +398,8 @@ void jl_init_threading(void) } if (jl_n_threads <= 0) jl_n_threads = 1; - jl_measure_compile_time = (uint8_t*)realloc(jl_measure_compile_time, jl_n_threads * sizeof(*jl_measure_compile_time)); - jl_cumulative_compile_time = (uint64_t*)realloc(jl_cumulative_compile_time, jl_n_threads * sizeof(*jl_cumulative_compile_time)); + jl_measure_compile_time = (uint8_t*)calloc(jl_n_threads, sizeof(*jl_measure_compile_time)); + jl_cumulative_compile_time = (uint64_t*)calloc(jl_n_threads, sizeof(*jl_cumulative_compile_time)); #ifndef __clang_analyzer__ jl_all_tls_states = (jl_ptls_t*)calloc(jl_n_threads, sizeof(void*)); #endif From 6e4ea5bd922b2ef0549751d991a9efd27ae41dfa Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 29 Mar 2021 19:17:08 +0000 Subject: [PATCH 041/439] [automated] Bump the Pkg stdlib from af7e41cd to 7cec9049 (#40235) Co-authored-by: Dilum Aluthge --- .../Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 | 1 + .../Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 | 1 + .../Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/md5 | 1 - .../Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 create mode 100644 deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/sha512 diff --git a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 new file mode 100644 index 0000000000000..3375a525ece00 --- /dev/null +++ b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 @@ -0,0 +1 @@ +ad612acc3e839f0296b415728174fd12 diff --git a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 new file mode 100644 index 0000000000000..fa50e4b75e174 --- /dev/null +++ b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 @@ -0,0 +1 @@ +a43936680d3ee33804d604dd56296105d2cfa5875938c30f81f07d31eee589cc321ce27f47d5034f3f459a83d839ceb50f6a7b5693ba0d52e1e8fde0665878e9 diff --git a/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/md5 b/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/md5 deleted file mode 100644 index 8ff865fe02593..0000000000000 --- a/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -f70da472ebac16aaec6f38e69e49c6d7 diff --git a/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/sha512 b/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/sha512 deleted file mode 100644 index 84f9ae288d8a2..0000000000000 --- a/deps/checksums/Pkg-af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -83f6966bc5a55f80fce9899e8f48a0e26dae37d88a5819b1a67d81d2ab5bf57999acd1a42b2ca7366c428efb2a8661679820550df8d8f7a4a74f9a4406da096d diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 5d9153eefe853..2dd0da784dbf9 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = af7e41cd9d9529bfc8e8fecd7e24c7392c73cdbc +PKG_SHA1 = 7cec9049e14d315c57810f93ce5a4b67c4698047 From ac50ac6058caa97c047c1751ca9cbbe0c1ceea2a Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 29 Mar 2021 16:33:05 -0500 Subject: [PATCH 042/439] Fix issue where approved credentials were not sent to git credential helpers (#40161) Due to the bug in the `GitCredential` constructor we were never writing credential data to the credential helper effectively making our use of git credential helpers read-only. --- stdlib/LibGit2/src/gitcredential.jl | 7 +++- stdlib/LibGit2/test/libgit2.jl | 61 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/stdlib/LibGit2/src/gitcredential.jl b/stdlib/LibGit2/src/gitcredential.jl index 0a442337531a7..1b97c29cd933e 100644 --- a/stdlib/LibGit2/src/gitcredential.jl +++ b/stdlib/LibGit2/src/gitcredential.jl @@ -30,7 +30,12 @@ function GitCredential(cfg::GitConfig, url::AbstractString) fill!(cfg, parse(GitCredential, url)) end -GitCredential(cred::UserPasswordCredential, url::AbstractString) = parse(GitCredential, url) +function GitCredential(user_pass_cred::UserPasswordCredential, url::AbstractString) + cred = parse(GitCredential, url) + cred.username = user_pass_cred.user + cred.password = deepcopy(user_pass_cred.pass) + return cred +end Base.:(==)(c1::GitCredential, c2::GitCredential) = (c1.protocol, c1.host, c1.path, c1.username, c1.password, c1.use_http_path) == (c2.protocol, c2.host, c2.path, c2.username, c2.password, c2.use_http_path) diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 93e530aee5d8e..892fb8bb6f3fe 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -600,6 +600,23 @@ end github_regex_test("ssh://git@github.com/$user/$repo", user, repo) @test !occursin(LibGit2.GITHUB_REGEX, "git@notgithub.com/$user/$repo.git") end + + @testset "UserPasswordCredential/url constructor" begin + user_pass_cred = LibGit2.UserPasswordCredential("user", "*******") + url = "https://github.com" + expected_cred = LibGit2.GitCredential("https", "github.com", nothing, "user", "*******") + + cred = LibGit2.GitCredential(user_pass_cred, url) + @test cred == expected_cred + + # Shredding the UserPasswordCredential shouldn't result in information being lost + # inside of a GitCredential. + Base.shred!(user_pass_cred) + @test cred == expected_cred + + Base.shred!(cred) + Base.shred!(expected_cred) + end end mktempdir() do dir @@ -2133,6 +2150,50 @@ mktempdir() do dir end end end + + @testset "approve/reject with UserPasswordCredential" begin + # In order to use the "store" credential helper `git` needs to be installed and + # on the path. + if GIT_INSTALLED + config_path = joinpath(dir, config_file) + isfile(config_path) && rm(config_path) + + credential_path = joinpath(dir, ".git-credentials") + isfile(credential_path) && rm(credential_path) + + LibGit2.with(LibGit2.GitConfig(config_path, LibGit2.Consts.CONFIG_LEVEL_APP)) do cfg + query = LibGit2.GitCredential("https", "mygithost") + filled = LibGit2.GitCredential("https", "mygithost", nothing, "alice", "1234") + user_pass_cred = LibGit2.UserPasswordCredential("alice", "1234") + url = "https://mygithost" + + # Requires `git` to be installed and available on the path. + LibGit2.set!(cfg, "credential.helper", "store --file \"$credential_path\"") + helper = only(LibGit2.credential_helpers(cfg, query)) + + @test !isfile(credential_path) + + Base.shred!(LibGit2.fill!(helper, deepcopy(query))) do result + @test result == query + end + + LibGit2.approve(cfg, user_pass_cred, url) + @test isfile(credential_path) + Base.shred!(LibGit2.fill!(helper, deepcopy(query))) do result + @test result == filled + end + + LibGit2.reject(cfg, user_pass_cred, url) + Base.shred!(LibGit2.fill!(helper, deepcopy(query))) do result + @test result == query + end + + Base.shred!(query) + Base.shred!(filled) + Base.shred!(user_pass_cred) + end + end + end end # The following tests require that we can fake a TTY so that we can provide passwords From 6fe0827ba48a135caa5bc32308aa7e1ffb43486e Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 29 Mar 2021 23:30:15 +0000 Subject: [PATCH 043/439] [automated] Bump the Pkg stdlib from 7cec9049 to 0fa812e2 (#40259) Co-authored-by: Dilum Aluthge --- .../Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 | 1 + .../Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 | 1 + .../Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 | 1 - .../Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 create mode 100644 deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 diff --git a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 new file mode 100644 index 0000000000000..c9d7f9e349814 --- /dev/null +++ b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 @@ -0,0 +1 @@ +71e5330f4797fc6f81b6ce79a3fff593 diff --git a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 new file mode 100644 index 0000000000000..7e18d20177a0f --- /dev/null +++ b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 @@ -0,0 +1 @@ +e38253c9b00c47550ec093139487145d498befd6de3d3fb504c4abbe2173d460c3bb769c82ea07531d11b3a0c356f5d4e44ae87293e0d5f770001b717f517920 diff --git a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 deleted file mode 100644 index 3375a525ece00..0000000000000 --- a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ad612acc3e839f0296b415728174fd12 diff --git a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 b/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 deleted file mode 100644 index fa50e4b75e174..0000000000000 --- a/deps/checksums/Pkg-7cec9049e14d315c57810f93ce5a4b67c4698047.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -a43936680d3ee33804d604dd56296105d2cfa5875938c30f81f07d31eee589cc321ce27f47d5034f3f459a83d839ceb50f6a7b5693ba0d52e1e8fde0665878e9 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 2dd0da784dbf9..62ac98653cb93 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 7cec9049e14d315c57810f93ce5a4b67c4698047 +PKG_SHA1 = 0fa812e2e6ebf61196d6048f15de5c2087a72454 From 0e3fab628f3a00efc815c1e53417b1e3afcf592b Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Tue, 30 Mar 2021 05:17:45 +0000 Subject: [PATCH 044/439] [automated] Bump the Pkg stdlib from 0fa812e2 to a4ade8ce (#40266) Co-authored-by: Dilum Aluthge --- .../Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 | 1 - .../Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 | 1 - .../Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 | 1 + .../Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 create mode 100644 deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 diff --git a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 deleted file mode 100644 index c9d7f9e349814..0000000000000 --- a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -71e5330f4797fc6f81b6ce79a3fff593 diff --git a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 b/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 deleted file mode 100644 index 7e18d20177a0f..0000000000000 --- a/deps/checksums/Pkg-0fa812e2e6ebf61196d6048f15de5c2087a72454.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e38253c9b00c47550ec093139487145d498befd6de3d3fb504c4abbe2173d460c3bb769c82ea07531d11b3a0c356f5d4e44ae87293e0d5f770001b717f517920 diff --git a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 new file mode 100644 index 0000000000000..14e88d4e67eb7 --- /dev/null +++ b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 @@ -0,0 +1 @@ +51f7ab137d891ad548e9b09480bbd51e diff --git a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 new file mode 100644 index 0000000000000..56e8852024dce --- /dev/null +++ b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 @@ -0,0 +1 @@ +996c8c8a17be23137f337674f886eceacc8c5bf66f12fa6f50e57454286f456c6f073eb1c05030a67065fbdaaee871e628b65eadbd9099b386ae5396d46d27a4 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 62ac98653cb93..10ead3c56021c 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 0fa812e2e6ebf61196d6048f15de5c2087a72454 +PKG_SHA1 = a4ade8cea58412a116be5066bb5f84f6d63fba3c From 0f828a2acc497f0c26965956a57cfa9ea69cdd09 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 30 Mar 2021 14:19:47 +0200 Subject: [PATCH 045/439] fix markdown list rendering (#40203) --- .../Markdown/src/render/terminal/formatting.jl | 18 ++++++++---------- stdlib/Markdown/test/runtests.jl | 8 ++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/stdlib/Markdown/src/render/terminal/formatting.jl b/stdlib/Markdown/src/render/terminal/formatting.jl index bacd82f7ed021..87022124b9c8a 100644 --- a/stdlib/Markdown/src/render/terminal/formatting.jl +++ b/stdlib/Markdown/src/render/terminal/formatting.jl @@ -9,8 +9,9 @@ end words(s) = split(s, " ") lines(s) = split(s, "\n") -function wrapped_lines!(lines, io::IO, s::AbstractString, width, i) +function wrapped_line(io::IO, s::AbstractString, width, i) ws = words(s) + lines = String[] for word in ws word_length = ansi_length(word) word_length == 0 && continue @@ -22,19 +23,16 @@ function wrapped_lines!(lines, io::IO, s::AbstractString, width, i) lines[end] *= " " * word # this could be more efficient end end - return i + return i, lines end function wrapped_lines(io::IO, s::AbstractString; width = 80, i = 0) - lines = AbstractString[] - if occursin(r"\n", s) - for ss in split(s, "\n") - i = wrapped_lines!(lines, io, ss, width, i) - end - else - wrapped_lines!(lines, io, s, width, i) + ls = String[] + for ss in lines(s) + i, line = wrapped_line(io, ss, width, i) + append!(ls, line) end - return lines + return ls end wrapped_lines(io::IO, f::Function, args...; width = 80, i = 0) = diff --git a/stdlib/Markdown/test/runtests.jl b/stdlib/Markdown/test/runtests.jl index f9983d10089f9..f90eefb85310e 100644 --- a/stdlib/Markdown/test/runtests.jl +++ b/stdlib/Markdown/test/runtests.jl @@ -1222,3 +1222,11 @@ end """) end +@testset "issue #37232: linebreaks" begin + s = @md_str """ + Misc:\\ + - line\\ + """ + @test sprint(show, MIME("text/plain"), s) == " Misc:\n - line" +end + From 3f4bbae067f43a36bba0bb85ee791862682cea1f Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 30 Mar 2021 08:44:48 -0400 Subject: [PATCH 046/439] Use BINARY=64 on aarch64 (#40265) Fix #39612 --- Make.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/Make.inc b/Make.inc index 519720a861ed7..5bcf86bc2e413 100644 --- a/Make.inc +++ b/Make.inc @@ -898,6 +898,7 @@ ifneq (,$(findstring aarch64,$(ARCH))) OPENBLAS_DYNAMIC_ARCH:=0 OPENBLAS_TARGET_ARCH:=ARMV8 USE_BLAS64:=1 +BINARY:=64 ifeq ($(OS),Darwin) # Apple Chips are all at least A12Z MCPU:=apple-a12 From 0700bea13da5b287d9670d0dc558aa78433ac313 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 30 Mar 2021 16:34:52 +0200 Subject: [PATCH 047/439] bump Pkg version to fix problem with Pkg.build (#40269) --- .../Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 | 1 + .../Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 | 1 + .../Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 | 1 - .../Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 create mode 100644 deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 diff --git a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 new file mode 100644 index 0000000000000..ab9c27e3272bc --- /dev/null +++ b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 @@ -0,0 +1 @@ +ae890308e62884dac6aaa69ba45ec1a1 diff --git a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 new file mode 100644 index 0000000000000..b3959f1dd6a87 --- /dev/null +++ b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 @@ -0,0 +1 @@ +2517ad47694a55eb009fde46b4d7bf70c82a2ace15145f61b6fd925c4ce34ead336f8c1be8edf872b89c6a43cdfdd90ea2c3a54a87f9beba1aa7cefa5f3b59dd diff --git a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 deleted file mode 100644 index 14e88d4e67eb7..0000000000000 --- a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -51f7ab137d891ad548e9b09480bbd51e diff --git a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 b/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 deleted file mode 100644 index 56e8852024dce..0000000000000 --- a/deps/checksums/Pkg-a4ade8cea58412a116be5066bb5f84f6d63fba3c.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -996c8c8a17be23137f337674f886eceacc8c5bf66f12fa6f50e57454286f456c6f073eb1c05030a67065fbdaaee871e628b65eadbd9099b386ae5396d46d27a4 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 10ead3c56021c..33ecf13468d35 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = a4ade8cea58412a116be5066bb5f84f6d63fba3c +PKG_SHA1 = 74098fe713066b8d6e4d8159c80a305b7a8fd408 From 42766ace9af350fd51cd33d0890fe6bb66a1638b Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Tue, 30 Mar 2021 14:44:02 -0400 Subject: [PATCH 048/439] make some constructors bold in stacktraces (#40264) --- base/show.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index 278a5c96df615..89a2fdef11ec9 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2226,7 +2226,7 @@ function show_signature_function(io::IO, @nospecialize(ft), demangle=false, farg uwf = unwrap_unionall(f) parens = isa(f, UnionAll) && !(isa(uwf, DataType) && f === uwf.name.wrapper) parens && print(io, "(") - show(io, f) + print_within_stacktrace(io, f, bold=true) parens && print(io, ")") else if html From 550e980b9def7b6aa8f41f075c4a168e865b6354 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 30 Mar 2021 16:29:36 -0400 Subject: [PATCH 049/439] avoid specializing a closure in the compiler (#40256) --- base/compiler/abstractinterpretation.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 6eefc453111c9..9b7434c0a5a45 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1450,9 +1450,9 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), if length(e.args) == 2 && isconcretetype(t) && !t.mutable at = abstract_eval_value(interp, e.args[2], vtypes, sv) n = fieldcount(t) - if isa(at, Const) && (val = at.val; isa(val, Tuple)) && n == length(val) && - let t = t, val = val; _all(i->val[i] isa fieldtype(t, i), 1:n); end - t = Const(ccall(:jl_new_structt, Any, (Any, Any), t, val)) + if isa(at, Const) && isa(at.val, Tuple) && n == length(at.val) && + let t = t; _all(i->getfield(at.val, i) isa fieldtype(t, i), 1:n); end + t = Const(ccall(:jl_new_structt, Any, (Any, Any), t, at.val)) elseif isa(at, PartialStruct) && at ⊑ Tuple && n == length(at.fields) && let t = t, at = at; _all(i->at.fields[i] ⊑ fieldtype(t, i), 1:n); end t = PartialStruct(t, at.fields) From 5cdf5261335d979ca9ce2967a4a8c4842bba7d72 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 30 Mar 2021 16:31:40 -0400 Subject: [PATCH 050/439] remove code for inserting methods in sorted order (#39797) We've reached the point where our algorithms no longer need to assume sorting. --- src/gf.c | 11 ++--- src/julia_internal.h | 10 +---- src/typemap.c | 101 ++++++++++++++----------------------------- test/errorshow.jl | 2 +- 4 files changed, 38 insertions(+), 86 deletions(-) diff --git a/src/gf.c b/src/gf.c index abc6ac775b644..f90d0e49fc8ca 100644 --- a/src/gf.c +++ b/src/gf.c @@ -69,9 +69,6 @@ void jl_call_tracer(tracer_cb callback, jl_value_t *tracee) /// ----- Definitions for various internal TypeMaps ----- /// -static struct jl_typemap_info method_defs = {1}; -static struct jl_typemap_info lambda_cache = {1}; - static int8_t jl_cachearg_offset(jl_methtable_t *mt) { return mt->offs; @@ -243,7 +240,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a jl_methtable_t *mt = dt->name->mt; newentry = jl_typemap_alloc(jl_anytuple_type, NULL, jl_emptysvec, (jl_value_t*)mi, 1, ~(size_t)0); - jl_typemap_insert(&mt->cache, (jl_value_t*)mt, newentry, 0, &lambda_cache); + jl_typemap_insert(&mt->cache, (jl_value_t*)mt, newentry, 0); mt->frozen = 1; JL_GC_POP(); @@ -1090,7 +1087,7 @@ static jl_method_instance_t *cache_method( guards++; // alternative approach: insert sentinel entry //jl_typemap_insert(cache, parent, (jl_tupletype_t*)matc->spec_types, - // NULL, jl_emptysvec, /*guard*/NULL, jl_cachearg_offset(mt), &lambda_cache, other->min_world, other->max_world); + // NULL, jl_emptysvec, /*guard*/NULL, jl_cachearg_offset(mt), other->min_world, other->max_world); } } } @@ -1165,7 +1162,7 @@ static jl_method_instance_t *cache_method( jl_gc_wb(mt, mt->leafcache); } else { - jl_typemap_insert(cache, parent, newentry, offs, &lambda_cache); + jl_typemap_insert(cache, parent, newentry, offs); } JL_GC_POP(); @@ -1641,7 +1638,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method // then add our new entry newentry = jl_typemap_alloc((jl_tupletype_t*)type, simpletype, jl_emptysvec, (jl_value_t*)method, method->primary_world, method->deleted_world); - jl_typemap_insert(&mt->defs, (jl_value_t*)mt, newentry, 0, &method_defs); + jl_typemap_insert(&mt->defs, (jl_value_t*)mt, newentry, 0); if (oldentry) { jl_method_t *m = oldentry->func.method; method_overwrite(newentry, m); diff --git a/src/julia_internal.h b/src/julia_internal.h index 96b01f153760f..f3f69bf8f9e7b 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1189,16 +1189,8 @@ void jl_smallintset_insert(jl_array_t **pcache, jl_value_t *parent, smallintset_ // -- typemap.c -- // -// a descriptor of a jl_typemap_t that gets -// passed around as self-documentation of the parameters of the type -struct jl_typemap_info { - int8_t unsorted; // whether this should be unsorted - jl_datatype_t **jl_contains; // the type that is being put in this -}; - void jl_typemap_insert(jl_typemap_t **cache, jl_value_t *parent, - jl_typemap_entry_t *newrec, int8_t offs, - const struct jl_typemap_info *tparams); + jl_typemap_entry_t *newrec, int8_t offs); jl_typemap_entry_t *jl_typemap_alloc( jl_tupletype_t *type, jl_tupletype_t *simpletype, jl_svec_t *guardsigs, jl_value_t *newvalue, size_t min_world, size_t max_world); diff --git a/src/typemap.c b/src/typemap.c index 50fb9635ff210..8714e4699d855 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -1087,10 +1087,7 @@ static unsigned jl_typemap_list_count_locked(jl_typemap_entry_t *ml) JL_NOTSAFEP return count; } -static void jl_typemap_level_insert_(jl_typemap_t *map, jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs, const struct jl_typemap_info *tparams); -static void jl_typemap_list_insert_sorted( - jl_typemap_t *map, jl_typemap_entry_t **pml, jl_value_t *parent, - jl_typemap_entry_t *newrec, const struct jl_typemap_info *tparams); +static void jl_typemap_level_insert_(jl_typemap_t *map, jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs); static jl_typemap_level_t *jl_new_typemap_level(void) { @@ -1108,8 +1105,7 @@ static jl_typemap_level_t *jl_new_typemap_level(void) } static jl_typemap_level_t *jl_method_convert_list_to_cache( - jl_typemap_t *map, jl_typemap_entry_t *ml, int8_t offs, - const struct jl_typemap_info *tparams) + jl_typemap_t *map, jl_typemap_entry_t *ml, int8_t offs) { jl_typemap_level_t *cache = jl_new_typemap_level(); jl_typemap_entry_t *next = NULL; @@ -1118,7 +1114,7 @@ static jl_typemap_level_t *jl_method_convert_list_to_cache( next = ml->next; ml->next = (jl_typemap_entry_t*)jl_nothing; // TODO: is it safe to be doing this concurrently with lookups? - jl_typemap_level_insert_(map, cache, ml, offs, tparams); + jl_typemap_level_insert_(map, cache, ml, offs); ml = next; } JL_GC_POP(); @@ -1127,26 +1123,29 @@ static jl_typemap_level_t *jl_method_convert_list_to_cache( static void jl_typemap_list_insert_( jl_typemap_t *map, jl_typemap_entry_t **pml, jl_value_t *parent, - jl_typemap_entry_t *newrec, const struct jl_typemap_info *tparams) + jl_typemap_entry_t *newrec) { - if (*pml == (void*)jl_nothing || newrec->isleafsig || (tparams && tparams->unsorted)) { - newrec->next = *pml; - jl_gc_wb(newrec, newrec->next); - jl_atomic_store_release(pml, newrec); - jl_gc_wb(parent, newrec); - } - else { - jl_typemap_list_insert_sorted(map, pml, parent, newrec, tparams); + jl_typemap_entry_t *l = *pml; + while ((jl_value_t*)l != jl_nothing) { + if (newrec->isleafsig || !l->isleafsig) + if (newrec->issimplesig || !l->issimplesig) + break; + pml = &l->next; + parent = (jl_value_t*)l; + l = l->next; } + newrec->next = l; + jl_gc_wb(newrec, newrec->next); + jl_atomic_store_release(pml, newrec); + jl_gc_wb(parent, newrec); } static void jl_typemap_insert_generic( jl_typemap_t *map, jl_typemap_t **pml, jl_value_t *parent, - jl_typemap_entry_t *newrec, int8_t offs, - const struct jl_typemap_info *tparams) + jl_typemap_entry_t *newrec, int8_t offs) { if (jl_typeof(*pml) == (jl_value_t*)jl_typemap_level_type) { - jl_typemap_level_insert_(map, (jl_typemap_level_t*)*pml, newrec, offs, tparams); + jl_typemap_level_insert_(map, (jl_typemap_level_t*)*pml, newrec, offs); return; } @@ -1154,31 +1153,29 @@ static void jl_typemap_insert_generic( if (count > MAX_METHLIST_COUNT) { *pml = (jl_typemap_t*)jl_method_convert_list_to_cache( map, (jl_typemap_entry_t *)*pml, - offs, tparams); + offs); jl_gc_wb(parent, *pml); - jl_typemap_level_insert_(map, (jl_typemap_level_t*)*pml, newrec, offs, tparams); + jl_typemap_level_insert_(map, (jl_typemap_level_t*)*pml, newrec, offs); return; } jl_typemap_list_insert_(map, (jl_typemap_entry_t **)pml, - parent, newrec, tparams); + parent, newrec); } static void jl_typemap_array_insert_( jl_typemap_t *map, jl_array_t **cache, jl_value_t *key, jl_typemap_entry_t *newrec, - jl_value_t *parent, int8_t offs, - const struct jl_typemap_info *tparams) + jl_value_t *parent, int8_t offs) { jl_typemap_t **pml = mtcache_hash_lookup_bp(*cache, key); if (pml != NULL) - jl_typemap_insert_generic(map, pml, (jl_value_t*)*cache, newrec, offs+1, tparams); + jl_typemap_insert_generic(map, pml, (jl_value_t*)*cache, newrec, offs+1); else mtcache_hash_insert(cache, parent, key, (jl_typemap_t*)newrec); } static void jl_typemap_level_insert_( - jl_typemap_t *map, jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs, - const struct jl_typemap_info *tparams) + jl_typemap_t *map, jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs) { jl_value_t *ttypes = jl_unwrap_unionall((jl_value_t*)newrec->sig); size_t l = jl_nparams(ttypes); @@ -1205,7 +1202,7 @@ static void jl_typemap_level_insert_( t1 = (jl_value_t*)jl_assume(jl_typeofbottom_type)->super; // If the type at `offs` is Any, put it in the Any list if (t1 && jl_is_any(t1)) { - jl_typemap_insert_generic(map, &cache->any, (jl_value_t*)cache, newrec, offs+1, tparams); + jl_typemap_insert_generic(map, &cache->any, (jl_value_t*)cache, newrec, offs+1); return; } // Don't put Varargs in the optimized caches (too hard to handle in lookup and bp) @@ -1216,12 +1213,12 @@ static void jl_typemap_level_insert_( // and we use the table indexed for that purpose. jl_value_t *a0 = jl_tparam0(t1); if (is_cache_leaf(a0, 1)) { - jl_typemap_array_insert_(map, &cache->targ, a0, newrec, (jl_value_t*)cache, offs, tparams); + jl_typemap_array_insert_(map, &cache->targ, a0, newrec, (jl_value_t*)cache, offs); return; } } if (is_cache_leaf(t1, 0)) { - jl_typemap_array_insert_(map, &cache->arg1, t1, newrec, (jl_value_t*)cache, offs, tparams); + jl_typemap_array_insert_(map, &cache->arg1, t1, newrec, (jl_value_t*)cache, offs); return; } @@ -1231,16 +1228,16 @@ static void jl_typemap_level_insert_( if (jl_is_type_type(t1)) { a0 = jl_type_extract_name(jl_tparam0(t1)); jl_datatype_t *super = a0 ? (jl_datatype_t*)jl_unwrap_unionall(((jl_typename_t*)a0)->wrapper) : jl_any_type; - jl_typemap_array_insert_(map, &cache->tname, (jl_value_t*)super->name, newrec, (jl_value_t*)cache, offs, tparams); + jl_typemap_array_insert_(map, &cache->tname, (jl_value_t*)super->name, newrec, (jl_value_t*)cache, offs); return; } a0 = jl_type_extract_name(t1); if (a0 && a0 != (jl_value_t*)jl_any_type->name) { - jl_typemap_array_insert_(map, &cache->name1, a0, newrec, (jl_value_t*)cache, offs, tparams); + jl_typemap_array_insert_(map, &cache->name1, a0, newrec, (jl_value_t*)cache, offs); return; } } - jl_typemap_list_insert_(map, &cache->linear, (jl_value_t*)cache, newrec, tparams); + jl_typemap_list_insert_(map, &cache->linear, (jl_value_t*)cache, newrec); } jl_typemap_entry_t *jl_typemap_alloc( @@ -1289,43 +1286,9 @@ jl_typemap_entry_t *jl_typemap_alloc( } void jl_typemap_insert(jl_typemap_t **cache, jl_value_t *parent, - jl_typemap_entry_t *newrec, int8_t offs, - const struct jl_typemap_info *tparams) -{ - jl_typemap_insert_generic(*cache, cache, parent, newrec, offs, tparams); -} - -static void jl_typemap_list_insert_sorted( - jl_typemap_t *map, jl_typemap_entry_t **pml, jl_value_t *parent, - jl_typemap_entry_t *newrec, const struct jl_typemap_info *tparams) + jl_typemap_entry_t *newrec, int8_t offs) { - jl_typemap_entry_t *l, **pl; - pl = pml; - l = *pml; - jl_value_t *pa = parent; - while ((jl_value_t*)l != jl_nothing) { - if (!l->isleafsig) { // quickly ignore all of the leafsig entries (these were handled by caller) - if (jl_type_morespecific((jl_value_t*)newrec->sig, (jl_value_t*)l->sig)) { - if (l->simplesig == (void*)jl_nothing || - newrec->simplesig != (void*)jl_nothing || - !jl_types_equal((jl_value_t*)l->sig, (jl_value_t*)newrec->sig)) { - // might need to insert multiple entries for a lookup differing only by their simplesig - // when simplesig contains a kind - // TODO: make this test more correct or figure out a better way to compute this - break; - } - } - } - pl = &l->next; - pa = (jl_value_t*)l; - l = l->next; - } - - // insert newrec at the first point it is more specific than the following method - newrec->next = l; - jl_gc_wb(newrec, l); - jl_atomic_store_release(pl, newrec); - jl_gc_wb(pa, newrec); + jl_typemap_insert_generic(*cache, cache, parent, newrec, offs); } #ifdef __cplusplus diff --git a/test/errorshow.jl b/test/errorshow.jl index 736e68dee1ef0..6848bb4a219f4 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -86,7 +86,7 @@ method_c2(x::Int32, y::Int32, z::Int32) = true method_c2(x::T, y::T, z::T) where {T<:Real} = true Base.show_method_candidates(buf, Base.MethodError(method_c2,(1., 1., 2))) -@test String(take!(buf)) == "\nClosest candidates are:\n method_c2(!Matched::Int32, ::Float64, ::Any...)$cfile$(c2line+2)\n method_c2(!Matched::Int32, ::Any...)$cfile$(c2line+1)\n method_c2(::T, ::T, !Matched::T) where T<:Real$cfile$(c2line+5)\n ..." +@test String(take!(buf)) == "\nClosest candidates are:\n method_c2(!Matched::Int32, ::Float64, ::Any...)$cfile$(c2line+2)\n method_c2(::T, ::T, !Matched::T) where T<:Real$cfile$(c2line+5)\n method_c2(!Matched::Int32, ::Any...)$cfile$(c2line+1)\n ..." c3line = @__LINE__() + 1 method_c3(x::Float64, y::Float64) = true From ba10fae87aa0223a7ac5a222e5e4852f15348591 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 31 Mar 2021 01:10:47 +0200 Subject: [PATCH 051/439] refactor IRShow (#40254) * refactor IRShow * fix case of undef types in new_nodes * fix undefined inst in new_node * use correct expr type printer --- base/compiler/ssair/show.jl | 452 +++++++++++++++++++----------------- test/show.jl | 2 +- 2 files changed, 238 insertions(+), 216 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 851cc46def6ea..1f822ee687214 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -487,191 +487,60 @@ function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false) return emit_lineinfo_update end +struct _UNDEF + global const UNDEF = _UNDEF.instance +end -function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_printer; verbose_linetable=false) - cols = (displaysize(io)::Tuple{Int,Int})[2] - used = BitSet() +function _stmt(code::IRCode, idx::Int) stmts = code.stmts - isempty(stmts) && return # unlikely, but avoid errors from reducing over empty sets - cfg = code.cfg - max_bb_idx_size = length(string(length(cfg.blocks))) - new_nodes = code.new_nodes.stmts - new_nodes_info = code.new_nodes.info - bb_idx = 1 - for stmt in stmts - scan_ssa_use!(push!, used, stmt[:inst]) - end - if any(i -> !isassigned(new_nodes.inst, i), 1:length(new_nodes)) - printstyled(io, "ERROR: New node array has unset entry\n", color=:red) - new_nodes_perm = filter(i -> isassigned(new_nodes.inst, i), 1:length(new_nodes)) - else - new_nodes_perm = collect(1:length(new_nodes)) - end - for nn in new_nodes_perm - scan_ssa_use!(push!, used, new_nodes[nn][:inst]) - end - sort!(new_nodes_perm, by = x -> (x = new_nodes_info[x]; (x.pos, x.attach_after))) - perm_idx = 1 + return isassigned(stmts.inst, idx) ? stmts[idx][:inst] : UNDEF +end +function _stmt(code::CodeInfo, idx::Int) + code = code.code + return isassigned(code, idx) ? code[idx] : UNDEF +end - if isempty(used) - maxlength_idx = 0 - else - maxused = maximum(used) - maxlength_idx = length(string(maxused)) - end - if !verbose_linetable - (loc_annotations, loc_methods, loc_lineno) = compute_ir_line_annotations(code) - max_loc_width = maximum(length(str) for str in loc_annotations) - max_lineno_width = maximum(length(str) for str in loc_lineno) - max_method_width = maximum(length(str) for str in loc_methods) - end - max_depth = maximum(compute_inlining_depth(code.linetable, stmts[i][:line]) for i in 1:length(stmts.line)) - last_stack = [] - for idx in 1:length(stmts) - if !isassigned(stmts.inst, idx) - # This is invalid, but do something useful rather - # than erroring, to make debugging easier - printstyled(io, "#UNDEF\n", color=:red) - continue - end - stmt = stmts[idx] - # Compute BB guard rail - if bb_idx > length(cfg.blocks) - # Even if invariants are violated, try our best to still print - bbrange = (length(cfg.blocks) == 0 ? 1 : last(cfg.blocks[end].stmts) + 1):typemax(Int) - bb_idx_str = "!" - bb_type = "─" - else - bbrange = cfg.blocks[bb_idx].stmts - bbrange = bbrange.start:bbrange.stop - bb_idx_str = string(bb_idx) - bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" - end - bb_pad = max_bb_idx_size - length(bb_idx_str) - bb_start_str = string(bb_idx_str, " ", bb_type, "─"^bb_pad, " ") - bb_guard_rail_cont = string("│ ", " "^max_bb_idx_size) - if idx == first(bbrange) - bb_guard_rail = bb_start_str - else - bb_guard_rail = bb_guard_rail_cont - end - floop = true - # Print linetable information - if verbose_linetable - stack = compute_loc_stack(code.linetable, stmt[:line]) - # We need to print any stack frames that did not exist in the last stack - ndepth = max(1, length(stack)) - rail = string(" "^(max_depth+1-ndepth), "│"^ndepth) - start_column = cols - max_depth - 10 - for (i, x) in enumerate(stack) - if i > length(last_stack) || last_stack[i] != x - entry = code.linetable[x] - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) - print(io, bb_guard_rail) - ssa_guard = " "^(maxlength_idx + 4 + (i - 1)) - entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) " - hline = string("─"^(start_column-length(entry_label)-length(bb_guard_rail)+max_depth-i), "┐") - printstyled(io, string(entry_label, hline), "\n"; color=:light_black) - bb_guard_rail = bb_guard_rail_cont - floop = false - end - end - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) - last_stack = stack - else - if idx <= length(loc_annotations) - # N.B.: The line array length not matching is invalid, - # but let's be robust here - annotation = loc_annotations[idx] - loc_method = loc_methods[idx] - lineno = loc_lineno[idx] - else - annotation = "!" - loc_method = "" - lineno = "" - end - # Print location information right aligned. If the line below is too long, it'll overwrite this, - # but that's what we want. - if get(io, :color, false) - method_start_column = cols - max_method_width - max_loc_width - 2 - filler = " "^(max_loc_width-length(annotation)) - printstyled(io, "\e[$(method_start_column)G$(annotation)$(filler)$(loc_method)\e[1G", color = :light_black) - end - printstyled(io, lineno, " "^(max_lineno_width - length(lineno) + 1); color = :light_black) - end - idx != last(bbrange) && print(io, bb_guard_rail) - print_sep = false - if idx == last(bbrange) - print_sep = true - end - # print new nodes first in the right position - while perm_idx <= length(new_nodes_perm) - node_idx = new_nodes_perm[perm_idx] - if new_nodes_info[node_idx].pos != idx - break - end - perm_idx += 1 - if !floop && !verbose_linetable - print(io, " "^(max_lineno_width + 1)) - end - if print_sep - if idx == first(bbrange) && floop - print(io, bb_start_str) - else - print(io, "│ ", " "^max_bb_idx_size) - end - end - print_sep = true - floop = false - new_node = new_nodes[node_idx] - node_idx += length(stmts) - show_type = should_print_ssa_type(new_node[:inst]) - with_output_color(:green, io) do io′ - print_stmt(io′, node_idx, new_node[:inst], used, maxlength_idx, false, show_type) - end - if !isassigned(stmts.type, idx) # try to be robust against errors - printstyled(io, "::#UNDEF", color=:red) - elseif show_type - expr_type_printer(io, new_node[:type], node_idx in used) - end - println(io) - end - if !floop && !verbose_linetable - print(io, " "^(max_lineno_width + 1)) - end - if print_sep - if idx == first(bbrange) && floop - print(io, bb_start_str) - elseif idx == last(bbrange) - print(io, "└", "─"^(1 + max_bb_idx_size), " ") - else - print(io, "│ ", " "^max_bb_idx_size) - end - end - if idx == last(bbrange) - bb_idx += 1 - end - show_type = should_print_ssa_type(stmt[:inst]) - print_stmt(io, idx, stmt[:inst], used, maxlength_idx, true, show_type) - if !isassigned(stmts.type, idx) # try to be robust against errors - printstyled(io, "::#UNDEF", color=:red) - elseif show_type - expr_type_printer(io, stmt[:type], idx in used) +function _type(code::IRCode, idx::Int) + stmts = code.stmts + return isassigned(stmts.type, idx) ? stmts[idx][:type] : UNDEF +end +function _type(code::CodeInfo, idx::Int) + types = code.ssavaluetypes + types isa Vector{Any} || return nothing + return isassigned(types, idx) ? types[idx] : UNDEF +end + +function statement_indices_to_labels(@nospecialize(stmt), cfg::CFG) + # convert statement index to labels, as expected by print_stmt + if stmt isa Expr + if stmt.head === :enter && length(stmt.args) == 1 && stmt.args[1] isa Int + stmt = Expr(:enter, block_for_inst(cfg, stmt.args[1]::Int)) end - println(io) + elseif isa(stmt, GotoIfNot) + stmt = GotoIfNot(stmt.cond, block_for_inst(cfg, stmt.dest)) + elseif stmt isa GotoNode + stmt = GotoNode(block_for_inst(cfg, stmt.label)) + elseif stmt isa PhiNode + e = stmt.edges + stmt = PhiNode(Int32[block_for_inst(cfg, Int(e[i])) for i in 1:length(e)], stmt.values) end + return stmt end -# Show a single statement, code.code[idx], in the context of the whole CodeInfo. +# Show a single statement, code.stmts[idx]/code.code[idx], in the context of the whole IRCode/CodeInfo. # Returns the updated value of bb_idx. # line_info_preprinter(io::IO, indent::String, idx::Int) may print relevant info # at the beginning of the line, and should at least print `indent`. It returns a # string that will be printed after the final basic-block annotation. # line_info_postprinter(io::IO, typ, used::Bool) prints the type-annotation at the end # of the statement -function show_ir_stmt(io::IO, code::CodeInfo, idx::Int, line_info_preprinter, line_info_postprinter, used::BitSet, cfg::CFG, bb_idx::Int) - stmts = code.code - types = code.ssavaluetypes +# pop_new_node!(idx::Int) -> (node_idx, new_node_inst, new_node_type) may return a new +# node at the current index `idx`, which is printed before the statement at index +# `idx`. This function is repeatedly called until it returns `nothing` +function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo}, idx::Int, line_info_preprinter, line_info_postprinter, + used::BitSet, cfg::CFG, bb_idx::Int, pop_new_node! = _ -> nothing; bb_color=:light_black) + stmt = _stmt(code, idx) + type = _type(code, idx) max_bb_idx_size = length(string(length(cfg.blocks))) if isempty(used) @@ -681,69 +550,222 @@ function show_ir_stmt(io::IO, code::CodeInfo, idx::Int, line_info_preprinter, li maxlength_idx = length(string(maxused)) end - if !isassigned(stmts, idx) + if stmt === UNDEF # This is invalid, but do something useful rather # than erroring, to make debugging easier printstyled(io, "#UNDEF\n", color=:red) return bb_idx end - stmt = stmts[idx] - # Compute BB guard rail - if bb_idx > length(cfg.blocks) - # If invariants are violated, print a special leader - linestart = " "^(max_bb_idx_size + 2) # not inside a basic block bracket - inlining_indent = line_info_preprinter(io, linestart, idx) - printstyled(io, "!!! ", "─"^max_bb_idx_size, color=:light_black) - else - bbrange = cfg.blocks[bb_idx].stmts - bbrange = bbrange.start:bbrange.stop - # Print line info update - linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=:light_black), context=io) - linestart *= " "^max_bb_idx_size - inlining_indent = line_info_preprinter(io, linestart, idx) - if idx == first(bbrange) - bb_idx_str = string(bb_idx) - bb_pad = max_bb_idx_size - length(bb_idx_str) - bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" - printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=:light_black) - elseif idx == last(bbrange) # print separator - printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=:light_black) + + i = 1 + while true + next = pop_new_node!(idx) + # Compute BB guard rail + if bb_idx > length(cfg.blocks) + # If invariants are violated, print a special leader + linestart = " "^(max_bb_idx_size + 2) # not inside a basic block bracket + inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) + printstyled(io, "!!! ", "─"^max_bb_idx_size, color=bb_color) else - printstyled(io, "│ ", " "^max_bb_idx_size, color=:light_black) + bbrange = cfg.blocks[bb_idx].stmts + bbrange = bbrange.start:bbrange.stop + # Print line info update + linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=bb_color), context=io) + linestart *= " "^max_bb_idx_size + # idx == 0 means only indentation is printed, so we don't print linfos + # multiple times if the are new nodes + inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) + + if i == 1 && idx == first(bbrange) + bb_idx_str = string(bb_idx) + bb_pad = max_bb_idx_size - length(bb_idx_str) + bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" + printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=bb_color) + elseif next === nothing && idx == last(bbrange) # print separator + printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=bb_color) + else + printstyled(io, "│ ", " "^max_bb_idx_size, color=bb_color) + end end - if idx == last(bbrange) - bb_idx += 1 + print(io, inlining_indent, " ") + + if next === nothing + if bb_idx <= length(cfg.blocks) && idx == last(bbrange) + bb_idx += 1 + end + break end - end - print(io, inlining_indent, " ") - # convert statement index to labels, as expected by print_stmt - if stmt isa Expr - if stmt.head === :enter && length(stmt.args) == 1 && stmt.args[1] isa Int - stmt = Expr(:enter, block_for_inst(cfg, stmt.args[1]::Int)) + + # print new nodes first in the right position + node_idx, new_node_inst, new_node_type = next + + @assert new_node_inst !== UNDEF # we filtered these out earlier + show_type = should_print_ssa_type(new_node_inst) + with_output_color(:green, io) do io′ + print_stmt(io′, node_idx, new_node_inst, used, maxlength_idx, false, show_type) end - elseif isa(stmt, GotoIfNot) - stmt = GotoIfNot(stmt.cond, block_for_inst(cfg, stmt.dest)) - elseif stmt isa GotoNode - stmt = GotoNode(block_for_inst(cfg, stmt.label)) - elseif stmt isa PhiNode - e = stmt.edges - stmt = PhiNode(Int32[block_for_inst(cfg, Int(e[i])) for i in 1:length(e)], stmt.values) + + if new_node_type === UNDEF # try to be robust against errors + printstyled(io, "::#UNDEF", color=:red) + elseif show_type + line_info_postprinter(io, new_node_type, node_idx in used) + end + println(io) + i += 1 end - show_type = types isa Vector{Any} && should_print_ssa_type(stmt) + if code isa CodeInfo + stmt = statement_indices_to_labels(stmt, cfg) + end + show_type = type !== nothing && should_print_ssa_type(stmt) print_stmt(io, idx, stmt, used, maxlength_idx, true, show_type) - if types isa Vector{Any} # ignore types for pre-inference code - if !isassigned(types, idx) + if type !== nothing # ignore types for pre-inference code + if type === UNDEF # This is an error, but can happen if passes don't update their type information printstyled(io, "::#UNDEF", color=:red) elseif show_type - typ = types[idx] - line_info_postprinter(io, typ, idx in used) + line_info_postprinter(io, type, idx in used) end end println(io) return bb_idx end +function ircode_new_nodes_iter(code::IRCode) + stmts = code.stmts + new_nodes = code.new_nodes.stmts + new_nodes_info = code.new_nodes.info + new_nodes_perm = filter(i -> isassigned(new_nodes.inst, i), 1:length(new_nodes)) + sort!(new_nodes_perm, by = x -> (x = new_nodes_info[x]; (x.pos, x.attach_after))) + perm_idx = Ref(1) + + function (idx::Int) + perm_idx[] <= length(new_nodes_perm) || return nothing + node_idx = new_nodes_perm[perm_idx[]] + if new_nodes_info[node_idx].pos != idx + return nothing + end + perm_idx[] += 1 + new_node = new_nodes[node_idx] + new_node_inst = isassigned(new_nodes.inst, node_idx) ? new_node[:inst] : UNDEF + new_node_type = isassigned(new_nodes.type, node_idx) ? new_node[:type] : UNDEF + node_idx += length(stmts) + return node_idx, new_node_inst, new_node_type + end +end + +# corresponds to `verbose_linetable=false` +function ircode_default_linfo_printer(code::IRCode) + loc_annotations, loc_methods, loc_lineno = compute_ir_line_annotations(code) + max_loc_width = maximum(length, loc_annotations) + max_lineno_width = maximum(length, loc_lineno) + max_method_width = maximum(length, loc_methods) + + function (io::IO, indent::String, idx::Int) + cols = (displaysize(io)::Tuple{Int,Int})[2] + + if idx == 0 + annotation = "" + loc_method = "" + lineno = "" + elseif idx <= length(loc_annotations) + # N.B.: The line array length not matching is invalid, + # but let's be robust here + annotation = loc_annotations[idx] + loc_method = loc_methods[idx] + lineno = loc_lineno[idx] + else + annotation = "!" + loc_method = "" + lineno = "" + end + # Print location information right aligned. If the line below is too long, it'll overwrite this, + # but that's what we want. + if get(io, :color, false) + method_start_column = cols - max_method_width - max_loc_width - 2 + filler = " "^(max_loc_width-length(annotation)) + printstyled(io, "\e[$(method_start_column)G$(annotation)$(filler)$(loc_method)\e[1G", color = :light_black) + end + printstyled(io, lineno, " "^(max_lineno_width - length(lineno) + 1); color = :light_black) + return "" + end +end + +_strip_color(s::String) = replace(s, r"\e\[\d+m" => "") + +# corresponds to `verbose_linetable=true` +function ircode_verbose_linfo_printer(code::IRCode, used::BitSet) + stmts = code.stmts + max_depth = maximum(compute_inlining_depth(code.linetable, stmts[i][:line]) for i in 1:length(stmts.line)) + last_stack = Ref(Int[]) + maxlength_idx = if isempty(used) + 0 + else + maxused = maximum(used) + length(string(maxused)) + end + + function (io::IO, indent::String, idx::Int) + idx == 0 && return "" + cols = (displaysize(io)::Tuple{Int,Int})[2] + stmt = stmts[idx] + + stack = compute_loc_stack(code.linetable, stmt[:line]) + # We need to print any stack frames that did not exist in the last stack + ndepth = max(1, length(stack)) + rail = string(" "^(max_depth+1-ndepth), "│"^ndepth) + start_column = cols - max_depth - 10 + for (i, x) in enumerate(stack) + if i > length(last_stack[]) || last_stack[][i] != x + entry = code.linetable[x] + printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) + print(io, indent) + ssa_guard = " "^(maxlength_idx + 4 + i) + entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) " + hline = string("─"^(start_column-length(entry_label)-length(_strip_color(indent))+max_depth-i), "┐") + printstyled(io, string(entry_label, hline), "\n"; color=:light_black) + end + end + last_stack[] = stack + printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) + return "" + end +end + +function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_printer; verbose_linetable=false) + stmts = code.stmts + isempty(stmts) && return # unlikely, but avoid errors from reducing over empty sets + used = BitSet() + cfg = code.cfg + for stmt in stmts + scan_ssa_use!(push!, used, stmt[:inst]) + end + new_nodes = code.new_nodes.stmts + warn_unset_entry = true + for nn in 1:length(new_nodes) + if isassigned(new_nodes.inst, nn) + scan_ssa_use!(push!, used, new_nodes[nn][:inst]) + elseif warn_unset_entry + printstyled(io, "ERROR: New node array has unset entry\n", color=:red) + warn_unset_entry = false + end + end + bb_idx = 1 + + pop_new_node! = ircode_new_nodes_iter(code) + + if verbose_linetable + line_info_preprinter = ircode_verbose_linfo_printer(code, used) + else + line_info_preprinter = ircode_default_linfo_printer(code) + end + + for idx in 1:length(stmts) + bb_idx = show_ir_stmt(io, code, idx, line_info_preprinter, expr_type_printer, + used, cfg, bb_idx, pop_new_node!; bb_color=:normal) + end + nothing +end + function statementidx_lineinfo_printer(f, code::CodeInfo) printer = f(code.linetable) return (io::IO, indent::String, idx::Int) -> printer(io, indent, idx > 0 ? code.codelocs[idx] : typemin(Int32)) diff --git a/test/show.jl b/test/show.jl index 51e6abca85f9b..dccbe1eee603e 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1906,7 +1906,7 @@ let src = code_typed(gcd, (Int, Int), debuginfo=:source)[1][1] push!(ir.stmts.inst, Core.Compiler.ReturnNode()) lines = split(sprint(show, ir), '\n') @test isempty(pop!(lines)) - @test pop!(lines) == " ! ── unreachable::#UNDEF" + @test pop!(lines) == " !!! ── unreachable::#UNDEF" end @testset "printing and interpolating nothing" begin From 619fd24f585f4f58af050c77073a50a2c97ab5ab Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 30 Mar 2021 19:50:36 -0400 Subject: [PATCH 052/439] Revert "[Libdl] Use RTLD_NOLOAD when calling dlpath(::String) (#39676)" (#40271) This reverts commit 514426d3fd2723c6ddfc33444bfc23891c55454d. --- base/libdl.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/libdl.jl b/base/libdl.jl index 9f37eb2034007..4f29260bb24f8 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -237,9 +237,10 @@ julia> dlpath("libjulia") ``` """ function dlpath(libname::Union{AbstractString, Symbol}) - dlopen(libname, RTLD_NOLOAD) do handle - return dlpath(handle) - end + handle = dlopen(libname) + path = dlpath(handle) + dlclose(handle) + return path end if Sys.isapple() From a5758aad30717ae2a71d83718e67579f30e805f6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 30 Mar 2021 22:00:15 -0400 Subject: [PATCH 053/439] make it possible to serialize SnoopCompile results (#39695) - use `nothing` instead of NULL as a sentinel in specializations - remove some Serializer restrictions around saving Methods --- src/dump.c | 2 +- src/gf.c | 17 +++++++++-------- src/precompile.c | 6 +++--- stdlib/Serialization/src/Serialization.jl | 22 ++++++++++++---------- test/worlds.jl | 4 ++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/dump.c b/src/dump.c index 484c31a93bac6..2a6c8318c2095 100644 --- a/src/dump.c +++ b/src/dump.c @@ -910,7 +910,7 @@ static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) size_t i, l = jl_svec_len(specializations); for (i = 0; i < l; i++) { jl_method_instance_t *callee = (jl_method_instance_t*)jl_svecref(specializations, i); - if (callee != NULL) + if ((jl_value_t*)callee != jl_nothing) collect_backedges(callee); } } diff --git a/src/gf.c b/src/gf.c index f90d0e49fc8ca..71c9c9f05f9ad 100644 --- a/src/gf.c +++ b/src/gf.c @@ -122,7 +122,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m J JL_GC_PUSH1(&specializations); // clang-sa doesn't realize this loop uses specializations for (i = cl; i > 0; i--) { jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i - 1]); - if (mi == NULL) + if ((jl_value_t*)mi == jl_nothing) break; if (jl_types_equal(mi->specTypes, type)) { if (locked) @@ -143,19 +143,20 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m J jl_method_instance_t **data = (jl_method_instance_t**)jl_svec_data(specializations); for (i = 0; i < cl; i++) { jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i]); - if (mi == NULL) + if ((jl_value_t*)mi == jl_nothing) break; assert(!jl_types_equal(mi->specTypes, type)); } } jl_method_instance_t *mi = jl_get_specialized(m, type, sparams); JL_GC_PUSH1(&mi); - if (hv ? (i + 1 >= cl || jl_svecref(specializations, i + 1) != NULL) : (i <= 1 || jl_svecref(specializations, i - 2) != NULL)) { + if (hv ? (i + 1 >= cl || jl_svecref(specializations, i + 1) != jl_nothing) : (i <= 1 || jl_svecref(specializations, i - 2) != jl_nothing)) { size_t ncl = cl < 8 ? 8 : (cl*3)>>1; jl_svec_t *nc = jl_alloc_svec_uninit(ncl); if (i > 0) memcpy((char*)jl_svec_data(nc), jl_svec_data(specializations), sizeof(void*) * i); - memset((char*)jl_svec_data(nc) + sizeof(void*) * i, 0, sizeof(void*) * (ncl - cl)); + for (int j = 0; j < ncl - cl; j++) + jl_svecset(nc, j+i, jl_nothing); if (i < cl) memcpy((char*)jl_svec_data(nc) + sizeof(void*) * (i + ncl - cl), (char*)jl_svec_data(specializations) + sizeof(void*) * i, @@ -168,7 +169,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m J } if (!hv) i -= 1; - assert(jl_svecref(specializations, i) == NULL); + assert(jl_svecref(specializations, i) == jl_nothing); jl_svecset(specializations, i, mi); // jl_atomic_store_release? if (hv) { // TODO: fuse lookup and insert steps? @@ -413,7 +414,7 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) size_t i, l = jl_svec_len(specializations); for (i = 0; i < l; i++) { jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); - if (mi) { + if ((jl_value_t*)mi != jl_nothing) { assert(jl_is_method_instance(mi)); if (jl_rettype_inferred(mi, jl_world_counter, jl_world_counter) == jl_nothing) jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi); @@ -1561,7 +1562,7 @@ static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *m l = jl_svec_len(specializations); for (i = 0; i < l; i++) { jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); - if (mi) { + if ((jl_value_t*)mi != jl_nothing) { invalidated = 1; invalidate_external(mi, methodentry->max_world); invalidate_backedges(mi, methodentry->max_world, "jl_method_table_disable"); @@ -1728,7 +1729,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method enum morespec_options ambig = morespec_unknown; for (i = 0; i < l; i++) { jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i]); - if (mi == NULL) + if ((jl_value_t*)mi == jl_nothing) continue; isect3 = jl_type_intersection(m->sig, (jl_value_t*)mi->specTypes); if (jl_type_intersection2(type, isect3, &isect, &isect2)) { diff --git a/src/precompile.c b/src/precompile.c index 886a0677b1899..9f6fa1a79e8a6 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -353,9 +353,9 @@ static int precompile_enq_all_specializations__(jl_typemap_entry_t *def, void *c jl_svec_t *specializations = def->func.method->specializations; size_t i, l = jl_svec_len(specializations); for (i = 0; i < l; i++) { - jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); - if (mi != NULL) - precompile_enq_specialization_(mi, closure); + jl_value_t *mi = jl_svecref(specializations, i); + if (mi != jl_nothing) + precompile_enq_specialization_((jl_method_instance_t*)mi, closure); } } if (m->ccallable) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index bee52a72f7798..cb3dc6a38600a 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -425,7 +425,7 @@ function serialize(s::AbstractSerializer, meth::Method) serialize(s, nothing) end if isdefined(meth, :generator) - serialize(s, Base._uncompressed_ast(meth, meth.generator.inferred)) # XXX: what was this supposed to do? + serialize(s, meth.generator) else serialize(s, nothing) end @@ -439,9 +439,12 @@ end function serialize(s::AbstractSerializer, linfo::Core.MethodInstance) serialize_cycle(s, linfo) && return - isa(linfo.def, Module) || error("can only serialize toplevel MethodInstance objects") writetag(s.io, METHODINSTANCE_TAG) - serialize(s, linfo.uninferred) + if isdefined(linfo, :uninferred) + serialize(s, linfo.uninferred) + else + writetag(s.io, UNDEFREF_TAG) + end serialize(s, nothing) # for backwards compat serialize(s, linfo.sparam_vals) serialize(s, Any) # for backwards compat @@ -1036,11 +1039,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) end meth.slot_syms = slot_syms if generator !== nothing - linfo = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()) - linfo.specTypes = Tuple - linfo.inferred = generator - linfo.def = meth - meth.generator = linfo + meth.generator = generator end if recursion_relation !== nothing meth.recursion_relation = recursion_relation @@ -1059,7 +1058,10 @@ end function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance}) linfo = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, (Ptr{Cvoid},), C_NULL) deserialize_cycle(s, linfo) - linfo.uninferred = deserialize(s)::CodeInfo + tag = Int32(read(s.io, UInt8)::UInt8) + if tag != UNDEFREF_TAG + linfo.uninferred = handle_deserialize(s, tag)::CodeInfo + end tag = Int32(read(s.io, UInt8)::UInt8) if tag != UNDEFREF_TAG # for reading files prior to v1.2 @@ -1068,7 +1070,7 @@ function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance}) linfo.sparam_vals = deserialize(s)::SimpleVector _rettype = deserialize(s) # for backwards compat linfo.specTypes = deserialize(s) - linfo.def = deserialize(s)::Module + linfo.def = deserialize(s) return linfo end diff --git a/test/worlds.jl b/test/worlds.jl index 692f4febd91cd..2b4f575e1905a 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -219,8 +219,8 @@ function instance(f, types) if isa(specs, Nothing) elseif isa(specs, Core.SimpleVector) for i = 1:length(specs) - if isassigned(specs, i) - mi = specs[i]::Core.MethodInstance + mi = specs[i] + if mi isa Core.MethodInstance if mi.specTypes <: tt && tt <: mi.specTypes inst = mi break From c0f8aef3bfcf59699ee0f4db46f183fcd8dde0c1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 31 Mar 2021 01:13:14 -0400 Subject: [PATCH 054/439] add stack-probes to make stack-overflow detection more reliable (#40068) Supported platforms are currently X86, PowerPC, and SystemZ. Fixes #25523 Fixes #36170 Closes #28577 Closes #30892 --- src/codegen.cpp | 35 +++++++++++++++-------------------- test/llvmpasses/noinline.jl | 2 +- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f0edf7b19fa29..b3acb943b3150 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1719,6 +1719,14 @@ static void jl_init_function(Function *F) F->addFnAttr("no-frame-pointer-elim", "true"); #endif #endif +#if JL_LLVM_VERSION >= 110000 && !defined(JL_ASAN_ENABLED) && !defined(_OS_WINDOWS_) + // ASAN won't like us accessing undefined memory causing spurious issues, + // and Windows has platform-specific handling which causes it to mishandle + // this annotation. Other platforms should just ignore this if they don't + // implement it. + F->addFnAttr("probe-stack", "inline-asm"); + //F->addFnAttr("stack-probe-size", 4096); // can use this to change the default +#endif } static std::pair uses_specsig(jl_method_instance_t *lam, jl_value_t *rettype, bool prefer_specsig) @@ -6297,20 +6305,7 @@ static std::pair, jl_llvm_functions_t> } } - /* - // step 6. (optional) check for stack overflow (the slower way) - Value *cur_sp = - ctx.builder.CreateCall(Intrinsic::getDeclaration(M, - Intrinsic::frameaddress), - ConstantInt::get(T_int32, 0)); - Value *sp_ok = - ctx.builder.CreateICmpUGT(cur_sp, - ConstantInt::get(T_size, - (uptrint_t)jl_stack_lo)); - error_unless(ctx, sp_ok, "stack overflow"); - */ - - // step 7. set up GC frame + // step 6. set up GC frame allocate_gc_frame(ctx, b0); Value *last_age = NULL; emit_last_age_field(ctx); @@ -6318,7 +6313,7 @@ static std::pair, jl_llvm_functions_t> last_age = tbaa_decorate(tbaa_gcframe, ctx.builder.CreateAlignedLoad(ctx.world_age_field, Align(sizeof(size_t)))); } - // step 8. allocate local variables slots + // step 7. allocate local variables slots // must be in the first basic block for the llvm mem2reg pass to work auto allocate_local = [&](jl_varinfo_t &varinfo, jl_sym_t *s) { jl_value_t *jt = varinfo.value.typ; @@ -6436,7 +6431,7 @@ static std::pair, jl_llvm_functions_t> } } - // step 9. move args into local variables + // step 8. move args into local variables Function::arg_iterator AI = f->arg_begin(); auto get_specsig_arg = [&](jl_value_t *argType, Type *llvmArgType, bool isboxed) { @@ -6566,7 +6561,7 @@ static std::pair, jl_llvm_functions_t> } } - // step 10. allocate rest argument + // step 9. allocate rest argument CallInst *restTuple = NULL; if (va && ctx.vaSlot != -1) { jl_varinfo_t &vi = ctx.slots[ctx.vaSlot]; @@ -6608,7 +6603,7 @@ static std::pair, jl_llvm_functions_t> } } - // step 11. Compute properties for each statements + // step 10. Compute properties for each statements // This needs to be computed by iterating in the IR order // instead of control flow order. auto in_user_mod = [] (jl_module_t *mod) { @@ -6730,7 +6725,7 @@ static std::pair, jl_llvm_functions_t> Instruction &prologue_end = ctx.builder.GetInsertBlock()->back(); - // step 12. Do codegen in control flow order + // step 11. Do codegen in control flow order std::vector workstack; std::map BB; std::map come_from_bb; @@ -7288,7 +7283,7 @@ static std::pair, jl_llvm_functions_t> PN->eraseFromParent(); } - // step 13. Perform any delayed instantiations + // step 12. Perform any delayed instantiations if (ctx.debug_enabled) { bool in_prologue = true; for (auto &BB : *ctx.f) { diff --git a/test/llvmpasses/noinline.jl b/test/llvmpasses/noinline.jl index f542968b21979..c4aa22bf80a71 100644 --- a/test/llvmpasses/noinline.jl +++ b/test/llvmpasses/noinline.jl @@ -17,5 +17,5 @@ include(joinpath("..", "testhelpers", "llvmpasses.jl")) return A + B end -# CHECK: attributes #{{[0-9]+}} = {{{([a-z]+ )*}} noinline {{([a-z]+ )*}}} +# CHECK: attributes #{{[0-9]+}} = {{{[^}]*}} noinline {{[^}]*}}} emit(simple_noinline, Float64, Float64) From a52b43d04e7e5044d78858d7e8a374b1f181f138 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 31 Mar 2021 18:30:39 +0200 Subject: [PATCH 055/439] exempt begin and underscore from macro hygiene (#40280) --- src/macroexpand.scm | 2 +- test/syntax.jl | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 882fe88a2e648..a0f05a3af687a 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -324,7 +324,7 @@ m parent-scope inarg)) (define (resolve-expansion-vars- e env m parent-scope inarg) - (cond ((or (eq? e 'end) (eq? e 'ccall) (eq? e 'cglobal)) + (cond ((or (eq? e 'begin) (eq? e 'end) (eq? e 'ccall) (eq? e 'cglobal) (underscore-symbol? e)) e) ((symbol? e) (let ((a (assq e env))) diff --git a/test/syntax.jl b/test/syntax.jl index d97f5aeb251c8..ecb1a0e642424 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2751,3 +2751,15 @@ end @test eval(:(x = $(QuoteNode(Core.SlotNumber(1))))) == Core.SlotNumber(1) @test_throws ErrorException("syntax: SSAValue objects should not occur in an AST") eval(:(x = $(Core.SSAValue(1)))) @test_throws ErrorException("syntax: Slot objects should not occur in an AST") eval(:(x = $(Core.SlotNumber(1)))) + +macro m_underscore_hygiene() + return :(_ = 1) +end + +@test @macroexpand(@m_underscore_hygiene()) == :(_ = 1) + +macro m_begin_hygiene(a) + return :($(esc(a))[begin]) +end + +@test @m_begin_hygiene([1, 2, 3]) == 1 From 8868d3fb15eed14de477c9d77b24e40e05219c07 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 31 Mar 2021 14:00:55 -0400 Subject: [PATCH 056/439] Add aliasscope expr to interpreter (#40275) --- src/interpreter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/interpreter.c b/src/interpreter.c index 5401cec75932f..008886f1c99c9 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -302,7 +302,8 @@ static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) else if (head == boundscheck_sym) { return jl_true; } - else if (head == meta_sym || head == coverageeffect_sym || head == inbounds_sym || head == loopinfo_sym) { + else if (head == meta_sym || head == coverageeffect_sym || head == inbounds_sym || head == loopinfo_sym || + head == aliasscope_sym || head == popaliasscope_sym) { return jl_nothing; } else if (head == gc_preserve_begin_sym || head == gc_preserve_end_sym) { From 637f52b8eb836bda45bdb282ff3dd3d347bef439 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 31 Mar 2021 23:10:08 +0200 Subject: [PATCH 057/439] fix #40258: nested string interpolation (#40261) * fix #40258: nested string interpolation fixes #40258 * fix interpolation with varargs * add additional test case * add additional test cases Co-authored-by: Nathan Daly * keep previous behavior, don't try to be too smart Co-authored-by: Nathan Daly Co-authored-by: Jeff Bezanson --- src/julia-syntax.scm | 11 ++++++----- test/syntax.jl | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 6dfe3c514c75d..aeb6ba49ea34f 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2384,11 +2384,12 @@ 'string (lambda (e) (expand-forms - `(call (top string) ,@(map (lambda (s) - (if (and (pair? s) (eq? (car s) 'string)) - (cadr s) - s)) - (cdr e))))) + `(call (top string) + ,@(map (lambda (s) + (if (and (length= s 2) (eq? (car s) 'string) (string? (cadr s))) + (cadr s) + s)) + (cdr e))))) '|::| (lambda (e) diff --git a/test/syntax.jl b/test/syntax.jl index ecb1a0e642424..aeaefdcbc832e 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2763,3 +2763,11 @@ macro m_begin_hygiene(a) end @test @m_begin_hygiene([1, 2, 3]) == 1 + +# issue 40258 +@test "a $("b $("c")")" == "a b c" + +@test "$(([[:a, :b], [:c, :d]]...)...)" == "abcd" + +@test eval(Expr(:string, "a", Expr(:string, "b", "c"))) == "abc" +@test eval(Expr(:string, "a", Expr(:string, "b", Expr(:string, "c")))) == "abc" From 13caa8abf2320ea7e6f7255adf3477cbd6096e87 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Thu, 1 Apr 2021 00:01:15 +0000 Subject: [PATCH 058/439] fix docstrings on `first` and `last` (#40278) --- base/abstractarray.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 4bc3c4f70ebb4..724b23c6e8ca3 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -391,7 +391,7 @@ end """ first(itr, n::Integer) -Get the first `n` elements of the iterable collection `itr`, or fewer elements if `v` is not +Get the first `n` elements of the iterable collection `itr`, or fewer elements if `itr` is not long enough. !!! compat "Julia 1.6" @@ -439,7 +439,7 @@ last(a) = a[end] """ last(itr, n::Integer) -Get the last `n` elements of the iterable collection `itr`, or fewer elements if `v` is not +Get the last `n` elements of the iterable collection `itr`, or fewer elements if `itr` is not long enough. !!! compat "Julia 1.6" From 80002db74c88fae5803688e930cd77ce0567c355 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 1 Apr 2021 15:01:16 +0200 Subject: [PATCH 059/439] add a missing propagate_inbounds to a getindex method (#40281) * add a missing propagate_inbounds --- base/abstractarray.jl | 2 +- test/boundscheck_exec.jl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 724b23c6e8ca3..47d6655991000 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1170,7 +1170,7 @@ function getindex(A::AbstractArray, I...) _getindex(IndexStyle(A), A, to_indices(A, I)...) end # To avoid invalidations from multidimensional.jl: getindex(A::Array, i1::Union{Integer, CartesianIndex}, I::Union{Integer, CartesianIndex}...) -getindex(A::Array, i1::Integer, I::Integer...) = A[to_indices(A, (i1, I...))...] +@propagate_inbounds getindex(A::Array, i1::Integer, I::Integer...) = A[to_indices(A, (i1, I...))...] function unsafe_getindex(A::AbstractArray, I...) @_inline_meta diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index 62a20921bd44e..e1a7029334a3d 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -251,5 +251,12 @@ if bc_opt == bc_default || bc_opt == bc_off @test occursin("vector.body", sprint(code_llvm, g27079, Tuple{Vector{Int}})) end +# Boundschecking removal of indices with different type, see #40281 +getindex_40281(v, a, b, c) = @inbounds getindex(v, a, b, c) +typed_40281 = sprint((io, args...) -> code_warntype(io, args...; optimize=true), getindex_40281, Tuple{Array{Float64, 3}, Int, UInt8, Int}) +if bc_opt == bc_default || bc_opt == bc_off + @test occursin("arrayref(false", typed_40281) + @test !occursin("arrayref(true", typed_40281) +end end From b2a586ef25c0dce47d8425b15d69c05300760800 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Thu, 1 Apr 2021 19:07:43 +0200 Subject: [PATCH 060/439] add Returns (#39794) --- NEWS.md | 1 + base/abstractarray.jl | 8 +++--- base/abstractarraymath.jl | 8 +++--- base/array.jl | 2 +- base/dict.jl | 2 +- base/env.jl | 2 +- base/exports.jl | 1 + base/multidimensional.jl | 12 ++++----- base/operators.jl | 36 ++++++++++++++++++++++++++ base/reshapedarray.jl | 2 +- base/show.jl | 1 + test/abstractarray.jl | 16 ++++++------ test/arrayops.jl | 24 ++++++++--------- test/bitarray.jl | 54 ++++++++++++++++++++------------------- test/ccall.jl | 2 +- test/channels.jl | 4 +-- test/core.jl | 8 +++--- test/generic_map_tests.jl | 2 +- test/iterators.jl | 10 ++++---- test/offsetarray.jl | 2 +- test/operators.jl | 14 ++++++++++ test/reduce.jl | 4 +-- test/show.jl | 2 +- test/subarray.jl | 8 +++--- test/tuple.jl | 2 +- 25 files changed, 141 insertions(+), 86 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0cf30ffdd0e2e..e9043bbebd4f4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -35,6 +35,7 @@ New library functions * Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]). * `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`. * New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971]) +* New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438]) New library features diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 47d6655991000..c59c20a10c37f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1604,7 +1604,7 @@ _cat_size_shape(dims, shape) = shape _cshp(ndim::Int, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () _cshp(ndim::Int, ::Tuple{}, ::Tuple{}, nshape) = nshape -_cshp(ndim::Int, dims, ::Tuple{}, ::Tuple{}) = ntuple(b -> 1, Val(length(dims))) +_cshp(ndim::Int, dims, ::Tuple{}, ::Tuple{}) = ntuple(Returns(1), Val(length(dims))) @inline _cshp(ndim::Int, dims, shape, ::Tuple{}) = (shape[1] + dims[1], _cshp(ndim + 1, tail(dims), tail(shape), ())...) @inline _cshp(ndim::Int, dims, ::Tuple{}, nshape) = @@ -1810,7 +1810,7 @@ function hvcat(nbc::Integer, as...) mod(n,nbc) != 0 && throw(ArgumentError("number of arrays $n is not a multiple of the requested number of block columns $nbc")) nbr = div(n,nbc) - hvcat(ntuple(i->nbc, nbr), as...) + hvcat(ntuple(Returns(nbc), nbr), as...) end """ @@ -2238,9 +2238,9 @@ function mapslices(f, A::AbstractArray; dims) end nextra = max(0, length(dims)-ndims(r1)) if eltype(Rsize) == Int - Rsize[dims] = [size(r1)..., ntuple(d->1, nextra)...] + Rsize[dims] = [size(r1)..., ntuple(Returns(1), nextra)...] else - Rsize[dims] = [axes(r1)..., ntuple(d->OneTo(1), nextra)...] + Rsize[dims] = [axes(r1)..., ntuple(Returns(OneTo(1)), nextra)...] end R = similar(r1, tuple(Rsize...,)) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 953c190ab12ef..7e88baaa0d840 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -123,7 +123,7 @@ julia> selectdim(A, 2, 3) @noinline function _selectdim(A, d, i, idxs) d >= 1 || throw(ArgumentError("dimension must be ≥ 1, got $d")) nd = ndims(A) - d > nd && (i == 1 || throw(BoundsError(A, (ntuple(k->Colon(),d-1)..., i)))) + d > nd && (i == 1 || throw(BoundsError(A, (ntuple(Returns(Colon()),d-1)..., i)))) return view(A, idxs...) end @@ -225,7 +225,7 @@ function repeat(A::AbstractArray, counts...) end """ - repeat(A::AbstractArray; inner=ntuple(x->1, ndims(A)), outer=ntuple(x->1, ndims(A))) + repeat(A::AbstractArray; inner=ntuple(Returns(1), ndims(A)), outer=ntuple(Returns(1), ndims(A))) Construct an array by repeating the entries of `A`. The i-th element of `inner` specifies the number of times that the individual entries of the i-th dimension of `A` should be @@ -491,7 +491,7 @@ julia> collect(eachslice(M, dims=2)) length(dims) == 1 || throw(ArgumentError("only single dimensions are supported")) dim = first(dims) dim <= ndims(A) || throw(DimensionMismatch("A doesn't have $dim dimensions")) - inds_before = ntuple(d->(:), dim-1) - inds_after = ntuple(d->(:), ndims(A)-dim) + inds_before = ntuple(Returns(:), dim-1) + inds_after = ntuple(Returns(:), ndims(A)-dim) return (view(A, inds_before..., i, inds_after...) for i in axes(A, dim)) end diff --git a/base/array.jl b/base/array.jl index e680d035897be..afaa3b5f19d6b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1734,7 +1734,7 @@ function vcat(arrays::Vector{T}...) where T return arr end -_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(x->1, n-1)..., length(x))) +_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(Returns(1), n-1)..., length(x))) ## find ## diff --git a/base/dict.jl b/base/dict.jl index cc5c9efb6ada8..1c176a2eab864 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -797,7 +797,7 @@ function iterate(d::ImmutableDict{K,V}, t=d) where {K, V} !isdefined(t, :parent) && return nothing (Pair{K,V}(t.key, t.value), t.parent) end -length(t::ImmutableDict) = count(x->true, t) +length(t::ImmutableDict) = count(Returns(true), t) isempty(t::ImmutableDict) = !isdefined(t, :parent) empty(::ImmutableDict, ::Type{K}, ::Type{V}) where {K, V} = ImmutableDict{K,V}() diff --git a/base/env.jl b/base/env.jl index 8f5256f25915e..b87d00670e772 100644 --- a/base/env.jl +++ b/base/env.jl @@ -77,7 +77,7 @@ variable may result in an uppercase `ENV` key.) const ENV = EnvDict() getindex(::EnvDict, k::AbstractString) = access_env(k->throw(KeyError(k)), k) -get(::EnvDict, k::AbstractString, def) = access_env(k->def, k) +get(::EnvDict, k::AbstractString, def) = access_env(Returns(def), k) get(f::Callable, ::EnvDict, k::AbstractString) = access_env(k->f(), k) in(k::AbstractString, ::KeySet{String, EnvDict}) = _hasenv(k) pop!(::EnvDict, k::AbstractString) = (v = ENV[k]; _unsetenv(k); v) diff --git a/base/exports.jl b/base/exports.jl index adfb1772600d3..39eaca645d0b2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -70,6 +70,7 @@ export Rational, Regex, RegexMatch, + Returns, RoundFromZero, RoundDown, RoundingMode, diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 9acb97a486fbb..7b41476d8d17d 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -104,9 +104,9 @@ module IteratorsMD # zeros and ones zero(::CartesianIndex{N}) where {N} = zero(CartesianIndex{N}) - zero(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 0, Val(N))) + zero(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(Returns(0), Val(N))) oneunit(::CartesianIndex{N}) where {N} = oneunit(CartesianIndex{N}) - oneunit(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 1, Val(N))) + oneunit(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(Returns(1), Val(N))) # arithmetic, min/max @inline (-)(index::CartesianIndex{N}) where {N} = @@ -458,7 +458,7 @@ module IteratorsMD # Split out the first N elements of a tuple @inline function split(t, V::Val) - ref = ntuple(d->true, V) # create a reference tuple of length N + ref = ntuple(Returns(true), V) # create a reference tuple of length N _split1(t, ref), _splitrest(t, ref) end @inline _split1(t, ref) = (t[1], _split1(tail(t), tail(ref))...) @@ -685,10 +685,10 @@ checkindex(::Type{Bool}, inds::Tuple, I::CartesianIndices) = all(checkindex.(Boo # rather than returning N, it returns an NTuple{N,Bool} so the result is inferrable @inline index_ndims(i1, I...) = (true, index_ndims(I...)...) @inline function index_ndims(i1::CartesianIndex, I...) - (map(x->true, i1.I)..., index_ndims(I...)...) + (map(Returns(true), i1.I)..., index_ndims(I...)...) end @inline function index_ndims(i1::AbstractArray{CartesianIndex{N}}, I...) where N - (ntuple(x->true, Val(N))..., index_ndims(I...)...) + (ntuple(Returns(true), Val(N))..., index_ndims(I...)...) end index_ndims() = () @@ -698,7 +698,7 @@ index_ndims() = () @inline index_dimsum(::Colon, I...) = (true, index_dimsum(I...)...) @inline index_dimsum(::AbstractArray{Bool}, I...) = (true, index_dimsum(I...)...) @inline function index_dimsum(::AbstractArray{<:Any,N}, I...) where N - (ntuple(x->true, Val(N))..., index_dimsum(I...)...) + (ntuple(Returns(true), Val(N))..., index_dimsum(I...)...) end index_dimsum() = () diff --git a/base/operators.jl b/base/operators.jl index 8b91657fda201..3153342d6c9d0 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -916,6 +916,42 @@ julia> [1:5;] |> x->x.^2 |> sum |> inv """ |>(x, f) = f(x) +""" + f = Returns(value) + +Create a callable `f` such that `f(args...; kw...) === value` holds. + +# Examples + +```jldoctest +julia> f = Returns(42); + +julia> f(1) +42 + +julia> f("hello", x=32) +42 + +julia> f.value +42 +``` + +!!! compat "Julia 1.7" + Returns requires at least Julia 1.7. +""" +struct Returns{V} <: Function + value::V + Returns{V}(value) where {V} = new{V}(value) + Returns(value) = new{Core.Typeof(value)}(value) +end + +(obj::Returns)(args...; kw...) = obj.value +function show(io::IO, obj::Returns) + show(io, typeof(obj)) + print(io, "(") + show(io, obj.value) + print(io, ")") +end # function composition """ diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index d9a9f4eafaa80..671dd2d86a840 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -146,7 +146,7 @@ end # product of trailing dims into the last element rdims_trailing(l, inds...) = length(l) * rdims_trailing(inds...) rdims_trailing(l) = length(l) -rdims(out::Val{N}, inds::Tuple) where {N} = rdims(ntuple(i -> OneTo(1), Val(N)), inds) +rdims(out::Val{N}, inds::Tuple) where {N} = rdims(ntuple(Returns(OneTo(1)), Val(N)), inds) rdims(out::Tuple{}, inds::Tuple{}) = () # N == 0, M == 0 rdims(out::Tuple{}, inds::Tuple{Any}) = () rdims(out::Tuple{}, inds::NTuple{M,Any}) where {M} = () diff --git a/base/show.jl b/base/show.jl index 89a2fdef11ec9..d16bb499ee16f 100644 --- a/base/show.jl +++ b/base/show.jl @@ -45,6 +45,7 @@ function show(io::IO, ::MIME"text/plain", f::Function) end show(io::IO, ::MIME"text/plain", c::ComposedFunction) = show(io, c) +show(io::IO, ::MIME"text/plain", c::Returns) = show(io, c) function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator}) isempty(iter) && get(io, :compact, false) && return show(io, iter) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index dd24dc28364c7..539af360bae2a 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -299,10 +299,10 @@ function test_scalar_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where B = T(A) @test A == B # Test indexing up to 5 dimensions - trailing5 = CartesianIndex(ntuple(x->1, max(ndims(B)-5, 0))) - trailing4 = CartesianIndex(ntuple(x->1, max(ndims(B)-4, 0))) - trailing3 = CartesianIndex(ntuple(x->1, max(ndims(B)-3, 0))) - trailing2 = CartesianIndex(ntuple(x->1, max(ndims(B)-2, 0))) + trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0))) + trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0))) + trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0))) + trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0))) i=0 for i5 = 1:size(B, 5) for i4 = 1:size(B, 4) @@ -419,10 +419,10 @@ function test_vector_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where N = prod(shape) A = reshape(Vector(1:N), shape) B = T(A) - trailing5 = CartesianIndex(ntuple(x->1, max(ndims(B)-5, 0))) - trailing4 = CartesianIndex(ntuple(x->1, max(ndims(B)-4, 0))) - trailing3 = CartesianIndex(ntuple(x->1, max(ndims(B)-3, 0))) - trailing2 = CartesianIndex(ntuple(x->1, max(ndims(B)-2, 0))) + trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0))) + trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0))) + trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0))) + trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0))) idxs = rand(1:N, 3, 3, 3) @test B[idxs] == A[idxs] == idxs @test B[vec(idxs)] == A[vec(idxs)] == vec(idxs) diff --git a/test/arrayops.jl b/test/arrayops.jl index 7ea2cf15d812d..80a37c9d2f26a 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1153,17 +1153,17 @@ end # issue #5177 c = fill(1,2,3,4) - m1 = mapslices(x-> fill(1,2,3), c, dims=[1,2]) - m2 = mapslices(x-> fill(1,2,4), c, dims=[1,3]) - m3 = mapslices(x-> fill(1,3,4), c, dims=[2,3]) + m1 = mapslices(_ -> fill(1,2,3), c, dims=[1,2]) + m2 = mapslices(_ -> fill(1,2,4), c, dims=[1,3]) + m3 = mapslices(_ -> fill(1,3,4), c, dims=[2,3]) @test size(m1) == size(m2) == size(m3) == size(c) - n1 = mapslices(x-> fill(1,6), c, dims=[1,2]) - n2 = mapslices(x-> fill(1,6), c, dims=[1,3]) - n3 = mapslices(x-> fill(1,6), c, dims=[2,3]) - n1a = mapslices(x-> fill(1,1,6), c, dims=[1,2]) - n2a = mapslices(x-> fill(1,1,6), c, dims=[1,3]) - n3a = mapslices(x-> fill(1,1,6), c, dims=[2,3]) + n1 = mapslices(_ -> fill(1,6) , c, dims=[1,2]) + n2 = mapslices(_ -> fill(1,6) , c, dims=[1,3]) + n3 = mapslices(_ -> fill(1,6) , c, dims=[2,3]) + n1a = mapslices(_ -> fill(1,1,6), c, dims=[1,2]) + n2a = mapslices(_ -> fill(1,1,6), c, dims=[1,3]) + n3a = mapslices(_ -> fill(1,1,6), c, dims=[2,3]) @test size(n1a) == (1,6,4) && size(n2a) == (1,3,6) && size(n3a) == (2,1,6) @test size(n1) == (6,1,4) && size(n2) == (6,3,1) && size(n3) == (2,6,1) @@ -1659,7 +1659,7 @@ end Nmax = 3 # TODO: go up to CARTESIAN_DIMS+2 (currently this exposes problems) for N = 1:Nmax #indexing with (UnitRange, UnitRange, UnitRange) - args = ntuple(d->UnitRange{Int}, N) + args = ntuple(Returns(UnitRange{Int}), N) @test Base.return_types(getindex, Tuple{Array{Float32, N}, args...}) == [Array{Float32, N}] @test Base.return_types(getindex, Tuple{BitArray{N}, args...}) == Any[BitArray{N}] @test Base.return_types(setindex!, Tuple{Array{Float32, N}, Array{Int, 1}, args...}) == [Array{Float32, N}] @@ -1786,7 +1786,7 @@ end @test mdsum(A) == 15 @test mdsum2(A) == 15 AA = reshape(aa, tuple(2, shp...)) - B = view(AA, 1:1, ntuple(i->Colon(), i)...) + B = view(AA, 1:1, ntuple(Returns(:), i)...) @test isa(Base.IndexStyle(B), Base.IteratorsMD.IndexCartesian) @test mdsum(B) == 15 @test mdsum2(B) == 15 @@ -1799,7 +1799,7 @@ end A = reshape(a, tuple(shp...)) @test mdsum(A) == 55 @test mdsum2(A) == 55 - B = view(A, ntuple(i->Colon(), i)...) + B = view(A, ntuple(Returns(:), i)...) @test mdsum(B) == 55 @test mdsum2(B) == 55 insert!(shp, 2, 1) diff --git a/test/bitarray.jl b/test/bitarray.jl index f246942452020..a5591fca26de7 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -1180,8 +1180,8 @@ timesofar("datamove") @check_bit_operation findfirst(x->x, b1) Union{Int,Nothing} @check_bit_operation findfirst(x->!x, b1) Union{Int,Nothing} - @check_bit_operation findfirst(x->true, b1) Union{Int,Nothing} - @check_bit_operation findfirst(x->false, b1) Union{Int,Nothing} + @check_bit_operation findfirst(Returns(true ), b1) Union{Int,Nothing} + @check_bit_operation findfirst(Returns(false), b1) Union{Int,Nothing} @check_bit_operation findall(b1) Vector{Int} end @@ -1275,49 +1275,51 @@ timesofar("find") @test_throws BoundsError findprevnot(b2, 1001) @test_throws BoundsError findprev(!, b2, 1001) @test_throws BoundsError findprev(identity, b1, 1001) - @test_throws BoundsError findprev(x->false, b1, 1001) - @test_throws BoundsError findprev(x->true, b1, 1001) + @test_throws BoundsError findprev(Returns(false), b1, 1001) + @test_throws BoundsError findprev(Returns(true ), b1, 1001) @test findprev(b1, 1000) == findprevnot(b2, 1000) == findprev(!, b2, 1000) == 777 @test findprev(b1, 777) == findprevnot(b2, 777) == findprev(!, b2, 777) == 777 @test findprev(b1, 776) == findprevnot(b2, 776) == findprev(!, b2, 776) == 77 @test findprev(b1, 77) == findprevnot(b2, 77) == findprev(!, b2, 77) == 77 @test findprev(b1, 76) == findprevnot(b2, 76) == findprev(!, b2, 76) == nothing @test findprev(b1, -1) == findprevnot(b2, -1) == findprev(!, b2, -1) == nothing - @test findprev(identity, b1, -1) == findprev(x->false, b1, -1) == findprev(x->true, b1, -1) == nothing + @test findprev(identity, b1, -1) == nothing + @test findprev(Returns(false), b1, -1) == nothing + @test findprev(Returns(true), b1, -1) == nothing @test_throws BoundsError findnext(b1, -1) @test_throws BoundsError findnextnot(b2, -1) @test_throws BoundsError findnext(!, b2, -1) @test_throws BoundsError findnext(identity, b1, -1) - @test_throws BoundsError findnext(x->false, b1, -1) - @test_throws BoundsError findnext(x->true, b1, -1) + @test_throws BoundsError findnext(Returns(false), b1, -1) + @test_throws BoundsError findnext(Returns(true), b1, -1) @test findnext(b1, 1) == findnextnot(b2, 1) == findnext(!, b2, 1) == 77 @test findnext(b1, 77) == findnextnot(b2, 77) == findnext(!, b2, 77) == 77 @test findnext(b1, 78) == findnextnot(b2, 78) == findnext(!, b2, 78) == 777 @test findnext(b1, 777) == findnextnot(b2, 777) == findnext(!, b2, 777) == 777 @test findnext(b1, 778) == findnextnot(b2, 778) == findnext(!, b2, 778) == nothing @test findnext(b1, 1001) == findnextnot(b2, 1001) == findnext(!, b2, 1001) == nothing - @test findnext(identity, b1, 1001) == findnext(x->false, b1, 1001) == findnext(x->true, b1, 1001) == nothing + @test findnext(identity, b1, 1001) == findnext(Returns(false), b1, 1001) == findnext(Returns(true), b1, 1001) == nothing @test findlast(b1) == Base.findlastnot(b2) == 777 @test findfirst(b1) == Base.findfirstnot(b2) == 77 b0 = BitVector() - @test findprev(x->true, b0, -1) == nothing - @test_throws BoundsError findprev(x->true, b0, 1) - @test_throws BoundsError findnext(x->true, b0, -1) - @test findnext(x->true, b0, 1) == nothing + @test findprev(Returns(true), b0, -1) == nothing + @test_throws BoundsError findprev(Returns(true), b0, 1) + @test_throws BoundsError findnext(Returns(true), b0, -1) + @test findnext(Returns(true), b0, 1) == nothing b1 = falses(10) - @test findprev(x->true, b1, 5) == 5 - @test findnext(x->true, b1, 5) == 5 - @test findprev(x->true, b1, -1) == nothing - @test findnext(x->true, b1, 11) == nothing - @test findprev(x->false, b1, 5) == nothing - @test findnext(x->false, b1, 5) == nothing - @test findprev(x->false, b1, -1) == nothing - @test findnext(x->false, b1, 11) == nothing - @test_throws BoundsError findprev(x->true, b1, 11) - @test_throws BoundsError findnext(x->true, b1, -1) + @test findprev(Returns(true), b1, 5) == 5 + @test findnext(Returns(true), b1, 5) == 5 + @test findprev(Returns(true), b1, -1) == nothing + @test findnext(Returns(true), b1, 11) == nothing + @test findprev(Returns(false), b1, 5) == nothing + @test findnext(Returns(false), b1, 5) == nothing + @test findprev(Returns(false), b1, -1) == nothing + @test findnext(Returns(false), b1, 11) == nothing + @test_throws BoundsError findprev(Returns(true), b1, 11) + @test_throws BoundsError findnext(Returns(true), b1, -1) @testset "issue 32568" for T = (UInt, BigInt) for x = (1, 2) @@ -1382,8 +1384,8 @@ timesofar("reductions") b2 = bitrand(l) @test map(~, b1) == map(x->~x, b1) == broadcast(~, b1) @test map(identity, b1) == map(x->x, b1) == b1 - @test map(zero, b1) == map(x->false, b1) == falses(l) - @test map(one, b1) == map(x->true, b1) == trues(l) + @test map(zero, b1) == map(Returns(false), b1) == falses(l) + @test map(one, b1) == map(Returns(true), b1) == trues(l) @test map(&, b1, b2) == map((x,y)->x&y, b1, b2) == broadcast(&, b1, b2) @test map(|, b1, b2) == map((x,y)->x|y, b1, b2) == broadcast(|, b1, b2) @@ -1407,8 +1409,8 @@ timesofar("reductions") @test map!(~, b, b1) == map!(x->~x, b, b1) == broadcast(~, b1) == b @test map!(!, b, b1) == map!(x->!x, b, b1) == broadcast(~, b1) == b @test map!(identity, b, b1) == map!(x->x, b, b1) == b1 == b - @test map!(zero, b, b1) == map!(x->false, b, b1) == falses(l) == b - @test map!(one, b, b1) == map!(x->true, b, b1) == trues(l) == b + @test map!(zero, b, b1) == map!(Returns(false), b, b1) == falses(l) == b + @test map!(one, b, b1) == map!(Returns(true), b, b1) == trues(l) == b @test map!(&, b, b1, b2) == map!((x,y)->x&y, b, b1, b2) == broadcast(&, b1, b2) == b @test map!(|, b, b1, b2) == map!((x,y)->x|y, b, b1, b2) == broadcast(|, b1, b2) == b diff --git a/test/ccall.jl b/test/ccall.jl index 8cb376c805611..88f693150eead 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -842,7 +842,7 @@ function check_code_trampoline(f, t, n::Int) @nospecialize(f, t) @test Base.return_types(f, t) == Any[Any] llvm = sprint(code_llvm, f, t) - @test count(x -> true, eachmatch(r"@jl_get_cfunction_trampoline\(", llvm)) == n + @test count(Returns(true), eachmatch(r"@jl_get_cfunction_trampoline\(", llvm)) == n end check_code_trampoline(testclosure, (Any, Any, Bool, Type), 2) check_code_trampoline(testclosure, (Any, Int, Bool, Type{Int}), 2) diff --git a/test/channels.jl b/test/channels.jl index c5b1b3f6db9a5..0611b387e6f88 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -333,7 +333,7 @@ end # interpreting the calling function. @noinline garbage_finalizer(f) = (finalizer(f, "gar" * "bage"); nothing) run = Ref(0) - garbage_finalizer(x -> nothing) # warmup + garbage_finalizer(Returns(nothing)) # warmup @test GC.enable(false) # test for finalizers trying to yield leading to failed attempts to context switch garbage_finalizer((x) -> (run[] += 1; sleep(1))) @@ -533,7 +533,7 @@ end # make sure that we don't accidentally create a one-shot timer let - t = Timer(t->nothing, 10, interval=0.00001) + t = Timer(Returns(nothing), 10, interval=0.00001) @test ccall(:uv_timer_get_repeat, UInt64, (Ptr{Cvoid},), t) == 1 close(t) end diff --git a/test/core.jl b/test/core.jl index 1053b8dffcf80..62ca2989abb42 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5972,11 +5972,11 @@ end for U in boxedunions local U for N in (1, 2, 3, 4) - A = Array{U}(undef, ntuple(x->0, N)...) + A = Array{U}(undef, ntuple(Returns(0), N)...) @test isempty(A) @test sizeof(A) == 0 - A = Array{U}(undef, ntuple(x->10, N)...) + A = Array{U}(undef, ntuple(Returns(10), N)...) @test length(A) == 10^N @test sizeof(A) == sizeof(Int) * (10^N) @test !isassigned(A, 1) @@ -6057,11 +6057,11 @@ using Serialization for U in unboxedunions local U for N in (1, 2, 3, 4) - A = Array{U}(undef, ntuple(x->0, N)...) + A = Array{U}(undef, ntuple(Returns(0), N)...) @test isempty(A) @test sizeof(A) == 0 - len = ntuple(x->10, N) + len = ntuple(Returns(10), N) mxsz = maximum(sizeof, Base.uniontypes(U)) A = Array{U}(undef, len) @test length(A) == prod(len) diff --git a/test/generic_map_tests.jl b/test/generic_map_tests.jl index 8fde731770bf3..8e77533362fe3 100644 --- a/test/generic_map_tests.jl +++ b/test/generic_map_tests.jl @@ -76,6 +76,6 @@ function run_map_equivalence_tests(mapf) testmap_equivalence(mapf, identity, (1,2,3,4)) testmap_equivalence(mapf, (x,y,z)->x+y+z, 1,2,3) testmap_equivalence(mapf, x->x ? false : true, BitMatrix(undef, 10,10)) - testmap_equivalence(mapf, x->"foobar", BitMatrix(undef, 10,10)) + testmap_equivalence(mapf, Returns("foobar"), BitMatrix(undef, 10,10)) testmap_equivalence(mapf, (x,y,z)->string(x,y,z), BitVector(undef, 10), fill(1.0, 10), "1234567890") end diff --git a/test/iterators.jl b/test/iterators.jl index b45a51fd87042..c4b438d279693 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -198,7 +198,7 @@ end @test collect(takewhile(<(4),1:10)) == [1,2,3] @test collect(takewhile(<(4),Iterators.countfrom(1))) == [1,2,3] @test collect(takewhile(<(4),5:10)) == [] - @test collect(takewhile(_->true,5:10)) == 5:10 + @test collect(takewhile(Returns(true),5:10)) == 5:10 @test collect(takewhile(isodd,[1,1,2,3])) == [1,1] @test collect(takewhile(<(2), takewhile(<(3), [1,1,2,3]))) == [1,1] end @@ -209,8 +209,8 @@ end @test collect(dropwhile(<(4), 1:10)) == 4:10 @test collect(dropwhile(<(4), 1:10)) isa Vector{Int} @test isempty(dropwhile(<(4), [])) - @test collect(dropwhile(_->false,1:3)) == 1:3 - @test isempty(dropwhile(_->true, 1:3)) + @test collect(dropwhile(Returns(false),1:3)) == 1:3 + @test isempty(dropwhile(Returns(true), 1:3)) @test collect(dropwhile(isodd,[1,1,2,3])) == [2,3] @test collect(dropwhile(iseven,dropwhile(isodd,[1,1,2,3]))) == [3] end @@ -381,7 +381,7 @@ let a = 1:2, end # size infinite or unknown raises an error - for itr in Any[countfrom(1), Iterators.filter(i->0, 1:10)] + for itr in Any[countfrom(1), Iterators.filter(Returns(0), 1:10)] @test_throws ArgumentError length(product(itr)) @test_throws ArgumentError size(product(itr)) @test_throws ArgumentError ndims(product(itr)) @@ -592,7 +592,7 @@ end end @testset "filter empty iterable #16704" begin - arr = filter(n -> true, 1:0) + arr = filter(Returns(true), 1:0) @test length(arr) == 0 @test eltype(arr) == Int end diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 5deb442f36222..50fe2fcef4c1f 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -235,7 +235,7 @@ targets2 = ["(fill(1.0), fill(1.0))", "([1.0], [1.0])", "([1.0], [1.0])"] @testset "printing of OffsetArray with n=$n" for n = 0:4 - a = OffsetArray(fill(1.,ntuple(d->1,n)), ntuple(identity,n)) + a = OffsetArray(fill(1.,ntuple(Returns(1),n)), ntuple(identity,n)) show(IOContext(io, :limit => true), MIME("text/plain"), a) @test String(take!(io)) == targets1[n+1] show(IOContext(io, :limit => true), MIME("text/plain"), (a,a)) diff --git a/test/operators.jl b/test/operators.jl index 070a924b41cdc..d07f3382f53a5 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -281,3 +281,17 @@ end end @test [Base.afoldl(+, 1:i...) for i = 1:40] == [i * (i + 1) ÷ 2 for i = 1:40] + +@testset "Returns" begin + @test @inferred(Returns(1)() ) === 1 + @test @inferred(Returns(1)(23) ) === 1 + @test @inferred(Returns("a")(2,3)) == "a" + @test @inferred(Returns(1)(x=1, y=2)) === 1 + @test @inferred(Returns(Int)()) === Int + @test @inferred(Returns(Returns(1))()) === Returns(1) + f = @inferred Returns(Int) + @inferred f(1,2) + val = [1,2,3] + @test Returns(val)(1) === val + @test sprint(show, Returns(1.0)) == "Returns{Float64}(1.0)" +end diff --git a/test/reduce.jl b/test/reduce.jl index f87b2285480f4..7f3963590fbe0 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -460,8 +460,8 @@ end @test reduce((a, b) -> a .& b, fill(trues(5), 24)) == trues(5) @test reduce((a, b) -> a .& b, fill(falses(5), 24)) == falses(5) -@test_throws TypeError any(x->0, [false]) -@test_throws TypeError all(x->0, [false]) +@test_throws TypeError any(Returns(0), [false]) +@test_throws TypeError all(Returns(0), [false]) # short-circuiting any and all diff --git a/test/show.jl b/test/show.jl index dccbe1eee603e..3a04abb3c6c0d 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1148,7 +1148,7 @@ let x = [], y = [], z = Base.ImmutableDict(x => y) """ dz = sprint(dump, z) @test 10 < countlines(IOBuffer(dz)) < 40 - @test sum(x -> 1, eachmatch(r"circular reference", dz)) == 4 + @test sum(Returns(1), eachmatch(r"circular reference", dz)) == 4 end # PR 16221 diff --git a/test/subarray.jl b/test/subarray.jl index 76f00ab7948cb..334211d3e3975 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -134,8 +134,8 @@ end function test_bounds(@nospecialize(A)) @test_throws BoundsError A[0] @test_throws BoundsError A[end+1] - trailing2 = ntuple(x->1, max(ndims(A)-2, 0)) - trailing3 = ntuple(x->1, max(ndims(A)-3, 0)) + trailing2 = ntuple(Returns(1), max(ndims(A)-2, 0)) + trailing3 = ntuple(Returns(1), max(ndims(A)-3, 0)) @test_throws BoundsError A[1, 0, trailing2...] @test_throws BoundsError A[1, end+1, trailing2...] @test_throws BoundsError A[1, 1, 0, trailing3...] @@ -214,10 +214,10 @@ end function runviews(SB::AbstractArray, indexN, indexNN, indexNNN) @assert ndims(SB) > 2 for i3 in indexN, i2 in indexN, i1 in indexN - runsubarraytests(SB, i1, i2, i3, ntuple(x->1, max(ndims(SB)-3, 0))...) + runsubarraytests(SB, i1, i2, i3, ntuple(Returns(1), max(ndims(SB)-3, 0))...) end for i2 in indexN, i1 in indexN - runsubarraytests(SB, i1, i2, ntuple(x->1, max(ndims(SB)-2, 0))...) + runsubarraytests(SB, i1, i2, ntuple(Returns(1), max(ndims(SB)-2, 0))...) end for i1 in indexNNN runsubarraytests(SB, i1) diff --git a/test/tuple.jl b/test/tuple.jl index 80a4323f6d2f2..7c274851ea555 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -278,7 +278,7 @@ end @testset "filter" begin @test filter(isodd, (1,2,3)) == (1, 3) @test filter(isequal(2), (true, 2.0, 3)) === (2.0,) - @test filter(i -> true, ()) == () + @test filter(Returns(true), ()) == () @test filter(identity, (true,)) === (true,) longtuple = ntuple(identity, 20) @test filter(iseven, longtuple) == ntuple(i->2i, 10) From e8eb174eac7117de7637a96d6abbc6aafd6f7934 Mon Sep 17 00:00:00 2001 From: rssdev10 Date: Fri, 2 Apr 2021 00:48:48 +0300 Subject: [PATCH 061/439] docs: clarification about the integer division with 'div' (#40253) --- base/div.jl | 4 ++-- base/operators.jl | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/div.jl b/base/div.jl index 2df79fbdc6124..d78220c530608 100644 --- a/base/div.jl +++ b/base/div.jl @@ -5,8 +5,8 @@ """ div(x, y, r::RoundingMode=RoundToZero) -The quotient from Euclidean division. Computes x/y, rounded to an integer according -to the rounding mode `r`. In other words, the quantity +The quotient from Euclidean (integer) division. Computes x/y, rounded to +an integer according to the rounding mode `r`. In other words, the quantity round(x/y,r) diff --git a/base/operators.jl b/base/operators.jl index 3153342d6c9d0..58f6024f71176 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -803,7 +803,8 @@ const % = rem div(x, y) ÷(x, y) -The quotient from Euclidean division. Computes `x/y`, truncated to an integer. +The quotient from Euclidean (integer) division. Generally equivalent +to a mathematical operation x/y without a fractional part. # Examples ```jldoctest From 56623b8280d4c9bb4b0d7406a677d0c1db8a596d Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" <37125+schneiderfelipe@users.noreply.github.com> Date: Thu, 1 Apr 2021 18:50:08 -0300 Subject: [PATCH 062/439] Support cis(A) for matrix A (#40194) --- NEWS.md | 1 + stdlib/LinearAlgebra/docs/src/index.md | 1 + stdlib/LinearAlgebra/src/dense.jl | 20 ++++++++++++++++++++ stdlib/LinearAlgebra/src/diagonal.jl | 2 +- stdlib/LinearAlgebra/src/symmetric.jl | 6 ++++++ stdlib/LinearAlgebra/test/dense.jl | 19 +++++++++++++++++++ stdlib/LinearAlgebra/test/diagonal.jl | 7 ++++++- stdlib/LinearAlgebra/test/symmetric.jl | 6 ++++++ 8 files changed, 60 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index e9043bbebd4f4..4831de4a33064 100644 --- a/NEWS.md +++ b/NEWS.md @@ -70,6 +70,7 @@ Standard library changes * On aarch64, OpenBLAS now uses an ILP64 BLAS like all other 64-bit platforms. ([#39436]) * OpenBLAS is updated to 0.3.13. ([#39216]) * SuiteSparse is updated to 5.8.1. ([#39455]) +* `cis(A)` now supports matrix arguments ([#40194]). #### Markdown diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 52e7860999287..48d44d98f7ca0 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -410,6 +410,7 @@ LinearAlgebra.nullspace Base.kron Base.kron! LinearAlgebra.exp(::StridedMatrix{<:LinearAlgebra.BlasFloat}) +Base.cis(::AbstractMatrix) Base.:^(::AbstractMatrix, ::Number) Base.:^(::Number, ::AbstractMatrix) LinearAlgebra.log(::StridedMatrix) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index ad288bef1ddc7..e21c4200f9394 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -557,6 +557,26 @@ julia> exp(A) exp(A::StridedMatrix{<:BlasFloat}) = exp!(copy(A)) exp(A::StridedMatrix{<:Union{Integer,Complex{<:Integer}}}) = exp!(float.(A)) +""" + cis(A::AbstractMatrix) + +Compute ``\\exp(i A)`` for a square matrix ``A``. + +!!! compat "Julia 1.7" + Support for using `cis` with matrices was added in Julia 1.7. + +# Examples +```jldoctest +julia> cis([π 0; 0 π]) ≈ -I +true +``` +""" +Base.cis(A::AbstractMatrix) = exp(im * A) # fallback +Base.cis(A::AbstractMatrix{<:Base.HWNumber}) = exp_maybe_inplace(float.(im .* A)) + +exp_maybe_inplace(A::StridedMatrix{<:Union{ComplexF32, ComplexF64}}) = exp!(A) +exp_maybe_inplace(A) = exp(A) + """ ^(b::Number, A::AbstractMatrix) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 10e8e64e01ae7..10a6f8ac446b9 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -602,7 +602,7 @@ function logdet(D::Diagonal{<:Complex}) # make sure branch cut is correct end # Matrix functions -for f in (:exp, :log, :sqrt, +for f in (:exp, :cis, :log, :sqrt, :cos, :sin, :tan, :csc, :sec, :cot, :cosh, :sinh, :tanh, :csch, :sech, :coth, :acos, :asin, :atan, :acsc, :asec, :acot, diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index ab031b4d30c43..f048425be31e2 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -770,6 +770,12 @@ for func in (:exp, :cos, :sin, :tan, :cosh, :sinh, :tanh, :atan, :asinh, :atanh) end end +function cis(A::Union{RealHermSymComplexHerm,SymTridiagonal{<:Real}}) + F = eigen(A) + # The returned matrix is unitary, and is complex-symmetric for real A + return F.vectors .* cis.(F.values') * F.vectors' +end + for func in (:acos, :asin) @eval begin function ($func)(A::HermOrSym{<:Real}) diff --git a/stdlib/LinearAlgebra/test/dense.jl b/stdlib/LinearAlgebra/test/dense.jl index 51edd334f1e0f..0c86fec9242b5 100644 --- a/stdlib/LinearAlgebra/test/dense.jl +++ b/stdlib/LinearAlgebra/test/dense.jl @@ -477,6 +477,17 @@ end [4.000000000000000 -1.414213562373094 -1.414213562373095 -1.414213562373095 4.999999999999996 -0.000000000000000 0 -0.000000000000002 3.000000000000000]) + + # cis always returns a complex matrix + if elty <: Real + eltyim = Complex{elty} + else + eltyim = elty + end + + @test cis(A1) ≈ convert(Matrix{eltyim}, [-0.339938 + 0.000941506im 0.772659 - 0.8469im 0.52745 + 0.566543im; + 0.650054 - 0.140179im -0.0762135 + 0.284213im 0.38633 - 0.42345im ; + 0.650054 - 0.140179im 0.913779 + 0.143093im -0.603663 - 0.28233im ]) rtol=7e-7 end @testset "Additional tests for $elty" for elty in (Float64, ComplexF64) @@ -560,8 +571,13 @@ end @test cos(A) ≈ cos(-A) @test sin(A) ≈ -sin(-A) @test tan(A) ≈ sin(A) / cos(A) + @test cos(A) ≈ real(exp(im*A)) @test sin(A) ≈ imag(exp(im*A)) + @test cos(A) ≈ real(cis(A)) + @test sin(A) ≈ imag(cis(A)) + @test cis(A) ≈ cos(A) + im * sin(A) + @test cosh(A) ≈ 0.5 * (exp(A) + exp(-A)) @test sinh(A) ≈ 0.5 * (exp(A) - exp(-A)) @test cosh(A) ≈ cosh(-A) @@ -605,6 +621,9 @@ end @test cos(A5) ≈ 0.5 * (exp(im*A5) + exp(-im*A5)) @test sin(A5) ≈ -0.5im * (exp(im*A5) - exp(-im*A5)) + @test cos(A5) ≈ 0.5 * (cis(A5) + cis(-A5)) + @test sin(A5) ≈ -0.5im * (cis(A5) - cis(-A5)) + @test cosh(A5) ≈ 0.5 * (exp(A5) + exp(-A5)) @test sinh(A5) ≈ 0.5 * (exp(A5) - exp(-A5)) end diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 043b2181a7908..61090830a65e0 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -88,7 +88,7 @@ Random.seed!(1) @test func(D) ≈ func(DM) atol=n^2*eps(relty)*(1+(elty<:Complex)) end if relty <: BlasFloat - for func in (exp, sinh, cosh, tanh, sech, csch, coth) + for func in (exp, cis, sinh, cosh, tanh, sech, csch, coth) @test func(D) ≈ func(DM) atol=n^3*eps(relty) end @test log(Diagonal(abs.(D.diag))) ≈ log(abs.(DM)) atol=n^3*eps(relty) @@ -102,6 +102,10 @@ Random.seed!(1) end end + @testset "Two-dimensional Euler formula for Diagonal" begin + @test cis(Diagonal([π, π])) ≈ -I + end + @testset "Linear solve" begin for (v, U) in ((vv, UU), (view(vv, 1:n), view(UU, 1:n, 1:2))) @test D*v ≈ DM*v atol=n*eps(relty)*(1+(elty<:Complex)) @@ -568,6 +572,7 @@ end @test ishermitian(Dsym) == false @test exp(D) == Diagonal([exp([1 2; 3 4]), exp([1 2; 3 4])]) + @test cis(D) == Diagonal([cis([1 2; 3 4]), cis([1 2; 3 4])]) @test log(D) == Diagonal([log([1 2; 3 4]), log([1 2; 3 4])]) @test sqrt(D) == Diagonal([sqrt([1 2; 3 4]), sqrt([1 2; 3 4])]) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index d23eecb5be46e..93b91294cfecb 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -11,13 +11,19 @@ Random.seed!(1010) @test ishermitian(σ) end +@testset "Two-dimensional Euler formula for Hermitian" begin + @test cis(Hermitian([π 0; 0 π])) ≈ -I +end + @testset "Hermitian matrix exponential/log" begin A1 = randn(4,4) + im*randn(4,4) A2 = A1 + A1' @test exp(A2) ≈ exp(Hermitian(A2)) + @test cis(A2) ≈ cis(Hermitian(A2)) @test log(A2) ≈ log(Hermitian(A2)) A3 = A1 * A1' # posdef @test exp(A3) ≈ exp(Hermitian(A3)) + @test cis(A3) ≈ cis(Hermitian(A3)) @test log(A3) ≈ log(Hermitian(A3)) A1 = randn(4,4) From 82dc40264d94581c6977dab01ec545c3cd4bb4ec Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Apr 2021 19:25:45 -0400 Subject: [PATCH 063/439] Update CSL (#40287) * deps: upgrade CSL This adds the `.so` files, particularly for libatomic that we need on FreeBSD * build: define uninstall targets even for deps that are not always installed Most commonly csl, llvm-tools, and clang, but there were other ones in the wrong lists also. --- Makefile | 4 +- contrib/refresh_checksums.mk | 10 +- deps/Makefile | 45 +++-- deps/checksums/compilersupportlibraries | 184 +++++++++--------- deps/llvm.mk | 2 + deps/tools/common.mk | 2 +- deps/tools/uninstallers.mk | 11 +- .../CompilerSupportLibraries_jll/Project.toml | 2 +- stdlib/Makefile | 6 +- 9 files changed, 139 insertions(+), 127 deletions(-) diff --git a/Makefile b/Makefile index 823ff3b86339d..72b2cf3ffb829 100644 --- a/Makefile +++ b/Makefile @@ -448,7 +448,7 @@ endif echo "base/version_git.jl" > light-source-dist.tmp # Download all stdlibs and include the tarball filenames in light-source-dist.tmp - @$(MAKE) -C stdlib getall NO_GIT=1 + @$(MAKE) -C stdlib getall DEPS_GIT=0 USE_BINARYBUILDER=0 -ls stdlib/srccache/*.tar.gz >> light-source-dist.tmp -ls stdlib/*/StdlibArtifacts.toml >> light-source-dist.tmp @@ -472,7 +472,7 @@ source-dist: # Make tarball with Julia code plus all dependencies full-source-dist: light-source-dist.tmp # Get all the dependencies downloaded - @$(MAKE) -C deps getall NO_GIT=1 + @$(MAKE) -C deps getall DEPS_GIT=0 USE_BINARYBUILDER=0 # Create file full-source-dist.tmp to hold all the filenames that go into the tarball cp light-source-dist.tmp full-source-dist.tmp diff --git a/contrib/refresh_checksums.mk b/contrib/refresh_checksums.mk index da0c69eed5510..12e3d4825ae42 100644 --- a/contrib/refresh_checksums.mk +++ b/contrib/refresh_checksums.mk @@ -47,7 +47,7 @@ endef # if $(3) is "assert", we set BINARYBUILDER_LLVM_ASSERTS=1 define checksum_dep checksum-$(1)-$(2)-$(3): - -$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/deps" $(call make_flags,$(1),$(2),$(3)) checksum-$(1) + -+$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/deps" $(call make_flags,$(1),$(2),$(3)) checksum-$(1) .PHONY: checksum-$(1)-$(2)-$(3) # Add this guy to his project target @@ -79,25 +79,27 @@ $(foreach triplet,$(CLANG_TRIPLETS),$(eval $(call checksum_dep,llvm,$(triplet),a # External stdlibs checksum-stdlibs: - -$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/stdlib" checksumall + -+$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/stdlib" checksumall all: checksum-stdlibs .PHONY: checksum-stdlibs # doc unicode data checksum-doc-unicodedata: - -$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/doc" checksum-unicodedata + -+$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/doc" checksum-unicodedata all: checksum-doc-unicodedata .PHONY: checksum-doc-unicodedata # Special LLVM source hashes for optional targets checksum-llvm-special-src: - -$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/deps" USE_BINARYBUILDER_LLVM=0 DEPS_GIT=0 BUILD_LLDB=1 BUILD_LLVM_CLANG=1 BUILD_CUSTOM_LIBCXX=1 USECLANG=1 checksum-llvm + -+$(MAKE) $(QUIET_MAKE) -C "$(JULIAHOME)/deps" USE_BINARYBUILDER_LLVM=0 DEPS_GIT=0 BUILD_LLDB=1 BUILD_LLVM_CLANG=1 BUILD_CUSTOM_LIBCXX=1 USECLANG=1 checksum-llvm all: checksum-llvm-special-src .PHONY: checksum-llvm-special-src # merge substring project names to avoid races pack-checksum-llvm-tools: | pack-checksum-llvm +pack-checksum-llvm: | checksum-llvm-tools pack-checksum-csl: | pack-checksum-compilersupportlibraries +pack-checksum-compilersupportlibraries: | checksum-csl # define how to pack parallel checksums into a single file format pack-checksum-%: FORCE diff --git a/deps/Makefile b/deps/Makefile index cc5d7a05f3902..3a1099df4d2e9 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -166,12 +166,26 @@ ifneq ($(OS), WINNT) DEP_LIBS += libwhich endif -# unlist targets that have not been converted to use the staged-install -DEP_LIBS_STAGED := $(DEP_LIBS) -DEP_LIBS_STAGED := $(filter-out csl,$(DEP_LIBS_STAGED)) -DEP_LIBS_STAGED := $(filter-out suitesparse,$(DEP_LIBS_STAGED)) -DEP_LIBS_STAGED := $(filter-out suitesparse-wrapper,$(DEP_LIBS_STAGED)) +DEP_LIBS_STAGED := $(filter-out suitesparse-wrapper,$(DEP_LIBS)) + +# list all targets +DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ + openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ + objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ + suitesparse suitesparse-wrapper +DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) +ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) +DEP_LIBS_ALL := $(filter-out lapack,$(DEP_LIBS_ALL)) +endif + +ifeq ($(USE_BINARYBUILDER_LLVM),0) +DEP_LIBS_ALL := $(filter-out clang llvm-tools,$(DEP_LIBS_ALL)) +endif + +ifeq ($(USE_BINARYBUILDER_SUITESPARSE),0) +DEP_LIBS_STAGED := $(filter-out suitesparse,$(DEP_LIBS_STAGED)) +endif ## Common build target prefixes @@ -183,21 +197,14 @@ compile: $(addprefix compile-, $(DEP_LIBS)) check: $(addprefix check-, $(DEP_LIBS)) fastcheck: $(addprefix fastcheck-, $(DEP_LIBS)) stage: $(addprefix stage-, $(DEP_LIBS_STAGED)) -install: $(addprefix install-, $(DEP_LIBS)) -cleanall: $(addprefix clean-, $(DEP_LIBS)) -distcleanall: $(addprefix distclean-, $(DEP_LIBS)) - rm -rf $(build_prefix) -getall: get-llvm get-libuv get-pcre get-openlibm get-dsfmt get-blastrampoline get-openblas get-lapack get-suitesparse get-unwind get-gmp get-mpfr get-patchelf get-utf8proc get-objconv get-mbedtls get-libssh2 get-nghttp2 get-curl get-libgit2 get-libwhich get-zlib get-p7zip get-csl - -# If we're building for MacOS, no matter what, `getall` should include `llvmunwind` -ifeq ($(OS),Darwin) -getall: get-llvmunwind -endif +install: version-check $(addprefix install-, $(DEP_LIBS)) +version-check: $(addprefix version-check-, $(DEP_LIBS_STAGED)) -# Same if we're building a purely-source archive, always include `llvmunwind` -ifeq ($(USE_BINARYBUILDER_LLVMUNWIND),0) -getall: get-llvmunwind -endif +uninstall: $(addprefix uninstall-, $(DEP_LIBS_STAGED_ALL)) +cleanall: $(addprefix clean-, $(DEP_LIBS_ALL)) +distcleanall: $(addprefix distclean-, $(DEP_LIBS_ALL)) + rm -rf $(build_prefix) +getall: $(addprefix get-, $(DEP_LIBS_ALL)) include $(SRCDIR)/csl.mk include $(SRCDIR)/llvm.mk diff --git a/deps/checksums/compilersupportlibraries b/deps/checksums/compilersupportlibraries index 8ad65ac42987a..b23ced42c436c 100644 --- a/deps/checksums/compilersupportlibraries +++ b/deps/checksums/compilersupportlibraries @@ -1,92 +1,92 @@ -CompilerSupportLibraries.v0.4.0+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/df1bb35cddff18f4512b57a2b36a6be7 -CompilerSupportLibraries.v0.4.0+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/d01fb4077b97d10d5b4c7567146d82d7e6a45a57296cae14e97fe3d4174083553d9318a0ad75bd492315fa9ee213bcf04cb3841c2a6302f87fc8a377e756f459 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/81e354bb883997335f1945cffd493978 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/5c1f79488019d9bf46906e5e921ccf0118b762baf522b02314177ce81ccfb839e75226802c844462dc9a70aaca609b465348e43297b918deb9c4d3c8e36a6b94 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/c9de5672d1e67cd2541eb8ae25188573 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/30381588684a1fe4818ef6e2d0e3dcf44f0dbf81fcb63a043b9c8e4b3a34e6b7b09511e94c3eeb5004ca45a17b9fd0b7e102bb0176672fef09f1b940edf15a03 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/b2f930fd61a2c22895f3102f950df915 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/89e3103c28429d4c9a020be7b0ed9b374bc48d2971671904e889a57a9bb9b8c81011b20143c0152814d1191d246d144242e4c71cbd45a3c4bf50ebd0ab967b15 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/be7aa1b8f769bcee21a615d4819f00f6 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/3404792c4bd24499fd83f7140c392fff7ac5360eb55ea580808d051f9bfc9c9f9e7b59be25ada594d71e3d94610fc4eb397daee6d84fa6bf4c988f6881e19c33 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/22e9e895ca30837fa5165bbf4b74e482 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/04600705e907ca1ea4a203d5e696171bae4777c4c9534f4ae3d20525d39be60de1916a2d0b12b7e710d144ac47b2472754e1b3e01295fb43934e6ed8c9201766 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/6a2518ceb9c3e57fabf0db12090a0872 -CompilerSupportLibraries.v0.4.0+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/19222a3dcbf9afbdf43192943a0a7ad9cbf4762c1a681567cbbf6093866e44465ff566a10595220c9366d92dde43dcba84d41c240e2192da042ddfeff3e9f1a4 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/96f355abd8fd31d6522c6d7d5b259971 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/1fd436c9e4d15ff199fa60fd9b715c16effbdb6c15f86b86e9b2dbfca70136da71a4a491caa2650eb415fc32620b40295729a6b375efe1a08f9c34cbbc317949 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/1aae7c2cdaf1ba04b9bad8119224eb24 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/913defbddb5d5069f1d8b9a1a4a5c2e325538baeb0203756cc91de45fb52b21defc7cbdca6f454803f792dba895ae146009d667ed508727f4aea627dc1ae419f -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/f1c35daa5d66fae11adcf6385ab6e095 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/6a7a9ef08709ce5c805ea19fc33bee65b85ee576cae747327eeb12f0950dfca4b871a0e9799d4961e5d703a0a6e116145542078d124258ab3a949957e368173b -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/fe30bb318b88b3270e92d3d8f84abb5f -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/d54f5e0c7780a8557b889b3fa5d2fcca639521d00d624a0a4a3f4a46b854a3615989040f122243f5dfa266d8f6ce700bcffc9ed1653f86eb8279d5c31b67c6f3 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/489e4a98eadee286d3c32ed08ba2b5a1 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/b4589dddadd17ba1ac3e086a9312db3301e5d828b4c17e9e8db3ed018eba4757c84282dd78b2b2c84f978fa9154c9f46f9e3f1e711207eb19ca0f834239b835d -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/cf0e32142c441673680d55b7c547a629 -CompilerSupportLibraries.v0.4.0+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/698af44f897dfb0682b49532666896b2d3430f1a172921f9184e17404e714448899a227882f8375193d0a0476a777754e7f679bc0dea987ad185eafad30eca0b -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/16897e51e3a1d61d1b9a7abd6e728d2a -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/3a9a56d80c1ba1eca7bee4156a7d56938564c27366a51395d6c8f74c3bb500b0b374deed3fc1efc75942e6a66dc354808a6c7a66d1952eba9dc81c9e0fb8cc69 -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/840d73fbd5ec7fe94708cd8179ccefbc -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/dcf7834d1f2b67356baedf0d3eeba4f5d3e62e0fd475ba3329668e18608fe1493fba07c9737bc4474e8276b09c6c73c76dcd6fde44d96149b740398c218a3432 -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/50a06e1bc8a8442c7a1369bc837ce504 -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/868970d00f5387f42a632c5fdbedc3e9135b6723ce3b1ae1735fd51a4a1faf91ab5fae94bc99c37aee75d9cc9547a7259cba584d95e0971ef97605592effeb39 -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/9998e35984f1c3b54b45dd8a4af2145a -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/2e653f25d5652003d2cfceae4d786187ea3911caff8555d9f4e10e0ad60d237afc18fdc5247804e3347825682e6e347a92b70699ba73bf497ec414467f1cfccf -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/64ac31833d8d69b57b6acb1767cf110c -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/31c762e0c5d8a0652fda77e10eb5d195d8e27e8cce9e020d8c186aa904e55687cf2e090e0eec55aa6e5e885fe165c099d05c93efb45d83fcd438f7f996a131ba -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/805a1d491313c87632b6e4527e499129 -CompilerSupportLibraries.v0.4.0+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/72d7e5387e3f1fb69f7d0ce51fed36cdd794b5c284dc9514c93e26458df860f83ca4581f4f6f53e838b26ed3563248c0beea7e8e2020e16d30a965e8d1f4de63 -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran3.tar.gz/md5/48eff236a6aedae30f871e9e5d1c14a6 -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/b913aaca516fcad91f11f4f797810d8f5fb240d92e428607ef982558f8e74a1dbdec3eee5983a5f0b7bfa9e6e750f724de4193b007fbfabfaf6705bd4b0fa523 -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran4.tar.gz/md5/6b377e6b8a2b120acbd24319dfef4efc -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/65248ec4ac7997faeeb4abba9a79b0707dab9d0dffaff293039f7c0886f972d1e118738e37c4e2168228de11b498be58bff996a3a335b9ad2799146f593106e8 -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran5.tar.gz/md5/964ce992265ecac408cfea1e7fbf434b -CompilerSupportLibraries.v0.4.0+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/c100995a619ea04361bba6de3e460b22a9187af61fc02d8c3f94191cf71f73e9ff2409d87078e34655be6aa352f75f395e419860b6dca976cb665caa20e31fbc -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran3.tar.gz/md5/3a1dab532cd7222708d27d1cab9428a1 -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran3.tar.gz/sha512/836acc03a34cb48b079ac2c8b397a03d01c1dad522a6be5c3ad81da98ee0979b981b14184f08e7308bdc69bc17bcd897d400853b0e6ce9a7821f9ab3c6a6890d -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran4.tar.gz/md5/7bae09d4f9460ae491605f6642c3f1dc -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran4.tar.gz/sha512/fb5bad1260aa3ad1ee135120ce0cfda4034380d85970c458a6dbac9cd24e3a7b996bffae8ccfcbd30223273e766c3a7d5945ea42c5237811a2b4af1db5027e09 -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran5.tar.gz/md5/c7e7cdd660accdeda123685c7691429a -CompilerSupportLibraries.v0.4.0+0.i686-linux-musl-libgfortran5.tar.gz/sha512/7015eb83612711a93dda9ae5fa709f74e72b33922e7f48ae98e8bc4798b8057ee315a65a27c2ab041623775407d37c686f4b3d64e1af27df6a32fd4d0edd5441 -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/2dcabd868fe7ddb4edd29078b840c093 -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/a70e6ee8cf73aacf0cbc7b4ac5f17b8e6914e93b106caba907c5ce8f2ab24fbf28ef50b60548ff6bd8e47461ec971a4f2c7519ffe0c13893ae48e4d6bbfd6a49 -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/0097f1075086376188cf594276edb421 -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/47cee1709879bea6a7d537a31438b39b5baf19b94a7575e7ae2a2271174884f484069c24d8e1dc927f3cc89f2007c5c1037b4c76e1747a1f9512d5055e30900f -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/e00d8689da404039de3956327e5e1abf -CompilerSupportLibraries.v0.4.0+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/24efa7cc047c9ebc7f9bb99c844691fc78333a8e78f11da4a0d8ef58e98cf64da20198fe97b735443220ef6860e9618b9e1bedfdf38b2e134d9366db4ae9da4e -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/118fede168fbaa2433c10c725ee445cf -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/447f0f4eaa72531c6118f65268d1e505323a210e04213358942b58a8a34f4e20c39306ac7d89f06e51df57265b04a1d0d4dad6c141b590cbd3389573ede0de8b -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/262d162451ffc50c25cf599285555c47 -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/137afd852f57a3b4d56f7ddf1ce2f7a3386bdb26d7e577e91af8d95e1fa08c2eb43623925158248f2b43df346cf2e87f308305087e3a3473eb6a0526ee259a5f -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/d3b8e3b11b74d1cac626ccab59e652b1 -CompilerSupportLibraries.v0.4.0+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/fcb110fa7b7966840a00f5fab2968d543d1c15354222ef6e693197797c337a3b9586caa66db7042280ebb46de51adf4903cb21c79b4cd1179f5aa1d4082e270b -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/1f593b25ca831267c4e02555304e447a -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/94b502cb4c02bdc1dda87e3608d9807925002eac68883c26cf27e358d48eff41fda0832fb6118c750a1386192e27bd6a0c14c9510d114edbf43efdc2e5bd1c13 -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/a23d18444255c8ebf5253dbd470169ab -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/50737af89141a126766829fafe19599e1dc645d8669cb10f05111aa4c031f3fffecdb9ec98dd4ac9fab541d5947582b284d650f86c3116db12c10387be42eff6 -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/dbc289277a5b2a960111e2a5eefa7f0c -CompilerSupportLibraries.v0.4.0+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/4affcc86a550400f5fefb0337a1d245849ecf7fdd305790197c60112a0d1e096fffdc4ac140a82952abf6eab220e8c631c392b8903ea586b5c0345c65c9116f7 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/dfc62f03e7b65447ed877a9eaa537e07 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/f782f5a7c87924e134778ce9f7f98f0d48f4626f8b7b371a5c7799cf5bc7ea3cd6cdf275769dfc2b9dc2da82181e49b9d77833ff5241d2600d58c9bfd78a189c -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/6e46faded79b17c6b77846fbf2e5119f -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/6cafdf6d79bc8a7125857c148282384477720038293ccae83dc9065f8457ee28d516468bf9c96320086c9f2dbefb6f57ce77a952bc105de2b67e47fb0b0b8a1c -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/68d2354ca386ba9ec4e98504fff2f222 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/ed3d1c0cbd34f62abd41694fc73ac38a34bc19674526e41090f66aaeeafe87cad382a5b17cfe8a622079571d646735d273249acd108bec9a1f42c195da98403b -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/ed7a41374016ffe35c8068b2090fb66f -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/a8089a9704b8ac0b7c8de2f329f4eaabca5daa508e015cfc6a1fb668e78167463a30d9c96f23e2a518dc8b730fe606253c360a13689fc6a098dd18ad61ce1fc7 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/1f425bdb591db55d4a821a3b83a1fed1 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/24a1d1fb3d388eff2521c7b0eafafe76b29c3571b784af1dcc0ff8ea2781aa81b26fcdd03a0a1efaba9a913b6b67ece29c3c867a3cc93dfe46eecb3fdd2ef5be -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/6c19ee02d1bf8be22d65155d0d430946 -CompilerSupportLibraries.v0.4.0+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/aaaaf2a731e9009171a555b66fd2b662e2bfb207ecf84cb54138c770bba0e8e5910190a7a279b1d1d6058645a2f0d8bbca92ce9ca39753cc14c886a7189431fa -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/6c9beb8a213ccae10713d336e4c48c1b -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/da25d33a824e71d254492c891cad0a0fd9e472e5320403830a4bf8c0f175f531775b4e468832c702edf1e46dac68725e04ccdcf8914ac6fa60b27cec45d5aa1e -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/dba2d41d040bba44d9a7767d4fb6c329 -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/16f9ec8a9897832b3a7408e192f9d0af222f369f33e5a698fd92f54f3c4326f0632f1e8ffb6757b6969d5a18f594f8f0e70457f8bb78a7740b8b26daf22171e4 -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/1dd16d636fc9a87668a9c6ad2abc1a93 -CompilerSupportLibraries.v0.4.0+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/6a2deb304127c06baf260e2614bdd1d397fff3bc0b11c192ed0e43b3681af805dc5f17d84ff4836b108be65f879743a13b49122015d5f343f5ff3c895bf46de8 -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/2edeb2d7edbd955a43ca3efc8830e292 -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/a89faa9dbac9ddb3544a743c61636a77ada4af5fb637f9391187fdcde293d766deee7a60a878a53a08eae6f35e4b64b981c0ec5a39a2038299549c07e0bcca10 -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/50d2b57735d2cba4a5411414a2e26e6d -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/f6db77083655181c0c28c2056962559ac5e77e6869dc990ba21e5d0c265d7705c482088587f6871dff1142c4a6ccc12ed24329f6c1f99146bf43f176dffbe28a -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/b1479d5d095e9f2b198e48ff24f0a0f9 -CompilerSupportLibraries.v0.4.0+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/a37fcc95658e91a820d6a4d13b51cf8ee6820b62142686ced67768d8f03eb09bd8cc3d0e7afc16abdde4a4fa764ece7bd92b8951cac06ad817e7ad13eaa784e2 +CompilerSupportLibraries.v0.4.0+1.aarch64-apple-darwin-libgfortran5.tar.gz/md5/b095e6f14bc7a1f9aa69a55619797c3b +CompilerSupportLibraries.v0.4.0+1.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/e3383c65fdafa0d58e9573ef008792c71ce77c7126b96b641de4813f679211e057d8d9d2617aedfaa5f73224b5a2656fd72534028201b533d75a21acbf087032 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran3.tar.gz/md5/f619396b91380a986621a35792aaf35b +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/342f8b7aac23a637c3223be7ca56243cf74ab0d21d2a3133a1bf6261efb760daee1288da96a219326c301a594576863668dc8bc726b6b998b92b3ecb152ed236 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran4.tar.gz/md5/83daebefd6c178f398390d765508cd30 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/da483ed5405a124101219e08162f4d6a82dfb7960efedd9462ae006c88446d291d62ddd9b1b9da948733f6f6cec4a55fcc3428edbb7a3b19d9520305813e9b6f +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran5.tar.gz/md5/b826a756dc995cff198e6e2902e6c709 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/761ec5d5403db0299871560add411e2bd1c113d4aca9a2cee6746592606df4c7aed927c987b825ccdfca6fe043af5d84a3f7b76b28e484eb0bf5ded47fe49042 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran3.tar.gz/md5/2e23248297f51bee77dee83e77124d5a +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran3.tar.gz/sha512/8124fa237efa09b30bb846cfd1dd373a9f7b558c7bdd612fb4bd442b6dde80ebf913ef303b53e110a9fd19d3f56fd6b85894e6bf06b5ce4850315684a6f871ec +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran4.tar.gz/md5/871b587fa0dd5cfb9ac137a354a68aca +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran4.tar.gz/sha512/a50d1e55a974e6df1d85155e92b7d3075d2e1ad19167fda6be1f1cfe8964aeea2f66f59dd1bbf7abb361aa3831705132ac2385755321f655de2cbd0cd89f9de2 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran5.tar.gz/md5/a68d999a5aab28aa9760ba3d4c2e9c69 +CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran5.tar.gz/sha512/141dc1be2e30a511de17eaaf507d5d082ea80b621a635836d0658fd1eb5e5cd37bf0779ff4a920d8322f46da98fd866bd5dbaa7d47c9aa236f26c7d0cfab51cb +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/acb29acfa67701327d81ba9a1f6765d7 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/54f813c3c69e5c8f4fde4ba8762d590315121f377df3512e71bf62b465b6eddc02cb1c4d9003b0c4c88d64ec36a2056363efb3eab9cefeba2b2658cd5f84086c +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/aae1759097c368ec3e12b0ac28c008b0 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/dfcc475f8e375a7fce81550efb12a21ee2589892a2453d094f0fbaa7d7524858b908995157d85123560c46fcd70093503d2b4224c785b57874f0affdaea776de +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/e7bfe1de2b3f9857053dfb61bd3b2698 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/0227a0a2732a3ee66911c42e031429827588746fe96d098cec3efeef2f157267b7e88f49279ca3749fbd487a3acbd3775267132033f8531503bf3b44b91ea347 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/c61cf2433e18b5f7b55fd958248b0640 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/1b6b4b7c413a5d4692ccbde26ece656b1786b07ebc573fb90f15ca00773acbd6f5abd981bd13fefd154deac0d7a718af90aaf85fd3c08ef35a805baccad459c3 +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/1da0f3569c47fb166311bde071fa4bca +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/75e6af64f9f1909ae95ac823d1487a7cc1b47c9415e58c2c8303d21ea923dc11da8a12c8e9c720ea34471273ee7ed99917c7f1775c6e7e4d861726d57954a61a +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/f20c66ad490a9a00cbb7fa7adb62905e +CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/9645aedfe08f381050bebb5a8c3c2510fa0a6a435d249c8c526a0135e597cbb44fd04546504c524c9343e7b3559b3ff2f0a4b207ebafcab20d4405044f3924f1 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/81eb7300e4730b93c6bb5305b983bf31 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/fa170b8311767d77d63161d01991584d4827068f4e8c563d49bb29783ba55a657da65b7c255fbe3b780cbcfe29faa292ee53893c6647e2457cfed7aaae47a7bd +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/add43dada47b0c2fe7191ecb816193aa +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/8368823e5cb1a557603e03ab4e336eb891e8c851f5ad212a7386e171dfd9c1aaec46b5b62d63e0a17df5c83e4b23cd68fe26fe131b9fe487ab7d0a7f426ec1c3 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/6f8ac553deac6733c9084a84a2a9dfb7 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/81b0e931da0787bf34809bca66f641e4f6d40a462d36b34aae3143da7a513b5c8f6abe7da910bda7bf7c1dc88c0eafde6421f07fb5ba171781453c09e9ef2b33 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/38d726f01a0c4c47d37e3a6fd173d8ca +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/227d7d509c44eafae7bacba3d3cc8b1004c0eed2943e3ff39dcd842a6a4fb8d7febe700205b51a85b18a799e801b6106d894881b95ef2780ad029cbd7e17f2f2 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/694772770ed5b196e8399dd4c59a9707 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/dfc66f0313db7e0be22f35d01b7a0e89b7836f2597683f647dcc193195206173c3050089d9e9ef299b96045abbbd8ea6a835af757ec10c95b89eeb4c31846245 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/d6ed143927e826db195e9387bca709a6 +CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/bffdf5d5737c031119bbf316b5718aa3c1b2cb671f446375c7fbf792d37dc8f1477b082515c007480c01789a7af9eca76e083052a6018bc0bdb6143bbf975134 +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran3.tar.gz/md5/34808173bf9105ae1ab9f6e636df5ddf +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran3.tar.gz/sha512/4d501538fbbee3a06b5cc72f19a579c1dc91257c15dff7ef040ca8353d94a013795b8fe3dd3c4e88eb2f2b1650ecc203933ef31b53f3c2cb7a17111e154c3fa3 +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran4.tar.gz/md5/352ea68c7571515ae58bc1b354f53cd3 +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran4.tar.gz/sha512/4f5e04ad93d536171a233f79f93e5e72af8b8a0243c24e1f48ef8f6fb92c47ebb2634a1305324f1a342c6cdf9b58a775a77245f581b64773124089e6ff2364bb +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran5.tar.gz/md5/dbe1270173a4d9c108990ebde51d3bee +CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran5.tar.gz/sha512/f196a5c24a2ca1cd05f56b5e76f425ba0acab4be46311fdb52a3ce81d9e748edcdd8e4ac259a70d8adab9b6ce1a1aea4cee81f95dad2deadd2ac3ee5b199af37 +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran3.tar.gz/md5/c72eab916829d79128ef055c9c657ff7 +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran3.tar.gz/sha512/c2d0b61e01cafe12fca7b969354fbbd26135b5ab8eb7f72a62614570b9d65144c0a51be65e62f5a837147f104c2a4edb0959494505bf33c08b9c6647cfeed5b0 +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran4.tar.gz/md5/a7ebe12727b11220f589faddee5223ac +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran4.tar.gz/sha512/313623ac2471e64891cb363c44e718ed710c92f6e5b8ef7fa0dd650c71f452705cc947e909763f8aeb8aac8597871b91359623398f8528ae4fdc4463de15d182 +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran5.tar.gz/md5/af98f0be67f87c73500eb44bb741253c +CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran5.tar.gz/sha512/358182533477e57b39a5c6d8e0213af6a9e68bb871489487408cd72c357e370875aeca8a59131e4303072dc9895f8f74f4fc0421088fb4fbd9801567db77b17b +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran3.tar.gz/md5/ec293a15d294d3ce3700cc85435775d5 +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran3.tar.gz/sha512/f24efd506bab60fad3dcd7c1a086a54471451830aa8b7cbd2b4fb65f6fcf4fbc3de326046df0758b7739ed4038a63d503d87f65c58870c915590c15145ab90b3 +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran4.tar.gz/md5/0f441cfb17e1f7280ce2fb606c30bcd1 +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran4.tar.gz/sha512/283547b14a5facb4f21f02900af64e279818cbf42c64932d3d73a4eb8109f0b7279d334c6991b9071a2d1c9dd5621a719f88137824dab335f83add4b77c4f46d +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran5.tar.gz/md5/c523c690bc0dd37394f3ecd2353b374c +CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran5.tar.gz/sha512/94b02c6be7fe0db7b71c0895d61540d4a75a0dacc544175b88378ddb4973ee8f98566e9a0ccaf70487dd1fd7d145b0e0b39b90ecd7124f60c2b27ddf7e2bfa65 +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/513231d8cbf949cd673e6940799ec8e4 +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/c1e294b989483f6da25f8e30134aca8516d4851f011ba9ec5e013ef071530586db5b8e2d5cbb26d63a9640d64c315392a0a5a902ebd8b6ed86bd579e89444d8e +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/6ebcb68cd8e48b8a996e61055cede76e +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/b2f6668dad0f17dbbaa8523a4e3f6bdc566995ace229805045624297fd620265fa34ab5f1209c3d6649ab24c471fdf30d8ced7e2ab48c215bac009763dd4e841 +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/4e7463a0692c3e3c2ec240052a890247 +CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/5cd5178825b606cc6641c1f7f1a6de19f4c8c0698e6a231eb8d543de981a3f49f5f4ff6c6f7688b541934db47640bc04d40cd4be8728bea76dff55ad1878c7d7 +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran3.tar.gz/md5/be58605737e90ff2803d8a496d4d4f7b +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/9d239ffc38bbafbfe40fbc0fabd3041220b7d18cb014145839e092031a94c714a584f65d941887f00bf1af6a1e967ccb76486759973adda94a9ab5d632bfc87a +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran4.tar.gz/md5/674f654730ac0277558c7cdb268b60fc +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/9c698e5d448567b6c6455832777b9a9747852ce258c4593ea37f110a880992e66c1f6ecfc3169debd1419daf1fb84f8ac5ff9209d152bf5a9198125ba65f2240 +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran5.tar.gz/md5/d70d29db5ef26da73c9cd56f8b41434c +CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/b52acf460687b74e9d7bcf12c119fd05986c30b76bf24ab1a207b5cb03ef531617577501ec051c79a7c647fcaf57756f92a3af1b4d6c0a5128f94742ffc8548c +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran3.tar.gz/md5/afbcf12c24b005d67b5e9392835c7b1c +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/682241805f6172071fd17905fd6caec4c64e872da6872aa55f5ef4c28bc492b58063b9eda023c7ddc2929b567f4cf9d7c28194aae5d4ab8a5f2426b94999d1db +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran4.tar.gz/md5/38084c6c747f95f23e01dbde2070f845 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/5995edc58b24f46fbf4ebf95ddc241c471bf1cf7cba33850dd31af84fffa397a97115da46ea34f462c51d3cb405c453c9c346dbbe9c8e0d3add077b801c8bec0 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran5.tar.gz/md5/9aba286d21dbd494e9b8cf2c5016af65 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/1854b43d8fe64da1ff2b2f5f40797fc3ae124d5b58969151947ab29c10a25c93df70ffbf794cfed3b76ed087d43912d5ae22e229455301bbc9599a1d376c3458 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran3.tar.gz/md5/dbf6c90f2d0364f8a8de269cd77caaef +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran3.tar.gz/sha512/360ef9d60b245df2f615f8f0bb3029e69b6a94f1eefd47846328fe6b6aea3819cdc2cf7638bc728a82593be64463ed24db4ed7b05c30ac295110a0f5cc23dcf3 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran4.tar.gz/md5/627a2b70b598a75c802831df08a0f70b +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran4.tar.gz/sha512/1b1f67d0af05dfb42e38736a21e8e73453322daf31183fdc9bbb7c86ee2a94e2aed9429fa5356e4d9095b10d08435134ebf7a34ee159bebf4ab3f1db646ed11e +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran5.tar.gz/md5/d58f6944d8e5c67a0b083c0f0d657ef3 +CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran5.tar.gz/sha512/8fff42ad9c0541bcdab8fdbfa9aa53cb5cf571e4076c7dbfa2801f1cc0d3710099e4257791253ff095cfe6268572bd675e1ba337639f0ddee25cb0c3880cc947 +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/e9d35321725b43bb9af51a36e8789eaf +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/2ee318a4db9f3c5b56187b9682d45b5fd8fd0e81dd63dfb39edfeabcb3b6acb77c97ec64dab6f8edf75fd0d689072a70c8438114772fce7d56a52bc97a19596d +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/8aed7f77e1488d3d88958330d7c97198 +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/ac22acc565d766f7ab18efcbea5adb1cc08c7a07c40bdb31208e084aad837fbba4b664a0d4ffc15e950d1aecb71e16b194c74f5027420a1aa231375fa70d1d56 +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/721fbc4c32245fc61c1cc6fa5c058e60 +CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/a99850a6b7cd7c7f7c1c38aab445b3f7bc4ad0af7b6d6589cfc98010c9e94dbde9d3f61e0c8bceed9e63b55344e854d0474df062c4714261c7d38608af12d5f6 +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/d97a2d7ea6f9f47be8bfbc03126a5e4a +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/bdbb297e0ce5872017b099cbd029334bb487c72b8d318041aa2994bbb0288712bcd42f1417051f498579ca0a387e3640d429ff6253ef642be4fe91139b7ecf9e +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/27f254507185ec2d1633405d8ae4c208 +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/c2e186d223f70b4aa0f8253af2831f6fe25598d89221136c41af5a9bbf1b64c185631cdf33c5f4e521fb02a477bed4cd3f0b770a2f5e01e4e78f279213e82468 +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/ae6057d7d7f67917910925904ef02f46 +CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/90b2620e20c02b970d4f6ca0cd13a2693ff4236048ee967edc1446e35c69f1f9d21acb992f61a613d4a88e29d25fb19628ef8af297c1eef9aa85b473632eaf5d diff --git a/deps/llvm.mk b/deps/llvm.mk index 461f04b6b2503..476375354da22 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -663,4 +663,6 @@ $(eval $(call bb-install,llvm,LLVM,false,true)) $(eval $(call bb-install,clang,CLANG,false,true)) $(eval $(call bb-install,llvm-tools,LLVM_TOOLS,false,true)) +install-clang install-llvm-tools: install-llvm + endif # USE_BINARYBUILDER_LLVM diff --git a/deps/tools/common.mk b/deps/tools/common.mk index 2fbceff51fdf8..aacae86139ee6 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -235,6 +235,6 @@ endif ## phony targets ## -.PHONY: default get extract configure compile fastcheck check install uninstall reinstall cleanall distcleanall \ +.PHONY: default get extract configure compile fastcheck check install uninstall reinstall cleanall distcleanall version-check \ get-* extract-* configure-* compile-* fastcheck-* check-* install-* uninstall-* reinstall-* clean-* distclean-* \ update-llvm diff --git a/deps/tools/uninstallers.mk b/deps/tools/uninstallers.mk index e6e37292ab1c4..48387914643db 100644 --- a/deps/tools/uninstallers.mk +++ b/deps/tools/uninstallers.mk @@ -2,10 +2,6 @@ # defines uninstallers and version-checks # based on the contents of the UNINSTALL_* variables and the manifest files -install: version-check -version-check: $(addprefix version-check-, $(DEP_LIBS_STAGED)) -uninstall: $(addprefix uninstall-, $(DEP_LIBS_STAGED)) - ## read 'uninstall-*' definition from either the manifest or the current session define define-uninstaller MANIFEST_$1 := $$(shell [ -e $$(build_prefix)/manifest/$1 ] && cat $$(build_prefix)/manifest/$1) @@ -17,12 +13,15 @@ ifneq ($$(UNINST_HOW_$1),) UNINST_WHO_$1 := $$(firstword $$(MANIFEST_$1)) UNINST_WHERE_$1 := $$(wordlist 3,99,$$(MANIFEST_$1)) $$(eval $$(call $$(UNINST_HOW_$1),$1,$$(UNINST_WHO_$1),$$(UNINST_WHERE_$1))) +else +uninstall-$1: + @echo "skipping uninstall: $1 not installed" endif endef -$(foreach dep,$(DEP_LIBS_STAGED),$(eval $(call define-uninstaller,$(dep)))) +$(foreach dep,$(DEP_LIBS_STAGED_ALL),$(eval $(call define-uninstaller,$(dep)))) # for each subproject with a manifest, keep the user aware if something is not the expected version -$(addprefix version-check-,$(DEP_LIBS_STAGED)) : version-check-% : install-% +$(addprefix version-check-,$(DEP_LIBS_STAGED_ALL)) : version-check-% : install-% @if [ ! -e $(build_prefix)/manifest/$* ] || ( \ [ "1" != "`wc -w $(build_prefix)/manifest/$* | cut -f 1 -d ' '`" ] && \ [ "$(UNINSTALL_$*)" != "`cat $(build_prefix)/manifest/$*`" ]) ; then \ diff --git a/stdlib/CompilerSupportLibraries_jll/Project.toml b/stdlib/CompilerSupportLibraries_jll/Project.toml index 87c7bd506a4f5..6f340407b6afb 100644 --- a/stdlib/CompilerSupportLibraries_jll/Project.toml +++ b/stdlib/CompilerSupportLibraries_jll/Project.toml @@ -1,6 +1,6 @@ name = "CompilerSupportLibraries_jll" uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.4.0+0" +version = "0.4.0+1" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/Makefile b/stdlib/Makefile index 718c18842f086..8ef2330f5a5ad 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -68,10 +68,12 @@ $(foreach module, $(STDLIBS), $(eval $(call symlink_target,$$(JULIAHOME)/stdlib/ STDLIBS_LINK_TARGETS := $(addprefix $(build_datarootdir)/julia/stdlib/$(VERSDIR)/,$(STDLIBS)) getall get: $(addprefix get-, $(STDLIBS_EXT) $(JLL_NAMES)) -install: $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS) +install: version-check $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS) +version-check: $(addprefix version-check-, $(STDLIBS_EXT)) +uninstall: $(addprefix uninstall-, $(STDLIBS_EXT)) clean: $(addprefix clean-, $(STDLIBS_EXT)) $(CLEAN_TARGETS) distclean: $(addprefix distclean-, $(STDLIBS_EXT)) clean checksumall: $(addprefix checksum-, $(STDLIBS_EXT)) -DEP_LIBS_STAGED := $(STDLIBS_EXT) +DEP_LIBS_STAGED_ALL := $(STDLIBS_EXT) include $(JULIAHOME)/deps/tools/uninstallers.mk From d07b5a134632d26bdbadde1b0352d2de8aae2906 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Apr 2021 23:24:48 -0400 Subject: [PATCH 064/439] replace broken replaceuserpath function with existing contractuser one (#40274) Fixes #39674 --- base/errorshow.jl | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 2baf5d2471315..099c00dd48592 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -552,13 +552,6 @@ end # replace `sf` as needed. const update_stackframes_callback = Ref{Function}(identity) -function replaceuserpath(str) - str = replace(str, homedir() => "~") - # seems to be necessary for some paths with small letter drive c:// etc - str = replace(str, lowercasefirst(homedir()) => "~") - return str -end - const STACKTRACE_MODULECOLORS = [:magenta, :cyan, :green, :yellow] const STACKTRACE_FIXEDCOLORS = IdDict(Base => :light_black, Core => :light_black) @@ -698,7 +691,7 @@ end function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, modulecolor) file, line = string(frame.file), frame.line stacktrace_expand_basepaths() && (file = something(find_source_file(file), file)) - stacktrace_contract_userdir() && (file = replaceuserpath(file)) + stacktrace_contract_userdir() && (file = contractuser(file)) # Used by the REPL to make it possible to open # the location of a stackframe/method in the editor. From 878e1cd52ebf14e8666d8d54a54a95ccee4405d3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Apr 2021 23:30:18 -0400 Subject: [PATCH 065/439] ENV: avoid using regex, since these strings are not necessarily valid utf8 (#40273) --- base/Base.jl | 8 ++++---- base/env.jl | 55 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 3b53173827610..3186e67b1add6 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -231,7 +231,9 @@ include("sysinfo.jl") include("libc.jl") using .Libc: getpid, gethostname, time -include("env.jl") +# Logging +include("logging.jl") +using .CoreLogging # Concurrency include("linked_list.jl") @@ -243,9 +245,7 @@ include("task.jl") include("threads_overloads.jl") include("weakkeydict.jl") -# Logging -include("logging.jl") -using .CoreLogging +include("env.jl") # BinaryPlatforms, used by Artifacts include("binaryplatforms.jl") diff --git a/base/env.jl b/base/env.jl index b87d00670e772..63b2df9c9acc8 100644 --- a/base/env.jl +++ b/base/env.jl @@ -87,7 +87,7 @@ setindex!(::EnvDict, v, k::AbstractString) = _setenv(k,string(v)) push!(::EnvDict, kv::Pair{<:AbstractString}) = setindex!(ENV, kv.second, kv.first) if Sys.iswindows() - GESW() = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) + GESW() = (pos = ccall(:GetEnvironmentStringsW, stdcall, Ptr{UInt16}, ()); (pos, pos)) function winuppercase(s::AbstractString) isempty(s) && return s LOCALE_INVARIANT = 0x0000007f @@ -99,32 +99,43 @@ if Sys.iswindows() return transcode(String, ws) end function iterate(hash::EnvDict, block::Tuple{Ptr{UInt16},Ptr{UInt16}} = GESW()) - if unsafe_load(block[1]) == 0 - ccall(:FreeEnvironmentStringsW, stdcall, Int32, (Ptr{UInt16},), block[2]) - return nothing + while true + if unsafe_load(block[1]) == 0 + ccall(:FreeEnvironmentStringsW, stdcall, Int32, (Ptr{UInt16},), block[2]) + return nothing + end + pos = block[1] + blk = block[2] + len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) + buf = Vector{UInt16}(undef, len) + GC.@preserve buf unsafe_copyto!(pointer(buf), pos, len) + env = transcode(String, buf) + pos += (len + 1) * 2 + if !isempty(env) + m = findnext('=', env, nextind(env, firstindex(env))) + else + m = nothing + end + if m === nothing + @warn "malformed environment entry: $env" + continue + end + return (Pair{String,String}(winuppercase(env[1:prevind(env, m)]), env[nextind(env, m):end]), (pos, blk)) end - pos = block[1] - blk = block[2] - len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) - buf = Vector{UInt16}(undef, len) - GC.@preserve buf unsafe_copyto!(pointer(buf), pos, len) - env = transcode(String, buf) - m = match(r"^(=?[^=]+)=(.*)$"s, env) - if m === nothing - error("malformed environment entry: $env") - end - return (Pair{String,String}(winuppercase(m.captures[1]), m.captures[2]), (pos+(len+1)*2, blk)) end else # !windows function iterate(::EnvDict, i=0) - env = ccall(:jl_environ, Any, (Int32,), i) - env === nothing && return nothing - env = env::String - m = match(r"^(.*?)=(.*)$"s, env) - if m === nothing - error("malformed environment entry: $env") + while true + env = ccall(:jl_environ, Any, (Int32,), i) + env === nothing && return nothing + env = env::String + m = findfirst('=', env) + if m === nothing + @warn "malformed environment entry: $env" + nothing + end + return (Pair{String,String}(env[1:prevind(env, m)], env[nextind(env, m):end]), i+1) end - return (Pair{String,String}(m.captures[1], m.captures[2]), i+1) end end # os-test From 0d9163b561a5f809b895b9cd8893d1a010197284 Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Fri, 2 Apr 2021 11:38:47 -0600 Subject: [PATCH 066/439] Fix #40318 by using UInt to convert instead of Int on Ptr --- stdlib/Printf/src/Printf.jl | 2 +- stdlib/Printf/test/runtests.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index ac57f95ec6bb9..2b620873bd61a 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -547,7 +547,7 @@ const __BIG_FLOAT_MAX__ = 8192 end # pointers -fmt(buf, pos, arg, spec::Spec{Pointer}) = fmt(buf, pos, Int(arg), ptrfmt(spec, arg)) +fmt(buf, pos, arg, spec::Spec{Pointer}) = fmt(buf, pos, UInt(arg), ptrfmt(spec, arg)) # old Printf compat function fix_dec end diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index d38c90734d4f1..498302a20ed0c 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -19,6 +19,9 @@ using Test, Printf @test (@sprintf "%-20p" C_NULL) == "0x00000000 " end + #40318 + @test @sprintf("%p", 0xfffffffffffe0000) == "0xfffffffffffe0000" + end @testset "%a" begin From fcf6779b1ec119b7a3686d08dfba7ba0acfd3f93 Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Fri, 2 Apr 2021 12:12:56 -0600 Subject: [PATCH 067/439] Fix rounding cases for fixed-width printing in ryu routines Fixes #40303. When printing values to fixed widths through the `Ryu.writefixed` or `Ryu.writeexp` routines, we have a "cleanup" section after a value has been printed to see if it needs to be rounded given the input precision and width. The core issue was the terminating condition: it previously only checked if we were at the start of a buffer or had encountered the `'-'` character. Via Printf formatting, however, it also allows specifying the `'+'` and `' '` characters to preceed a formatted number. Hence, in the OP, the `'1'` character was getting "rounded" up to the `','` character. The fix here is correctly checking if the `plus` or `space` options were passed to the routine and if so, include those in our rounding termination check. The original issue only reported the "plus" case for the `f` format specifier, but the same bug affects the `e` format specifier and the "space" option. --- base/ryu/exp.jl | 2 +- base/ryu/fixed.jl | 2 +- stdlib/Printf/test/runtests.jl | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/base/ryu/exp.jl b/base/ryu/exp.jl index cf1fe23105b8c..6356206971f8b 100644 --- a/base/ryu/exp.jl +++ b/base/ryu/exp.jl @@ -213,7 +213,7 @@ roundPos = pos while true roundPos -= 1 - if roundPos == (startpos - 1) || buf[roundPos] == UInt8('-') + if roundPos == (startpos - 1) || buf[roundPos] == UInt8('-') || (plus && buf[roundPos] == UInt8('+')) || (space && buf[roundPos] == UInt8(' ')) buf[roundPos + 1] = UInt8('1') e += 1 break diff --git a/base/ryu/fixed.jl b/base/ryu/fixed.jl index 4be1b3741832e..14713111a95a1 100644 --- a/base/ryu/fixed.jl +++ b/base/ryu/fixed.jl @@ -166,7 +166,7 @@ dotPos = 1 while true roundPos -= 1 - if roundPos == (startpos - 1) || (buf[roundPos] == UInt8('-')) + if roundPos == (startpos - 1) || (buf[roundPos] == UInt8('-')) || (plus && buf[roundPos] == UInt8('+')) || (space && buf[roundPos] == UInt8(' ')) buf[roundPos + 1] = UInt8('1') if dotPos > 1 buf[dotPos] = UInt8('0') diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index d38c90734d4f1..c74739d66ba51 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -141,6 +141,10 @@ end @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.0f", 1.234) == "+00000001" @test Printf.@sprintf("%+ #09.0f", 1.234) == "+0000001." + + #40303 + @test Printf.@sprintf("%+7.1f", 9.96) == " +10.0" + @test Printf.@sprintf("% 7.1f", 9.96) == " 10.0" end @testset "%e" begin @@ -202,6 +206,10 @@ end @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.0e", 1.234) == "+0001e+00" @test Printf.@sprintf("%+ #09.0e", 1.234) == "+001.e+00" + + #40303 + @test Printf.@sprintf("%+9.1e", 9.96) == " +1.0e+01" + @test Printf.@sprintf("% 9.1e", 9.96) == " 1.0e+01" end @testset "strings" begin From 5332d7d4e40ca2189e4ab597bf937f272f471bda Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Fri, 2 Apr 2021 13:41:29 -0600 Subject: [PATCH 068/439] Fix 32-bit --- stdlib/Printf/src/Printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 2b620873bd61a..e00b6becbb0f1 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -547,7 +547,7 @@ const __BIG_FLOAT_MAX__ = 8192 end # pointers -fmt(buf, pos, arg, spec::Spec{Pointer}) = fmt(buf, pos, UInt(arg), ptrfmt(spec, arg)) +fmt(buf, pos, arg, spec::Spec{Pointer}) = fmt(buf, pos, UInt64(arg), ptrfmt(spec, arg)) # old Printf compat function fix_dec end From 73aa7e4df5775dce521615a0da5c09e1735a3cd2 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Sat, 3 Apr 2021 04:43:39 +0200 Subject: [PATCH 069/439] fix macro hygiene for `@nospecialize(::T)` (#40293) --- src/macroexpand.scm | 3 ++- test/syntax.jl | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index a0f05a3af687a..5e55c7bbb29c1 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -210,7 +210,8 @@ ((atom? v) '()) (else (case (car v) - ((... kw |::| =) (try-arg-name (cadr v))) + ((|::|) (if (length= v 2) '() (try-arg-name (cadr v)))) + ((... kw =) (try-arg-name (cadr v))) ((escape) (list v)) ((hygienic-scope) (try-arg-name (cadr v))) ((meta) ;; allow certain per-argument annotations diff --git a/test/syntax.jl b/test/syntax.jl index aeaefdcbc832e..eb49a9dfddd60 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2771,3 +2771,9 @@ end @test eval(Expr(:string, "a", Expr(:string, "b", "c"))) == "abc" @test eval(Expr(:string, "a", Expr(:string, "b", Expr(:string, "c")))) == "abc" + +macro m_nospecialize_unnamed_hygiene() + return :(f(@nospecialize(::Any)) = Any) +end + +@test @m_nospecialize_unnamed_hygiene()(1) === Any From 9c7bb03eda4d8f225e1b8b5436ecb4eab92d8be5 Mon Sep 17 00:00:00 2001 From: Andrey Oskin Date: Sat, 3 Apr 2021 05:48:56 +0300 Subject: [PATCH 070/439] in printstyled, support underline and other flags (#40288) --- base/errorshow.jl | 8 +------- base/util.jl | 36 ++++++++++++++++++++++++++++-------- test/misc.jl | 20 ++++++++++++++++++++ 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 099c00dd48592..814d70ba05f91 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -731,13 +731,7 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, m # filename, separator, line # use escape codes for formatting, printstyled can't do underlined and color # codes are bright black (90) and underlined (4) - function print_underlined(io::IO, s...) - colored = get(io, :color, false)::Bool - start_s = colored ? "\033[90;4m" : "" - end_s = colored ? "\033[0m" : "" - print(io, start_s, s..., end_s) - end - print_underlined(io, pathparts[end], ":", line) + printstyled(io, pathparts[end], ":", line; color = :light_black, underline = true) # inlined printstyled(io, inlined ? " [inlined]" : "", color = :light_black) diff --git a/base/util.jl b/base/util.jl index e91ab3780824f..c489503d40133 100644 --- a/base/util.jl +++ b/base/util.jl @@ -67,7 +67,9 @@ Printing with the color `:nothing` will print the string without modifications. """ text_colors -function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}, io::IO, args...; bold::Bool = false) +function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}, io::IO, args...; + bold::Bool = false, underline::Bool = false, blink::Bool = false, + reverse::Bool = false, hidden::Bool = false) buf = IOBuffer() iscolor = get(io, :color, false)::Bool try f(IOContext(buf, io), args...) @@ -77,9 +79,22 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol} print(io, str) else bold && color === :bold && (color = :nothing) + underline && color === :underline && (color = :nothing) + blink && color === :blink && (color = :nothing) + reverse && color === :reverse && (color = :nothing) + hidden && color === :hidden && (color = :nothing) enable_ansi = get(text_colors, color, text_colors[:default]) * - (bold ? text_colors[:bold] : "") - disable_ansi = (bold ? disable_text_style[:bold] : "") * + (bold ? text_colors[:bold] : "") * + (underline ? text_colors[:underline] : "") * + (blink ? text_colors[:blink] : "") * + (reverse ? text_colors[:reverse] : "") * + (hidden ? text_colors[:hidden] : "") + + disable_ansi = (hidden ? disable_text_style[:hidden] : "") * + (reverse ? disable_text_style[:reverse] : "") * + (blink ? disable_text_style[:blink] : "") * + (underline ? disable_text_style[:underline] : "") * + (bold ? disable_text_style[:bold] : "") * get(disable_text_style, color, text_colors[:default]) first = true for line in split(str, '\n') @@ -94,18 +109,23 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol} end """ - printstyled([io], xs...; bold::Bool=false, color::Union{Symbol,Int}=:normal) + printstyled([io], xs...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Symbol,Int}=:normal) Print `xs` in a color specified as a symbol or integer, optionally in bold. `color` may take any of the values $(Base.available_text_colors_docstring) or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors. If the keyword `bold` is given as `true`, the result will be printed in bold. +If the keyword `underline` is given as `true`, the result will be printed underlined. +If the keyword `blink` is given as `true`, the result will blink. +If the keyword `reverse` is given as `true`, the result will have foreground and background colors inversed. +If the keyword `hidden` is given as `true`, the result will be hidden. +Keywords can be given in any combination. """ -printstyled(io::IO, msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) = - with_output_color(print, color, io, msg...; bold=bold) -printstyled(msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) = - printstyled(stdout, msg...; bold=bold, color=color) +printstyled(io::IO, msg...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) = + with_output_color(print, color, io, msg...; bold=bold, underline=underline, blink=blink, reverse=reverse, hidden=hidden) +printstyled(msg...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) = + printstyled(stdout, msg...; bold=bold, underline=underline, blink=blink, reverse=reverse, hidden=hidden, color=color) """ Base.julia_cmd(juliapath=joinpath(Sys.BINDIR::String, julia_exename())) diff --git a/test/misc.jl b/test/misc.jl index da9591ed2770d..2305b78250ef2 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -621,6 +621,26 @@ let buf = IOBuffer() # Check that boldness is turned off printstyled(buf_color, "foo"; bold=true, color=:red) @test String(take!(buf)) == "\e[31m\e[1mfoo\e[22m\e[39m" + + # Check that underline is turned off + printstyled(buf_color, "foo"; color = :red, underline = true) + @test String(take!(buf)) == "\e[31m\e[4mfoo\e[24m\e[39m" + + # Check that blink is turned off + printstyled(buf_color, "foo"; color = :red, blink = true) + @test String(take!(buf)) == "\e[31m\e[5mfoo\e[25m\e[39m" + + # Check that reverse is turned off + printstyled(buf_color, "foo"; color = :red, reverse = true) + @test String(take!(buf)) == "\e[31m\e[7mfoo\e[27m\e[39m" + + # Check that hidden is turned off + printstyled(buf_color, "foo"; color = :red, hidden = true) + @test String(take!(buf)) == "\e[31m\e[8mfoo\e[28m\e[39m" + + # Check that all options can be turned on simultaneously + printstyled(buf_color, "foo"; color = :red, bold = true, underline = true, blink = true, reverse = true, hidden = true) + @test String(take!(buf)) == "\e[31m\e[1m\e[4m\e[5m\e[7m\e[8mfoo\e[28m\e[27m\e[25m\e[24m\e[22m\e[39m" end abstract type DA_19281{T, N} <: AbstractArray{T, N} end From c3d84cec7806f37b34343511785fffbd5b908e6d Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sat, 3 Apr 2021 11:50:51 +0900 Subject: [PATCH 071/439] docs: fix typos in AbstractDict (#40325) --- base/abstractdict.jl | 4 ++-- base/essentials.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/abstractdict.jl b/base/abstractdict.jl index cfd964759bcce..e4565c98fbcbe 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -249,7 +249,7 @@ merge!(combine::Callable, args...) = mergewith!(combine, args...) """ keytype(type) -Get the key type of an dictionary type. Behaves similarly to [`eltype`](@ref). +Get the key type of a dictionary type. Behaves similarly to [`eltype`](@ref). # Examples ```jldoctest @@ -263,7 +263,7 @@ keytype(a::AbstractDict) = keytype(typeof(a)) """ valtype(type) -Get the value type of an dictionary type. Behaves similarly to [`eltype`](@ref). +Get the value type of a dictionary type. Behaves similarly to [`eltype`](@ref). # Examples ```jldoctest diff --git a/base/essentials.jl b/base/essentials.jl index 1a0e971d3a73f..c92167c553cb7 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -26,7 +26,7 @@ abstract type AbstractDict{K,V} end """ Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)} -Transforms an indexable container into an Dictionary-view of the same data. +Transforms an indexable container into a Dictionary-view of the same data. Modifying the key-space of the underlying data may invalidate this object. """ struct Pairs{K, V, I, A} <: AbstractDict{K, V} From 03abc458ea73bfa14713a6362fc60b097e7be337 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 2 Apr 2021 23:25:14 -0400 Subject: [PATCH 072/439] Fix reduce(vcat,...) type inference (#40277) (#40294) --- base/abstractarray.jl | 2 +- test/abstractarray.jl | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c59c20a10c37f..1531a0eb48b9f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1490,7 +1490,7 @@ AbstractVecOrTuple{T} = Union{AbstractVector{<:T}, Tuple{Vararg{T}}} _typed_vcat_similar(V, ::Type{T}, n) where T = similar(V[1], T, n) _typed_vcat(::Type{T}, V::AbstractVecOrTuple{AbstractVector}) where T = - _typed_vcat!(_typed_vcat_similar(V, T, mapreduce(length, +, V)), V) + _typed_vcat!(_typed_vcat_similar(V, T, sum(map(length, V))), V) function _typed_vcat!(a::AbstractVector{T}, V::AbstractVecOrTuple{AbstractVector}) where T pos = 1 diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 539af360bae2a..453952fdb81d2 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1280,3 +1280,9 @@ end @test Int[0 t...; t... 0] == [0 1 2; 1 2 0] @test_throws ArgumentError Int[t...; 3 4 5] end + +@testset "reduce(vcat, ...) inferrence #40277" begin + x_vecs = ([5, ], [1.0, 2.0, 3.0]) + @test @inferred(reduce(vcat, x_vecs)) == [5.0, 1.0, 2.0, 3.0] + @test @inferred(reduce(vcat, ([10.0], [20.0], Bool[]))) == [10.0, 20.0] +end From e1f6a64e4d4d0eb0a14ff1af1f018f2c94b0d56a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 3 Apr 2021 07:26:55 +0400 Subject: [PATCH 073/439] Fix mapreduce docstring (#40214) --- base/reducedim.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 85807851cd23d..92647a23f0e1a 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -295,7 +295,7 @@ reducedim!(op, R::AbstractArray{RT}, A::AbstractArrayOrBroadcasted) where {RT} = """ mapreduce(f, op, A::AbstractArray...; dims=:, [init]) -Evaluates to the same as `reduce(op, map(f, A); dims=dims, init=init)`, but is generally +Evaluates to the same as `reduce(op, map(f, A...); dims=dims, init=init)`, but is generally faster because the intermediate array is avoided. !!! compat "Julia 1.2" From 90338777498b9af67eeb1fd56553dea3a2124cae Mon Sep 17 00:00:00 2001 From: Henri Dehaybe <47037088+HenriDeh@users.noreply.github.com> Date: Sat, 3 Apr 2021 05:33:36 +0200 Subject: [PATCH 074/439] adding default argument value to `reset!(stateful)` (#40158) I think that most of the time when one calls `reset!(::Stateful)` it will be to simply restart from the begin without changing the iterated collection. So I figured that would avoid `reset!(sf, sf.itr)`. I also added the use of `reset!` to the documentation examples because it's not documented anywhere. This way users know of its existence. --- base/iterators.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/base/iterators.jl b/base/iterators.jl index eebffed16dcfb..2eb944c929b64 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1211,6 +1211,12 @@ julia> collect(a) 2-element Vector{Char}: 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase) 'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase) + +julia> Iterators.reset!(a); popfirst!(a) +'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) + +julia> Iterators.reset!(a, "hello"); popfirst!(a) +'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase) ``` ```jldoctest @@ -1239,7 +1245,7 @@ mutable struct Stateful{T, VS} end end -function reset!(s::Stateful{T,VS}, itr::T) where {T,VS} +function reset!(s::Stateful{T,VS}, itr::T=s.itr) where {T,VS} s.itr = itr setfield!(s, :nextvalstate, iterate(itr)) s.taken = 0 From fbd718fd2809a575f0761c84a0987bd6fbf4070f Mon Sep 17 00:00:00 2001 From: srz_zumix Date: Sat, 3 Apr 2021 12:40:32 +0900 Subject: [PATCH 075/439] cgmemmgr: check rlimit before using map_size_inc to map more memory (#40136) --- src/cgmemmgr.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index 8684178ab02a6..23d8b7437b823 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -10,6 +10,7 @@ #ifdef _OS_LINUX_ # include # include +# include #endif #ifndef _OS_WINDOWS_ # include @@ -22,6 +23,7 @@ #endif #ifdef _OS_FREEBSD_ # include +# include #endif #include "julia_assert.h" @@ -206,10 +208,24 @@ static intptr_t get_anon_hdl(void) static size_t map_offset = 0; // Multiple of 128MB. // Hopefully no one will set a ulimit for this to be a problem... -static constexpr size_t map_size_inc = 128 * 1024 * 1024; +static constexpr size_t map_size_inc_default = 128 * 1024 * 1024; static size_t map_size = 0; static jl_mutex_t shared_map_lock; +static size_t get_map_size_inc() +{ + rlimit rl; + if (getrlimit(RLIMIT_FSIZE, &rl) != -1) { + if (rl.rlim_cur != RLIM_INFINITY) { + return std::min(map_size_inc_default, rl.rlim_cur); + } + if (rl.rlim_max != RLIM_INFINITY) { + return std::min(map_size_inc_default, rl.rlim_max); + } + } + return map_size_inc_default; +} + static void *create_shared_map(size_t size, size_t id) { void *addr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, @@ -224,7 +240,7 @@ static intptr_t init_shared_map() if (anon_hdl == -1) return -1; map_offset = 0; - map_size = map_size_inc; + map_size = get_map_size_inc(); int ret = ftruncate(anon_hdl, map_size); if (ret != 0) { perror(__func__); @@ -238,6 +254,7 @@ static void *alloc_shared_page(size_t size, size_t *id, bool exec) assert(size % jl_page_size == 0); size_t off = jl_atomic_fetch_add(&map_offset, size); *id = off; + size_t map_size_inc = get_map_size_inc(); if (__unlikely(off + size > map_size)) { JL_LOCK_NOGC(&shared_map_lock); size_t old_size = map_size; From c4d66c8f829b6d77f86366d3e993c27aab1e01c8 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Sat, 3 Apr 2021 15:21:34 +1100 Subject: [PATCH 076/439] Fix `eltype` example in Methods section of manual (#40017) The code as written doesn't work when passing `eltype(Array{T} where T <: Integer)`, because `Array{T} where T <: Integer` is not a subtype of `AbstractArray{Any}` (but it *is* a subtype of `AbstractArray`). This was confusing when trying to understand why `Base.eltype(Array{T} where T <: Integer)` returned `Any`, so this re-worded the correct example, to make a little more clear where the fallback is defined. Removed the two other "correct" examples, and replaced them with another warning about a possible mistake (namely for types without supertypes). --- doc/src/manual/methods.md | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 73d41294173be..a94d674501e04 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -546,38 +546,19 @@ Here are a few common design patterns that come up sometimes when using dispatch ### Extracting the type parameter from a super-type -Here is the correct code template for returning the element-type `T` -of any arbitrary subtype of `AbstractArray`: +Here is a correct code template for returning the element-type `T` +of any arbitrary subtype of `AbstractArray` that has well-defined +element type: ```julia abstract type AbstractArray{T, N} end eltype(::Type{<:AbstractArray{T}}) where {T} = T ``` -using so-called triangular dispatch. Note that if `T` is a `UnionAll` -type, as e.g. `eltype(Array{T} where T <: Integer)`, then `Any` is -returned (as does the version of `eltype` in `Base`). -Another way, which used to be the only correct way before the advent of -triangular dispatch in Julia v0.6, is: - -```julia -abstract type AbstractArray{T, N} end -eltype(::Type{AbstractArray}) = Any -eltype(::Type{AbstractArray{T}}) where {T} = T -eltype(::Type{AbstractArray{T, N}}) where {T, N} = T -eltype(::Type{A}) where {A<:AbstractArray} = eltype(supertype(A)) -``` - -Another possibility is the following, which could be useful to adapt -to cases where the parameter `T` would need to be matched more -narrowly: -```julia -eltype(::Type{AbstractArray{T, N} where {T<:S, N<:M}}) where {M, S} = Any -eltype(::Type{AbstractArray{T, N} where {T<:S}}) where {N, S} = Any -eltype(::Type{AbstractArray{T, N} where {N<:M}}) where {M, T} = T -eltype(::Type{AbstractArray{T, N}}) where {T, N} = T -eltype(::Type{A}) where {A <: AbstractArray} = eltype(supertype(A)) -``` +using so-called triangular dispatch. Note that `UnionAll` types, for +example `eltype(AbstractArray{T} where T <: Integer)`, do not match the +above method. The implementation of `eltype` in `Base` adds a fallback +method to `Any` for such cases. One common mistake is to try and get the element-type by using introspection: @@ -596,6 +577,25 @@ Here we have created a type `BitVector` which has no parameters, but where the element-type is still fully specified, with `T` equal to `Bool`! +Another mistake is to try to walk up the type hierarchy using +`supertype`: +```julia +eltype_wrong(::Type{AbstractArray{T}}) where {T} = T +eltype_wrong(::Type{AbstractArray{T, N}}) where {T, N} = T +eltype_wrong(::Type{A}) where {A<:AbstractArray} = eltype_wrong(supertype(A)) +``` + +While this works for declared types, it fails for types without +supertypes: + +```julia-repl +julia> eltype_wrong(Union{AbstractArray{Int}, AbstractArray{Float64}}) +ERROR: MethodError: no method matching supertype(::Type{Union{AbstractArray{Float64,N} where N, AbstractArray{Int64,N} where N}}) +Closest candidates are: + supertype(::DataType) at operators.jl:43 + supertype(::UnionAll) at operators.jl:48 +``` + ### Building a similar type with a different type parameter When building generic code, there is often a need for constructing a similar From 4076e875442bf146fd7bdf87c41aba4fcfb7e7cc Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 3 Apr 2021 08:20:36 +0200 Subject: [PATCH 077/439] remove mention that non-underscored symbols denote public API (#40145) --- doc/src/manual/style-guide.md | 3 --- doc/src/manual/variables.md | 2 -- 2 files changed, 5 deletions(-) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 10f4b8ea54878..8e863e866b366 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -142,9 +142,6 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. as word separators. Underscores are also used to indicate a combination of concepts ([`remotecall_fetch`](@ref) as a more efficient implementation of `fetch(remotecall(...))`) or as modifiers. * functions mutating at least one of their arguments end in `!`. - * use identifiers starting with `_` to - denote functions, macros or variables that should be considered private and not part of a package's - public API. * conciseness is valued, but avoid abbreviation ([`indexin`](@ref) rather than `indxin`) as it becomes difficult to remember whether and how particular words are abbreviated. diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 65619dd02430d..c68fbd304d33a 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -141,7 +141,5 @@ conventions: * Functions that write to their arguments have names that end in `!`. These are sometimes called "mutating" or "in-place" functions because they are intended to produce changes in their arguments after the function is called, not just return a value. - * Names starting with an underscore denote functions, macros or variables that are only used internally - by a package and are not part of its public API. For more information about stylistic conventions, see the [Style Guide](@ref). From 8fc052f312216eba357c3f4f441fc248173f9786 Mon Sep 17 00:00:00 2001 From: "Adam A. Oppenheimer" Date: Sat, 3 Apr 2021 08:16:45 -0400 Subject: [PATCH 078/439] Update noteworthy-differences.md (#40326) They to there --- doc/src/manual/noteworthy-differences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index ad1727ec6d1c0..d19c774f044b0 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -240,7 +240,7 @@ For users coming to Julia from R, these are some noteworthy differences: * In Julia, the standard operators over a matrix type are matrix operations, whereas, in Python, the standard operators are element-wise operations. When both `A` and `B` are matrices, `A * B` in Julia performs matrix multiplication, not element-wise multiplication as in Python. `A * B` in Julia is equivalent with `A @ B` in Python, whereas `A * B` in Python is equivalent with `A .* B` in Julia. * The adjoint operator `'` in Julia returns an adjoint of a vector (a lazy representation of row vector), whereas the transpose operator `.T` over a vector in Python returns the original vector (non-op). * In Julia, a function may contain multiple concrete implementations (called *methods*), which are selected via multiple dispatch based on the types of all arguments to the call, as compared to functions in Python, which have a single implementation and no polymorphism (as opposed to Python method calls which use a different syntax and allows dispatch on the receiver of the method). - * There are no classes in Julia. Instead they are structures (mutable or immutable), containing data but no methods. + * There are no classes in Julia. Instead there are structures (mutable or immutable), containing data but no methods. * Calling a method of a class instance in Python (`x = MyClass(*args); x.f(y)`) corresponds to a function call in Julia, e.g. `x = MyType(args...); f(x, y)`. In general, multiple dispatch is more flexible and powerful than the Python class system. * Julia structures may have exactly one abstract supertype, whereas Python classes can inherit from one or more (abstract or concrete) superclasses. * The logical Julia program structure (Packages and Modules) is independent of the file structure (`include` for additional files), whereas the Python code structure is defined by directories (Packages) and files (Modules). From bf1ab0e145d0baf559620bbb354b85e04d887810 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sat, 3 Apr 2021 21:18:10 +0900 Subject: [PATCH 079/439] make radical operators juxtaposable (#40173) * make radical operators juxtaposable * fix test * update NEWS.md [skip ci] Co-authored-by: Jameson Nash --- NEWS.md | 1 + src/julia-parser.scm | 6 ++++-- test/syntax.jl | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4831de4a33064..4c2f4beae153e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,7 @@ New language features * `(; a, b) = x` can now be used to destructure properties `a` and `b` of `x`. This syntax is equivalent to `a = getproperty(x, :a)` and similarly for `b`. ([#39285]) +* Implicit multiplication by juxtaposition is now allowed for radical symbols (e.g., `x√y` and `x∛y`). ([#40173]) Language changes ---------------- diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 0b3f52ca61647..9e279fead3fd2 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -101,6 +101,8 @@ (define unary-op? (Set unary-ops)) +(define radical-op? (Set '(√ ∛ ∜))) + ; operators that are both unary and binary (define unary-and-binary-ops (append! '($ & ~) (add-dots '(+ - ⋆ ± ∓)))) @@ -973,7 +975,7 @@ (not (memv t '(#\( #\[ #\{)))) ) (not (ts:space? s)) - (not (operator? t)) + (or (not (operator? t)) (radical-op? t)) (not (closing-token? t)) (not (newline? t)) (or (and (not (string? expr)) (not (eqv? t #\"))) @@ -996,7 +998,7 @@ (begin #;(if (and (number? ex) (= ex 0)) (error "juxtaposition with literal \"0\"")) - (let ((next (parse-factor s))) + (let ((next (if (radical-op? next) (parse-unary s) (parse-factor s)))) (loop `(call * ,ex ,next) (cons next args)))) (if (length= args 1) diff --git a/test/syntax.jl b/test/syntax.jl index eb49a9dfddd60..bfd7beacb89c6 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1357,7 +1357,6 @@ end @test Meta.parse("√3x^2") == Expr(:call, :*, Expr(:call, :√, 3), Expr(:call, :^, :x, 2)) @test Meta.parse("-3x^2") == Expr(:call, :*, -3, Expr(:call, :^, :x, 2)) @test_throws ParseError Meta.parse("2!3") -@test_throws ParseError Meta.parse("2√3") # issue #27914 @test Meta.parse("2f(x)") == Expr(:call, :*, 2, Expr(:call, :f, :x)) @@ -2752,6 +2751,11 @@ end @test_throws ErrorException("syntax: SSAValue objects should not occur in an AST") eval(:(x = $(Core.SSAValue(1)))) @test_throws ErrorException("syntax: Slot objects should not occur in an AST") eval(:(x = $(Core.SlotNumber(1)))) +# juxtaposition of radical symbols (#40094) +@test Meta.parse("2√3") == Expr(:call, :*, 2, Expr(:call, :√, 3)) +@test Meta.parse("2∛3") == Expr(:call, :*, 2, Expr(:call, :∛, 3)) +@test Meta.parse("2∜3") == Expr(:call, :*, 2, Expr(:call, :∜, 3)) + macro m_underscore_hygiene() return :(_ = 1) end From 872954ee80e73431b2214ece2a826caed8e0d76d Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 3 Apr 2021 08:19:26 -0400 Subject: [PATCH 080/439] =?UTF-8?q?document=20rtol=20and=20atol=20for=20?= =?UTF-8?q?=E2=89=88=20in=20at-test=20macro=20(#40061)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * document rtol and atol for ≈ in at-test macro * Update stdlib/Test/docs/src/index.md Co-authored-by: Stefan Karpinski * Update stdlib/Test/docs/src/index.md Co-authored-by: Stefan Karpinski Co-authored-by: Jameson Nash --- stdlib/Test/docs/src/index.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index 8e3ba439ab155..82922773f899b 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -200,6 +200,13 @@ Test Failed at none:1 Evaluated: 1 ≈ 0.999999 ERROR: There was an error during testing ``` +You can specify relative and absolute tolerances by setting the `rtol` and `atol` keyword arguments of `isapprox`, respectively, +after the `≈` comparison: +```jldoctest +julia> @test 1 ≈ 0.999999 rtol=1e-5 +Test Passed +``` +Note that this is not a specific feature of the `≈` but rather a general feature of the `@test` macro: `@test a b key=val` is transformed by the macro into `@test op(a, b, key=val)`. It is, however, particularly useful for `≈` tests. ```@docs Test.@inferred From 78b629f506cf2672f7648f8a2ec7ac6fa8ae1b2f Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 3 Apr 2021 16:35:26 +0400 Subject: [PATCH 081/439] Add a method to similar with Integers (#39933) --- base/abstractarray.jl | 1 + test/abstractarray.jl | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 1531a0eb48b9f..36ab17b4bff9d 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -746,6 +746,7 @@ similar(a::AbstractArray, ::Type{T}, dims::DimOrInd...) where {T} = similar(a, # define this method to convert supported axes to Ints, with the expectation that an offset array # package will define a method with dims::Tuple{Union{Integer, UnitRange}, Vararg{Union{Integer, UnitRange}}} similar(a::AbstractArray, ::Type{T}, dims::Tuple{Union{Integer, OneTo}, Vararg{Union{Integer, OneTo}}}) where {T} = similar(a, T, to_shape(dims)) +similar(a::AbstractArray, ::Type{T}, dims::Tuple{Integer, Vararg{Integer}}) where {T} = similar(a, T, to_shape(dims)) # similar creates an Array by default similar(a::AbstractArray, ::Type{T}, dims::Dims{N}) where {T,N} = Array{T,N}(undef, dims) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 453952fdb81d2..b75869f3ed9d6 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -857,6 +857,18 @@ end @testset "to_shape" begin @test Base.to_shape(()) === () @test Base.to_shape(1) === 1 + @test Base.to_shape(big(1)) === Base.to_shape(1) + @test Base.to_shape(Int8(1)) === Base.to_shape(1) +end + +@testset "issue #39923: similar" begin + for ax in [(big(2), big(3)), (big(2), 3), (UInt64(2), 3), (2, UInt32(3)), + (big(2), Base.OneTo(3)), (Base.OneTo(2), Base.OneTo(big(3)))] + + A = similar(ones(), Int, ax) + @test axes(A) === (Base.OneTo(2), Base.OneTo(3)) + @test eltype(A) === Int + end end @testset "issue #19267" begin From 8d1f0523793cfb37f791e50021dadbe0061bf836 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Sat, 3 Apr 2021 21:36:55 +0900 Subject: [PATCH 082/439] make fuzzy scoring more robust against whitespaces (#39932) --- stdlib/REPL/src/docview.jl | 4 +++- stdlib/REPL/test/docview.jl | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 0e45d5a89345f..7431906209baa 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -550,8 +550,10 @@ function matchinds(needle, haystack; acronym::Bool = false) is = Int[] lastc = '\0' for (i, char) in enumerate(haystack) + while !isempty(chars) && isspace(first(chars)) + popfirst!(chars) # skip spaces + end isempty(chars) && break - while chars[1] == ' ' popfirst!(chars) end # skip spaces if lowercase(char) == lowercase(chars[1]) && (!acronym || !isletter(lastc)) push!(is, i) diff --git a/stdlib/REPL/test/docview.jl b/stdlib/REPL/test/docview.jl index 5001a981a35f8..1cc5037c1c806 100644 --- a/stdlib/REPL/test/docview.jl +++ b/stdlib/REPL/test/docview.jl @@ -41,3 +41,9 @@ end # https://github.com/JuliaLang/julia/issues/37757 @test REPL.insert_hlines(IOBuffer(), nothing) === nothing end + +@testset "fuzzy score" begin + # https://github.com/JunoLab/FuzzyCompletions.jl/issues/7 + # shouldn't throw when there is a space in a middle of query + @test (REPL.matchinds("a ", "a file.txt"); true) +end From aaf2b9fe59188dd41664819751ae27047c1272b2 Mon Sep 17 00:00:00 2001 From: Moritz Schauer Date: Sat, 3 Apr 2021 14:43:09 +0200 Subject: [PATCH 083/439] Verbalize definition of isapprox in docstring (#39765) * Verbalize definition of isapprox * More examples for isapprox --- base/floatfuncs.jl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 2bca2989bab0b..1b3a088524c8e 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -225,9 +225,11 @@ end """ isapprox(x, y; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps, nans::Bool=false[, norm::Function]) -Inexact equality comparison: `true` if `norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))`. The -default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. The keyword -argument `nans` determines whether or not NaN values are considered equal (defaults to false). +Inexact equality comparison. Two numbers compare equal if their relative distance *or* their +absolute distance is within tolerance bounds: `isapprox` returns `true` if +`norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))`. The default `atol` is zero and the +default `rtol` depends on the types of `x` and `y`. The keyword argument `nans` determines +whether or not NaN values are considered equal (defaults to false). For real or complex floating-point values, if an `atol > 0` is not specified, `rtol` defaults to the square root of [`eps`](@ref) of the type of `x` or `y`, whichever is bigger (least precise). @@ -259,13 +261,16 @@ but an absurdly large tolerance if `x` is the # Examples ```jldoctest -julia> 0.1 ≈ (0.1 - 1e-10) +julia> isapprox(0.1, 0.15; atol=0.05) true -julia> isapprox(10, 11; atol = 2) +julia> isapprox(0.1, 0.15; rtol=0.34) true -julia> isapprox([10.0^9, 1.0], [10.0^9, 2.0]) +julia> isapprox(0.1, 0.15; rtol=0.33) +false + +julia> 0.1 + 1e-10 ≈ 0.1 true julia> 1e-10 ≈ 0 @@ -273,6 +278,9 @@ false julia> isapprox(1e-10, 0, atol=1e-8) true + +julia> isapprox([10.0^9, 1.0], [10.0^9, 2.0]) # using `norm` +true ``` """ function isapprox(x::Number, y::Number; From 2ee8c87751a13eb6874ae6e4d27ffd59f3dc5b9e Mon Sep 17 00:00:00 2001 From: Atsushi Sakai Date: Sun, 4 Apr 2021 00:39:59 +0900 Subject: [PATCH 084/439] doc: add cross references in subset-related operators (#39750) --- base/abstractset.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/abstractset.jl b/base/abstractset.jl index 179b9f7be5d4b..659417b7bfd4e 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -246,6 +246,8 @@ function ⊇ end Determine whether every element of `a` is also in `b`, using [`in`](@ref). +See also [`⊊`](@ref), [`⊈`](@ref). + # Examples ```jldoctest julia> issubset([1, 2], [1, 2, 3]) @@ -306,6 +308,8 @@ function ⊋ end Determines if `a` is a subset of, but not equal to, `b`. +See also [`issubset`](@ref) (`⊆`), [`⊈`](@ref). + # Examples ```jldoctest julia> (1, 2) ⊊ (1, 2, 3) @@ -329,6 +333,8 @@ function ⊉ end Negation of `⊆` and `⊇`, i.e. checks that `a` is not a subset of `b`. +See also [`issubset`](@ref) (`⊆`), [`⊊`](@ref). + # Examples ```jldoctest julia> (1, 2) ⊈ (2, 3) From 9c5064311d26dd3122fe537e00335923bde8d795 Mon Sep 17 00:00:00 2001 From: Arsh Sharma <43717431+Sov-trotter@users.noreply.github.com> Date: Sat, 3 Apr 2021 21:38:35 +0530 Subject: [PATCH 085/439] Add hint in case of missing operator (#40304) * Add hint for missing operators * Move hint to it's own error type * Clear the hint handler after displaying hint * Don't clear the already empty array in tests * Don't pop the hint handler * Rename handler --- base/errorshow.jl | 12 ++++++++++++ test/errorshow.jl | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/base/errorshow.jl b/base/errorshow.jl index 814d70ba05f91..7bf602a6b6771 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -319,6 +319,7 @@ function showerror(io::IO, ex::MethodError) "\nYou can convert to a column vector with the vec() function.") end end + Experimental.register_error_hint(noncallable_number_hint_handler, MethodError) Experimental.show_error_hints(io, ex, arg_types_param, kwargs) try show_method_candidates(io, ex, kwargs) @@ -879,3 +880,14 @@ function show(io::IO, ip::InterpreterIP) print(io, " in $(ip.code) at statement $(Int(ip.stmt))") end end + +# handler for displaying a hint in case the user tries to call +# the instance of a number(misses out hte operator) +# eg: (1 + 2)(3 + 4) +function noncallable_number_hint_handler(io, ex, arg_types, kwargs) + if ex.f isa Number + print(io, "\nMaybe you forgot to use an operator such as ") + printstyled(io, "*, ^, %, / etc. ", color=:cyan) + print(io, "?") + end +end diff --git a/test/errorshow.jl b/test/errorshow.jl index 6848bb4a219f4..ccca259a224be 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -634,6 +634,13 @@ catch ex end pop!(Base.Experimental._hint_handlers[DomainError]) # order is undefined, don't copy this +let err_str + err_str = @except_str (1 + 2)(3 + 4) MethodError + @test occursin("objects of type $(typeof(3)) are not callable", err_str) + @test occursin("Maybe you forgot to use an operator such as *, ^, %, / etc. ?", err_str) +end +pop!(Base.Experimental._hint_handlers[MethodError]) # order is undefined, don't copy this + # Execute backtrace once before checking formatting, see #38858 backtrace() From 28e63dc65a3ca3850ac2b530bd8a7a89cda551dc Mon Sep 17 00:00:00 2001 From: Jose Antonio Pereiro Morejon <44244693+josePereiro@users.noreply.github.com> Date: Sat, 3 Apr 2021 12:08:50 -0400 Subject: [PATCH 086/439] Add register_error_hint for UndefVarError (#39850) * add show_error_hints for UndefVarError Hi, I just include the show_error_hints part from #39089 Further relevant discussion in [discourse](https://discourse.julialang.org/t/help-with-register-error-hint/56140/4) * Update errorshow.jl * Update Base.jl Co-authored-by: Simeon Schaub --- base/Base.jl | 6 +++--- base/errorshow.jl | 16 ++++++++++------ test/errorshow.jl | 2 ++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 3186e67b1add6..5a4826fe5df26 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -337,6 +337,9 @@ include("meta.jl") include("stacktraces.jl") using .StackTraces +# experimental API's +include("experimental.jl") + # utilities include("deepcopy.jl") include("download.jl") @@ -360,9 +363,6 @@ include("util.jl") include("asyncmap.jl") -# experimental API's -include("experimental.jl") - # deprecated functions include("deprecated.jl") diff --git a/base/errorshow.jl b/base/errorshow.jl index 7bf602a6b6771..dacc14b683820 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -159,14 +159,18 @@ showerror(io::IO, ex::UndefKeywordError) = print(io, "UndefKeywordError: keyword argument $(ex.var) not assigned") function showerror(io::IO, ex::UndefVarError) + print(io, "UndefVarError: $(ex.var) not defined") + Experimental.show_error_hints(io, ex) +end + +Experimental.register_error_hint(UndefVarError) do io::IO, ex::UndefVarError if ex.var in [:UTF16String, :UTF32String, :WString, :utf16, :utf32, :wstring, :RepString] - return showerror(io, ErrorException(""" - `$(ex.var)` has been moved to the package LegacyStrings.jl: - Run Pkg.add("LegacyStrings") to install LegacyStrings on Julia v0.5-; - Then do `using LegacyStrings` to get `$(ex.var)`. - """)) + println(io) + print(io, """ + `$(ex.var)` has been moved to the package LegacyStrings.jl: + Run Pkg.add("LegacyStrings") to install LegacyStrings on Julia v0.5-; + Then do `using LegacyStrings` to get `$(ex.var)`.""") end - print(io, "UndefVarError: $(ex.var) not defined") end function showerror(io::IO, ex::InexactError) diff --git a/test/errorshow.jl b/test/errorshow.jl index ccca259a224be..9d8ed7e2c6198 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -797,3 +797,5 @@ if Sys.isapple() || (Sys.islinux() && Sys.ARCH === :x86_64) end end end # Sys.isapple() + +@test contains(sprint(Base.showerror, UndefVarError(:UTF16String)), "LegacyStrings") From 03ec87ff04e404e899450c3bd693b9694c2feaea Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Sun, 4 Apr 2021 02:55:01 +1000 Subject: [PATCH 087/439] Adds method to summary() for functions (#39173) --- base/show.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/show.jl b/base/show.jl index 35b4dfdb5efb1..4ff7d6916f0de 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2769,6 +2769,9 @@ function array_summary(io::IO, a, inds) print(io, " with indices ", inds2string(inds)) end +## `summary` for Function +summary(io::IO, f::Function) = show(io, MIME"text/plain"(), f) + """ showarg(io::IO, x, toplevel) From ad513ca527000cbfc8f2506bf17e451f4303905d Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 3 Apr 2021 13:12:10 -0400 Subject: [PATCH 088/439] docs: Reference functions instead of methods (#38986) By referencing methods sometimes and not just functions, there was some duplication and confusion. For instance, we had `get(::Any, ::Any, ::Any)` method and also a `get` function, the latter of which duplicated the documentation for the former on the same page. --- doc/src/base/collections.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 347d2d33724d4..fe4d8f80b1cd0 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -200,10 +200,8 @@ Base.IdDict Base.WeakKeyDict Base.ImmutableDict Base.haskey -Base.get(::Any, ::Any, ::Any) Base.get -Base.get!(::Any, ::Any, ::Any) -Base.get!(::Function, ::Any, ::Any) +Base.get! Base.getkey Base.delete! Base.pop!(::Any, ::Any, ::Any) From 78d3ff41b971d9e510b7d1e07138c3fbd334d13e Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Sat, 3 Apr 2021 19:15:20 +0200 Subject: [PATCH 089/439] Use dot and views in QR code (#38973) The QR-code is quite ancient, and was written without using other linalg routines because views were expensive then. This lets LinearAlgebra to use dot and norm and such, which are likely optimized for special number types. --- stdlib/LinearAlgebra/src/generic.jl | 33 ++++++++--------------------- stdlib/LinearAlgebra/src/qr.jl | 12 +++++------ 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 8e0ca4fb72ad5..17a565ee76cb2 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1487,21 +1487,17 @@ end # Elementary reflection similar to LAPACK. The reflector is not Hermitian but # ensures that tridiagonalization of Hermitian matrices become real. See lawn72 -@inline function reflector!(x::AbstractVector) +@inline function reflector!(x::AbstractVector{T}) where {T} require_one_based_indexing(x) n = length(x) n == 0 && return zero(eltype(x)) @inbounds begin ξ1 = x[1] - normu = abs2(ξ1) - for i = 2:n - normu += abs2(x[i]) - end + normu = norm(x) if iszero(normu) return zero(ξ1/normu) end - normu = sqrt(normu) - ν = copysign(normu, real(ξ1)) + ν = T(copysign(normu, real(ξ1))) ξ1 += ν x[1] = -ν for i = 2:n @@ -1512,29 +1508,18 @@ end end # apply reflector from left -@inline function reflectorApply!(x::AbstractVector, τ::Number, A::StridedMatrix) +@inline function reflectorApply!(x::AbstractVector, τ::Number, A::AbstractMatrix) require_one_based_indexing(x) m, n = size(A) if length(x) != m throw(DimensionMismatch("reflector has length $(length(x)), which must match the first dimension of matrix A, $m")) end m == 0 && return A - @inbounds begin - for j = 1:n - # dot - vAj = A[1, j] - for i = 2:m - vAj += x[i]'*A[i, j] - end - - vAj = conj(τ)*vAj - - # ger - A[1, j] -= vAj - for i = 2:m - A[i, j] -= x[i]*vAj - end - end + @inbounds for j = 1:n + Aj, xj = view(A, 2:m, j), view(x, 2:m) + vAj = conj(τ)*(A[1, j] + dot(xj, Aj)) + A[1, j] -= vAj + axpy!(-vAj, xj, Aj) end return A end diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index c9ba49d2cd1ad..cd5d17565fa3f 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -198,7 +198,7 @@ function qrfactUnblocked!(A::AbstractMatrix{T}) where {T} end # Find index for columns with largest two norm -function indmaxcolumn(A::StridedMatrix) +function indmaxcolumn(A::AbstractMatrix) mm = norm(view(A, :, 1)) ii = 1 for i = 2:size(A, 2) @@ -211,7 +211,7 @@ function indmaxcolumn(A::StridedMatrix) return ii end -function qrfactPivotedUnblocked!(A::StridedMatrix) +function qrfactPivotedUnblocked!(A::AbstractMatrix) m, n = size(A) piv = Vector(UnitRange{BlasInt}(1,n)) τ = Vector{eltype(A)}(undef, min(m,n)) @@ -287,14 +287,14 @@ julia> a = [1 2; 3 4] 3 4 julia> qr!(a) -ERROR: InexactError: Int64(-3.1622776601683795) +ERROR: InexactError: Int64(3.1622776601683795) Stacktrace: [...] ``` """ -qr!(A::StridedMatrix, ::Val{false}) = qrfactUnblocked!(A) -qr!(A::StridedMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A) -qr!(A::StridedMatrix) = qr!(A, Val(false)) +qr!(A::AbstractMatrix, ::Val{false}) = qrfactUnblocked!(A) +qr!(A::AbstractMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A) +qr!(A::AbstractMatrix) = qr!(A, Val(false)) _qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T)))) From d8b730290d3e098246db5ed777779720d00632ff Mon Sep 17 00:00:00 2001 From: Debraj Bhal <69663512+krishna-vasudev@users.noreply.github.com> Date: Sat, 3 Apr 2021 22:52:48 +0530 Subject: [PATCH 090/439] doc: Add example for NaN comparison (#38953) --- .../manual/integers-and-floating-point-numbers.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 9b5b24637e5ae..8ba962da27184 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -369,6 +369,7 @@ the real number line: | `-Inf16` | `-Inf32` | `-Inf` | negative infinity | a value less than all finite floating-point values | | `NaN16` | `NaN32` | `NaN` | not a number | a value not `==` to any floating-point value (including itself) | + For further discussion of how these non-finite floating-point values are ordered with respect to each other and other floats, see [Numeric Comparisons](@ref). By the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754-2008), these floating-point values are the results of certain arithmetic operations: @@ -409,6 +410,18 @@ NaN julia> 0 * Inf NaN + +julia> NaN == NaN +false + +julia> NaN != NaN +true + +julia> NaN < NaN +false + +julia> NaN > NaN +false ``` The [`typemin`](@ref) and [`typemax`](@ref) functions also apply to floating-point types: From 8b6a778bb46276e46caf95eb8376dcbd5d7b8ef7 Mon Sep 17 00:00:00 2001 From: Benjamin Galliot Date: Sat, 3 Apr 2021 20:18:03 +0200 Subject: [PATCH 091/439] Add test for Unicode named subpatterns and property mixes of scripts and classes. (#40328) --- test/regex.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/regex.jl b/test/regex.jl index 0a28d3464579d..0202dc4758e2f 100644 --- a/test/regex.jl +++ b/test/regex.jl @@ -101,6 +101,17 @@ @test keys(m) == ["a", 2, "b"] end + # Unicode named subpatterns and property mixes of scripts and classes (issues #35322/#35459 and #40231) + let m = match(r"(?\d)[\pZs]*(?<文本>[\p{Han}\p{P}]+)", "1 孔生雪笠,聖裔也。為人蘊藉,工詩。") + @test haskey(m, :numéro) + @test haskey(m, "文本") + @test !haskey(m, "ゑ") + @test (m[:numéro], m[:文本]) == ("1", "孔生雪笠,聖裔也。為人蘊藉,工詩。") + @test (m[1], m[2]) == (m[:numéro], m[:文本]) + @test sprint(show, m) == "RegexMatch(\"1 孔生雪笠,聖裔也。為人蘊藉,工詩。\", numéro=\"1\", 文本=\"孔生雪笠,聖裔也。為人蘊藉,工詩。\")" + @test keys(m) == ["numéro", "文本"] + end + # Backcapture reference in substitution string @test replace("abcde", r"(..)(?Pd)" => s"\gxy\\\1") == "adxy\\bce" @test_throws ErrorException replace("a", r"(?P)" => s"\g") From 12b8948b79c35e45b4c0c24ab8a758785d1d46d9 Mon Sep 17 00:00:00 2001 From: fp4code Date: Sat, 3 Apr 2021 20:24:06 +0200 Subject: [PATCH 092/439] Fixed segfault when adding OffsetArray and UniformScaling (#38544) --- stdlib/LinearAlgebra/src/uniformscaling.jl | 8 ++++---- stdlib/LinearAlgebra/test/uniformscaling.jl | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index c59871e0641ef..13acea982e7e0 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -215,8 +215,8 @@ end function (+)(A::AbstractMatrix, J::UniformScaling) checksquare(A) B = copy_oftype(A, Base._return_type(+, Tuple{eltype(A), typeof(J)})) - @inbounds for i in axes(A, 1) - B[i,i] += J + for i in intersect(axes(A,1), axes(A,2)) + @inbounds B[i,i] += J end return B end @@ -224,8 +224,8 @@ end function (-)(J::UniformScaling, A::AbstractMatrix) checksquare(A) B = convert(AbstractMatrix{Base._return_type(+, Tuple{eltype(A), typeof(J)})}, -A) - @inbounds for i in axes(A, 1) - B[i,i] += J + for i in intersect(axes(A,1), axes(A,2)) + @inbounds B[i,i] += J end return B end diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 27f6641657e81..0f86f0555cba7 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -7,6 +7,8 @@ using Test, LinearAlgebra, Random, SparseArrays const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") isdefined(Main, :Quaternions) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "Quaternions.jl")) using .Main.Quaternions +isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl")) +using .Main.OffsetArrays Random.seed!(123) @@ -504,4 +506,12 @@ end end end +@testset "offset arrays" begin + A = OffsetArray(zeros(4,4), -1:2, 0:3) + @test sum(I + A) ≈ 3.0 + @test sum(A + I) ≈ 3.0 + @test sum(I - A) ≈ 3.0 + @test sum(A - I) ≈ -3.0 +end + end # module TestUniformscaling From c90e8e17d8e017e6eea1eed0a72bbebb77af84b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Sat, 3 Apr 2021 20:39:47 +0200 Subject: [PATCH 093/439] Clean up of Boolean range indexing (#39993) This PR references the following comments: https://github.com/JuliaLang/julia/pull/31829/files#r592887561 https://github.com/JuliaLang/julia/pull/31829/files#r592887003 https://github.com/JuliaLang/julia/pull/39962/files#r592888379 --- base/multidimensional.jl | 2 +- base/range.jl | 30 +++++------------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 7b41476d8d17d..d9251cdebe096 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -278,7 +278,7 @@ module IteratorsMD CartesianIndices(A::AbstractArray) = CartesianIndices(axes(A)) - _convert2ind(sz::Bool) = Base.OneTo(Int(sz)) + _convert2ind(sz::Bool) = Base.OneTo(Int8(sz)) _convert2ind(sz::Integer) = Base.OneTo(sz) _convert2ind(sz::AbstractUnitRange) = first(sz):last(sz) _convert2ind(sz::OrdinalRange) = first(sz):step(sz):last(sz) diff --git a/base/range.jl b/base/range.jl index 54aeef84cae19..cafa048377851 100644 --- a/base/range.jl +++ b/base/range.jl @@ -828,17 +828,7 @@ function getindex(r::AbstractUnitRange, s::AbstractUnitRange{T}) where {T<:Integ @boundscheck checkbounds(r, s) if T === Bool - if length(s) == 0 - return r - elseif length(s) == 1 - if first(s) - return r - else - return range(r[1], length=0) - end - else # length(s) == 2 - return range(r[2], length=1) - end + range(first(s) ? first(r) : last(r), length = Int(last(s))) else f = first(r) st = oftype(f, f + first(s)-1) @@ -857,17 +847,7 @@ function getindex(r::AbstractUnitRange, s::StepRange{T}) where {T<:Integer} @boundscheck checkbounds(r, s) if T === Bool - if length(s) == 0 - return range(first(r), step=one(eltype(r)), length=0) - elseif length(s) == 1 - if first(s) - return range(first(r), step=one(eltype(r)), length=1) - else - return range(first(r), step=one(eltype(r)), length=0) - end - else # length(s) == 2 - return range(r[2], step=one(eltype(r)), length=1) - end + range(first(s) ? first(r) : last(r), step=oneunit(eltype(r)), length = Int(last(s))) else st = oftype(first(r), first(r) + s.start-1) return range(st, step=step(s), length=length(s)) @@ -888,7 +868,7 @@ function getindex(r::StepRange, s::AbstractRange{T}) where {T<:Integer} return range(first(r), step=step(r), length=0) end else # length(s) == 2 - return range(r[2], step=step(r), length=1) + return range(last(r), step=step(r), length=1) end else st = oftype(r.start, r.start + (first(s)-1)*step(r)) @@ -910,7 +890,7 @@ function getindex(r::StepRangeLen{T}, s::OrdinalRange{S}) where {T, S<:Integer} return StepRangeLen{T}(first(r), step(r), 0, 1) end else # length(s) == 2 - return StepRangeLen{T}(r[2], step(r), 1, 1) + return StepRangeLen{T}(last(r), step(r), 1, 1) end else # Find closest approach to offset by s @@ -935,7 +915,7 @@ function getindex(r::LinRange{T}, s::OrdinalRange{S}) where {T, S<:Integer} return LinRange(first(r), first(r), 0) end else # length(s) == 2 - return LinRange(r[2], r[2], 1) + return LinRange(last(r), last(r), 1) end else vfirst = unsafe_getindex(r, first(s)) From 595b0e69603c0c27431c10e65793ca698ba39a96 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 3 Apr 2021 14:40:13 -0400 Subject: [PATCH 094/439] correct reverseind example for Unicode (#40156) --- base/strings/basic.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index c9108966325f8..750c6e83df99b 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -676,13 +676,16 @@ cases where `v` contains non-ASCII characters.) # Examples ```jldoctest -julia> r = reverse("Julia") -"ailuJ" +julia> s = "Julia🚀" +"Julia🚀" -julia> for i in 1:length(r) - print(r[reverseind("Julia", i)]) +julia> r = reverse(s) +"🚀ailuJ" + +julia> for i in eachindex(s) + print(r[reverseind(r, i)]) end -Julia +Julia🚀 ``` """ reverseind(s::AbstractString, i::Integer) = thisind(s, ncodeunits(s)-i+1) From b0b4a482965d68dbd4083968f78f66b9122f4aac Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Sat, 3 Apr 2021 20:43:43 +0200 Subject: [PATCH 095/439] fix inconsistent BroadcastFunction behavior (#40330) fixes #40309 --- base/broadcast.jl | 8 +++++++- test/broadcast.jl | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index de3263a64011b..c6d079d318acf 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -1300,7 +1300,13 @@ macro __dot__(x) esc(__dot__(x)) end -@inline broadcasted_kwsyntax(f, args...; kwargs...) = broadcasted((args...)->f(args...; kwargs...), args...) +@inline function broadcasted_kwsyntax(f, args...; kwargs...) + if isempty(kwargs) # some BroadcastStyles dispatch on `f`, so try to preserve its type + return broadcasted(f, args...) + else + return broadcasted((args...) -> f(args...; kwargs...), args...) + end +end @inline function broadcasted(f, args...) args′ = map(broadcastable, args) broadcasted(combine_styles(args′...), f, args′...) diff --git a/test/broadcast.jl b/test/broadcast.jl index 6e97d609a42b0..28c56b2c2e636 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -1015,3 +1015,7 @@ end @test a_ == dropdims(a .* c, dims=(findall(==(1), size(c))...,)) end end + +# issue 40309 +@test Base.broadcasted_kwsyntax(+, [1], [2]) isa Broadcast.Broadcasted{<:Any, <:Any, typeof(+)} +@test Broadcast.BroadcastFunction(+)(2:3, 2:3) === 4:2:6 From d0438c02b1a896d95c7a318158a551722a61497a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 3 Apr 2021 18:53:20 -0400 Subject: [PATCH 096/439] Revert "Fix some inferability issues in SparseArrays" (#40332) --- stdlib/SparseArrays/src/sparsematrix.jl | 10 +++------- stdlib/SparseArrays/src/sparsevector.jl | 17 +++++++++-------- stdlib/SparseArrays/test/sparse.jl | 12 ++++++------ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 5bcdc9fff9ff3..7bd988d881152 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -2045,7 +2045,7 @@ function _findr(op, A, region, Tv) throw(ArgumentError("array slices must be non-empty")) else ri = Base.reduced_indices0(A, region) - return (zeros(Tv, ri), zeros(Ti, ri)) + return (similar(A, ri), zeros(Ti, ri)) end end @@ -3274,10 +3274,6 @@ dropstored!(A::AbstractSparseMatrixCSC, ::Colon) = dropstored!(A, :, :) # Sparse concatenation -promote_idxtype(::AbstractSparseMatrixCSC{<:Any, Ti}) where {Ti} = Ti -promote_idxtype(::AbstractSparseMatrixCSC{<:Any, Ti}, X::AbstractSparseMatrixCSC...) where {Ti} = - promote_type(Ti, promote_idxtype(X...)) - function vcat(X::AbstractSparseMatrixCSC...) num = length(X) mX = Int[ size(x, 1) for x in X ] @@ -3292,7 +3288,7 @@ function vcat(X::AbstractSparseMatrixCSC...) end Tv = promote_eltype(X...) - Ti = promote_idxtype(X...) + Ti = promote_eltype(map(x->rowvals(x), X)...) nnzX = Int[ nnz(x) for x in X ] nnz_res = sum(nnzX) @@ -3344,7 +3340,7 @@ function hcat(X::AbstractSparseMatrixCSC...) n = sum(nX) Tv = promote_eltype(X...) - Ti = promote_idxtype(X...) + Ti = promote_eltype(map(x->rowvals(x), X)...) colptr = Vector{Ti}(undef, n+1) nnzX = Int[ nnz(x) for x in X ] diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 30747ffda82e7..777be897ea7df 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -1091,16 +1091,17 @@ function vcat(Xin::_SparseConcatGroup...) X = map(x -> SparseMatrixCSC(issparse(x) ? x : sparse(x)), Xin) vcat(X...) end -hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) = - vcat(_hvcat_rows(rows, X...)...) -function _hvcat_rows((row1, rows...)::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) - if row1 ≤ 0 - throw(ArgumentError("length of block row must be positive, got $row1")) +function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) + nbr = length(rows) # number of block rows + + tmp_rows = Vector{SparseMatrixCSC}(undef, nbr) + k = 0 + @inbounds for i = 1 : nbr + tmp_rows[i] = hcat(X[(1 : rows[i]) .+ k]...) + k += rows[i] end - # provide X[1] separately to convince inference that we don't call hcat() without arguments - return (hcat(X[1], X[2 : row1]...), _hvcat_rows(rows, X[row1+1:end]...)...) + vcat(tmp_rows...) end -_hvcat_rows(::Tuple{}, X::_SparseConcatGroup...) = () # make sure UniformScaling objects are converted to sparse matrices for concatenation promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = SparseMatrixCSC diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 35b1d8aec74d4..ef5159d41031d 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -165,7 +165,7 @@ end sz34 = spzeros(3, 4) se77 = sparse(1.0I, 7, 7) @testset "h+v concatenation" begin - @test @inferred(hvcat((3, 2), se44, sz42, sz41, sz34, se33)) == se77 # [se44 sz42 sz41; sz34 se33] + @test [se44 sz42 sz41; sz34 se33] == se77 @test length(nonzeros([sp33 0I; 1I 0I])) == 6 end @@ -1338,10 +1338,10 @@ end @testset "argmax, argmin, findmax, findmin" begin S = sprand(100,80, 0.5) A = Array(S) - @test @inferred(argmax(S)) == argmax(A) - @test @inferred(argmin(S)) == argmin(A) - @test @inferred(findmin(S)) == findmin(A) - @test @inferred(findmax(S)) == findmax(A) + @test argmax(S) == argmax(A) + @test argmin(S) == argmin(A) + @test findmin(S) == findmin(A) + @test findmax(S) == findmax(A) for region in [(1,), (2,), (1,2)], m in [findmax, findmin] @test m(S, dims=region) == m(A, dims=region) end @@ -2201,7 +2201,7 @@ end # Test that concatenations of pairs of sparse matrices yield sparse arrays @test issparse(vcat(spmat, spmat)) @test issparse(hcat(spmat, spmat)) - @test issparse(@inferred(hvcat((2,), spmat, spmat))) + @test issparse(hvcat((2,), spmat, spmat)) @test issparse(cat(spmat, spmat; dims=(1,2))) # Test that concatenations of a sparse matrice with a dense matrix/vector yield sparse arrays @test issparse(vcat(spmat, densemat)) From 3c0ad21c5000285ed5bbd990ec95cef5d3d93a02 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 3 Apr 2021 18:55:19 -0400 Subject: [PATCH 097/439] test: fix bad copy in #40304 (#40334) --- test/errorshow.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/errorshow.jl b/test/errorshow.jl index 9d8ed7e2c6198..9496e45526c20 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -639,7 +639,6 @@ let err_str @test occursin("objects of type $(typeof(3)) are not callable", err_str) @test occursin("Maybe you forgot to use an operator such as *, ^, %, / etc. ?", err_str) end -pop!(Base.Experimental._hint_handlers[MethodError]) # order is undefined, don't copy this # Execute backtrace once before checking formatting, see #38858 backtrace() From 0596d5123481460fedb821ed42f428c881c0391b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 4 Apr 2021 01:39:57 -0400 Subject: [PATCH 098/439] remove UndefVarError deprecation from v0.5 (#40333) Looks like this got lost in deprecation removal? --- base/errorshow.jl | 10 ---------- test/errorshow.jl | 2 -- 2 files changed, 12 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index dacc14b683820..5c47824579aad 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -163,16 +163,6 @@ function showerror(io::IO, ex::UndefVarError) Experimental.show_error_hints(io, ex) end -Experimental.register_error_hint(UndefVarError) do io::IO, ex::UndefVarError - if ex.var in [:UTF16String, :UTF32String, :WString, :utf16, :utf32, :wstring, :RepString] - println(io) - print(io, """ - `$(ex.var)` has been moved to the package LegacyStrings.jl: - Run Pkg.add("LegacyStrings") to install LegacyStrings on Julia v0.5-; - Then do `using LegacyStrings` to get `$(ex.var)`.""") - end -end - function showerror(io::IO, ex::InexactError) print(io, "InexactError: ", ex.func, '(') nameof(ex.T) === ex.func || print(io, ex.T, ", ") diff --git a/test/errorshow.jl b/test/errorshow.jl index 9496e45526c20..60d7353adb1e8 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -796,5 +796,3 @@ if Sys.isapple() || (Sys.islinux() && Sys.ARCH === :x86_64) end end end # Sys.isapple() - -@test contains(sprint(Base.showerror, UndefVarError(:UTF16String)), "LegacyStrings") From 89fff18d590db9be84598e0045003b903d48d2df Mon Sep 17 00:00:00 2001 From: Mustafa M Date: Sun, 4 Apr 2021 05:54:36 -0400 Subject: [PATCH 099/439] Fix relpath when path and startpath are in the same drive (#40323) * Fix relpath when path and startpath are in the same drive When startpath == ".", assume the startpath is in the same drive. This subsequently required tweaking the existing logic to then canonicalize the drive casing in instances where the drive casing differs. --- base/path.jl | 14 +++++++++----- test/path.jl | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/base/path.jl b/base/path.jl index 449085c00f26d..88d050e750118 100644 --- a/base/path.jl +++ b/base/path.jl @@ -517,12 +517,16 @@ function relpath(path::String, startpath::String = ".") curdir = "." pardir = ".." path == startpath && return curdir - path_drive, path_without_drive = splitdrive(path) - startpath_drive, startpath_without_drive = splitdrive(startpath) - path_arr = split(abspath(path_without_drive), path_separator_re) - start_arr = split(abspath(startpath_without_drive), path_separator_re) if Sys.iswindows() - lowercase(path_drive) != lowercase(startpath_drive) && return abspath(path) + path_drive, path_without_drive = splitdrive(path) + startpath_drive, startpath_without_drive = splitdrive(startpath) + isempty(startpath_drive) && (startpath_drive = path_drive) # by default assume same as path drive + uppercase(path_drive) == uppercase(startpath_drive) || return abspath(path) # if drives differ return first path + path_arr = split(abspath(path_drive * path_without_drive), path_separator_re) + start_arr = split(abspath(path_drive * startpath_without_drive), path_separator_re) + else + path_arr = split(abspath(path), path_separator_re) + start_arr = split(abspath(startpath), path_separator_re) end i = 0 while i < min(length(path_arr), length(start_arr)) diff --git a/test/path.jl b/test/path.jl index ca772e24d41de..e263b7c7db917 100644 --- a/test/path.jl +++ b/test/path.jl @@ -290,6 +290,10 @@ # Additional cases @test_throws ArgumentError relpath(S("$(sep)home$(sep)user$(sep)dir_withendsep$(sep)"), "") @test_throws ArgumentError relpath(S(""), S("$(sep)home$(sep)user$(sep)dir_withendsep$(sep)")) + + # issue 40237 + path = "..$(sep)a$(sep)b$(sep)c" + @test relpath(abspath(path)) == path end test_relpath() end From 58fba2b3564d30888ce03cfa9ba0840b1ccdac18 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sun, 4 Apr 2021 19:29:44 -0400 Subject: [PATCH 100/439] Use 0.3.13+4 openblas binaries to fix #40279 (#40343) * Use 0.3.13+4 openblas binaries to fix #40279 * Add tests and doctest fixes for #40343 (#40346) * Update checksums * changed a doctest to have nicer output Co-authored-by: Pablo San-Jose --- deps/checksums/gmp | 4 +- deps/checksums/libgit2 | 4 +- deps/checksums/openblas | 184 ++++++++++----------- deps/checksums/pcre | 4 +- deps/checksums/suitesparse | 4 + stdlib/LinearAlgebra/docs/src/index.md | 14 +- stdlib/LinearAlgebra/src/symmetriceigen.jl | 4 +- stdlib/LinearAlgebra/src/tridiag.jl | 8 +- stdlib/LinearAlgebra/test/schur.jl | 26 +++ stdlib/OpenBLAS_jll/Project.toml | 2 +- 10 files changed, 142 insertions(+), 112 deletions(-) diff --git a/deps/checksums/gmp b/deps/checksums/gmp index db01480b953d0..da510e3dc2388 100644 --- a/deps/checksums/gmp +++ b/deps/checksums/gmp @@ -1,3 +1,5 @@ +gmp-6.2.1.tar.bz2/md5/28971fc21cf028042d4897f02fd355ea +gmp-6.2.1.tar.bz2/sha512/8904334a3bcc5c896ececabc75cda9dec642e401fb5397c4992c4fabea5e962c9ce8bd44e8e4233c34e55c8010cc28db0545f5f750cbdbb5f00af538dc763be9 GMP.v6.2.1+0.aarch64-apple-darwin.tar.gz/md5/e805c580078e4d6bcaeb6781cb6d56fa GMP.v6.2.1+0.aarch64-apple-darwin.tar.gz/sha512/62435e80f5fa0b67e2788c8bfc3681426add7a9b2853131bbebe890d1a2d9b54cebaea0860f6ddd0e93e1ae302baba39851d5f58a65acf0b2a9ea1226bb4eea4 GMP.v6.2.1+0.aarch64-linux-gnu-cxx03.tar.gz/md5/5384d6ba6fd408bc71c2781b643cd59a @@ -56,5 +58,3 @@ GMP.v6.2.1+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/1499a265b438cf5169286c1830eb573 GMP.v6.2.1+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/d2e6fe76abe0a0cb1a7445ea93cd5bd0bf9f729aec8df9c76d06a1f6f5e67cce442be69b66950eb33aa22cfda2e5a308f2bade64018a27bebfcb4b7a97e1d047 GMP.v6.2.1+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/fdb4187f617511d8eb19f67f8499a8d0 GMP.v6.2.1+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/bb6d8ead1c20cffebc2271461d3787cfad794fee2b32e23583af6521c0667ed9107805268a996d23d6edcab9fe653e542a210cab07252f7713af0c23feb76fb3 -gmp-6.2.1.tar.bz2/md5/28971fc21cf028042d4897f02fd355ea -gmp-6.2.1.tar.bz2/sha512/8904334a3bcc5c896ececabc75cda9dec642e401fb5397c4992c4fabea5e962c9ce8bd44e8e4233c34e55c8010cc28db0545f5f750cbdbb5f00af538dc763be9 diff --git a/deps/checksums/libgit2 b/deps/checksums/libgit2 index 0603b2ab9a662..6d836e4a4501c 100644 --- a/deps/checksums/libgit2 +++ b/deps/checksums/libgit2 @@ -1,3 +1,5 @@ +libgit2-7f4fa178629d559c037a1f72f79f79af9c1ef8ce.tar.gz/md5/c6a819fb0bf924df61e1595624a0988a +libgit2-7f4fa178629d559c037a1f72f79f79af9c1ef8ce.tar.gz/sha512/3de9c042115b309dae3b8e0008edf2e762addd90a7bdb54b3cf634811271ab9dbfea35656650eb53a3faec73caf33ed199fb885ec21f611c79d909d9f4fe48c5 LibGit2.v1.2.3+0.aarch64-apple-darwin.tar.gz/md5/0eb4d35fa6078de8da3dc79a420d5bc5 LibGit2.v1.2.3+0.aarch64-apple-darwin.tar.gz/sha512/aff23e9d56827be54d8f515489eed92d9cb4d9a1b69c12bbee44fa1343ebc906b38b082c11e6ecb227d256de5cba19b2f3a03c022b88809a33c225c34db08f7c LibGit2.v1.2.3+0.aarch64-linux-gnu.tar.gz/md5/f2f31aa978e43aa68a0e73107067c7cd @@ -30,5 +32,3 @@ LibGit2.v1.2.3+0.x86_64-unknown-freebsd.tar.gz/md5/e1623fd3f8f564085d47ec650a40e LibGit2.v1.2.3+0.x86_64-unknown-freebsd.tar.gz/sha512/295d55b78b21ef1c2ba471c8b5618b168dd633e986db9e1ec3e9630e352446ab18e8fd0992010b6afdd922463bb285bc45885a8b35a502d574553fe61c1f7b9f LibGit2.v1.2.3+0.x86_64-w64-mingw32.tar.gz/md5/c845901c4d9dc145f76469d45abad934 LibGit2.v1.2.3+0.x86_64-w64-mingw32.tar.gz/sha512/21951f3bc902f30b8cc75c3af233aa7fe8457e412e7758d556bf71de149c7f2325a5c4c204a7a462cc6a61b3dcb90f0d25e684ffd8617b0a1505a1d31cf2f69a -libgit2-7f4fa178629d559c037a1f72f79f79af9c1ef8ce.tar.gz/md5/c6a819fb0bf924df61e1595624a0988a -libgit2-7f4fa178629d559c037a1f72f79f79af9c1ef8ce.tar.gz/sha512/3de9c042115b309dae3b8e0008edf2e762addd90a7bdb54b3cf634811271ab9dbfea35656650eb53a3faec73caf33ed199fb885ec21f611c79d909d9f4fe48c5 diff --git a/deps/checksums/openblas b/deps/checksums/openblas index 722bd059bfd85..05b7ab29f55b7 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,94 +1,94 @@ -OpenBLAS.v0.3.13+3.aarch64-apple-darwin-libgfortran5.tar.gz/md5/8604b202881c267dc73330e81722c2d4 -OpenBLAS.v0.3.13+3.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/9adc2e3234d3eeb6b0d970498b4b80427b32252fb76f9b28245c84a589cb20349dde2ff2822a26302bbb97ddcfbfa4ffbf98d6881f3c1684a6acce1fe3c3bd8f -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran3.tar.gz/md5/33e09a2f2d4abac4b272faff4d85ff23 -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/e3faf2f1de1244a6715c2cca032944b2ed0ff03c43bc617d5243738b3b02e4a87c93545beae7d3d5fae829389b20b303c2f3c59617031b3858438b03e19e1182 -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran4.tar.gz/md5/e3f9326cbcf0c1475c3b15498ce7dbc9 -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/fcb338fbf314e9421c711d84078948829936c710335e210d9f5d5a9c3e281f37d50abd6912543857ab325b8d6af7cef3266ea7ef3b74eb46b63b59ccb0c34882 -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran5.tar.gz/md5/b60363440ca1f92ec312bb0f3be60f08 -OpenBLAS.v0.3.13+3.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/45be2d0259ddd67c1f7b53d60dd3af74cb51f2bd83aa308a14e03488452563d0099521101d37ba37e44e1f80981608f1cc8f05539e90b3b7bb53735098b49bee -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran3.tar.gz/md5/f3d5076cc0d15a7516dfcb94214b91e5 -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran3.tar.gz/sha512/6015eb06ce1bb9b63434cd1561e9866a89b30afb104300089b0745a7beabc390415b033f317d687e10894c0b5f73794798ca50d2eeb27e10d03ce5eb4808682e -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran4.tar.gz/md5/579def3457520102a98d4114686b2a19 -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran4.tar.gz/sha512/c8887e1f0331cee22c02e96fa829f82f9fa571f97fcaacee5714da113345ef779c987e4565a09ab84104db7fb08ae741cee118da7e05ee86ebe72c55d36ed245 -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran5.tar.gz/md5/ba72ad025cbf670c15ce092403d6a40c -OpenBLAS.v0.3.13+3.aarch64-linux-musl-libgfortran5.tar.gz/sha512/ba1fbb3e70d63490cc94502651babd71c88f0aa430a334308e9abe5f3fdcb41ba1652fd9cfedb88ba19da460589318bae816f50e8fad917d87f3542d9e15e71b -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/998bcfd194dc81449e7cfdd553128547 -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/34e7730cf5dd58887566890a5ca7571989be29c0d824b6374ff6a06db20218945c868e8b224e9fa8dfc2388e9d3f9f1bba051202cb2ebcf5f0c37d985433d0d9 -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/6d3548f1992a6104e2a929b726b9d4e1 -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/ae7604b788ac0a1210be4c8cfdd1428426c8d8c13839fb2a970c3f3265daa978487c2bd572d83ff926a13f0f01afe49aa8230452002242622e915990b20856f3 -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/f9001a75f9b953bcc80be5b2a429d31b -OpenBLAS.v0.3.13+3.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/8afec322b5922242e225273ec4787a98e1fde9f6c9ebb785fa0e1a579327d7e9a3f7095f0891f4da83e0e75b63224d812984f62930310a27b9da95bdfb883028 -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/daa9a1fb3c4424688b46aec8fd4cee51 -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/6fb73a80b571c2f40a39f512b0626da62a6e10b1ded8e6f816796a9121a03ce84dd1a6a852a89d7815edf867332c60d03843030405d8d5ec0bc4be5e4b5034af -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/a01df5e91de4c24963367ffcfc12dc49 -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/893a5ad53ec1d5d0917b95ea424936778276db7bacfd7f807551de299ad5b886552fe681ea374043156daf763434d78129e5e8e783ef56d360651de8f610b1e5 -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/9d32ba768cb1f3723153a0921f83ddd2 -OpenBLAS.v0.3.13+3.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/1b7b22c5d5827ea542e1a275af1807303614f62c50a3f799ddd099e8546adf7c75ee7771fe627904c28d78bd1ed2a9ee16f11e1e63e2e02567ab725a5b4a723e -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/9471ef8b127fae0d7cd76a876da0e2f1 -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/53e83a7f1abcb2465d2440e6ffcc8981b67908d1920bdd627fa7d09e78388a0d90d6e06881f2f8b187755ca61a144f95e0839358b1890d914b117e13701dc00e -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/4d9125d5a35b37b5bf411257748209b2 -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/419f20c048c2a60b1f75ea095ede7c7079a4711e07850612b916d395b9b9e7014c01328269a13b1025718f7e2fa8f384343d5797e78941b091f806711800ac59 -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/b05d4c436a309f862f0345e6d770e712 -OpenBLAS.v0.3.13+3.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/e136fe5ca3016715d657f792a832099f4e4b8f29b7e5e18b83b4706c9e1f421c9457f50dbf99b940b9663f3316677796eb38c6c391ed2135f308bee1ac59389f -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/a9c01d75a82bad9cdb640402dcad81d9 -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/6143d3e2fc094d837c6d37047496aa3a4f4c5d01f3fb72e47c681c144b6af02c6b0310932910c0f3aac9a7e19c2bc0c14e0f792fc2e9193aaa1448bce6ccb84d -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/c59422761f5b7d9696a4c1c505787f41 -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/22984386ea44e0e07889d89208556cc65af038b34e95f199aacb1499dc7c1e8086c7e2c05179bbd9723f0e40e791a348bbb8db6634c954efe7f79e4676fe36f2 -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/29e90223144b14a357f42e44724c11d8 -OpenBLAS.v0.3.13+3.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/37b36ce6fe8fd14df505da7a0f57bdf5884fe5b030902a95794923a69d30eba7bc93a2da662db5648aa90bc95a88bd95625b3eb2e90a67fc9349f8f0e930ef64 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran3.tar.gz/md5/28791e1d052d430c42220c18b0d6df61 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran3.tar.gz/sha512/679d10e7ae4c2a8d38943ef20eb075ed9bc2ecb74dd4fb8e476c67b07659ce2fab39fb3bd30034dd7ed2d4d4103597a394e868642a92095de00188e373e38cd7 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran4.tar.gz/md5/ca5dca3237f0b718e8f8603c3cb1e472 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran4.tar.gz/sha512/914ab098759866ab3cd368b136ca6d2382a597ef426422314229a5f39344530e7c89f248c011eb183b8bde68e8d2dbd51ed7d0b6b1438c63322a100470378271 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran5.tar.gz/md5/d0fdd71df8ad278b1054fe2a2e133807 -OpenBLAS.v0.3.13+3.i686-linux-gnu-libgfortran5.tar.gz/sha512/5c0cbbe3992b60a5c51760257f2eebf54113db0ad93de3c8f5f9ed1aa64ccb2a5485ccfea9e127ca473d910cddccaa5e278f93c90328fe770c78557c46f7d57b -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran3.tar.gz/md5/215c7e2db8890d637cc63707b13dc0c6 -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran3.tar.gz/sha512/710e60446d05ad5f61e24f14769144ee621729973769f1e970df2fe330f821379af549f9dfbac6bb5034477443c063e0f7bcfe7cfe848f37ea4a9e44fc0af602 -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran4.tar.gz/md5/27a879f4c90c1509365f7b4712ac7313 -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran4.tar.gz/sha512/188fe3ad0b214d4b75f53f63c39183e609f34f8e0d70cce221bd46d3fac659318479413d65f66238f01c4d3c699224ac5d0e007bbfd27bdea527d36a37c22017 -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran5.tar.gz/md5/83547926ba627e621437f7843a8ddac7 -OpenBLAS.v0.3.13+3.i686-linux-musl-libgfortran5.tar.gz/sha512/425e8534e5efdf1c6e10ba63ead9e57e687f0a61892d64de0a36f0beaf845cbd9ad914d564fba5d57a343316c5e6d768af991a15c40cad0b0d00304f4d05f6b8 -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran3.tar.gz/md5/6f1994558d66532e3723d5a4d0bb01ad -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran3.tar.gz/sha512/52de4b2a43e512496a14c8d01987df0d75f78eef9ae273dace45ede477a04ee47ad70535566dd50bf9ea0c752625f8ad57e70d7dbee8f4e123fdb08fd4729b7b -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran4.tar.gz/md5/4a74f60ac55729a0a94d3f664a42ea59 -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran4.tar.gz/sha512/94d77add6def979b01da61026994174f0b9f4a6a4f3d57a3994fcc4091e69b6dcb5dca004ca75fa7fc93ca256847094c99eb97b5ccf274d6412608f0ccd06c2b -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran5.tar.gz/md5/6e01d0fb2859715b6821d216431325af -OpenBLAS.v0.3.13+3.i686-w64-mingw32-libgfortran5.tar.gz/sha512/667ee31f42614a6e99ffbc67668a320aba2b315684c812c3dda18929f2dc1199c56b39cbf012970950a5e5ac12b6f3d4ad6cf126448074b6b0fbe5dd665ce915 -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/e117edbb8c90a7d998c45a6764dc4354 -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/906f73b660439e0f453bd81d6b32cd59f954556a202d1ff7fc28c44d0b3eccfeb94f926eb91515b7b2047c342c152de25d007e3dc5d9b5646368d35c8d491cc7 -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/9c2d20df24b2fbe8a46bff4c2892be4f -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/916340447ef790e0fc80a37ad6b1bc173bcda7176204dac70a62d49176b08a2d90862cbe9587c6704548cdce71f41424d35746e2e73fea19841d26da02afd233 -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/8bbad84a47b5aa9ef3ac7621b5faa190 -OpenBLAS.v0.3.13+3.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/35fadabc402fd38fdcabf91da9d22745d92fe25d434276f79075ed0574ffe6a55964a77a8f50a22a0e5d0aaffbee17b1d5e415d7fd7f4b3f0b09fed3b64256b6 -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran3.tar.gz/md5/0813317427a6a7a49306b0e448c5a5fb -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/50686a37ff7511e786e8544b64d94c02a84f95d75e3dfb477aa3e504c6404ca9e3679add9a8491228e62343cd8e493933399dec654b016b431127171bf94cbcc -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran4.tar.gz/md5/ab6bd7d9c409102bf586a8aed4ebd13a -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/bd9d1d1901004f775df626fb640d8631ccb4de985b5964fe62cf0058e419184f2d9250e20c6341add1add892d2011e0d21d3823536a2b647f7ca78f60db489c8 -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran5.tar.gz/md5/e369283ebd3ebd30fa05204ca53a5cf7 -OpenBLAS.v0.3.13+3.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/24d19a0fc08421493713e3a61b7c9519346d8237e0f74f74fe98bd34cdd0031d084cef7d46f43c53bfb7f24bf7e7bd0899f03df7dd167c4762b0f9c3d4173289 -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran3.tar.gz/md5/8a4063223249acc7be6b0fff2e7204b7 -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/13ca28a88c9f5e61f1716a7244b9085b3e463a658bc414b2d3a16413ab448799081a3d92c7e67c71b702ab5337b5c9399f9a070c0e38d5ceb06526d4739129cf -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran4.tar.gz/md5/84cba3ec45759145675c96c269e48240 -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/a66872e004eeabedc3963d9cb341df2ceb46da66f97a6103fedc7b900adff9b63503b2fed87565cdb972112d881cf668a72a4a666fb16e75abaaee3e8df720d3 -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran5.tar.gz/md5/f71a6b64bca5a25132db4626749020bd -OpenBLAS.v0.3.13+3.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/03a0315a48aaa4424adebc6670e1ec1c2819836eccfb8b8f327f66d8ec482b4ab45b76f1fe8cc6eefe408b33106fa0389690457e047ebbb08c1c8aa66281e87b -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran3.tar.gz/md5/98baf7e5285880268bdf86d5c4fe694b -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran3.tar.gz/sha512/263f4d98fc89c8d7593707b10859c369bf72bd80aeff26f2f7e9484b4360c9faa28ace33ae3cd5a5f0c4870d59c8412e9be3fac212af5c17689bd609d2054481 -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran4.tar.gz/md5/6113194122b3fce00fe129af2ae48526 -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran4.tar.gz/sha512/fd2b93ded2be5a2850cdfe55a02465f41b0bf1f8b5a0d7341ea475de08f870c45ee320d15492a526fd6f4490e2b944898c974a0dcc1a0294e3e585593e4ad734 -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran5.tar.gz/md5/902b38c5eba17b699763936f6f7c4875 -OpenBLAS.v0.3.13+3.x86_64-linux-musl-libgfortran5.tar.gz/sha512/34eeaa9cc9fb7e9b1a2151f98b6d2bf36a6c0edc87e02fd3aa322547be4ea195f2c1739b90a9027dfbc9512f4af9e8d76e6d78c1a1f8cce9173aebcedf47c550 -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/7b01325206d4e9ebc9d8169ab19cafa0 -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/81a34637bd98073e64ecd11682e2ecfa7906f1032cb2549ea72adc83d471790baf3b6c43f6247a33469c7c275fe444f488f0a04139d131fb4a52919a25f05ab0 -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/6df828a5f9cb90e6d897e7934a6d447c -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/5a703ce4e1360ec76c782237e827cd99ad65696a659cfd1dbeb9ad8d1b751c4943e3edde4c53c2f1c17afdcde83bdfae60f6116a3602a96129f16f77e2faf5bc -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/2c9cb0175741399c21f7a685795833b3 -OpenBLAS.v0.3.13+3.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/6f4b51bfa30310c85c813b03e6fa44acae7479935cb9fdc977286519bb00b3860f1ea502a3c2072884739dd108103dcfb9ee167a9d31d1b31fca7f087fc7dc7e -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/ed4b72c7f57927c3b89efcbd7e9bb21b -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/c6663ec291ad053523f6a1d4c5fcbed83c7a412f534db90e0f690582e5ec19c7bcc65c903322e7e2a75a453caf5cdd9251ba7a83de5d44b8cd45ca022c6f7fdb -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/960dca2ea7e3d72ddbe918ed61787f25 -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/a78af513c6b6b5a0fd7fa5f5b5c598d4724025eb12e57653559c772092095b0c8b2e50ea174205d28aef9c3c503999674882c3771f02a2683bdfa62abb1f4474 -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/d3a0f811ae8e70033c9c75c9684dba2e -OpenBLAS.v0.3.13+3.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/0db4a8aba989d291b9ffbb8856f0922b38f84e6d321ef9ffdb56b455dacbf32252109c505e8f1d37f7e75c20d839ae3490a9353bbcfaefe7bab7fbef3b0a0c1f openblas-d2b11c47774b9216660e76e2fc67e87079f26fa1.tar.gz/md5/d50510c8b60b477b1ece4abafe66bf4d openblas-d2b11c47774b9216660e76e2fc67e87079f26fa1.tar.gz/sha512/95ce349353bea5e9c30455410b92fa9ebc833e58163a53a65b396c76fddf19147a323a3c69eea5892354488c67b027e20dc9b03754a0988f3bc8a4e9ad446b8b +OpenBLAS.v0.3.13+4.aarch64-apple-darwin-libgfortran5.tar.gz/md5/4f2775159e7d83cd4447e3fd7868e7e1 +OpenBLAS.v0.3.13+4.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/f8bc618d335ac1782531784bcf4d76fea587142fb0546ccacaeb0fcfae1e8a59a5ef1afbba33277521a56fe580467b0574afa7c97ad82cd76f5e154d2a390557 +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran3.tar.gz/md5/4317a7a4f2bc43dac7e9853288143c9a +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/2e0dda3cfe8b2df6e652499c8ed5a21ebc02357bee555e121d516c8c1a015521034c5887907956e8fe3d1f9cf892e0cd6a8fe63cc97a60ee12e6ce1d501a56a5 +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran4.tar.gz/md5/4a91f26298c2f20930a2759da48cd565 +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/2005ce29bd7b35c828b672776a4a65e9555d7cdcbeb093220075a85f69cc3168bc669648ad2795c63f5c78c5c6495e0e3328741789b3360a4320689e83645315 +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran5.tar.gz/md5/3bd51556c64a5b2b1e1b556040462d17 +OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/b278d8d8e95e3e8c79167659144bb0d876cd086f8323324faa10f85f9f382e94e613b19e7f677b692b5402fb2d6c54ad134d8c55b7441c48f32e90272eeb884f +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran3.tar.gz/md5/db27b95b3dc9f9705910eaec615f3098 +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran3.tar.gz/sha512/e6b8d98b0b24e219df5cf53956b1f2aedb3ac65d362dffb714d7c9110dbcca4bf47576464c5b6a1309354eb6f2ba48a932d665e552b90f2f679d7a5f5bb7b4f3 +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran4.tar.gz/md5/66f42f04c7f9deda3440426685f60f5e +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran4.tar.gz/sha512/bedb7b3b7151bb3e4241d7e05271e0d0b6cbec0c4c8f4f8a5e32fdef753a3d34f5fb7c51a5e8d9e522fa4dd7a3eac6dfac75a9fef36175ef923a7b1e399f8818 +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran5.tar.gz/md5/1418bfbd20bf08cfc6e018f9e6534569 +OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran5.tar.gz/sha512/a78c8b68e418580a7d40c8be50a5abb06b4ca04a4e5daa5579db394da509119a417a1c191f1eccdd308559f81f7c1a8e324ecb0a86d74a6e68a4748a59b95643 +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/d8ba3b4c6e681e5ca74526b39389b762 +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/57cb062d9eb7b94934cd9448f2a92e5b5bfd28fd98aff2d94efb3e3aa40c2ae53a03c928babf266d46cd91d9ff9c5e51b7f8690b98136f511ab9374e1d16636a +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/0a6d019340b05ded69a11b0ae5be68d3 +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/bbcb4cde29c004e4f146cb31c95de10c900123483019888b0319be93882139416a03971dc8cca6c3c2b3419ea5f6f8108641b43caae63fd0b3db93cb24e17655 +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/f73dce27904ccc783ee8f3ce951c5d47 +OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/6f914e74c0c9279370515ee799696cb710ecf79cd9685652b78a0d3deffd39783327b67d305d041454f083fd744eb80cc242a1de8d0c60cdb905e0da200a22d0 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/4ea568b64c1afc936dbc74ffe024fdf9 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/6fdf28b89b78aa06fe715258920ab0d2a142f3b134eaebcddae8f5c5bcb4e2e33009934840ec5d0ccbfd6b33c5f3f46e7b99d8d73afe14ba420b096caa1778e0 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/e0ac5999379580d28c739c28f53eb3b0 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/20641f43324267db53b9593bd7ed08909499838679344af99767cd56e7e47a223a0ca7c5d5b9857d8c09e8b044228d10e828a55167f93bea4f48bd523029fac3 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/a2f55bd99b92e9a4dbb8cac2d67da859 +OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/ba2529bf0387019a2749dca1c3ef1b85226ce10624e52d5422bb998178d2d7a4c2015a62f93288bde7fded6edc65c5e148d606dea5901f4d21d8d1a34f49fdeb +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/2f4ed5c58bed415739fdf0fb8e322ed5 +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/1900cd263760c5deecd097b24e1b60d9082deaf68e5173c77a2b750188b51ed6611f157f06861be76c0796d08ab8f177024d0725435c15fe10c857a7fb384fa7 +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/246b3797012725bfc3de103432d7681c +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/3909bb3ef6e7212df4535198b0027a45804079eabf8bbf17b8826a85f30c55cbb36f63859b036bc27b9231a8697ac2fb5411fafca886e720d8246bc81dd14a6c +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/0e9f2ed5aa7b218037187346d8981112 +OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/26a57c52159c16d7886e25ce4e8a4bc21c903eda09f7720cb5bfb3d7757cd6f9aa0502c4dbb36ca03697937d92ab4f5a98394dc1b950d580806991494327ec68 +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/1590ae03eaa30cb72599513bc826da3d +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/1d12d05e8a60dcaf311e72d5303e4d150dd552c0e8df653bf6f1cc643b6b695c47d2f97a8096c029ef6d45be1d83664040964ab06f9f16f01f51cf1d6b515ee8 +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/c36b060c2fc5913d0e67b466eb023616 +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/921e6d07063a5823529d45830f58437889d63c17c39110a60a37a703fe60d9ba40cd28a703e8f2cfc40825a9a2fc0afb0d39ba985522f8b2a70beb6be7366dbd +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/1c30ccf8a80a0762e5866003667aa219 +OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/c1109c32b2468d4d47cbe3c972330e66671e1e35cae358addf3017df2a4912e36f0f9a8113929f67422034c64935e363e6d4a259dc67b0467b7d5ac7d287cf55 +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran3.tar.gz/md5/f1fffae5cd41d0b275ca2364c4d37b9f +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran3.tar.gz/sha512/2da97e72d42649bbd8a03eda67659410ab99532fbdea3bf1b49298dbd3964c66e23eececcc58e943ed8cea239a0d089ede97720e9f46f1a3800843c41d290e33 +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran4.tar.gz/md5/7d8f65b490d9d2739090d4fff81c60fa +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran4.tar.gz/sha512/fceb132f445f6e596ae8473a14b0c4d23b8f16dea9ebf6df23a94c1343afe842ab3e40915d9d425e30d76950eee3bfdd7dd18ebf13352c5b46c2423c5719ecd6 +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran5.tar.gz/md5/bb2df68fe4f49ed1669450b4ef15843e +OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran5.tar.gz/sha512/3d247832dba3ab2adbd9da9a79702bf64f227faba22bcb50828971299ef3f377ddbc424f9c3c625d159feca0dd781ca9de259317d8d7035ed60a45a4ff545c3f +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran3.tar.gz/md5/2609e74add74c2b36e3eb05ffe1639d0 +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran3.tar.gz/sha512/621ded00ea9708d520f18329bb649bbdb1b2e8a2c38a1b1611b39deb5e97443fcd9c5be2aaeed595c368e37f9d895c4bcb22a4544b1c3cde86d8c7de68ed403e +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran4.tar.gz/md5/a39578b29870bca9708882806c4f8309 +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran4.tar.gz/sha512/e2b79008d56c9afb685163186d40719fdb4cf62f2956c20d82d997549af447d936fdff2d2b232689d6a15840a72a6341e8a5962eeff11c748277de648d8c565b +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran5.tar.gz/md5/2d17bc3fcbb5dcef7f6d4613d67afcf9 +OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran5.tar.gz/sha512/8181ff5218b557a9bb5b25854b3d38e08730cda1c0a7396c13a3fd3c7583e04e843793d3fa1b17bfb58eed19c2e1d4b3867fd5df4651fe37d84bbf19c1362ee7 +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran3.tar.gz/md5/882e9ab41d7fe18e08530d3f4480fa03 +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran3.tar.gz/sha512/2243b59ea4c14f0611ac6dd6a7a9a8f2beed61f2a65084a89aeacf79c16ac198de508aa2f34ca586c8af7029bbde3f29b05b4e8e97777a1a8546afad1113fdd0 +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran4.tar.gz/md5/e14ce353b77e2e80063c9c07b77d4bd5 +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran4.tar.gz/sha512/a8e362f9dd9ca06ef6efc4927782e12e097941babc18b17c72f8d69aade416cc1886a89e34161dcda756ec3821a33f2bedf4dca4d641186a9e8e3db9486a56b4 +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran5.tar.gz/md5/f718d5df066df8998961c041fd53e35b +OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran5.tar.gz/sha512/6b5702c135a576915bc4cc6fc1127521bb2d10d28797d24941c15ae870b70fbb62a25e63842da35ab641346fae68368476edbd0751f8b6108db2e5457d507aef +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/6e294aa03b2e48913bee0b389ea93645 +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/4ddc7c0f3013f2069e5924f4f96f8d882b473b01e3dfbf7e865bf3a93fed94a57b4477c3fbfd4f2579f2ba78832bfbbe0c2d597e8d636aeb7dc283dd0514144b +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/8020654c032cd0e99630517e7f56e980 +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/92373120aaf73cdc6046e1c4a81541469a38025e181ec3fd7334d126fd78afb1db0342e431a293821a1226b30b20aa75aa60059cca11ee327ba452f7e378efe0 +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/8300b47873e3a81a61b8c280332e3764 +OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/163e35797e4a0f9ed15dd5d4707cb0ab54d0de548264c71c983050dc07015a8e329657429821a8a52a59805445169af80e12999fe61814ba5ab4685d66db9ad2 +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran3.tar.gz/md5/2459157e3b79311b181e88213d2afbf6 +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/723187b212869a4d9abbac586ee934b4d0cbb50430f336d7d9b7130207241189058abe324c6fe3a4ec9eb8007653d2fa548affbe7880f6aa3a2dd40d099f6fc5 +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran4.tar.gz/md5/5df3ecfad7ecc904852c1123b1e7c8cc +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/643d115abe50d10a09d2f02254b797ba2b81deb3173457a96c81d1f02036330c208b7ac545cf41838864ddd1be16567ad685cc2e5899df4993b423cf2c2ad34b +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran5.tar.gz/md5/3de8f778d3aa3102227fed3c0540843a +OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/69343d8baaa8c435e219d640df79f7a314dc67e494d50acb67fe13f8f5fd16d0bb84b19f575afc9ebb2db79d3e7dd08ccfda7a8143f80a00ecd5b8056ddac6b1 +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran3.tar.gz/md5/46114a6da46772f5a13330d1c4786f57 +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/a805be012462ed47bf153cbb7f2fe476e9988f57165927e4c6ce5e344c6580a6547f492d0df555e4f4f34c4a55efb179c32451f0c7143419543c9a10566a5fe6 +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran4.tar.gz/md5/84e64d74834762a018fa403c3bbe0f77 +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/112c073fa91a6a5e01092b0eba062ac9201e3ebbe875a98e5c214f45f05eb7ddc00939d3dd55954b136b6fbe532b7a8aa2dfa91b278d3202ebfc7d9a966fa37d +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran5.tar.gz/md5/020c74f778e0729d5dc1267f7c6a3fd4 +OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/1587083156596a8839972516fc96484dd58dbd5bd134ea3054a843f995f69c8a0a08d174ff2a6ec37961d825d5cc55f99e1daa7828587ee68669026e655c16f8 +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran3.tar.gz/md5/e179ad17125cd6726c641d30e3633edd +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran3.tar.gz/sha512/139f92f57d5c56970f741421d614b2c0c8f2fced0c19ac5615cdd8f84b8c3fda96a56f938a64ccc1431d1938c15ce86fd19b5465b79e814f39e8afdf624068b4 +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran4.tar.gz/md5/a19460cdfb1ab3e334c4a23a7fa40aa8 +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran4.tar.gz/sha512/702ded70c3195ad624b0e03f9bdadc9be8cc5e991b26bb2d863458a908e17d27bcfcee71eec2547e4e43c8afa204103ff6fe2eefe07db4f031d757f4367d9755 +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran5.tar.gz/md5/eba567bf765f5e438e8fee579c1f91b5 +OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran5.tar.gz/sha512/8e02ac4b56b2634e6c9481bba7ca8878ae1dd9f0c153975f7983e6aeab5cb3a03409ee3c237e066bef2da41b8f36483c3a5026b6acc85a77071e73c342cec4bc +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/321c44260b7d2443a177a9839bd5a7a6 +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/ac2f99d265bc44d61d2d7422afc790f9e52d8309e07c810fabab6951dd50993652f2271f591677bfe0d9ba123e7375382b59ce477b8a05d916efa093eb83cdda +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/9e650bc22e9b14320396c5621e25960d +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/847a6d689e81b7296ab08b4ff9881ce1a26af39b76199189b31d10fc0a18a24b9ffafb47c3d81c285a78691fba3c823dbf4a9aa5940b65331a10cc2eaff1b7d7 +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/65e2f7649e70277f90165a97eb19a67d +OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/62602e42c89805ab3963dc2989545a8a0f17ace7193bab527b54c2ca4c5066eefc0f6ef110c0a5e43fd4d6c9e7922be7e40a1ac9813b7fd1b3873756d9785675 +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/ad7ad7a00aae93c8347171c2319895ed +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/a87c5e5c7917885916cd38379944f9eb4830748d5488037834cfd6f87e50b35133a94906c56fd4f9c3716e8c3ea4f00ae214b3edbad86f0a4ccf89653eba5c7b +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/ab072184c8caf97ad243937701bfbeb8 +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/0ed921eda9756e262a840bdc4ec4f91c419f18efc15511b3ab5eb4407bade5b73cfdc8b9e8c2d42c1cd500a98729d452040bd41fe3080d5fdec30e12841fe975 +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/532b261f05ee1c0f131a55ba138df9c6 +OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/407279412cc912cf56cdafd5569eddfdca92dc01a045fb3450b9cedb9c9d2efbcf01d44bf8de94c197c4bad398e911ad651ac08a3ccd3741c1ad30661451471a diff --git a/deps/checksums/pcre b/deps/checksums/pcre index 05a06f9844ddf..f7e1fa0c1a3ba 100644 --- a/deps/checksums/pcre +++ b/deps/checksums/pcre @@ -1,3 +1,5 @@ +pcre2-10.36.tar.bz2/md5/bd7e7421ff3fa2e2d5429229ecfad095 +pcre2-10.36.tar.bz2/sha512/fc2a920562c80c3d31cedd94028fab55314ae0fb168cac7178f286c344a11fc514939edc3b83b8e0b57c872db4e595fd5530fd1d4b8c779be629553e9ec965a3 PCRE2.v10.36.0+2.aarch64-apple-darwin.tar.gz/md5/12ac3bee39df3a79f868f6463964953b PCRE2.v10.36.0+2.aarch64-apple-darwin.tar.gz/sha512/a1a1312931deb7f742f80886188babcf9c179ed3f156626fb23d92633fde896d1ee9b2d72cd99ae4a1f8048971b6d939e9b0b10c455d4eeec24b265968593486 PCRE2.v10.36.0+2.aarch64-linux-gnu.tar.gz/md5/32240ccddee3040aeedcbe69ea52fcad @@ -30,5 +32,3 @@ PCRE2.v10.36.0+2.x86_64-unknown-freebsd.tar.gz/md5/97410029c0b6ed5f7fb0d14e1f121 PCRE2.v10.36.0+2.x86_64-unknown-freebsd.tar.gz/sha512/229e910759da2959ddef83ca89e05a050c266b8e755c85dfce6a786658be541911c3b78a0fca7dfdee1b41fbbdccf57da75cf9fe45fd2821dba8d2aaeabfd538 PCRE2.v10.36.0+2.x86_64-w64-mingw32.tar.gz/md5/39827564bca329768e0380bd79b869fe PCRE2.v10.36.0+2.x86_64-w64-mingw32.tar.gz/sha512/4579049b99fca3334d726b0ca1f07524d1643a758e375b5b02b8f294ba7d9c2a4130da1a1523de29033233a8848105b3cb660e15bb4a759593405d805ee99883 -pcre2-10.36.tar.bz2/md5/bd7e7421ff3fa2e2d5429229ecfad095 -pcre2-10.36.tar.bz2/sha512/fc2a920562c80c3d31cedd94028fab55314ae0fb168cac7178f286c344a11fc514939edc3b83b8e0b57c872db4e595fd5530fd1d4b8c779be629553e9ec965a3 diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 98bf43c0c3a92..82e4a00578de6 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -25,6 +25,10 @@ SuiteSparse.v5.8.1+0.powerpc64le-linux-gnu.tar.gz/sha512/412611fd82923e042001774 SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/md5/d266370cc574c8ca8b2b8a94d6b877f4 SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/sha512/2377d662f91d01229e3c44ec1c5624b6361e823ff90d625acc3bab8f68ada1b3b7b67f4e56c8896f890e5780bd2fcb494b5a1f91c9c7803715eac2a2a4bb938f SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-musl.tar.gz/md5/8a8ade173d751514e03a6987aee56ca1 SuiteSparse.v5.8.1+0.x86_64-linux-musl.tar.gz/sha512/7393063fd2f88bf5dbe1378d6d34206bde446f1ed971d2dd334c3cca96075334f4f8ca69f7d406d532a631fd8a76d739df27dab7928e596a1d38ba9c96fbc9d6 diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 48d44d98f7ca0..e71ac571d0b9b 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -31,20 +31,20 @@ julia> inv(A) As well as other useful operations, such as finding eigenvalues or eigenvectors: ```jldoctest -julia> A = [-4. -17.; 2. 2.] +julia> A = [-4. -9.; 2. 2.] 2×2 Matrix{Float64}: - -4.0 -17.0 - 2.0 2.0 + -4.0 -9.0 + 2.0 2.0 julia> eigvals(A) 2-element Vector{ComplexF64}: - -1.0 - 5.0im - -1.0 + 5.0im + -1.0 - 3.0im + -1.0 + 3.0im julia> eigvecs(A) 2×2 Matrix{ComplexF64}: - 0.945905-0.0im 0.945905+0.0im - -0.166924+0.278207im -0.166924-0.278207im + 0.904534-0.0im 0.904534+0.0im + -0.301511+0.301511im -0.301511-0.301511im ``` In addition, Julia provides many [factorizations](@ref man-linalg-factorizations) which can be used to diff --git a/stdlib/LinearAlgebra/src/symmetriceigen.jl b/stdlib/LinearAlgebra/src/symmetriceigen.jl index 0f18d290b4d62..e98f46d13dcd1 100644 --- a/stdlib/LinearAlgebra/src/symmetriceigen.jl +++ b/stdlib/LinearAlgebra/src/symmetriceigen.jl @@ -99,7 +99,7 @@ julia> eigvals(A, 2:2) julia> eigvals(A) 3-element Vector{Float64}: - -2.1400549446402604 + -2.140054944640259 1.0000000000000002 5.140054944640259 ``` @@ -139,7 +139,7 @@ julia> eigvals(A, -1, 2) julia> eigvals(A) 3-element Vector{Float64}: - -2.1400549446402604 + -2.140054944640259 1.0000000000000002 5.140054944640259 ``` diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 8420750f8f4a1..b19e2b5de1efb 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -330,15 +330,15 @@ julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) julia> eigvals(A) 3-element Vector{Float64}: - -2.1400549446402604 + -2.140054944640259 1.0000000000000002 5.140054944640259 julia> eigvecs(A) 3×3 Matrix{Float64}: - 0.418304 -0.83205 0.364299 - -0.656749 -7.39009e-16 0.754109 - 0.627457 0.5547 0.546448 + 0.418304 0.83205 0.364299 + -0.656749 8.21121e-16 0.754109 + 0.627457 -0.5547 0.546448 julia> eigvecs(A, [1.]) 3×1 Matrix{Float64}: diff --git a/stdlib/LinearAlgebra/test/schur.jl b/stdlib/LinearAlgebra/test/schur.jl index feb0ef8513b89..5d2589dd44afe 100644 --- a/stdlib/LinearAlgebra/test/schur.jl +++ b/stdlib/LinearAlgebra/test/schur.jl @@ -134,4 +134,30 @@ aimg = randn(n,n)/2 end end +@testset "Generalized Schur convergence" begin + # Check for convergence issues, #40279 + problematic_pencils = [ + ( ComplexF64[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 3.7796350217469814 -3.3125635598133054 0.0 0.0 0.0 0.0 0.0 0.0 6.418270043493963 -6.625127119626611 0.0 0.0 0.0 0.0 0.0 -1.0; -3.312563559813306 3.779635021746982 0.0 0.0 0.0 0.0 0.0 0.0 -6.625127119626612 6.418270043493964 -1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 3.7796350217469814 0.0 0.0 -3.3125635598133054 0.0 0.0 0.0 -1.0 6.418270043493963 0.0 0.0 -6.625127119626611 0.0 0.0; 0.0 0.0 0.0 3.779635021746982 -3.312563559813306 0.0 0.0 0.0 0.0 0.0 0.0 6.418270043493964 -6.625127119626612 0.0 -1.0 0.0; 0.0 0.0 0.0 -3.3125635598133054 3.7796350217469814 0.0 0.0 0.0 0.0 0.0 0.0 -6.625127119626611 6.418270043493963 -1.0 0.0 0.0; 0.0 0.0 -3.312563559813306 0.0 0.0 3.779635021746982 0.0 0.0 0.0 0.0 -6.625127119626612 0.0 -1.0 6.418270043493964 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 3.7796350217469814 -3.3125635598133054 0.0 0.0 0.0 -1.0 0.0 0.0 6.418270043493963 -6.625127119626611; 0.0 0.0 0.0 0.0 0.0 0.0 -3.312563559813306 3.779635021746982 -1.0 0.0 0.0 0.0 0.0 0.0 -6.625127119626612 6.418270043493964], + ComplexF64[1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -3.7796350217469814 3.312563559813306 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.3125635598133054 -3.779635021746982 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -3.7796350217469814 0.0 0.0 3.312563559813306 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -3.779635021746982 3.3125635598133054 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.312563559813306 -3.7796350217469814 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.3125635598133054 0.0 0.0 -3.779635021746982 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -3.7796350217469814 3.312563559813306; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.3125635598133054 -3.779635021746982] + ), + ( ComplexF64[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.62 -1.0 0.0 0.0 0.0 0.0 -1.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 -1.0 -2.62 0.0 0.0 0.0 0.0 0.0; 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62 0.0; 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 -1.0 0.0 0.0 0.0 0.0 0.0 -2.62], + ComplexF64[1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0] + ), + ( ComplexF64[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 0.33748484079831426 -0.10323794456968927 0.0 0.0 0.0 0.0 0.0 0.0 -2.5940303184033713 -0.20647588913937853 0.0 0.0 0.0 0.0 0.0 -1.0; -0.10323794456968927 0.3374848407983142 0.0 0.0 0.0 0.0 0.0 0.0 -0.20647588913937853 -2.5940303184033713 -1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.33748484079831426 0.0 0.0 -0.10323794456968927 0.0 0.0 0.0 -1.0 -2.5940303184033713 0.0 0.0 -0.20647588913937853 0.0 0.0; 0.0 0.0 0.0 0.3374848407983142 -0.10323794456968927 0.0 0.0 0.0 0.0 0.0 0.0 -2.5940303184033713 -0.20647588913937853 0.0 -1.0 0.0; 0.0 0.0 0.0 -0.10323794456968927 0.33748484079831426 0.0 0.0 0.0 0.0 0.0 0.0 -0.20647588913937853 -2.5940303184033713 -1.0 0.0 0.0; 0.0 0.0 -0.10323794456968927 0.0 0.0 0.3374848407983142 0.0 0.0 0.0 0.0 -0.20647588913937853 0.0 -1.0 -2.5940303184033713 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.33748484079831426 -0.10323794456968927 0.0 0.0 0.0 -1.0 0.0 0.0 -2.5940303184033713 -0.20647588913937853; 0.0 0.0 0.0 0.0 0.0 0.0 -0.10323794456968927 0.3374848407983142 -1.0 0.0 0.0 0.0 0.0 0.0 -0.20647588913937853 -2.5940303184033713], + ComplexF64[1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.33748484079831426 0.10323794456968927 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.10323794456968927 -0.3374848407983142 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.33748484079831426 0.0 0.0 0.10323794456968927 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.3374848407983142 0.10323794456968927 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.10323794456968927 -0.33748484079831426 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.10323794456968927 0.0 0.0 -0.3374848407983142 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.33748484079831426 0.10323794456968927; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.10323794456968927 -0.3374848407983142] + ), + ( ComplexF64[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 1.7391668762048442 -1.309613611600033 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.150333752409688 -2.619227223200066 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0; -1.3096136116000332 1.739166876204844 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.6192272232000664 2.150333752409688 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.739166876204844 0.0 0.0 -1.3096136116000332 0.0 0.0 0.0 0.0 0.0 -1.0 2.150333752409688 0.0 0.0 -2.6192272232000664 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.739166876204844 0.0 0.0 0.0 0.0 -1.3096136116000332 0.0 -1.0 0.0 0.0 2.150333752409688 0.0 0.0 0.0 0.0 -2.6192272232000664 0.0; 0.0 0.0 0.0 0.0 1.7391668762048442 0.0 0.0 0.0 0.0 -1.309613611600033 0.0 0.0 0.0 0.0 2.150333752409688 -1.0 0.0 0.0 0.0 -2.619227223200066; 0.0 0.0 -1.309613611600033 0.0 0.0 1.7391668762048442 0.0 0.0 0.0 0.0 0.0 0.0 -2.619227223200066 0.0 -1.0 2.150333752409688 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.739166876204844 -1.3096136116000332 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.150333752409688 -2.6192272232000664 0.0 -1.0; 0.0 0.0 0.0 0.0 0.0 0.0 -1.309613611600033 1.7391668762048442 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.619227223200066 2.150333752409688 -1.0 0.0; 0.0 0.0 0.0 -1.309613611600033 0.0 0.0 0.0 0.0 1.7391668762048442 0.0 0.0 0.0 0.0 -2.619227223200066 0.0 0.0 0.0 -1.0 2.150333752409688 0.0; 0.0 0.0 0.0 0.0 -1.3096136116000332 0.0 0.0 0.0 0.0 1.739166876204844 0.0 0.0 0.0 0.0 -2.6192272232000664 0.0 -1.0 0.0 0.0 2.150333752409688], + ComplexF64[1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.7391668762048442 1.3096136116000332 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.309613611600033 -1.739166876204844 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.739166876204844 0.0 0.0 1.309613611600033 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.739166876204844 0.0 0.0 0.0 0.0 1.309613611600033 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.7391668762048442 0.0 0.0 0.0 0.0 1.3096136116000332; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.3096136116000332 0.0 0.0 -1.7391668762048442 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.739166876204844 1.309613611600033 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.3096136116000332 -1.7391668762048442 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.3096136116000332 0.0 0.0 0.0 0.0 -1.7391668762048442 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.309613611600033 0.0 0.0 0.0 0.0 -1.739166876204844] + ), + ( ComplexF64[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0; 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230788 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007; 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769246 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230784 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769246 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230784 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.90076923076925 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0000000000000007 -12.019230769230788; -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 -6.009615384615393 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384622 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769244 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615393 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384622 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769244 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.490384615384624 -1.0000000000000007 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -12.019230769230784 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.900769230769248], + ComplexF64[1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615393 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615393 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384622 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615392 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384622 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.009615384615394 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -6.490384615384624] + )] + + for (A, B) in problematic_pencils + f = schur(A, B) + @test f.Q*f.S*f.Z' ≈ A + @test f.Q*f.T*f.Z' ≈ B + end +end + end # module TestSchur diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index e732272c12e09..b3bf88b2afb57 100644 --- a/stdlib/OpenBLAS_jll/Project.toml +++ b/stdlib/OpenBLAS_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenBLAS_jll" uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.13+3" +version = "0.3.13+4" [deps] CompilerSupportLibraries_jll = "e66e0078-7015-5450-92f7-15fbd957f2ae" From b7809051397dddc70408bb4670b8094bb126c157 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Mon, 5 Apr 2021 10:37:56 -0700 Subject: [PATCH 101/439] Fix real matrix sqrt and log for edge cases (#40144) * Add failing tests * Improve 2x2 real sqrt for scalar diagonal * Avoid sylvester if zero is a solution * Avoid unnecessary sqrt * Use correct variable names * Avoid erroring due to NaNs * Exactly adapt Higham's algorithm, with hypot * Remove unreachable branch * Add failing tests * Handle overflow/underflow * Invert instead of dividing * Apply d=0 constraint from standardized real schur form * Handle underflow * Avoid underflow/overflow in log diagonal blocks * Add tests for log underflow/overflow --- stdlib/LinearAlgebra/src/triangular.jl | 46 ++++++++++++++++---------- stdlib/LinearAlgebra/test/dense.jl | 32 ++++++++++++++++++ 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index cfc4e948d8d3d..1752d29a9ec65 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -2156,12 +2156,17 @@ end # 35(4), (2013), C394–C410. # Eq. 6.1 Base.@propagate_inbounds function _log_diag_block_2x2!(A, A0) - a, b, c, d = A0[1,1], A0[1,2], A0[2,1], A0[2,2] - bc = b * c - s = sqrt(-bc) + a, b, c = A0[1,1], A0[1,2], A0[2,1] + # avoid underflow/overflow for large/small b and c + s = sqrt(abs(b)) * sqrt(abs(c)) θ = atan(s, a) t = θ / s - a1 = log(a^2 - bc) / 2 + au = abs(a) + if au > s + a1 = log1p((s / au)^2) / 2 + log(au) + else + a1 = log1p((au / s)^2) / 2 + log(s) + end A[1,1] = a1 A[2,1] = c*t A[1,2] = b*t @@ -2435,25 +2440,30 @@ function _sqrt_quasitriu_offdiag_block!(R, A) return R end +# real square root of 2x2 diagonal block of quasi-triangular matrix from real Schur +# decomposition. Eqs 6.8-6.9 and Algorithm 6.5 of +# Higham, 2008, "Functions of Matrices: Theory and Computation", SIAM. Base.@propagate_inbounds function _sqrt_real_2x2!(R, A) - a11, a21, a12, a22 = A[1, 1], A[2, 1], A[1, 2], A[2, 2] - θ = (a11 + a22) / 2 - μ² = -(a11 - a22)^2 / 4 - a21 * a12 - μ = sqrt(μ²) - if θ > 0 - α = sqrt((sqrt(θ^2 + μ²) + θ) / 2) - else - α = μ / sqrt(2 * (sqrt(θ^2 + μ²) - θ)) - end + # in the real Schur form, A[1, 1] == A[2, 2], and A[2, 1] * A[1, 2] < 0 + θ, a21, a12 = A[1, 1], A[2, 1], A[1, 2] + # avoid overflow/underflow of μ + # for real sqrt, |d| ≤ 2 max(|a12|,|a21|) + μ = sqrt(abs(a12)) * sqrt(abs(a21)) + α = _real_sqrt(θ, μ) c = 2α - d = α - θ / c - R[1, 1] = a11 / c + d + R[1, 1] = α R[2, 1] = a21 / c R[1, 2] = a12 / c - R[2, 2] = a22 / c + d + R[2, 2] = α return R end +# real part of square root of θ+im*μ +@inline function _real_sqrt(θ, μ) + t = sqrt((abs(θ) + hypot(θ, μ)) / 2) + return θ ≥ 0 ? t : μ / 2t +end + Base.@propagate_inbounds function _sqrt_quasitriu_offdiag_block_1x1!(R, A, i, j) Rii = R[i, i] Rjj = R[j, j] @@ -2522,7 +2532,9 @@ Base.@propagate_inbounds function _sqrt_quasitriu_offdiag_block_2x2!(R, A, i, j) Rii = @view R[irange, irange] Rjj = @view R[jrange, jrange] Rij = @view R[irange, jrange] - _sylvester_2x2!(Rii, Rjj, Rij) + if !iszero(Rij) && !all(isnan, Rij) + _sylvester_2x2!(Rii, Rjj, Rij) + end return R end diff --git a/stdlib/LinearAlgebra/test/dense.jl b/stdlib/LinearAlgebra/test/dense.jl index 0c86fec9242b5..1cd9c8e6898b2 100644 --- a/stdlib/LinearAlgebra/test/dense.jl +++ b/stdlib/LinearAlgebra/test/dense.jl @@ -889,6 +889,38 @@ end end end +@testset "issue #40141" begin + x = [-1 -eps() 0 0; eps() -1 0 0; 0 0 -1 -eps(); 0 0 eps() -1] + @test sqrt(x)^2 ≈ x + + x2 = [-1 -eps() 0 0; 3eps() -1 0 0; 0 0 -1 -3eps(); 0 0 eps() -1] + @test sqrt(x2)^2 ≈ x2 + + x3 = [-1 -eps() 0 0; eps() -1 0 0; 0 0 -1 -eps(); 0 0 eps() Inf] + @test all(isnan, sqrt(x3)) + + # test overflow/underflow handled + x4 = [0 -1e200; 1e200 0] + @test sqrt(x4)^2 ≈ x4 + + x5 = [0 -1e-200; 1e-200 0] + @test sqrt(x5)^2 ≈ x5 + + x6 = [1.0 1e200; -1e-200 1.0] + @test sqrt(x6)^2 ≈ x6 +end + +@testset "matrix logarithm block diagonal underflow/overflow" begin + x1 = [0 -1e200; 1e200 0] + @test exp(log(x1)) ≈ x1 + + x2 = [0 -1e-200; 1e-200 0] + @test exp(log(x2)) ≈ x2 + + x3 = [1.0 1e200; -1e-200 1.0] + @test exp(log(x3)) ≈ x3 +end + @testset "issue #7181" begin A = [ 1 5 9 2 6 10 From 454fc51714c9ba2a5122268fb9405e6f6f4bfc11 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 5 Apr 2021 21:13:58 -0400 Subject: [PATCH 102/439] argmin ranges bug: you cannot pass an unsorted array to searchsorted --- base/range.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/range.jl b/base/range.jl index cafa048377851..41120e1bcdaf0 100644 --- a/base/range.jl +++ b/base/range.jl @@ -705,7 +705,7 @@ function argmin(r::AbstractRange) elseif step(r) > 0 firstindex(r) else - first(searchsorted(r, last(r))) + lastindex(r) end end @@ -720,7 +720,7 @@ function argmax(r::AbstractRange) if isempty(r) throw(ArgumentError("range must be non-empty")) elseif step(r) > 0 - first(searchsorted(r, last(r))) + lastindex(r) else firstindex(r) end From 40d4f4a0d71b3129282e58b9a2f9b7f930ad13d3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 5 Apr 2021 20:30:25 -0400 Subject: [PATCH 103/439] searchsorted ranges: simplify code, fix bug with Unsigned needle This avoids computing `length` unnecessarily, which often requires a division, and is therefore often expensive. --- base/sort.jl | 82 ++++++++++++++++--------------------------------- test/sorting.jl | 45 +++++++++++++++++---------- 2 files changed, 54 insertions(+), 73 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index 6a3883215c0b4..1a994398bea04 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -231,92 +231,62 @@ end function searchsortedlast(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering)::keytype(a) require_one_based_indexing(a) - if step(a) == 0 - lt(o, x, first(a)) ? 0 : length(a) + f, h, l = first(a), step(a), last(a) + if lt(o, x, f) + 0 + elseif h == 0 || !lt(o, x, l) + length(a) else - n = round(Integer, clamp((x - first(a)) / step(a) + 1, 1, length(a))) + n = round(Integer, (x - f) / h + 1) lt(o, x, a[n]) ? n - 1 : n end end function searchsortedfirst(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering)::keytype(a) require_one_based_indexing(a) - if step(a) == 0 - lt(o, first(a), x) ? length(a) + 1 : 1 + f, h, l = first(a), step(a), last(a) + if !lt(o, f, x) + 1 + elseif h == 0 || lt(o, l, x) + length(a) + 1 else - n = round(Integer, clamp((x - first(a)) / step(a) + 1, 1, length(a))) + n = round(Integer, (x - f) / h + 1) lt(o, a[n], x) ? n + 1 : n end end function searchsortedlast(a::AbstractRange{<:Integer}, x::Real, o::DirectOrdering)::keytype(a) require_one_based_indexing(a) - h = step(a) - if h == 0 - lt(o, x, first(a)) ? 0 : length(a) - elseif h > 0 && x < first(a) - firstindex(a) - 1 - elseif h > 0 && x >= last(a) - lastindex(a) - elseif h < 0 && x > first(a) - firstindex(a) - 1 - elseif h < 0 && x <= last(a) - lastindex(a) + f, h, l = first(a), step(a), last(a) + if lt(o, x, f) + 0 + elseif h == 0 || !lt(o, x, l) + length(a) else if o isa ForwardOrdering - fld(floor(Integer, x) - first(a), h) + 1 + fld(floor(Integer, x) - f, h) + 1 else - fld(ceil(Integer, x) - first(a), h) + 1 + fld(ceil(Integer, x) - f, h) + 1 end end end function searchsortedfirst(a::AbstractRange{<:Integer}, x::Real, o::DirectOrdering)::keytype(a) require_one_based_indexing(a) - h = step(a) - if h == 0 - lt(o, first(a), x) ? length(a)+1 : 1 - elseif h > 0 && x <= first(a) - firstindex(a) - elseif h > 0 && x > last(a) - lastindex(a) + 1 - elseif h < 0 && x >= first(a) - firstindex(a) - elseif h < 0 && x < last(a) - lastindex(a) + 1 + f, h, l = first(a), step(a), last(a) + if !lt(o, f, x) + 1 + elseif h == 0 || lt(o, l, x) + length(a) + 1 else if o isa ForwardOrdering - -fld(floor(Integer, -x) + Signed(first(a)), h) + 1 + cld(ceil(Integer, x) - f, h) + 1 else - -fld(ceil(Integer, -x) + Signed(first(a)), h) + 1 + cld(floor(Integer, x) - f, h) + 1 end end end -function searchsortedfirst(a::AbstractRange{<:Integer}, x::Unsigned, o::DirectOrdering)::keytype(a) - require_one_based_indexing(a) - if lt(o, first(a), x) - if step(a) == 0 - length(a) + 1 - else - min(cld(x - first(a), step(a)), length(a)) + 1 - end - else - 1 - end -end - -function searchsortedlast(a::AbstractRange{<:Integer}, x::Unsigned, o::DirectOrdering)::keytype(a) - require_one_based_indexing(a) - if lt(o, x, first(a)) - 0 - elseif step(a) == 0 - length(a) - else - min(fld(x - first(a), step(a)) + 1, length(a)) - end -end - searchsorted(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering) = searchsortedfirst(a, x, o) : searchsortedlast(a, x, o) diff --git a/test/sorting.jl b/test/sorting.jl index 6bf7d60bd859d..718a7f819e203 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -105,7 +105,7 @@ end @test searchsorted(fill(R(1), 15), T(1), 6, 10, Forward) == 6:10 end - for (rg,I) in [(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)] + for (rg,I) in Any[(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)] rg_r = reverse(rg) rgv, rgv_r = [rg;], [rg_r;] for i = I @@ -144,7 +144,7 @@ end @testset "issue 32568" begin for R in numTypes, T in numTypes - for arr in [R[1:5;], R(1):R(5), R(1):2:R(5)] + for arr in Any[R[1:5;], R(1):R(5), R(1):2:R(5)] @test eltype(searchsorted(arr, T(2))) == keytype(arr) @test eltype(searchsorted(arr, T(2), big(1), big(4), Forward)) == keytype(arr) @test searchsortedfirst(arr, T(2)) isa keytype(arr) @@ -164,35 +164,46 @@ end @test searchsorted([1,2], Inf) === 3:2 @test searchsorted(1:2, Inf) === 3:2 - for coll in [ + for coll in Any[ Base.OneTo(10), 1:2, + 0x01:0x02, -4:6, 5:2:10, [1,2], 1.0:4, [10.0,20.0], ] - for huge in [Inf, 1e300] + for huge in Any[Inf, 1e300, typemax(Int64), typemax(UInt64)] @test searchsortedfirst(coll, huge) === lastindex(coll) + 1 - @test searchsortedfirst(coll, -huge)=== firstindex(coll) @test searchsortedlast(coll, huge) === lastindex(coll) - @test searchsortedlast(coll, -huge) === firstindex(coll) - 1 @test searchsorted(coll, huge) === lastindex(coll)+1 : lastindex(coll) - @test searchsorted(coll, -huge) === firstindex(coll) : firstindex(coll) - 1 - - @test searchsortedfirst(reverse(coll), huge, rev=true) === firstindex(coll) - @test searchsortedfirst(reverse(coll), -huge, rev=true) === lastindex(coll) + 1 - @test searchsortedlast(reverse(coll), huge, rev=true) === firstindex(coll) - 1 - @test searchsortedlast(reverse(coll), -huge, rev=true) === lastindex(coll) - @test searchsorted(reverse(coll), huge, rev=true) === firstindex(coll):firstindex(coll) - 1 - @test searchsorted(reverse(coll), -huge, rev=true) === lastindex(coll)+1:lastindex(coll) + if !(eltype(coll) <: Unsigned) + @test searchsortedfirst(reverse(coll), huge, rev=true) === firstindex(coll) + @test searchsortedlast(reverse(coll), huge, rev=true) === firstindex(coll) - 1 + @test searchsorted(reverse(coll), huge, rev=true) === firstindex(coll):firstindex(coll) - 1 + end + + if !(huge isa Unsigned) + @test searchsortedfirst(coll, -huge)=== firstindex(coll) + @test searchsortedlast(coll, -huge) === firstindex(coll) - 1 + @test searchsorted(coll, -huge) === firstindex(coll) : firstindex(coll) - 1 + if !(eltype(coll) <: Unsigned) + @test searchsortedfirst(reverse(coll), -huge, rev=true) === lastindex(coll) + 1 + @test searchsortedlast(reverse(coll), -huge, rev=true) === lastindex(coll) + @test searchsorted(reverse(coll), -huge, rev=true) === lastindex(coll)+1:lastindex(coll) + end + end end end - @testset "issue ##34408" begin + + @test_broken length(reverse(0x1:0x2)) == 2 + @testset "issue #34408" begin r = 1f8-10:1f8 # collect(r) = Float32[9.999999e7, 9.999999e7, 9.999999e7, 9.999999e7, 1.0e8, 1.0e8, 1.0e8, 1.0e8, 1.0e8] - @test_broken searchsorted(collect(r)) == searchsorted(r) + for i in r + @test_broken searchsorted(collect(r), i) == searchsorted(r, i) + end end end @testset "issue #35272" begin @@ -329,7 +340,7 @@ end @test insorted(T(10), R.(collect(1:10)), by=(>=(5))) end - for (rg,I) in [(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)] + for (rg,I) in Any[(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)] rg_r = reverse(rg) rgv, rgv_r = collect(rg), collect(rg_r) for i = I From fedefe913a265581d6ba4444b8bcd6dbf77e333b Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 6 Apr 2021 05:03:45 +0200 Subject: [PATCH 104/439] Normalize (simplify) `UnionAll`s when used as type parameter (#36211) --- src/jltypes.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ test/core.jl | 9 +++++ test/subtype.jl | 2 +- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index 61541c54a808b..2ba69caf1991e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1153,6 +1153,92 @@ static jl_value_t *extract_wrapper(jl_value_t *t JL_PROPAGATES_ROOT) JL_GLOBALLY return NULL; } +int _may_substitute_ub(jl_value_t *v, jl_tvar_t *var, int inside_inv, int *cov_count) JL_NOTSAFEPOINT +{ + if (v == (jl_value_t*)var) { + if (inside_inv) { + return 0; + } + else { + (*cov_count)++; + return *cov_count <= 1 || jl_is_concrete_type(var->ub); + } + } + else if (jl_is_uniontype(v)) { + return _may_substitute_ub(((jl_uniontype_t*)v)->a, var, inside_inv, cov_count) && + _may_substitute_ub(((jl_uniontype_t*)v)->b, var, inside_inv, cov_count); + } + else if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + if (ua->var == var) + return 1; + return _may_substitute_ub(ua->var->lb, var, inside_inv, cov_count) && + _may_substitute_ub(ua->var->ub, var, inside_inv, cov_count) && + _may_substitute_ub(ua->body, var, inside_inv, cov_count); + } + else if (jl_is_datatype(v)) { + int invar = inside_inv || !jl_is_tuple_type(v); + for (size_t i = 0; i < jl_nparams(v); i++) { + if (!_may_substitute_ub(jl_tparam(v,i), var, invar, cov_count)) + return 0; + } + } + else if (jl_is_vararg(v)) { + jl_vararg_t *va = (jl_vararg_t*)v; + int old_count = *cov_count; + if (va->T && !_may_substitute_ub(va->T, var, inside_inv, cov_count)) + return 0; + if (*cov_count > old_count && !jl_is_concrete_type(var->ub)) + return 0; + if (va->N && !_may_substitute_ub(va->N, var, 1, cov_count)) + return 0; + } + return 1; +} + +// Check whether `var` may be replaced with its upper bound `ub` in `v where var<:ub` +// Conditions: +// * `var` does not appear in invariant position +// * `var` appears at most once (in covariant position) and not in a `Vararg` +// unless the upper bound is concrete (diagonal rule) +int may_substitute_ub(jl_value_t *v, jl_tvar_t *var) JL_NOTSAFEPOINT +{ + int cov_count = 0; + return _may_substitute_ub(v, var, 0, &cov_count); +} + +jl_value_t *normalize_unionalls(jl_value_t *t) +{ + JL_GC_PUSH1(&t); + if (jl_is_uniontype(t)) { + jl_uniontype_t *u = (jl_uniontype_t*)t; + jl_value_t *a = NULL; + jl_value_t *b = NULL; + JL_GC_PUSH2(&a, &b); + a = normalize_unionalls(u->a); + b = normalize_unionalls(u->b); + if (a != u->a || b != u->b) { + t = jl_new_struct(jl_uniontype_type, a, b); + } + JL_GC_POP(); + } + else if (jl_is_unionall(t)) { + jl_unionall_t *u = (jl_unionall_t*)t; + jl_value_t *body = normalize_unionalls(u->body); + if (body != u->body) { + JL_GC_PUSH1(&body); + t = jl_new_struct(jl_unionall_type, u->var, body); + JL_GC_POP(); + u = (jl_unionall_t*)t; + } + + if (u->var->lb == u->var->ub || may_substitute_ub(body, u->var)) + t = jl_instantiate_unionall(u, u->var->ub); + } + JL_GC_POP(); + return t; +} + static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals, jl_typeenv_t *prev, jl_typestack_t *stack); static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, @@ -1162,6 +1248,11 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value jl_typename_t *tn = dt->name; int istuple = (tn == jl_tuple_typename); int isnamedtuple = (tn == jl_namedtuple_typename); + if (dt->name != jl_type_typename) { + for (size_t i = 0; i < ntp; i++) + iparams[i] = normalize_unionalls(iparams[i]); + } + // check type cache if (cacheable) { size_t i; diff --git a/test/core.jl b/test/core.jl index 62ca2989abb42..04c261e861ab2 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7560,3 +7560,12 @@ function f18621() end @test f18621() == 1:5 @test [_ for _ in 1:5] == 1:5 + +# issue #35130 +const T35130 = Tuple{Vector{Int}, <:Any} +@eval struct A35130 + x::Vector{Tuple{Vector{Int}, Any}} + A35130(x) = $(Expr(:new, :A35130, :x)) +end +h35130(x) = A35130(Any[x][1]::Vector{T35130}) +@test h35130(T35130[([1],1)]) isa A35130 diff --git a/test/subtype.jl b/test/subtype.jl index 3c720dc4bf032..6956c212301ea 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -140,7 +140,7 @@ function test_diagonal() @test !issub(Type{Tuple{T,Any} where T}, Type{Tuple{T,T}} where T) @test !issub(Type{Tuple{T,Any,T} where T}, Type{Tuple{T,T,T}} where T) @test_broken issub(Type{Tuple{T} where T}, Type{Tuple{T}} where T) - @test_broken issub(Ref{Tuple{T} where T}, Ref{Tuple{T}} where T) + @test issub(Ref{Tuple{T} where T}, Ref{Tuple{T}} where T) @test !issub(Type{Tuple{T,T} where T}, Type{Tuple{T,T}} where T) @test !issub(Type{Tuple{T,T,T} where T}, Type{Tuple{T,T,T}} where T) @test isequal_type(Ref{Tuple{T, T} where Int<:T<:Int}, From bda6b947930136552fe9c26e56c091cf303cd707 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 6 Apr 2021 11:07:15 -0400 Subject: [PATCH 105/439] ensure require_one_based_indexing can constant-fold for ranges (#40358) Refs performance issue noted in #38527 --- base/abstractarray.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 36ab17b4bff9d..6552e7128ef8b 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -96,7 +96,8 @@ end Return `true` if the indices of `A` start with something other than 1 along any axis. If multiple arguments are passed, equivalent to `has_offset_axes(A) | has_offset_axes(B) | ...`. """ -has_offset_axes(A) = _tuple_any(x->Int(first(x))::Int != 1, axes(A)) +has_offset_axes(A) = _tuple_any(x->Int(first(x))::Int != 1, axes(A)) +has_offset_axes(A::AbstractVector) = Int(firstindex(A))::Int != 1 # improve performance of a common case (ranges) has_offset_axes(A...) = _tuple_any(has_offset_axes, A) has_offset_axes(::Colon) = false From 2fc32f2ea247c0c03ea78b229ff159af84c45fb1 Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Tue, 6 Apr 2021 16:19:22 +0100 Subject: [PATCH 106/439] Update Emoji Completions (#39111) * Update Emoji Completions * =new should overwrite old --- stdlib/REPL/src/emoji_symbols.jl | 406 +++++++++++++++++++++++++++++-- 1 file changed, 389 insertions(+), 17 deletions(-) diff --git a/stdlib/REPL/src/emoji_symbols.jl b/stdlib/REPL/src/emoji_symbols.jl index 40f943cf246dd..49a55c97f6564 100644 --- a/stdlib/REPL/src/emoji_symbols.jl +++ b/stdlib/REPL/src/emoji_symbols.jl @@ -1,21 +1,37 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -#= +#== +using Pkg: @pkg_str +pkg"activate --temp" +pkg"add JSON@0.21" + import JSON -emojis = JSON.parsefile(download("https://raw.githubusercontent.com/iamcal/emoji-data/0f0cf4ea8845eb52d26df2a48c3c31c3b8cad14e/emoji_pretty.json")) -result = Dict() -for emj in emojis - name = "\\:" * emj["short_name"] * ":" - unicode = emj["unified"] - if '-' in unicode - continue +function emoji_data(url) + emojis = JSON.parsefile(download(url)) + result = Dict() + for emj in emojis + name = "\\:" * emj["short_name"] * ":" + unicode = emj["unified"] + if '-' in unicode + continue + end + result[name] = "$(Char(parse(UInt32, unicode, base = 16)))" end - result[name] = "$(Char(parse(UInt32, unicode, base = 16)))" + return result end -skeys = sort(collect(keys(result))) +# We combine multiple versions as the data changes, and not only by growing. +result = mapfoldr(emoji_data, merge, [ + # Newer versions must be added to the bottom list as we want the newer versions to + # overwrite the old with names that changed but still keep old ones that were removed + "https://raw.githubusercontent.com/iamcal/emoji-data/0f0cf4ea8845eb52d26df2a48c3c31c3b8cad14e/emoji_pretty.json", + "https://raw.githubusercontent.com/iamcal/emoji-data/e512953312c012f6bd00e3f2ef6bf152ca3710f8/emoji_pretty.json", + ]; + init=Dict() +) +skeys = sort(collect(keys(result))) open("emoji_symbols.jl", "w") do fh println(fh, "const emoji_symbols = Dict(") for key in skeys @@ -34,14 +50,22 @@ const emoji_symbols = Dict( "\\:8ball:" => "🎱", "\\:a:" => "🅰", "\\:ab:" => "🆎", + "\\:abacus:" => "🧮", "\\:abc:" => "🔤", "\\:abcd:" => "🔡", "\\:accept:" => "🉑", + "\\:accordion:" => "🪗", + "\\:adhesive_bandage:" => "🩹", + "\\:adult:" => "🧑", "\\:aerial_tramway:" => "🚡", "\\:airplane:" => "✈", + "\\:airplane_arriving:" => "🛬", + "\\:airplane_departure:" => "🛫", "\\:alarm_clock:" => "⏰", "\\:alien:" => "👽", "\\:ambulance:" => "🚑", + "\\:amphora:" => "🏺", + "\\:anatomical_heart:" => "🫀", "\\:anchor:" => "⚓", "\\:angel:" => "👼", "\\:anger:" => "💢", @@ -76,40 +100,59 @@ const emoji_symbols = Dict( "\\:astonished:" => "😲", "\\:athletic_shoe:" => "👟", "\\:atm:" => "🏧", + "\\:auto_rickshaw:" => "🛺", + "\\:avocado:" => "🥑", + "\\:axe:" => "🪓", "\\:b:" => "🅱", "\\:baby:" => "👶", "\\:baby_bottle:" => "🍼", "\\:baby_chick:" => "🐤", "\\:baby_symbol:" => "🚼", "\\:back:" => "🔙", + "\\:bacon:" => "🥓", + "\\:badger:" => "🦡", + "\\:badminton_racquet_and_shuttlecock:" => "🏸", + "\\:bagel:" => "🥯", "\\:baggage_claim:" => "🛄", + "\\:baguette_bread:" => "🥖", + "\\:ballet_shoes:" => "🩰", "\\:balloon:" => "🎈", "\\:ballot_box_with_check:" => "☑", "\\:bamboo:" => "🎍", "\\:banana:" => "🍌", "\\:bangbang:" => "‼", + "\\:banjo:" => "🪕", "\\:bank:" => "🏦", "\\:bar_chart:" => "📊", "\\:barber:" => "💈", "\\:baseball:" => "⚾", + "\\:basket:" => "🧺", "\\:basketball:" => "🏀", + "\\:bat:" => "🦇", "\\:bath:" => "🛀", "\\:bathtub:" => "🛁", "\\:battery:" => "🔋", "\\:bear:" => "🐻", + "\\:bearded_person:" => "🧔", + "\\:beaver:" => "🦫", "\\:bee:" => "🐝", "\\:beer:" => "🍺", "\\:beers:" => "🍻", - "\\:beetle:" => "🐞", + "\\:beetle:" => "🪲", "\\:beginner:" => "🔰", "\\:bell:" => "🔔", + "\\:bell_pepper:" => "🫑", "\\:bento:" => "🍱", + "\\:beverage_box:" => "🧃", "\\:bicyclist:" => "🚴", "\\:bike:" => "🚲", "\\:bikini:" => "👙", + "\\:billed_cap:" => "🧢", "\\:bird:" => "🐦", "\\:birthday:" => "🎂", + "\\:bison:" => "🦬", "\\:black_circle:" => "⚫", + "\\:black_heart:" => "🖤", "\\:black_joker:" => "🃏", "\\:black_large_square:" => "⬛", "\\:black_medium_small_square:" => "◾", @@ -122,59 +165,88 @@ const emoji_symbols = Dict( "\\:blue_book:" => "📘", "\\:blue_car:" => "🚙", "\\:blue_heart:" => "💙", + "\\:blueberries:" => "🫐", "\\:blush:" => "😊", "\\:boar:" => "🐗", "\\:boat:" => "⛵", "\\:bomb:" => "💣", + "\\:bone:" => "🦴", "\\:book:" => "📖", "\\:bookmark:" => "🔖", "\\:bookmark_tabs:" => "📑", "\\:books:" => "📚", "\\:boom:" => "💥", + "\\:boomerang:" => "🪃", "\\:boot:" => "👢", "\\:bouquet:" => "💐", "\\:bow:" => "🙇", + "\\:bow_and_arrow:" => "🏹", + "\\:bowl_with_spoon:" => "🥣", "\\:bowling:" => "🎳", + "\\:boxing_glove:" => "🥊", "\\:boy:" => "👦", + "\\:brain:" => "🧠", "\\:bread:" => "🍞", + "\\:breast-feeding:" => "🤱", + "\\:bricks:" => "🧱", "\\:bride_with_veil:" => "👰", "\\:bridge_at_night:" => "🌉", "\\:briefcase:" => "💼", + "\\:briefs:" => "🩲", + "\\:broccoli:" => "🥦", "\\:broken_heart:" => "💔", + "\\:broom:" => "🧹", + "\\:brown_heart:" => "🤎", + "\\:bubble_tea:" => "🧋", + "\\:bucket:" => "🪣", "\\:bug:" => "🐛", "\\:bulb:" => "💡", "\\:bullettrain_front:" => "🚅", "\\:bullettrain_side:" => "🚄", + "\\:burrito:" => "🌯", "\\:bus:" => "🚌", "\\:busstop:" => "🚏", "\\:bust_in_silhouette:" => "👤", "\\:busts_in_silhouette:" => "👥", + "\\:butter:" => "🧈", + "\\:butterfly:" => "🦋", "\\:cactus:" => "🌵", "\\:cake:" => "🍰", "\\:calendar:" => "📆", + "\\:call_me_hand:" => "🤙", "\\:calling:" => "📲", "\\:camel:" => "🐫", "\\:camera:" => "📷", + "\\:camera_with_flash:" => "📸", "\\:cancer:" => "♋", "\\:candy:" => "🍬", + "\\:canned_food:" => "🥫", + "\\:canoe:" => "🛶", "\\:capital_abcd:" => "🔠", "\\:capricorn:" => "♑", "\\:car:" => "🚗", "\\:card_index:" => "📇", "\\:carousel_horse:" => "🎠", + "\\:carpentry_saw:" => "🪚", + "\\:carrot:" => "🥕", "\\:cat2:" => "🐈", "\\:cat:" => "🐱", "\\:cd:" => "💿", + "\\:chair:" => "🪑", + "\\:champagne:" => "🍾", "\\:chart:" => "💹", "\\:chart_with_downwards_trend:" => "📉", "\\:chart_with_upwards_trend:" => "📈", "\\:checkered_flag:" => "🏁", + "\\:cheese_wedge:" => "🧀", "\\:cherries:" => "🍒", "\\:cherry_blossom:" => "🌸", "\\:chestnut:" => "🌰", "\\:chicken:" => "🐔", + "\\:child:" => "🧒", "\\:children_crossing:" => "🚸", "\\:chocolate_bar:" => "🍫", + "\\:chopsticks:" => "🥢", "\\:christmas_tree:" => "🎄", "\\:church:" => "⛪", "\\:cinema:" => "🎦", @@ -184,6 +256,7 @@ const emoji_symbols = Dict( "\\:cl:" => "🆑", "\\:clap:" => "👏", "\\:clapper:" => "🎬", + "\\:clinking_glasses:" => "🥂", "\\:clipboard:" => "📋", "\\:clock1030:" => "🕥", "\\:clock10:" => "🕙", @@ -213,10 +286,17 @@ const emoji_symbols = Dict( "\\:closed_lock_with_key:" => "🔐", "\\:closed_umbrella:" => "🌂", "\\:cloud:" => "☁", + "\\:clown_face:" => "🤡", "\\:clubs:" => "♣", + "\\:coat:" => "🧥", + "\\:cockroach:" => "🪳", "\\:cocktail:" => "🍸", + "\\:coconut:" => "🥥", "\\:coffee:" => "☕", + "\\:coin:" => "🪙", + "\\:cold_face:" => "🥶", "\\:cold_sweat:" => "😰", + "\\:compass:" => "🧭", "\\:computer:" => "💻", "\\:confetti_ball:" => "🎊", "\\:confounded:" => "😖", @@ -235,20 +315,30 @@ const emoji_symbols = Dict( "\\:couplekiss:" => "💏", "\\:cow2:" => "🐄", "\\:cow:" => "🐮", + "\\:crab:" => "🦀", "\\:credit_card:" => "💳", "\\:crescent_moon:" => "🌙", + "\\:cricket:" => "🦗", + "\\:cricket_bat_and_ball:" => "🏏", "\\:crocodile:" => "🐊", + "\\:croissant:" => "🥐", + "\\:crossed_fingers:" => "🤞", "\\:crossed_flags:" => "🎌", "\\:crown:" => "👑", "\\:cry:" => "😢", "\\:crying_cat_face:" => "😿", "\\:crystal_ball:" => "🔮", + "\\:cucumber:" => "🥒", + "\\:cup_with_straw:" => "🥤", + "\\:cupcake:" => "🧁", "\\:cupid:" => "💘", + "\\:curling_stone:" => "🥌", "\\:curly_loop:" => "➰", "\\:currency_exchange:" => "💱", "\\:curry:" => "🍛", "\\:custard:" => "🍮", "\\:customs:" => "🛃", + "\\:cut_of_meat:" => "🥩", "\\:cyclone:" => "🌀", "\\:dancer:" => "💃", "\\:dancers:" => "👯", @@ -256,15 +346,22 @@ const emoji_symbols = Dict( "\\:dart:" => "🎯", "\\:dash:" => "💨", "\\:date:" => "📅", + "\\:deaf_person:" => "🧏", "\\:deciduous_tree:" => "🌳", + "\\:deer:" => "🦌", "\\:department_store:" => "🏬", "\\:diamond_shape_with_a_dot_inside:" => "💠", "\\:diamonds:" => "♦", "\\:disappointed:" => "😞", "\\:disappointed_relieved:" => "😥", + "\\:disguised_face:" => "🥸", + "\\:diving_mask:" => "🤿", + "\\:diya_lamp:" => "🪔", "\\:dizzy:" => "💫", "\\:dizzy_face:" => "😵", + "\\:dna:" => "🧬", "\\:do_not_litter:" => "🚯", + "\\:dodo:" => "🦤", "\\:dog2:" => "🐕", "\\:dog:" => "🐶", "\\:dollar:" => "💵", @@ -276,20 +373,29 @@ const emoji_symbols = Dict( "\\:dragon_face:" => "🐲", "\\:dress:" => "👗", "\\:dromedary_camel:" => "🐪", + "\\:drooling_face:" => "🤤", + "\\:drop_of_blood:" => "🩸", "\\:droplet:" => "💧", + "\\:drum_with_drumsticks:" => "🥁", + "\\:duck:" => "🦆", + "\\:dumpling:" => "🥟", "\\:dvd:" => "📀", "\\:e-mail:" => "📧", + "\\:eagle:" => "🦅", "\\:ear:" => "👂", "\\:ear_of_rice:" => "🌾", + "\\:ear_with_hearing_aid:" => "🦻", "\\:earth_africa:" => "🌍", "\\:earth_americas:" => "🌎", "\\:earth_asia:" => "🌏", - "\\:egg:" => "🍳", + "\\:egg:" => "🥚", "\\:eggplant:" => "🍆", "\\:eight_pointed_black_star:" => "✴", "\\:eight_spoked_asterisk:" => "✳", "\\:electric_plug:" => "🔌", "\\:elephant:" => "🐘", + "\\:elevator:" => "🛗", + "\\:elf:" => "🧝", "\\:email:" => "✉", "\\:end:" => "🔚", "\\:envelope_with_arrow:" => "📩", @@ -298,22 +404,41 @@ const emoji_symbols = Dict( "\\:european_post_office:" => "🏤", "\\:evergreen_tree:" => "🌲", "\\:exclamation:" => "❗", + "\\:exploding_head:" => "🤯", "\\:expressionless:" => "😑", "\\:eyeglasses:" => "👓", "\\:eyes:" => "👀", + "\\:face_palm:" => "🤦", + "\\:face_vomiting:" => "🤮", + "\\:face_with_cowboy_hat:" => "🤠", + "\\:face_with_hand_over_mouth:" => "🤭", + "\\:face_with_head_bandage:" => "🤕", + "\\:face_with_monocle:" => "🧐", + "\\:face_with_raised_eyebrow:" => "🤨", + "\\:face_with_rolling_eyes:" => "🙄", + "\\:face_with_symbols_on_mouth:" => "🤬", + "\\:face_with_thermometer:" => "🤒", "\\:facepunch:" => "👊", "\\:factory:" => "🏭", + "\\:fairy:" => "🧚", + "\\:falafel:" => "🧆", "\\:fallen_leaf:" => "🍂", "\\:family:" => "👪", "\\:fast_forward:" => "⏩", "\\:fax:" => "📠", "\\:fearful:" => "😨", + "\\:feather:" => "🪶", "\\:feet:" => "🐾", + "\\:fencer:" => "🤺", "\\:ferris_wheel:" => "🎡", + "\\:field_hockey_stick_and_ball:" => "🏑", "\\:file_folder:" => "📁", "\\:fire:" => "🔥", "\\:fire_engine:" => "🚒", + "\\:fire_extinguisher:" => "🧯", + "\\:firecracker:" => "🧨", "\\:fireworks:" => "🎆", + "\\:first_place_medal:" => "🥇", "\\:first_quarter_moon:" => "🌓", "\\:first_quarter_moon_with_face:" => "🌛", "\\:fish:" => "🐟", @@ -321,17 +446,27 @@ const emoji_symbols = Dict( "\\:fishing_pole_and_fish:" => "🎣", "\\:fist:" => "✊", "\\:flags:" => "🎏", + "\\:flamingo:" => "🦩", "\\:flashlight:" => "🔦", + "\\:flatbread:" => "🫓", "\\:floppy_disk:" => "💾", "\\:flower_playing_cards:" => "🎴", "\\:flushed:" => "😳", + "\\:fly:" => "🪰", + "\\:flying_disc:" => "🥏", + "\\:flying_saucer:" => "🛸", "\\:foggy:" => "🌁", + "\\:fondue:" => "🫕", + "\\:foot:" => "🦶", "\\:football:" => "🏈", "\\:footprints:" => "👣", "\\:fork_and_knife:" => "🍴", + "\\:fortune_cookie:" => "🥠", "\\:fountain:" => "⛲", "\\:four_leaf_clover:" => "🍀", + "\\:fox_face:" => "🦊", "\\:free:" => "🆓", + "\\:fried_egg:" => "🍳", "\\:fried_shrimp:" => "🍤", "\\:fries:" => "🍟", "\\:frog:" => "🐸", @@ -340,25 +475,35 @@ const emoji_symbols = Dict( "\\:full_moon:" => "🌕", "\\:full_moon_with_face:" => "🌝", "\\:game_die:" => "🎲", + "\\:garlic:" => "🧄", "\\:gem:" => "💎", "\\:gemini:" => "♊", + "\\:genie:" => "🧞", "\\:ghost:" => "👻", "\\:gift:" => "🎁", "\\:gift_heart:" => "💝", + "\\:giraffe_face:" => "🦒", "\\:girl:" => "👧", + "\\:glass_of_milk:" => "🥛", "\\:globe_with_meridians:" => "🌐", + "\\:gloves:" => "🧤", + "\\:goal_net:" => "🥅", "\\:goat:" => "🐐", + "\\:goggles:" => "🥽", "\\:golf:" => "⛳", + "\\:gorilla:" => "🦍", "\\:grapes:" => "🍇", "\\:green_apple:" => "🍏", "\\:green_book:" => "📗", "\\:green_heart:" => "💚", + "\\:green_salad:" => "🥗", "\\:grey_exclamation:" => "❕", "\\:grey_question:" => "❔", "\\:grimacing:" => "😬", "\\:grin:" => "😁", "\\:grinning:" => "😀", "\\:guardsman:" => "💂", + "\\:guide_dog:" => "🦮", "\\:guitar:" => "🎸", "\\:gun:" => "🔫", "\\:haircut:" => "💇", @@ -367,10 +512,13 @@ const emoji_symbols = Dict( "\\:hamster:" => "🐹", "\\:hand:" => "✋", "\\:handbag:" => "👜", + "\\:handball:" => "🤾", + "\\:handshake:" => "🤝", "\\:hankey:" => "💩", "\\:hatched_chick:" => "🐥", "\\:hatching_chick:" => "🐣", "\\:headphones:" => "🎧", + "\\:headstone:" => "🪦", "\\:hear_no_evil:" => "🙉", "\\:heart:" => "❤", "\\:heart_decoration:" => "💟", @@ -385,24 +533,36 @@ const emoji_symbols = Dict( "\\:heavy_minus_sign:" => "➖", "\\:heavy_multiplication_x:" => "✖", "\\:heavy_plus_sign:" => "➕", + "\\:hedgehog:" => "🦔", "\\:helicopter:" => "🚁", "\\:herb:" => "🌿", "\\:hibiscus:" => "🌺", "\\:high_brightness:" => "🔆", "\\:high_heel:" => "👠", + "\\:hiking_boot:" => "🥾", + "\\:hindu_temple:" => "🛕", + "\\:hippopotamus:" => "🦛", "\\:hocho:" => "🔪", "\\:honey_pot:" => "🍯", + "\\:hook:" => "🪝", "\\:horse:" => "🐴", "\\:horse_racing:" => "🏇", "\\:hospital:" => "🏥", + "\\:hot_face:" => "🥵", + "\\:hotdog:" => "🌭", "\\:hotel:" => "🏨", "\\:hotsprings:" => "♨", "\\:hourglass:" => "⌛", "\\:hourglass_flowing_sand:" => "⏳", "\\:house:" => "🏠", "\\:house_with_garden:" => "🏡", + "\\:hugging_face:" => "🤗", "\\:hushed:" => "😯", + "\\:hut:" => "🛖", + "\\:i_love_you_hand_sign:" => "🤟", "\\:ice_cream:" => "🍨", + "\\:ice_cube:" => "🧊", + "\\:ice_hockey_stick_and_puck:" => "🏒", "\\:icecream:" => "🍦", "\\:id:" => "🆔", "\\:ideograph_advantage:" => "🉐", @@ -421,8 +581,12 @@ const emoji_symbols = Dict( "\\:japanese_goblin:" => "👺", "\\:japanese_ogre:" => "👹", "\\:jeans:" => "👖", + "\\:jigsaw:" => "🧩", "\\:joy:" => "😂", "\\:joy_cat:" => "😹", + "\\:juggling:" => "🤹", + "\\:kaaba:" => "🕋", + "\\:kangaroo:" => "🦘", "\\:key:" => "🔑", "\\:keycap_ten:" => "🔟", "\\:kimono:" => "👘", @@ -432,78 +596,136 @@ const emoji_symbols = Dict( "\\:kissing_closed_eyes:" => "😚", "\\:kissing_heart:" => "😘", "\\:kissing_smiling_eyes:" => "😙", + "\\:kite:" => "🪁", + "\\:kiwifruit:" => "🥝", + "\\:kneeling_person:" => "🧎", + "\\:knot:" => "🪢", "\\:koala:" => "🐨", "\\:koko:" => "🈁", + "\\:lab_coat:" => "🥼", + "\\:lacrosse:" => "🥍", + "\\:ladder:" => "🪜", + "\\:ladybug:" => "🐞", "\\:large_blue_circle:" => "🔵", "\\:large_blue_diamond:" => "🔷", + "\\:large_blue_square:" => "🟦", + "\\:large_brown_circle:" => "🟤", + "\\:large_brown_square:" => "🟫", + "\\:large_green_circle:" => "🟢", + "\\:large_green_square:" => "🟩", + "\\:large_orange_circle:" => "🟠", "\\:large_orange_diamond:" => "🔶", + "\\:large_orange_square:" => "🟧", + "\\:large_purple_circle:" => "🟣", + "\\:large_purple_square:" => "🟪", + "\\:large_red_square:" => "🟥", + "\\:large_yellow_circle:" => "🟡", + "\\:large_yellow_square:" => "🟨", "\\:last_quarter_moon:" => "🌗", "\\:last_quarter_moon_with_face:" => "🌜", "\\:laughing:" => "😆", + "\\:leafy_green:" => "🥬", "\\:leaves:" => "🍃", "\\:ledger:" => "📒", + "\\:left-facing_fist:" => "🤛", "\\:left_luggage:" => "🛅", "\\:left_right_arrow:" => "↔", "\\:leftwards_arrow_with_hook:" => "↩", + "\\:leg:" => "🦵", "\\:lemon:" => "🍋", "\\:leo:" => "♌", "\\:leopard:" => "🐆", "\\:libra:" => "♎", "\\:light_rail:" => "🚈", "\\:link:" => "🔗", + "\\:lion_face:" => "🦁", "\\:lips:" => "👄", "\\:lipstick:" => "💄", + "\\:lizard:" => "🦎", + "\\:llama:" => "🦙", + "\\:lobster:" => "🦞", "\\:lock:" => "🔒", "\\:lock_with_ink_pen:" => "🔏", "\\:lollipop:" => "🍭", + "\\:long_drum:" => "🪘", "\\:loop:" => "➿", + "\\:lotion_bottle:" => "🧴", "\\:loud_sound:" => "🔊", "\\:loudspeaker:" => "📢", "\\:love_hotel:" => "🏩", "\\:love_letter:" => "💌", "\\:low_brightness:" => "🔅", + "\\:luggage:" => "🧳", + "\\:lungs:" => "🫁", + "\\:lying_face:" => "🤥", "\\:m:" => "Ⓜ", "\\:mag:" => "🔍", "\\:mag_right:" => "🔎", + "\\:mage:" => "🧙", + "\\:magic_wand:" => "🪄", + "\\:magnet:" => "🧲", "\\:mahjong:" => "🀄", "\\:mailbox:" => "📫", "\\:mailbox_closed:" => "📪", "\\:mailbox_with_mail:" => "📬", "\\:mailbox_with_no_mail:" => "📭", + "\\:mammoth:" => "🦣", "\\:man:" => "👨", + "\\:man_and_woman_holding_hands:" => "👫", + "\\:man_dancing:" => "🕺", "\\:man_with_gua_pi_mao:" => "👲", "\\:man_with_turban:" => "👳", + "\\:mango:" => "🥭", "\\:mans_shoe:" => "👞", + "\\:manual_wheelchair:" => "🦽", "\\:maple_leaf:" => "🍁", + "\\:martial_arts_uniform:" => "🥋", "\\:mask:" => "😷", "\\:massage:" => "💆", + "\\:mate_drink:" => "🧉", "\\:meat_on_bone:" => "🍖", + "\\:mechanical_arm:" => "🦾", + "\\:mechanical_leg:" => "🦿", "\\:mega:" => "📣", "\\:melon:" => "🍈", "\\:memo:" => "📝", + "\\:menorah_with_nine_branches:" => "🕎", "\\:mens:" => "🚹", + "\\:merperson:" => "🧜", "\\:metro:" => "🚇", + "\\:microbe:" => "🦠", "\\:microphone:" => "🎤", "\\:microscope:" => "🔬", + "\\:middle_finger:" => "🖕", + "\\:military_helmet:" => "🪖", "\\:milky_way:" => "🌌", "\\:minibus:" => "🚐", "\\:minidisc:" => "💽", + "\\:mirror:" => "🪞", "\\:mobile_phone_off:" => "📴", + "\\:money_mouth_face:" => "🤑", "\\:money_with_wings:" => "💸", "\\:moneybag:" => "💰", "\\:monkey:" => "🐒", "\\:monkey_face:" => "🐵", "\\:monorail:" => "🚝", "\\:moon:" => "🌔", + "\\:moon_cake:" => "🥮", "\\:mortar_board:" => "🎓", + "\\:mosque:" => "🕌", + "\\:mosquito:" => "🦟", + "\\:motor_scooter:" => "🛵", + "\\:motorized_wheelchair:" => "🦼", "\\:mount_fuji:" => "🗻", "\\:mountain_bicyclist:" => "🚵", "\\:mountain_cableway:" => "🚠", "\\:mountain_railway:" => "🚞", "\\:mouse2:" => "🐁", "\\:mouse:" => "🐭", + "\\:mouse_trap:" => "🪤", "\\:movie_camera:" => "🎥", "\\:moyai:" => "🗿", + "\\:mrs_claus:" => "🤶", "\\:muscle:" => "💪", "\\:mushroom:" => "🍄", "\\:musical_keyboard:" => "🎹", @@ -512,8 +734,12 @@ const emoji_symbols = Dict( "\\:mute:" => "🔇", "\\:nail_care:" => "💅", "\\:name_badge:" => "📛", + "\\:nauseated_face:" => "🤢", + "\\:nazar_amulet:" => "🧿", "\\:necktie:" => "👔", "\\:negative_squared_cross_mark:" => "❎", + "\\:nerd_face:" => "🤓", + "\\:nesting_dolls:" => "🪆", "\\:neutral_face:" => "😐", "\\:new:" => "🆕", "\\:new_moon:" => "🌑", @@ -521,6 +747,7 @@ const emoji_symbols = Dict( "\\:newspaper:" => "📰", "\\:ng:" => "🆖", "\\:night_with_stars:" => "🌃", + "\\:ninja:" => "🥷", "\\:no_bell:" => "🔕", "\\:no_bicycles:" => "🚳", "\\:no_entry:" => "⛔", @@ -539,55 +766,89 @@ const emoji_symbols = Dict( "\\:o2:" => "🅾", "\\:o:" => "⭕", "\\:ocean:" => "🌊", + "\\:octagonal_sign:" => "🛑", "\\:octopus:" => "🐙", "\\:oden:" => "🍢", "\\:office:" => "🏢", "\\:ok:" => "🆗", "\\:ok_hand:" => "👌", "\\:ok_woman:" => "🙆", + "\\:older_adult:" => "🧓", "\\:older_man:" => "👴", "\\:older_woman:" => "👵", + "\\:olive:" => "🫒", "\\:on:" => "🔛", "\\:oncoming_automobile:" => "🚘", "\\:oncoming_bus:" => "🚍", "\\:oncoming_police_car:" => "🚔", "\\:oncoming_taxi:" => "🚖", + "\\:one-piece_swimsuit:" => "🩱", + "\\:onion:" => "🧅", "\\:open_file_folder:" => "📂", "\\:open_hands:" => "👐", "\\:open_mouth:" => "😮", "\\:ophiuchus:" => "⛎", "\\:orange_book:" => "📙", + "\\:orange_heart:" => "🧡", + "\\:orangutan:" => "🦧", + "\\:otter:" => "🦦", "\\:outbox_tray:" => "📤", + "\\:owl:" => "🦉", "\\:ox:" => "🐂", + "\\:oyster:" => "🦪", "\\:package:" => "📦", "\\:page_facing_up:" => "📄", "\\:page_with_curl:" => "📃", "\\:pager:" => "📟", "\\:palm_tree:" => "🌴", + "\\:palms_up_together:" => "🤲", + "\\:pancakes:" => "🥞", "\\:panda_face:" => "🐼", "\\:paperclip:" => "📎", + "\\:parachute:" => "🪂", "\\:parking:" => "🅿", + "\\:parrot:" => "🦜", "\\:part_alternation_mark:" => "〽", "\\:partly_sunny:" => "⛅", + "\\:partying_face:" => "🥳", "\\:passport_control:" => "🛂", "\\:peach:" => "🍑", + "\\:peacock:" => "🦚", + "\\:peanuts:" => "🥜", "\\:pear:" => "🍐", "\\:pencil2:" => "✏", "\\:penguin:" => "🐧", "\\:pensive:" => "😔", + "\\:people_hugging:" => "🫂", "\\:performing_arts:" => "🎭", "\\:persevere:" => "😣", + "\\:person_climbing:" => "🧗", + "\\:person_doing_cartwheel:" => "🤸", "\\:person_frowning:" => "🙍", + "\\:person_in_lotus_position:" => "🧘", + "\\:person_in_steamy_room:" => "🧖", + "\\:person_in_tuxedo:" => "🤵", "\\:person_with_blond_hair:" => "👱", + "\\:person_with_headscarf:" => "🧕", "\\:person_with_pouting_face:" => "🙎", + "\\:petri_dish:" => "🧫", "\\:phone:" => "☎", + "\\:pickup_truck:" => "🛻", + "\\:pie:" => "🥧", "\\:pig2:" => "🐖", "\\:pig:" => "🐷", "\\:pig_nose:" => "🐽", "\\:pill:" => "💊", + "\\:pinata:" => "🪅", + "\\:pinched_fingers:" => "🤌", + "\\:pinching_hand:" => "🤏", "\\:pineapple:" => "🍍", "\\:pisces:" => "♓", "\\:pizza:" => "🍕", + "\\:placard:" => "🪧", + "\\:place_of_worship:" => "🛐", + "\\:pleading_face:" => "🥺", + "\\:plunger:" => "🪠", "\\:point_down:" => "👇", "\\:point_left:" => "👈", "\\:point_right:" => "👉", @@ -595,16 +856,24 @@ const emoji_symbols = Dict( "\\:point_up_2:" => "👆", "\\:police_car:" => "🚓", "\\:poodle:" => "🐩", + "\\:popcorn:" => "🍿", "\\:post_office:" => "🏣", "\\:postal_horn:" => "📯", "\\:postbox:" => "📮", "\\:potable_water:" => "🚰", + "\\:potato:" => "🥔", + "\\:potted_plant:" => "🪴", "\\:pouch:" => "👝", "\\:poultry_leg:" => "🍗", "\\:pound:" => "💷", "\\:pouting_cat:" => "😾", "\\:pray:" => "🙏", + "\\:prayer_beads:" => "📿", + "\\:pregnant_woman:" => "🤰", + "\\:pretzel:" => "🥨", + "\\:prince:" => "🤴", "\\:princess:" => "👸", + "\\:probing_cane:" => "🦯", "\\:purple_heart:" => "💜", "\\:purse:" => "👛", "\\:pushpin:" => "📌", @@ -612,19 +881,24 @@ const emoji_symbols = Dict( "\\:question:" => "❓", "\\:rabbit2:" => "🐇", "\\:rabbit:" => "🐰", + "\\:raccoon:" => "🦝", "\\:racehorse:" => "🐎", "\\:radio:" => "📻", "\\:radio_button:" => "🔘", "\\:rage:" => "😡", "\\:railway_car:" => "🚃", "\\:rainbow:" => "🌈", + "\\:raised_back_of_hand:" => "🤚", "\\:raised_hands:" => "🙌", "\\:raising_hand:" => "🙋", "\\:ram:" => "🐏", "\\:ramen:" => "🍜", "\\:rat:" => "🐀", + "\\:razor:" => "🪒", + "\\:receipt:" => "🧾", "\\:recycle:" => "♻", "\\:red_circle:" => "🔴", + "\\:red_envelope:" => "🧧", "\\:registered:" => "®", "\\:relaxed:" => "☺", "\\:relieved:" => "😌", @@ -633,14 +907,22 @@ const emoji_symbols = Dict( "\\:restroom:" => "🚻", "\\:revolving_hearts:" => "💞", "\\:rewind:" => "⏪", + "\\:rhinoceros:" => "🦏", "\\:ribbon:" => "🎀", "\\:rice:" => "🍚", "\\:rice_ball:" => "🍙", "\\:rice_cracker:" => "🍘", "\\:rice_scene:" => "🎑", + "\\:right-facing_fist:" => "🤜", "\\:ring:" => "💍", + "\\:ringed_planet:" => "🪐", + "\\:robot_face:" => "🤖", + "\\:rock:" => "🪨", "\\:rocket:" => "🚀", + "\\:roll_of_paper:" => "🧻", "\\:roller_coaster:" => "🎢", + "\\:roller_skate:" => "🛼", + "\\:rolling_on_the_floor_laughing:" => "🤣", "\\:rooster:" => "🐓", "\\:rose:" => "🌹", "\\:rotating_light:" => "🚨", @@ -650,41 +932,70 @@ const emoji_symbols = Dict( "\\:runner:" => "🏃", "\\:running_shirt_with_sash:" => "🎽", "\\:sa:" => "🈂", + "\\:safety_pin:" => "🧷", + "\\:safety_vest:" => "🦺", "\\:sagittarius:" => "♐", "\\:sake:" => "🍶", + "\\:salt:" => "🧂", "\\:sandal:" => "👡", + "\\:sandwich:" => "🥪", "\\:santa:" => "🎅", + "\\:sari:" => "🥻", "\\:satellite:" => "📡", + "\\:satellite_antenna:" => "📡", + "\\:sauropod:" => "🦕", "\\:saxophone:" => "🎷", + "\\:scarf:" => "🧣", "\\:school:" => "🏫", "\\:school_satchel:" => "🎒", "\\:scissors:" => "✂", + "\\:scooter:" => "🛴", + "\\:scorpion:" => "🦂", "\\:scorpius:" => "♏", "\\:scream:" => "😱", "\\:scream_cat:" => "🙀", + "\\:screwdriver:" => "🪛", "\\:scroll:" => "📜", + "\\:seal:" => "🦭", "\\:seat:" => "💺", + "\\:second_place_medal:" => "🥈", "\\:secret:" => "㊙", "\\:see_no_evil:" => "🙈", "\\:seedling:" => "🌱", + "\\:selfie:" => "🤳", + "\\:sewing_needle:" => "🪡", + "\\:shallow_pan_of_food:" => "🥘", + "\\:shark:" => "🦈", "\\:shaved_ice:" => "🍧", "\\:sheep:" => "🐑", "\\:shell:" => "🐚", "\\:ship:" => "🚢", "\\:shirt:" => "👕", + "\\:shopping_trolley:" => "🛒", + "\\:shorts:" => "🩳", "\\:shower:" => "🚿", + "\\:shrimp:" => "🦐", + "\\:shrug:" => "🤷", + "\\:shushing_face:" => "🤫", "\\:signal_strength:" => "📶", "\\:six_pointed_star:" => "🔯", + "\\:skateboard:" => "🛹", "\\:ski:" => "🎿", - "\\:skin-tone-2:" => "\U1f3fb", - "\\:skin-tone-3:" => "\U1f3fc", - "\\:skin-tone-4:" => "\U1f3fd", - "\\:skin-tone-5:" => "\U1f3fe", - "\\:skin-tone-6:" => "\U1f3ff", + "\\:skin-tone-2:" => "🏻", + "\\:skin-tone-3:" => "🏼", + "\\:skin-tone-4:" => "🏽", + "\\:skin-tone-5:" => "🏾", + "\\:skin-tone-6:" => "🏿", "\\:skull:" => "💀", + "\\:skunk:" => "🦨", + "\\:sled:" => "🛷", "\\:sleeping:" => "😴", + "\\:sleeping_accommodation:" => "🛌", "\\:sleepy:" => "😪", + "\\:slightly_frowning_face:" => "🙁", + "\\:slightly_smiling_face:" => "🙂", "\\:slot_machine:" => "🎰", + "\\:sloth:" => "🦥", "\\:small_blue_diamond:" => "🔹", "\\:small_orange_diamond:" => "🔸", "\\:small_red_triangle:" => "🔺", @@ -693,17 +1004,24 @@ const emoji_symbols = Dict( "\\:smile_cat:" => "😸", "\\:smiley:" => "😃", "\\:smiley_cat:" => "😺", + "\\:smiling_face_with_3_hearts:" => "🥰", + "\\:smiling_face_with_tear:" => "🥲", "\\:smiling_imp:" => "😈", "\\:smirk:" => "😏", "\\:smirk_cat:" => "😼", "\\:smoking:" => "🚬", "\\:snail:" => "🐌", "\\:snake:" => "🐍", + "\\:sneezing_face:" => "🤧", "\\:snowboarder:" => "🏂", "\\:snowflake:" => "❄", "\\:snowman:" => "⛄", + "\\:snowman_without_snow:" => "⛄", + "\\:soap:" => "🧼", "\\:sob:" => "😭", "\\:soccer:" => "⚽", + "\\:socks:" => "🧦", + "\\:softball:" => "🥎", "\\:soon:" => "🔜", "\\:sos:" => "🆘", "\\:sound:" => "🔉", @@ -718,45 +1036,71 @@ const emoji_symbols = Dict( "\\:speaker:" => "🔈", "\\:speech_balloon:" => "💬", "\\:speedboat:" => "🚤", + "\\:spock-hand:" => "🖖", + "\\:sponge:" => "🧽", + "\\:spoon:" => "🥄", + "\\:sports_medal:" => "🏅", + "\\:squid:" => "🦑", + "\\:standing_person:" => "🧍", + "\\:star-struck:" => "🤩", "\\:star2:" => "🌟", "\\:star:" => "⭐", "\\:stars:" => "🌠", "\\:station:" => "🚉", "\\:statue_of_liberty:" => "🗽", "\\:steam_locomotive:" => "🚂", + "\\:stethoscope:" => "🩺", "\\:stew:" => "🍲", "\\:straight_ruler:" => "📏", "\\:strawberry:" => "🍓", "\\:stuck_out_tongue:" => "😛", "\\:stuck_out_tongue_closed_eyes:" => "😝", "\\:stuck_out_tongue_winking_eye:" => "😜", + "\\:stuffed_flatbread:" => "🥙", "\\:sun_with_face:" => "🌞", "\\:sunflower:" => "🌻", "\\:sunglasses:" => "😎", "\\:sunny:" => "☀", "\\:sunrise:" => "🌅", "\\:sunrise_over_mountains:" => "🌄", + "\\:superhero:" => "🦸", + "\\:supervillain:" => "🦹", "\\:surfer:" => "🏄", "\\:sushi:" => "🍣", "\\:suspension_railway:" => "🚟", + "\\:swan:" => "🦢", "\\:sweat:" => "😓", "\\:sweat_drops:" => "💦", "\\:sweat_smile:" => "😅", "\\:sweet_potato:" => "🍠", "\\:swimmer:" => "🏊", "\\:symbols:" => "🔣", + "\\:synagogue:" => "🕍", "\\:syringe:" => "💉", + "\\:t-rex:" => "🦖", + "\\:table_tennis_paddle_and_ball:" => "🏓", + "\\:taco:" => "🌮", "\\:tada:" => "🎉", + "\\:takeout_box:" => "🥡", + "\\:tamale:" => "🫔", "\\:tanabata_tree:" => "🎋", "\\:tangerine:" => "🍊", "\\:taurus:" => "♉", "\\:taxi:" => "🚕", "\\:tea:" => "🍵", + "\\:teapot:" => "🫖", + "\\:teddy_bear:" => "🧸", "\\:telephone_receiver:" => "📞", "\\:telescope:" => "🔭", "\\:tennis:" => "🎾", "\\:tent:" => "⛺", + "\\:test_tube:" => "🧪", + "\\:the_horns:" => "🤘", + "\\:thinking_face:" => "🤔", + "\\:third_place_medal:" => "🥉", + "\\:thong_sandal:" => "🩴", "\\:thought_balloon:" => "💭", + "\\:thread:" => "🧵", "\\:ticket:" => "🎫", "\\:tiger2:" => "🐅", "\\:tiger:" => "🐯", @@ -766,6 +1110,9 @@ const emoji_symbols = Dict( "\\:tokyo_tower:" => "🗼", "\\:tomato:" => "🍅", "\\:tongue:" => "👅", + "\\:toolbox:" => "🧰", + "\\:tooth:" => "🦷", + "\\:toothbrush:" => "🪥", "\\:top:" => "🔝", "\\:tophat:" => "🎩", "\\:tractor:" => "🚜", @@ -784,6 +1131,8 @@ const emoji_symbols = Dict( "\\:truck:" => "🚚", "\\:trumpet:" => "🎺", "\\:tulip:" => "🌷", + "\\:tumbler_glass:" => "🥃", + "\\:turkey:" => "🦃", "\\:turtle:" => "🐢", "\\:tv:" => "📺", "\\:twisted_rightwards_arrows:" => "🔀", @@ -802,11 +1151,15 @@ const emoji_symbols = Dict( "\\:u7981:" => "🈲", "\\:u7a7a:" => "🈳", "\\:umbrella:" => "☔", + "\\:umbrella_with_rain_drops:" => "☔", "\\:unamused:" => "😒", "\\:underage:" => "🔞", + "\\:unicorn_face:" => "🦄", "\\:unlock:" => "🔓", "\\:up:" => "🆙", + "\\:upside_down_face:" => "🙃", "\\:v:" => "✌", + "\\:vampire:" => "🧛", "\\:vertical_traffic_light:" => "🚦", "\\:vhs:" => "📼", "\\:vibration_mode:" => "📳", @@ -815,15 +1168,19 @@ const emoji_symbols = Dict( "\\:violin:" => "🎻", "\\:virgo:" => "♍", "\\:volcano:" => "🌋", + "\\:volleyball:" => "🏐", "\\:vs:" => "🆚", + "\\:waffle:" => "🧇", "\\:walking:" => "🚶", "\\:waning_crescent_moon:" => "🌘", "\\:waning_gibbous_moon:" => "🌖", "\\:warning:" => "⚠", "\\:watch:" => "⌚", "\\:water_buffalo:" => "🐃", + "\\:water_polo:" => "🤽", "\\:watermelon:" => "🍉", "\\:wave:" => "👋", + "\\:waving_black_flag:" => "🏴", "\\:wavy_dash:" => "〰", "\\:waxing_crescent_moon:" => "🌒", "\\:wc:" => "🚾", @@ -835,25 +1192,40 @@ const emoji_symbols = Dict( "\\:white_check_mark:" => "✅", "\\:white_circle:" => "⚪", "\\:white_flower:" => "💮", + "\\:white_heart:" => "🤍", "\\:white_large_square:" => "⬜", "\\:white_medium_small_square:" => "◽", "\\:white_medium_square:" => "◻", "\\:white_small_square:" => "▫", "\\:white_square_button:" => "🔳", + "\\:wilted_flower:" => "🥀", "\\:wind_chime:" => "🎐", + "\\:window:" => "🪟", "\\:wine_glass:" => "🍷", "\\:wink:" => "😉", "\\:wolf:" => "🐺", "\\:woman:" => "👩", "\\:womans_clothes:" => "👚", + "\\:womans_flat_shoe:" => "🥿", "\\:womans_hat:" => "👒", "\\:womens:" => "🚺", + "\\:wood:" => "🪵", + "\\:woozy_face:" => "🥴", + "\\:worm:" => "🪱", "\\:worried:" => "😟", "\\:wrench:" => "🔧", + "\\:wrestlers:" => "🤼", "\\:x:" => "❌", + "\\:yarn:" => "🧶", + "\\:yawning_face:" => "🥱", "\\:yellow_heart:" => "💛", "\\:yen:" => "💴", + "\\:yo-yo:" => "🪀", "\\:yum:" => "😋", + "\\:zany_face:" => "🤪", "\\:zap:" => "⚡", + "\\:zebra_face:" => "🦓", + "\\:zipper_mouth_face:" => "🤐", + "\\:zombie:" => "🧟", "\\:zzz:" => "💤", ) From 4489288cc74ff0988bec52b0b8db050d3cfb5a66 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 6 Apr 2021 11:46:23 -0500 Subject: [PATCH 107/439] Provide an error message for deserialize_msg --- stdlib/Distributed/src/messages.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Distributed/src/messages.jl b/stdlib/Distributed/src/messages.jl index bfff8a4d5d1a7..e9d1b0f648167 100644 --- a/stdlib/Distributed/src/messages.jl +++ b/stdlib/Distributed/src/messages.jl @@ -80,7 +80,7 @@ for (idx, tname) in enumerate(msgtypes) end end -let msg_cases = :(@assert false) +let msg_cases = :(@assert false "Message type index ($idx) expected to be between 1:$($(length(msgtypes)))") for i = length(msgtypes):-1:1 mti = msgtypes[i] msg_cases = :(if idx == $i From 9f8cc3d5e6687a4ed1d6584f6b067a70ff3844e2 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 6 Apr 2021 11:46:54 -0500 Subject: [PATCH 108/439] Remove unnecessary multiple returns --- stdlib/Distributed/src/messages.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/Distributed/src/messages.jl b/stdlib/Distributed/src/messages.jl index e9d1b0f648167..47f70e044a2c0 100644 --- a/stdlib/Distributed/src/messages.jl +++ b/stdlib/Distributed/src/messages.jl @@ -84,14 +84,14 @@ let msg_cases = :(@assert false "Message type index ($idx) expected to be betwee for i = length(msgtypes):-1:1 mti = msgtypes[i] msg_cases = :(if idx == $i - return $(Expr(:call, QuoteNode(mti), fill(:(deserialize(s)), fieldcount(mti))...)) + $(Expr(:call, QuoteNode(mti), fill(:(deserialize(s)), fieldcount(mti))...)) else $msg_cases end) end @eval function deserialize_msg(s::AbstractSerializer) idx = read(s.io, UInt8) - $msg_cases + return $msg_cases end end From e3c0dec3c4c5d51fa51e3c24d405d13629ae7145 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 6 Apr 2021 13:59:29 -0400 Subject: [PATCH 109/439] errorshow: fix bad test from #40304 (#40376) This conflicted with a test in core.jl for callable numbers --- base/errorshow.jl | 2 +- test/errorshow.jl | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 5c47824579aad..9b974f2b86aa7 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -876,7 +876,7 @@ function show(io::IO, ip::InterpreterIP) end # handler for displaying a hint in case the user tries to call -# the instance of a number(misses out hte operator) +# the instance of a number (probably missing the operator) # eg: (1 + 2)(3 + 4) function noncallable_number_hint_handler(io, ex, arg_types, kwargs) if ex.f isa Number diff --git a/test/errorshow.jl b/test/errorshow.jl index 60d7353adb1e8..4a6796a454f78 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -634,9 +634,10 @@ catch ex end pop!(Base.Experimental._hint_handlers[DomainError]) # order is undefined, don't copy this +struct ANumber <: Number end let err_str - err_str = @except_str (1 + 2)(3 + 4) MethodError - @test occursin("objects of type $(typeof(3)) are not callable", err_str) + err_str = @except_str ANumber()(3 + 4) MethodError + @test occursin("objects of type $(curmod_prefix)ANumber are not callable", err_str) @test occursin("Maybe you forgot to use an operator such as *, ^, %, / etc. ?", err_str) end From e34a90490d82e1f72ef7a6f2050343f90cdb28fa Mon Sep 17 00:00:00 2001 From: WorldsOkayestAirman Date: Tue, 6 Apr 2021 14:30:31 -0400 Subject: [PATCH 110/439] Allow enabling multiple external profilers in build (#38741) --- src/init.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/init.c b/src/init.c index f66403c58199c..05d7690cd47b0 100644 --- a/src/init.c +++ b/src/init.c @@ -687,22 +687,26 @@ void _julia_init(JL_IMAGE_SEARCH rel) #endif #endif -#if defined(JL_USE_INTEL_JITEVENTS) +#if \ + defined(JL_USE_INTEL_JITEVENTS) || \ + defined(JL_USE_OPROFILE_JITEVENTS) || \ + defined(JL_USE_PERF_JITEVENTS) const char *jit_profiling = getenv("ENABLE_JITPROFILING"); +#endif + +#if defined(JL_USE_INTEL_JITEVENTS) if (jit_profiling && atoi(jit_profiling)) { jl_using_intel_jitevents = 1; } #endif #if defined(JL_USE_OPROFILE_JITEVENTS) - const char *jit_profiling = getenv("ENABLE_JITPROFILING"); if (jit_profiling && atoi(jit_profiling)) { jl_using_oprofile_jitevents = 1; } #endif #if defined(JL_USE_PERF_JITEVENTS) - const char *jit_profiling = getenv("ENABLE_JITPROFILING"); if (jit_profiling && atoi(jit_profiling)) { jl_using_perf_jitevents= 1; } From 79e198b29f620114e86950cf9f24c48b049d9c67 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 6 Apr 2021 15:35:18 -0400 Subject: [PATCH 111/439] fix #40249, reshaping SharedArray on another process (#40286) --- stdlib/SharedArrays/src/SharedArrays.jl | 21 +++++++++++---------- stdlib/SharedArrays/test/runtests.jl | 6 ++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/stdlib/SharedArrays/src/SharedArrays.jl b/stdlib/SharedArrays/src/SharedArrays.jl index 347d22180f7b5..85f1eb4fff150 100644 --- a/stdlib/SharedArrays/src/SharedArrays.jl +++ b/stdlib/SharedArrays/src/SharedArrays.jl @@ -295,14 +295,21 @@ size(S::SharedArray) = S.dims elsize(::Type{SharedArray{T,N}}) where {T,N} = elsize(Array{T,N}) # aka fieldtype(T, :s) IndexStyle(::Type{<:SharedArray}) = IndexLinear() +function local_array_by_id(refid) + if isa(refid, Future) + refid = remoteref_id(refid) + end + fetch(channel_from_id(refid)) +end + function reshape(a::SharedArray{T}, dims::NTuple{N,Int}) where {T,N} if length(a) != prod(dims) throw(DimensionMismatch("dimensions must be consistent with array size")) end refs = Vector{Future}(undef, length(a.pids)) for (i, p) in enumerate(a.pids) - refs[i] = remotecall(p, a.refs[i], dims) do r,d - reshape(fetch(r),d) + refs[i] = remotecall(p, a.refs[i], dims) do r, d + reshape(local_array_by_id(r), d) end end @@ -382,7 +389,7 @@ function shared_pids(pids) # only use workers on the current host pids = procs(myid()) if length(pids) > 1 - pids = filter(x -> x != 1, pids) + pids = filter(!=(1), pids) end onlocalhost = true @@ -419,13 +426,7 @@ sub_1dim(S::SharedArray, pidx) = view(S.s, range_1dim(S, pidx)) function init_loc_flds(S::SharedArray{T,N}, empty_local=false) where T where N if myid() in S.pids S.pidx = findfirst(isequal(myid()), S.pids) - if isa(S.refs[1], Future) - refid = remoteref_id(S.refs[S.pidx]) - else - refid = S.refs[S.pidx] - end - c = channel_from_id(refid) - S.s = fetch(c) + S.s = local_array_by_id(S.refs[S.pidx]) S.loc_subarr_1d = sub_1dim(S, S.pidx) else S.pidx = 0 diff --git a/stdlib/SharedArrays/test/runtests.jl b/stdlib/SharedArrays/test/runtests.jl index 7a4d46d4777b3..7f1bbb6891ce0 100644 --- a/stdlib/SharedArrays/test/runtests.jl +++ b/stdlib/SharedArrays/test/runtests.jl @@ -176,6 +176,12 @@ d = SharedArrays.shmem_fill(1.0, (10,10,10)) @test fill(1., 100, 10) == reshape(d,(100,10)) d = SharedArrays.shmem_fill(1.0, (10,10,10)) @test_throws DimensionMismatch reshape(d,(50,)) +# issue #40249, reshaping on another process +let m = SharedArray{ComplexF64}(10, 20, 30) + m2 = remotecall_fetch(() -> reshape(m, (100, :)), id_other) + @test size(m2) == (100, 60) + @test m2 isa SharedArray +end # rand, randn d = SharedArrays.shmem_rand(dims) From 54b610bd4165aa1edd2b4e67c3b75aee428f490c Mon Sep 17 00:00:00 2001 From: Carsten Bauer Date: Tue, 6 Apr 2021 22:35:00 +0200 Subject: [PATCH 112/439] Show methods for LBTConfig and LBTLibraryInfo (#40357) * show methods for LBTConfig and LBTLibraryInfo * add interface information to LBTConfig printing * interface information in show fallback of LBTConfig and LBTLibraryInfo * LBTConfig(...) instead of LBTConfig() for n>3 libs --- stdlib/LinearAlgebra/src/lbt.jl | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/stdlib/LinearAlgebra/src/lbt.jl b/stdlib/LinearAlgebra/src/lbt.jl index 4ed93188d1f61..67ce521a9aa7e 100644 --- a/stdlib/LinearAlgebra/src/lbt.jl +++ b/stdlib/LinearAlgebra/src/lbt.jl @@ -103,6 +103,42 @@ struct LBTConfig end end +Base.show(io::IO, lbt::LBTLibraryInfo) = print(io, "LBTLibraryInfo(", basename(lbt.libname), ", ", lbt.interface, ")") +function Base.show(io::IO, mime::MIME{Symbol("text/plain")}, lbt::LBTLibraryInfo) + summary(io, lbt); println(io) + println(io, "├ Library: ", basename(lbt.libname)) + println(io, "├ Interface: ", lbt.interface) + print(io, "└ F2C: ", lbt.f2c) +end + +function Base.show(io::IO, lbt::LBTConfig) + if length(lbt.loaded_libs) <= 3 + print(io, "LBTConfig(") + gen = (string("[", uppercase(string(l.interface)), "] ", + basename(l.libname)) for l in lbt.loaded_libs) + print(io, join(gen, ", ")) + print(io, ")") + else + print(io, "LBTConfig(...)") + end +end +function Base.show(io::IO, mime::MIME{Symbol("text/plain")}, lbt::LBTConfig) + summary(io, lbt); println(io) + println(io, "Libraries: ") + for (i,l) in enumerate(lbt.loaded_libs) + char = i == length(lbt.loaded_libs) ? "└" : "├" + interface_str = if l.interface == :ilp64 + "ILP64" + elseif l.interface == :lp64 + " LP64" + else + "UNKWN" + end + print(io, char, " [", interface_str,"] ", basename(l.libname)) + i !== length(lbt.loaded_libs) && println() + end +end + function lbt_get_config() config_ptr = ccall((:lbt_get_config, libblastrampoline), Ptr{lbt_config_t}, ()) return LBTConfig(unsafe_load(config_ptr)) From 336cdf80f38b89b42e2fb72e1057f6fced1493d0 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 6 Apr 2021 14:10:05 -0700 Subject: [PATCH 113/439] [build] Add `symlink_system_library` calls for CSL (#40217) * [build] Add `symlink_system_library` calls for CSL We differentiate between a `USE_BINARYBUILDER_CSL=0` configuration (where we copy the CSL libraries into the Julia build tree) versus a `USE_SYSTEM_CSL=1` configuration (where we symlink them in a manner similar to other system libararies) * Expand `JL_PRIVATE_LIBS-1` for versioned library names as well Without this, we fail to install things like `libgcc_s.so.1` when installed into the private libdir by `symlink_system_libraries`. --- Make.inc | 23 +++++++++++++- Makefile | 7 ++-- base/Makefile | 88 ++++++++++++++++++++++++++++++--------------------- deps/csl.mk | 40 ++++++++--------------- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/Make.inc b/Make.inc index 5bcf86bc2e413..04181edf07596 100644 --- a/Make.inc +++ b/Make.inc @@ -596,6 +596,21 @@ else SHLIB_EXT := so endif +ifeq ($(OS),WINNT) +define versioned_libname +$$(if $(2),$(1)-$(2).$(SHLIB_EXT),$(1).$(SHLIB_EXT)) +endef +else ifeq ($(OS),Darwin) +define versioned_libname +$$(if $(2),$(1).$(2).$(SHLIB_EXT),$(1).$(SHLIB_EXT)) +endef +else +define versioned_libname +$$(if $(2),$(1).$(SHLIB_EXT).$(2),$(1).$(SHLIB_EXT)) +endef +endif + + ifeq ($(SHLIB_EXT), so) define SONAME_FLAGS -Wl,-soname=$1 @@ -1148,6 +1163,8 @@ BB_TRIPLET_LIBGFORTRAN := $(subst $(SPACE),-,$(filter-out cxx%,$(subst -,$(SPACE BB_TRIPLET_CXXABI := $(subst $(SPACE),-,$(filter-out libgfortran%,$(subst -,$(SPACE),$(BB_TRIPLET_LIBGFORTRAN_CXXABI)))) BB_TRIPLET := $(subst $(SPACE),-,$(filter-out cxx%,$(filter-out libgfortran%,$(subst -,$(SPACE),$(BB_TRIPLET_LIBGFORTRAN_CXXABI))))) +LIBGFORTRAN_VERSION := $(subst libgfortran,,$(filter libgfortran%,$(subst -,$(SPACE),$(BB_TRIPLET_LIBGFORTRAN)))) + # This is the set of projects that BinaryBuilder dependencies are hooked up for. BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM SUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP CSL define SET_BB_DEFAULT @@ -1480,8 +1497,12 @@ ifneq ($(findstring $(OS),Linux FreeBSD),) LIBGCC_NAME := libgcc_s.$(SHLIB_EXT).1 endif - +# USE_SYSTEM_CSL causes it to get symlinked into build_private_shlibdir +ifeq ($(USE_SYSTEM_CSL),1) +LIBGCC_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_private_shlibdir)/$(LIBGCC_NAME)) +else LIBGCC_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/$(LIBGCC_NAME)) +endif LIBGCC_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBGCC_NAME)) # USE_SYSTEM_LIBM and USE_SYSTEM_OPENLIBM causes it to get symlinked into build_private_shlibdir diff --git a/Makefile b/Makefile index 72b2cf3ffb829..f7bad6350c77e 100644 --- a/Makefile +++ b/Makefile @@ -290,8 +290,11 @@ endif done \ done for suffix in $(JL_PRIVATE_LIBS-1) ; do \ - lib=$(build_private_libdir)/$${suffix}.$(SHLIB_EXT); \ - $(INSTALL_M) $$lib $(DESTDIR)$(private_libdir) ; \ + for lib in $(build_private_libdir)/$${suffix}.$(SHLIB_EXT)*; do \ + if [ "$${lib##*.}" != "dSYM" ]; then \ + $(INSTALL_M) $$lib $(DESTDIR)$(private_libdir) ; \ + fi \ + done \ done endif # Install `7z` into libexec/ diff --git a/base/Makefile b/base/Makefile index e024e546f94d3..2bef6aab7f1f4 100644 --- a/base/Makefile +++ b/base/Makefile @@ -169,53 +169,69 @@ endif # echo "$$P" define symlink_system_library -symlink_$1: $$(build_private_libdir)/$1.$$(SHLIB_EXT) -$$(build_private_libdir)/$1.$$(SHLIB_EXT): - REALPATH=`$$(call spawn,$$(build_depsbindir)/libwhich) -p $$(notdir $$@)` && \ - $$(call resolve_path,REALPATH) && \ - [ -e "$$$$REALPATH" ] && \ - ([ ! -e "$$@" ] || rm "$$@") && \ - echo ln -sf "$$$$REALPATH" "$$@" && \ - ln -sf "$$$$REALPATH" "$$@" -ifneq ($2,) -ifneq ($$(USE_SYSTEM_$2),0) -SYMLINK_SYSTEM_LIBRARIES += symlink_$1 -endif +libname_$2 := $$(notdir $(call versioned_libname,$2,$3)) +libpath_$2 := $$(shell $$(call spawn,$$(build_depsbindir)/libwhich) -p $$(libname_$2) 2>/dev/null) +symlink_$2: $$(build_private_libdir)/$$(libname_$2) +$$(build_private_libdir)/$$(libname_$2): + @if [ -e "$$(libpath_$2)" ]; then \ + REALPATH=$$(libpath_$2); \ + $$(call resolve_path,REALPATH) && \ + [ -e "$$$$REALPATH" ] && \ + ([ ! -e "$$@" ] || rm "$$@") && \ + echo ln -sf "$$$$REALPATH" "$$@" && \ + ln -sf "$$$$REALPATH" "$$@"; \ + else \ + if [ "$4" != "ALLOW_FAILURE" ]; then \ + echo "System library symlink failure: Unable to locate $$(libname_$2) on your system!" >&2; \ + false; \ + fi; \ + fi +ifneq ($$(USE_SYSTEM_$1),0) +SYMLINK_SYSTEM_LIBRARIES += symlink_$2 endif endef # the following excludes: libuv.a, libutf8proc.a -$(eval $(call symlink_system_library,$(LIBMNAME))) ifneq ($(USE_SYSTEM_LIBM),0) -SYMLINK_SYSTEM_LIBRARIES += symlink_$(LIBMNAME) +$(eval $(call symlink_system_library,LIBM,$(LIBMNAME))) else ifneq ($(USE_SYSTEM_OPENLIBM),0) -SYMLINK_SYSTEM_LIBRARIES += symlink_$(LIBMNAME) +$(eval $(call symlink_system_library,OPENLIBM,$(LIBMNAME))) endif -$(eval $(call symlink_system_library,libpcre2-8,PCRE)) -$(eval $(call symlink_system_library,libdSFMT,DSFMT)) -$(eval $(call symlink_system_library,$(LIBBLASNAME),BLAS)) +$(eval $(call symlink_system_library,CSL,libgcc_s,1)) +ifneq (,$(LIBGFORTRAN_VERSION)) +$(eval $(call symlink_system_library,CSL,libgfortran,$(LIBGFORTRAN_VERSION))) +endif +$(eval $(call symlink_system_library,CSL,libquadmath,0)) +$(eval $(call symlink_system_library,CSL,libstdc++,6)) +# We allow libssp, libatomic and libgomp to fail as they are not available on all systems +$(eval $(call symlink_system_library,CSL,libssp,0,ALLOW_FAILURE)) +$(eval $(call symlink_system_library,CSL,libatomic,1,ALLOW_FAILURE)) +$(eval $(call symlink_system_library,CSL,libgomp,1,ALLOW_FAILURE)) +$(eval $(call symlink_system_library,PCRE,libpcre2-8)) +$(eval $(call symlink_system_library,DSFMT,libdSFMT)) +$(eval $(call symlink_system_library,BLAS,$(LIBBLASNAME))) ifneq ($(LIBLAPACKNAME),$(LIBBLASNAME)) -$(eval $(call symlink_system_library,$(LIBLAPACKNAME),LAPACK)) +$(eval $(call symlink_system_library,LAPACK,$(LIBLAPACKNAME))) endif -$(eval $(call symlink_system_library,libgmp,GMP)) -$(eval $(call symlink_system_library,libmpfr,MPFR)) -$(eval $(call symlink_system_library,libmbedtls,MBEDTLS)) -$(eval $(call symlink_system_library,libmbedcrypto,MBEDTLS)) -$(eval $(call symlink_system_library,libmbedx509,MBEDTLS)) -$(eval $(call symlink_system_library,libssh2,LIBSSH2)) -$(eval $(call symlink_system_library,libnghttp2,NGHTTP2)) -$(eval $(call symlink_system_library,libcurl,CURL)) -$(eval $(call symlink_system_library,libgit2,LIBGIT2)) -$(eval $(call symlink_system_library,libamd,SUITESPARSE)) -$(eval $(call symlink_system_library,libcamd,SUITESPARSE)) -$(eval $(call symlink_system_library,libccolamd,SUITESPARSE)) -$(eval $(call symlink_system_library,libcholmod,SUITESPARSE)) -$(eval $(call symlink_system_library,libcolamd,SUITESPARSE)) -$(eval $(call symlink_system_library,libumfpack,SUITESPARSE)) -$(eval $(call symlink_system_library,libspqr,SUITESPARSE)) -$(eval $(call symlink_system_library,libsuitesparseconfig,SUITESPARSE)) +$(eval $(call symlink_system_library,GMP,libgmp)) +$(eval $(call symlink_system_library,MPFR,libmpfr)) +$(eval $(call symlink_system_library,MBEDTLS,libmbedtls)) +$(eval $(call symlink_system_library,MBEDTLS,libmbedcrypto)) +$(eval $(call symlink_system_library,MBEDTLS,libmbedx509)) +$(eval $(call symlink_system_library,LIBSSH2,libssh2)) +$(eval $(call symlink_system_library,NGHTTP2,libnghttp2)) +$(eval $(call symlink_system_library,CURL,libcurl)) +$(eval $(call symlink_system_library,LIBGIT2,libgit2)) +$(eval $(call symlink_system_library,SUITESPARSE,libamd)) +$(eval $(call symlink_system_library,SUITESPARSE,libcamd)) +$(eval $(call symlink_system_library,SUITESPARSE,libccolamd)) +$(eval $(call symlink_system_library,SUITESPARSE,libcholmod)) +$(eval $(call symlink_system_library,SUITESPARSE,libcolamd)) +$(eval $(call symlink_system_library,SUITESPARSE,libumfpack)) +$(eval $(call symlink_system_library,SUITESPARSE,libspqr)) +$(eval $(call symlink_system_library,SUITESPARSE,libsuitesparseconfig)) # EXCLUDED LIBRARIES (installed/used, but not vendored for use with dlopen): # libunwind endif # WINNT diff --git a/deps/csl.mk b/deps/csl.mk index 095d4ceec4a1e..423201cbb5a0c 100644 --- a/deps/csl.mk +++ b/deps/csl.mk @@ -19,48 +19,34 @@ $$(build_shlibdir)/$(1): | $$(build_shlibdir) [ -n "$$$${SRC_LIB}" ] && cp $$$${SRC_LIB} $$(build_shlibdir) endef -ifeq ($(OS),WINNT) -define gen_libname -$$(if $(2),lib$(1)-$(2).$(SHLIB_EXT),lib$(1).$(SHLIB_EXT)) -endef -else ifeq ($(OS),Darwin) -define gen_libname -$$(if $(2),lib$(1).$(2).$(SHLIB_EXT),lib$(1).$(SHLIB_EXT)) -endef -else -define gen_libname -$$(if $(2),lib$(1).$(SHLIB_EXT).$(2),lib$(1).$(SHLIB_EXT)) -endef -endif - # libgfortran has multiple names; we're just going to copy any version we can find # Since we're only looking in the location given by `$(FC)` this should only succeed for one. -$(eval $(call copy_csl,$(call gen_libname,gfortran,3))) -$(eval $(call copy_csl,$(call gen_libname,gfortran,4))) -$(eval $(call copy_csl,$(call gen_libname,gfortran,5))) +$(eval $(call copy_csl,$(call versioned_libname,libgfortran,3))) +$(eval $(call copy_csl,$(call versioned_libname,libgfortran,4))) +$(eval $(call copy_csl,$(call versioned_libname,libgfortran,5))) # These are all libraries that we should always have -$(eval $(call copy_csl,$(call gen_libname,quadmath,0))) -$(eval $(call copy_csl,$(call gen_libname,stdc++,6))) -$(eval $(call copy_csl,$(call gen_libname,ssp,0))) -$(eval $(call copy_csl,$(call gen_libname,atomic,1))) -$(eval $(call copy_csl,$(call gen_libname,gomp,1))) +$(eval $(call copy_csl,$(call versioned_libname,libquadmath,0))) +$(eval $(call copy_csl,$(call versioned_libname,libstdc++,6))) +$(eval $(call copy_csl,$(call versioned_libname,libssp,0))) +$(eval $(call copy_csl,$(call versioned_libname,libatomic,1))) +$(eval $(call copy_csl,$(call versioned_libname,libgomp,1))) ifeq ($(OS),WINNT) # Windwos has special gcc_s names ifeq ($(ARCH),i686) -$(eval $(call copy_csl,$(call gen_libname,gcc_s_sjlj,1))) +$(eval $(call copy_csl,$(call versioned_libname,libgcc_s_sjlj,1))) else -$(eval $(call copy_csl,$(call gen_libname,gcc_s_seh,1))) +$(eval $(call copy_csl,$(call versioned_libname,libgcc_s_seh,1))) endif else -$(eval $(call copy_csl,$(call gen_libname,gcc_s,1))) +$(eval $(call copy_csl,$(call versioned_libname,libgcc_s,1))) endif # winpthread is only Windows, pthread is only others ifeq ($(OS),WINNT) -$(eval $(call copy_csl,$(call gen_libname,winpthread,1))) +$(eval $(call copy_csl,$(call versioned_libname,libwinpthread,1))) else -$(eval $(call copy_csl,$(call gen_libname,pthread,0))) +$(eval $(call copy_csl,$(call versioned_libname,libpthread,0))) endif get-csl: From 2e1de7dccf84c834762eb4ed7a3efeb2898a69df Mon Sep 17 00:00:00 2001 From: Logan Kilpatrick <23kilpatrick23@gmail.com> Date: Tue, 6 Apr 2021 14:39:03 -0700 Subject: [PATCH 114/439] doc: update reducedim.jl to fix a few doc strings (#40351) Closes #40300, and fixes other docs discrepancies --- base/reducedim.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 92647a23f0e1a..e21854ef31c18 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -612,7 +612,7 @@ maximum(A::AbstractArray; dims) """ maximum(f, A::AbstractArray; dims) -Compute the maximum value from of calling the function `f` on each element of an array over the given +Compute the maximum value by calling the function `f` on each element of an array over the given dimensions. # Examples @@ -687,7 +687,7 @@ minimum(A::AbstractArray; dims) """ minimum(f, A::AbstractArray; dims) -Compute the minimum value from of calling the function `f` on each element of an array over the given +Compute the minimum value by calling the function `f` on each element of an array over the given dimensions. # Examples @@ -760,7 +760,7 @@ all(A::AbstractArray; dims) """ all(p, A; dims) -Determine whether predicate p returns true for all elements along the given dimensions of an array. +Determine whether predicate `p` returns `true` for all elements along the given dimensions of an array. # Examples ```jldoctest @@ -832,7 +832,7 @@ any(::AbstractArray; dims) """ any(p, A; dims) -Determine whether predicate p returns true for any elements along the given dimensions of an array. +Determine whether predicate `p` returns `true` for any elements along the given dimensions of an array. # Examples ```jldoctest From d9f0f04477bde51d858400a123cf40ccf4adc38d Mon Sep 17 00:00:00 2001 From: Tommy-Xavier Robillard <42289375+TommyXR@users.noreply.github.com> Date: Tue, 6 Apr 2021 17:39:38 -0400 Subject: [PATCH 115/439] Add `lock` wrapper for Channels (#39312) Added lock(f, c::Channel) utility function --- NEWS.md | 2 ++ base/channels.jl | 1 + base/condition.jl | 1 - base/weakkeydict.jl | 2 ++ 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4c2f4beae153e..140da486c30bf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,6 +36,8 @@ New library functions * Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]). * `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`. * New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971]) +* New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}; kwargs...)` ([#38438]) +* Two arguments method `lock(f, lck)` now accepts a `Channel` as the second argument. ([#39312]) * New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438]) diff --git a/base/channels.jl b/base/channels.jl index fc6e1381b64b5..3b171ede0699e 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -422,6 +422,7 @@ n_avail(c::Channel) = isbuffered(c) ? length(c.data) : length(c.cond_put.waitq) isempty(c::Channel) = isbuffered(c) ? isempty(c.data) : isempty(c.cond_put.waitq) lock(c::Channel) = lock(c.cond_take) +lock(f, c::Channel) = lock(f, c.cond_take) unlock(c::Channel) = unlock(c.cond_take) trylock(c::Channel) = trylock(c.cond_take) diff --git a/base/condition.jl b/base/condition.jl index 4b9f57e47ab29..cf0bca8d9dc46 100644 --- a/base/condition.jl +++ b/base/condition.jl @@ -76,7 +76,6 @@ trylock(c::GenericCondition) = trylock(c.lock) islocked(c::GenericCondition) = islocked(c.lock) lock(f, c::GenericCondition) = lock(f, c.lock) -unlock(f, c::GenericCondition) = unlock(f, c.lock) # have waiter wait for c function _wait2(c::GenericCondition, waiter::Task) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index c7ec172af46aa..8e1a3d480b995 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -84,6 +84,8 @@ empty(d::WeakKeyDict, ::Type{K}, ::Type{V}) where {K, V} = WeakKeyDict{K, V}() IteratorSize(::Type{<:WeakKeyDict}) = SizeUnknown() islocked(wkh::WeakKeyDict) = islocked(wkh.lock) +lock(wkh::WeakKeyDict) = lock(wkh.lock) +unlock(wkh::WeakKeyDict) = unlock(wkh.lock) lock(f, wkh::WeakKeyDict) = lock(f, wkh.lock) trylock(f, wkh::WeakKeyDict) = trylock(f, wkh.lock) From 70333daa3f8ca7613c7ee11a7989ae615b3f822e Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 6 Apr 2021 17:41:07 -0400 Subject: [PATCH 116/439] don't use realpath in Sys.which (#40233) As [discussed recently on discourse](https://discourse.julialang.org/t/weird-sys-which-function/58070), some programs require a certain executable name to function correctly, and behave badly if you call `realpath` to expand symbolic links (potentially changing the program name). c.f. discussion in #26559, implemented `Sys.which` --- base/sysinfo.jl | 2 +- test/spawn.jl | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 4c113971266d7..01e7866c50d19 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -516,7 +516,7 @@ function which(program_name::String) program_path = joinpath(path_dir, pname) # If we find something that matches our name and we can execute if isfile(program_path) && isexecutable(program_path) - return realpath(program_path) + return program_path end end end diff --git a/test/spawn.jl b/test/spawn.jl index dcc1bae234118..b2111fed07378 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -582,8 +582,8 @@ end psep = if Sys.iswindows() ";" else ":" end withenv("PATH" => "$(Sys.BINDIR)$(psep)$(ENV["PATH"])") do julia_exe = joinpath(Sys.BINDIR, Base.julia_exename()) - @test Sys.which("julia") == realpath(julia_exe) - @test Sys.which(julia_exe) == realpath(julia_exe) + @test Sys.which("julia") == abspath(julia_exe) + @test Sys.which(julia_exe) == abspath(julia_exe) end # Check that which behaves correctly when passed an empty string @@ -598,8 +598,8 @@ mktempdir() do dir touch(foo_path) chmod(foo_path, 0o777) if !Sys.iswindows() - @test Sys.which("foo") == realpath(foo_path) - @test Sys.which(foo_path) == realpath(foo_path) + @test Sys.which("foo") == abspath(foo_path) + @test Sys.which(foo_path) == abspath(foo_path) chmod(foo_path, 0o666) @test Sys.which("foo") === nothing @@ -636,20 +636,20 @@ mktempdir() do dir touch(foo2_path) chmod(foo1_path, 0o777) chmod(foo2_path, 0o777) - @test Sys.which("foo") == realpath(foo1_path) + @test Sys.which("foo") == abspath(foo1_path) # chmod() doesn't change which() on Windows, so don't bother to test that if !Sys.iswindows() chmod(foo1_path, 0o666) - @test Sys.which("foo") == realpath(foo2_path) + @test Sys.which("foo") == abspath(foo2_path) chmod(foo1_path, 0o777) end if Sys.iswindows() # On windows, check that pwd() takes precedence, except when we provide a path cd(joinpath(dir, "bin2")) do - @test Sys.which("foo") == realpath(foo2_path) - @test Sys.which(foo1_path) == realpath(foo1_path) + @test Sys.which("foo") == abspath(foo2_path) + @test Sys.which(foo1_path) == abspath(foo1_path) end end @@ -662,7 +662,9 @@ mktempdir() do dir touch(bar_path) chmod(bar_path, 0o777) cd(dir) do - @test Sys.which(joinpath("bin1", "bar")) == realpath(bar_path) + p = Sys.which(joinpath("bin1", "bar")) + @test p == abspath("bin1", basename(bar_path)) + @test Base.samefile(p, bar_path) end end end From df48fb615ac5ee0307b4139184dfcbf7e5fb14b1 Mon Sep 17 00:00:00 2001 From: hsm207 Date: Wed, 7 Apr 2021 05:47:51 +0800 Subject: [PATCH 117/439] test: simple tests for hash_64_32 and hash_32_32 (#35520) Tests to help improve coverage --- test/hashing.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/hashing.jl b/test/hashing.jl index c2afd7426ecb3..e5223ed407062 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -260,3 +260,27 @@ end # PR #40083 @test hash(1:1000) == hash(collect(1:1000)) + +@testset "test the other core data hashing functions" begin + @testset "hash_64_32" begin + vals = vcat( + typemin(UInt64) .+ UInt64[1:4;], + typemax(UInt64) .- UInt64[4:-1:0;] + ) + + for a in vals, b in vals + @test isequal(a, b) == (Base.hash_64_32(a) == Base.hash_64_32(b)) + end + end + + @testset "hash_32_32" begin + vals = vcat( + typemin(UInt32) .+ UInt32[1:4;], + typemax(UInt32) .- UInt32[4:-1:0;] + ) + + for a in vals, b in vals + @test isequal(a, b) == (Base.hash_32_32(a) == Base.hash_32_32(b)) + end + end +end \ No newline at end of file From 73523202a7a4808cd45df1692014338fed047bc0 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 6 Apr 2021 14:48:26 -0700 Subject: [PATCH 118/439] Remove a few redundant diagonal `ldiv!` methods (#38484) --- stdlib/LinearAlgebra/src/diagonal.jl | 43 +++++----------------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 10a6f8ac446b9..e83c5274ac3d6 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -420,35 +420,6 @@ mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:Rea (/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) -function ldiv!(D::Diagonal{T}, v::AbstractVector{T}) where {T} - if length(v) != length(D.diag) - throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(length(v)) rows")) - end - for i = 1:length(D.diag) - d = D.diag[i] - if iszero(d) - throw(SingularException(i)) - end - v[i] = d\v[i] - end - v -end -function ldiv!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} - require_one_based_indexing(V) - if size(V,1) != length(D.diag) - throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(size(V,1)) rows")) - end - for i = 1:length(D.diag) - d = D.diag[i] - if iszero(d) - throw(SingularException(i)) - end - for j = 1:size(V,2) - @inbounds V[i,j] = d\V[i,j] - end - end - V -end ldiv!(x::AbstractArray, A::Diagonal, b::AbstractArray) = (x .= A.diag .\ b) ldiv!(adjD::Adjoint{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} = @@ -610,8 +581,13 @@ for f in (:exp, :cis, :log, :sqrt, @eval $f(D::Diagonal) = Diagonal($f.(D.diag)) end -#Linear solver -function ldiv!(D::Diagonal, B::StridedVecOrMat) +(\)(D::Diagonal, A::AbstractMatrix) = + ldiv!(D, (typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A)) + +(\)(D::Diagonal, b::AbstractVector) = D.diag .\ b +(\)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .\ Db.diag) + +function ldiv!(D::Diagonal, B::AbstractVecOrMat) m, n = size(B, 1), size(B, 2) if m != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $m rows")) @@ -628,11 +604,6 @@ function ldiv!(D::Diagonal, B::StridedVecOrMat) end return B end -(\)(D::Diagonal, A::AbstractMatrix) = - ldiv!(D, (typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A)) - -(\)(D::Diagonal, b::AbstractVector) = D.diag .\ b -(\)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .\ Db.diag) function inv(D::Diagonal{T}) where T Di = similar(D.diag, typeof(inv(zero(T)))) From 8218480f059b7d2ba3388646497b76759248dd86 Mon Sep 17 00:00:00 2001 From: Pramodh Gopalan V Date: Wed, 7 Apr 2021 10:59:20 +0530 Subject: [PATCH 119/439] Add docs for _ as a variable (#40183) --- doc/src/manual/variables.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index c68fbd304d33a..3711264d84382 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -110,6 +110,19 @@ A space is required between an operator that ends with a subscript/superscript l variable name. For example, if `+ᵃ` is an operator, then `+ᵃx` must be written as `+ᵃ x` to distinguish it from `+ ᵃx` where `ᵃx` is the variable name. + +A particular class of variable names is one that contains only underscores. These identifiers can only be assigned values but cannot be used to assign values to other variables. +More technically, they can only be used as an [L-value](https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue), but not as an + [R-value](https://en.wikipedia.org/wiki/R-value): + +```julia-repl +julia> x, ___ = size([2 2; 1 1]) +(2, 2) + +julia> y = ___ +ERROR: syntax: all-underscore identifier used as rvalue +``` + The only explicitly disallowed names for variables are the names of the built-in [Keywords](@ref): ```julia-repl From 8a14ef2dc68e43abead5557477c84ea2d059aefe Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 7 Apr 2021 08:50:41 +0200 Subject: [PATCH 120/439] Add type asserts to (try)parse(::TimeType, ...) to help inference. --- stdlib/Dates/src/parse.jl | 4 ++-- stdlib/Dates/test/io.jl | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/stdlib/Dates/src/parse.jl b/stdlib/Dates/src/parse.jl index 07a65a73b70c3..a5bbc686c955d 100644 --- a/stdlib/Dates/src/parse.jl +++ b/stdlib/Dates/src/parse.jl @@ -282,7 +282,7 @@ function Base.parse(::Type{T}, str::AbstractString, df::DateFormat=default_forma val = tryparsenext_internal(T, str, pos, len, df, true) @assert val !== nothing values, endpos = val - return T(values...) + return T(values...)::T end function Base.tryparse(::Type{T}, str::AbstractString, df::DateFormat=default_format(T)) where T<:TimeType @@ -292,7 +292,7 @@ function Base.tryparse(::Type{T}, str::AbstractString, df::DateFormat=default_fo values, endpos = res if validargs(T, values...) === nothing # TODO: validargs gets called twice, since it's called again in the T constructor - return T(values...) + return T(values...)::T end return nothing end diff --git a/stdlib/Dates/test/io.jl b/stdlib/Dates/test/io.jl index 11a02af9e1255..822d0101c28ba 100644 --- a/stdlib/Dates/test/io.jl +++ b/stdlib/Dates/test/io.jl @@ -572,4 +572,14 @@ end end end +@testset "inference with dynamic dateformat string" begin + datetime = DateTime(2020, 4, 7) + f1() = DateTime("2020-04-07", "yyyy-mm-dd") + f2() = DateTime("2020-04-07", DateFormat("yyyy-mm-dd")) + f3() = parse(DateTime, "2020-04-07", DateFormat("yyyy-mm-dd")) + @test (@inferred f1()) == (@inferred f2()) == (@inferred f3()) == datetime + g() = tryparse(DateTime, "2020-04-07", DateFormat("yyyy-mm-dd")) + @test (@inferred Nothing g()) == datetime +end + end From d02aba4c212a5489f7e7a6a4defa6f4663c5606b Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 7 Apr 2021 09:11:12 -0700 Subject: [PATCH 121/439] Bump libblastrampoline to v3.0.4 (#40381) This should fix some armv7l issues, as libblastrampoline had the same issues in its armv7l trampolines as Julia itself had. It also fixes some errors in armv7l interface autodetection. --- stdlib/libblastrampoline_jll/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/libblastrampoline_jll/Project.toml b/stdlib/libblastrampoline_jll/Project.toml index 6b107b1348090..d44c420b56332 100644 --- a/stdlib/libblastrampoline_jll/Project.toml +++ b/stdlib/libblastrampoline_jll/Project.toml @@ -1,6 +1,6 @@ name = "libblastrampoline_jll" uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "3.0.2+0" +version = "3.0.4+0" [deps] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" From 76c1d1d262c8cee22ec4aef4b01457dc74264412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 7 Apr 2021 19:48:19 +0100 Subject: [PATCH 122/439] [Test] Define `broken`/`skip` keyword argument for `@test` (#39322) * [Test] Define `broken`/`skip` keyword argument for `@test` They make it less tedious having tests failing consistently only under specific conditions. * [Test] Use new `@test ... broken=cond` in some tests --- NEWS.md | 15 ++++++++ stdlib/Test/src/Test.jl | 69 ++++++++++++++++++++++++++++++++++-- stdlib/Test/test/runtests.jl | 12 +++++++ test/complex.jl | 12 ++----- test/ranges.jl | 28 +++++---------- 5 files changed, 104 insertions(+), 32 deletions(-) diff --git a/NEWS.md b/NEWS.md index 140da486c30bf..81565dba4d01d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -63,6 +63,21 @@ Standard library changes * `keys(::RegexMatch)` is now defined to return the capture's keys, by name if named, or by index if not ([#37299]). * `keys(::Generator)` is now defined to return the iterator's keys ([#34678]) * `RegexMatch` now iterate to give their captures. ([#34355]). +* `Test.@test` now accepts `broken` and `skip` boolean keyword arguments, which + mimic `Test.@test_broken` and `Test.@test_skip` behavior, but allows skipping + tests failing only under certain conditions. For example + ```julia + if T == Float64 + @test_broken isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) + else + @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) + end + ``` + can be replaced by + ```julia + @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) broken=(T == Float64) + ``` + ([#39322]) #### Package Manager diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 0a260b68bc2dd..74531b482524f 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -342,6 +342,8 @@ end """ @test ex @test f(args...) key=val ... + @test ex broken=true + @test ex skip=true Tests that the expression `ex` evaluates to `true`. Returns a `Pass` `Result` if it does, a `Fail` `Result` if it is @@ -368,12 +370,71 @@ Test Passed This is equivalent to the uglier test `@test ≈(π, 3.14, atol=0.01)`. It is an error to supply more than one expression unless the first is a call expression and the rest are assignments (`k=v`). + +You can use any key for the `key=val` arguments, except for `broken` and `skip`, +which have special meanings in the context of `@test`: + +* `broken=cond` indicates a test that should pass but currently consistently + fails when `cond==true`. 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`. Regular `@test ex` is + evaluated when `cond==false`. +* `skip=cond` marks a test that should not be executed but should be included in + test summary reporting as `Broken`, when `cond==true`. This can be useful for + tests that intermittently fail, or tests of not-yet-implemented functionality. + Regular `@test ex` is evaluated when `cond==false`. + +# Examples + +```jldoctest +julia> @test 2 + 2 ≈ 6 atol=1 broken=true +Test Broken + Expression: ≈(2 + 2, 6, atol = 1) + +julia> @test 2 + 2 ≈ 5 atol=1 broken=false +Test Passed + +julia> @test 2 + 2 == 5 skip=true +Test Broken + Skipped: 2 + 2 == 5 + +julia> @test 2 + 2 == 4 skip=false +Test Passed +``` + +!!! compat "Julia 1.7" + The `broken` and `skip` keyword arguments require at least Julia 1.7. """ macro test(ex, kws...) + # Collect the broken/skip keywords and remove them from the rest of keywords + broken = [kw.args[2] for kw in kws if kw.args[1] === :broken] + skip = [kw.args[2] for kw in kws if kw.args[1] === :skip] + kws = filter(kw -> kw.args[1] ∉ (:skip, :broken), kws) + # Validation of broken/skip keywords + for (kw, name) in ((broken, :broken), (skip, :skip)) + if length(kw) > 1 + error("invalid test macro call: cannot set $(name) keyword multiple times") + end + end + if length(skip) > 0 && length(broken) > 0 + error("invalid test macro call: cannot set both skip and broken keywords") + end + + # Build the test expression test_expr!("@test", ex, kws...) orig_ex = Expr(:inert, ex) + result = get_test_result(ex, __source__) - :(do_test($result, $orig_ex)) + + return quote + if $(length(skip) > 0 && esc(skip[1])) + record(get_testset(), Broken(:skipped, $orig_ex)) + else + let _do = $(length(broken) > 0 && esc(broken[1])) ? do_broken_test : do_test + _do($result, $orig_ex) + end + end + end end """ @@ -383,7 +444,8 @@ end 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`. +if the expression evaluates to `true`. This is equivalent to +[`@test ex broken=true`](@ref @test). The `@test_broken f(args...) key=val...` form works as for the `@test` macro. @@ -412,7 +474,8 @@ end 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. +fail, or tests of not-yet-implemented functionality. This is equivalent to +[`@test ex skip=true`](@ref @test). The `@test_skip f(args...) key=val...` form works as for the `@test` macro. diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 541e8dcc2bf7d..b4d7f6afc2391 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -25,6 +25,18 @@ import Logging: Debug, Info, Warn @test isapprox(1, 2; atol) @test isapprox(1, 3; a.atol) end +@testset "@test with skip/broken kwargs" begin + # Make sure the local variables can be used in conditions + a = 1 + @test 2 + 2 == 4 broken=false + @test error() broken=true + @test !Sys.iswindows() broken=Sys.iswindows() + @test 1 ≈ 2 atol=1 broken=a==2 + @test false skip=true + @test true skip=false + @test Grogu skip=isone(a) + @test 41 ≈ 42 rtol=1 skip=false +end @testset "@test keyword precedence" begin atol = 2 # post-semicolon keyword, suffix keyword, pre-semicolon keyword diff --git a/test/complex.jl b/test/complex.jl index 56c446896bf53..6fe3046ca9a07 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -1088,16 +1088,8 @@ end @test isequal(one(T) / complex(T(-NaN), T(-Inf)), complex(-zero(T), zero(T))) # divide complex by complex Inf - if T == Float64 - @test_broken isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) - @test_broken isequal(complex(one(T)) / complex(T(-Inf), T(Inf)), complex(-zero(T), -zero(T))) - elseif T == Float32 - @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) - @test_broken isequal(complex(one(T)) / complex(T(-Inf), T(Inf)), complex(-zero(T), -zero(T))) - else - @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) - @test isequal(complex(one(T)) / complex(T(-Inf), T(Inf)), complex(-zero(T), -zero(T))) - end + @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) broken=(T==Float64) + @test isequal(complex(one(T)) / complex(T(-Inf), T(Inf)), complex(-zero(T), -zero(T))) broken=(T in (Float32, Float64)) end end diff --git a/test/ranges.jl b/test/ranges.jl index fd12a0829ce5e..b0693a32527d2 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -618,14 +618,10 @@ end @test broadcast(+, T(1):2:6, 0.3) === T(1)+0.3:2:5+0.3 @test broadcast(-, T(1):2:6, 1) === T(0):2:4 @test broadcast(-, T(1):2:6, 0.3) === T(1)-0.3:2:5-0.3 - if T <: Unsigned - @test_broken broadcast(-, T(1):3) == -T(1):-1:-T(3) - @test_broken broadcast(-, 2, T(1):3) == T(1):-1:-T(1) - else - @test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2) - @test broadcast(-, T(1):3) == -T(1):-1:-T(3) - @test broadcast(-, 2, T(1):3) == T(1):-1:-T(1) - end + is_unsigned = T <: Unsigned + is_unsigned && @test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2) + @test broadcast(-, T(1):3) == -T(1):-1:-T(3) broken=is_unsigned + @test broadcast(-, 2, T(1):3) == T(1):-1:-T(1) broken=is_unsigned end @testset "operations between ranges and arrays" for T in (Int, UInt, Int128) @test all(([T(1):5;] + (T(5):-1:1)) .=== T(6)) @@ -1569,17 +1565,11 @@ end @testset "constant-valued ranges (issues #10391 and #29052)" begin for r in ((1:4), (1:1:4), (1.0:4.0)) - if eltype(r) === Int - @test_broken @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] - @test_broken @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] - @test_broken @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] - @test_broken @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] - else - @test @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] - @test @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] - @test @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] - @test @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] - end + is_int = eltype(r) === Int + @test @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] broken=is_int + @test @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] broken=is_int + @test @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] broken=is_int + @test @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] broken=is_int @test @inferred(r .+ (4.0:-1:1)) == [5.0, 5.0, 5.0, 5.0] @test @inferred(0.0 * r) == [0.0, 0.0, 0.0, 0.0] @test @inferred(0.0 .* r) == [0.0, 0.0, 0.0, 0.0] From 263451e8b5ede5a6da2420a91ff993e9dc4c5efa Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 7 Apr 2021 20:58:21 -0400 Subject: [PATCH 123/439] Allow setting lower bound on Experimental.@optlevel (#39536) * allow setting lower bound on Experimental.at-optlevel * rename arg to min-optlevel * Apply suggestions from code review Co-authored-by: Jeff Bezanson * more suggestions from code review Co-authored-by: Jeff Bezanson --- base/experimental.jl | 3 ++- base/options.jl | 1 + base/util.jl | 1 + doc/man/julia.1 | 4 ++++ doc/src/manual/command-line-options.md | 1 + src/jitlayers.cpp | 3 +++ src/jloptions.c | 22 ++++++++++++++++++++++ src/julia.h | 1 + test/cmdlineargs.jl | 3 +++ 9 files changed, 38 insertions(+), 1 deletion(-) diff --git a/base/experimental.jl b/base/experimental.jl index b928b6ba0e1d9..7e30792dda4e8 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -114,7 +114,8 @@ parent module. Supported values are 0, 1, 2, and 3. The effective optimization level is the minimum of that specified on the -command line and in per-module settings. +command line and in per-module settings. If a `--min-optlevel` value is +set on the command line, that is enforced as a lower bound. """ macro optlevel(n::Int) return Expr(:meta, :optlevel, n) diff --git a/base/options.jl b/base/options.jl index 9ef4f78e90824..16dc884e8651e 100644 --- a/base/options.jl +++ b/base/options.jl @@ -21,6 +21,7 @@ struct JLOptions code_coverage::Int8 malloc_log::Int8 opt_level::Int8 + opt_level_min::Int8 debug_level::Int8 check_bounds::Int8 depwarn::Int8 diff --git a/base/util.jl b/base/util.jl index c489503d40133..503ba5c390e1c 100644 --- a/base/util.jl +++ b/base/util.jl @@ -181,6 +181,7 @@ function julia_cmd(julia=joinpath(Sys.BINDIR::String, julia_exename())) opts.can_inline == 0 && push!(addflags, "--inline=no") opts.use_compiled_modules == 0 && push!(addflags, "--compiled-modules=no") opts.opt_level == 2 || push!(addflags, "-O$(opts.opt_level)") + opts.opt_level_min == 0 || push!(addflags, "--min-optlevel=$(opts.opt_level_min)") push!(addflags, "-g$(opts.debug_level)") if opts.code_coverage != 0 # Forward the code-coverage flag only if applicable (if the filename is pid-dependent) diff --git a/doc/man/julia.1 b/doc/man/julia.1 index 49ee30e0af90e..8e2ed9f94c76a 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -145,6 +145,10 @@ Run time-intensive code optimizations -O , --optimize= Set the optimization level to +.TP +--min-optlevel= +Set the minimum optimization level to , overriding per-module settings + .TP -g Enable generation of full debug info diff --git a/doc/src/manual/command-line-options.md b/doc/src/manual/command-line-options.md index b6dd1b6b02722..47d581af430e5 100644 --- a/doc/src/manual/command-line-options.md +++ b/doc/src/manual/command-line-options.md @@ -28,6 +28,7 @@ The following is a complete list of command-line switches available when launchi |`--warn-overwrite={yes\|no}` |Enable or disable method overwrite warnings| |`-C`, `--cpu-target ` |Limit usage of CPU features up to ``; set to `help` to see the available options| |`-O`, `--optimize={0,1,2,3}` |Set the optimization level (default level is 2 if unspecified or 3 if used without a level)| +|`--min-optlevel={0,1,2,3}` |Set the lower bound on per-module optimization (default is 0)| |`-g`, `-g ` |Enable / Set the level of debug info generation (default level is 1 if unspecified or 2 if used without a level)| |`--inline={yes\|no}` |Control whether inlining is permitted, including overriding `@inline` declarations| |`--check-bounds={yes\|no}` |Emit bounds checks always or never (ignoring declarations)| diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 77ce3c93eadd3..eb9c91e301184 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -586,11 +586,13 @@ CompilerResultT JuliaOJIT::CompilerT::operator()(Module &M) JL_TIMING(LLVM_OPT); int optlevel; + int optlevel_min; if (jl_generating_output()) { optlevel = 0; } else { optlevel = jl_options.opt_level; + optlevel_min = jl_options.opt_level_min; for (auto &F : M.functions()) { if (!F.getBasicBlockList().empty()) { Attribute attr = F.getFnAttribute("julia-optimization-level"); @@ -602,6 +604,7 @@ CompilerResultT JuliaOJIT::CompilerT::operator()(Module &M) } } } + optlevel = std::max(optlevel, optlevel_min); } if (optlevel == 0) jit.PM0.run(M); diff --git a/src/jloptions.c b/src/jloptions.c index cc5c85a06f034..4fbf83e8f5e30 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -47,6 +47,7 @@ jl_options_t jl_options = { 0, // quiet 0, // code_coverage 0, // malloc_log 2, // opt_level + 0, // opt_level_min #ifdef JL_DEBUG_BUILD 2, // debug_level [debug build] #else @@ -122,6 +123,7 @@ static const char opts[] = // code generation options " -C, --cpu-target Limit usage of CPU features up to ; set to \"help\" to see the available options\n" " -O, --optimize={0,1,2,3} Set the optimization level (default level is 2 if unspecified or 3 if used without a level)\n" + " --min-optlevel={0,1,2,3} Set a lower bound on the optimization level (default is 0)\n" " -g, -g Enable / Set the level of debug info generation" #ifdef JL_DEBUG_BUILD " (default level for julia-debug is 2 if unspecified or if used without a level)\n" @@ -190,6 +192,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_worker, opt_bind_to, opt_handle_signals, + opt_optlevel_min, opt_output_o, opt_output_asm, opt_output_ji, @@ -236,6 +239,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "code-coverage", optional_argument, 0, opt_code_coverage }, { "track-allocation",optional_argument, 0, opt_track_allocation }, { "optimize", optional_argument, 0, 'O' }, + { "min-optlevel", optional_argument, 0, opt_optlevel_min }, { "check-bounds", required_argument, 0, opt_check_bounds }, { "output-bc", required_argument, 0, opt_output_bc }, { "output-unopt-bc", required_argument, 0, opt_output_unopt_bc }, @@ -536,6 +540,24 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) jl_options.opt_level = 3; } break; + case opt_optlevel_min: // minimum module optimize level + if (optarg != NULL) { + if (!strcmp(optarg,"0")) + jl_options.opt_level_min = 0; + else if (!strcmp(optarg,"1")) + jl_options.opt_level_min = 1; + else if (!strcmp(optarg,"2")) + jl_options.opt_level_min = 2; + else if (!strcmp(optarg,"3")) + jl_options.opt_level_min = 3; + else + jl_errorf("julia: invalid argument to --min-optlevel (%s)", optarg); + break; + } + else { + jl_options.opt_level_min = 0; + } + break; case 'i': // isinteractive jl_options.isinteractive = 1; break; diff --git a/src/julia.h b/src/julia.h index 3b28558fcd695..588b4397e3ab1 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1991,6 +1991,7 @@ typedef struct { int8_t code_coverage; int8_t malloc_log; int8_t opt_level; + int8_t opt_level_min; int8_t debug_level; int8_t check_bounds; int8_t depwarn; diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 92d6ac9b1ee22..13e7251ba3a95 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -350,6 +350,9 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` @test readchomp(`$exename -E "Base.JLOptions().opt_level" --optimize`) == "3" @test readchomp(`$exename -E "Base.JLOptions().opt_level" -O0`) == "0" + @test readchomp(`$exename -E "Base.JLOptions().opt_level_min"`) == "0" + @test readchomp(`$exename -E "Base.JLOptions().opt_level_min" --min-optlevel=2`) == "2" + # -g @test readchomp(`$exename -E "Base.JLOptions().debug_level" -g`) == "2" let code = writereadpipeline("code_llvm(stdout, +, (Int64, Int64), raw=true, dump_module=true)", `$exename -g0`) From 35a186be87ca6f1dcb07fa606792395c3492b8bf Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 7 Apr 2021 21:07:31 -0400 Subject: [PATCH 124/439] Only print a single `LoadError:` prefix for nested LoadErrors during showerror (#38725) * fold repeated `LoadError :` prints during showerror * Only print a single LoadError: prefix --- base/errorshow.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 9b974f2b86aa7..d11130523a88f 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -92,7 +92,7 @@ function showerror(io::IO, ex, bt; backtrace=true) end function showerror(io::IO, ex::LoadError, bt; backtrace=true) - print(io, "LoadError: ") + !isa(ex.error, LoadError) && print(io, "LoadError: ") showerror(io, ex.error, bt, backtrace=backtrace) print(io, "\nin expression starting at $(ex.file):$(ex.line)") end From 0da808d12bb39a61060f5ffbdfebcea045cd9429 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 7 Apr 2021 21:11:05 -0400 Subject: [PATCH 125/439] add option to `compilecache` so that Pkg precompilation can not skip different versions of loaded modules (#40345) * allow Pkg precomp to not skip loaded modules * rename to ignore_loaded_modules * arg alignment --- base/loading.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 1f317b1b161d9..fc4b1b2f1b687 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1303,16 +1303,20 @@ end const MAX_NUM_PRECOMPILE_FILES = Ref(10) -function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, internal_stdout::IO = stdout) +function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, internal_stdout::IO = stdout, + ignore_loaded_modules::Bool = true) + @nospecialize internal_stderr internal_stdout # decide where to put the resulting cache file cachepath = compilecache_dir(pkg) # build up the list of modules that we want the precompile process to preserve concrete_deps = copy(_concrete_dependencies) - for (key, mod) in loaded_modules - if !(mod === Main || mod === Core || mod === Base) - push!(concrete_deps, key => module_build_id(mod)) + if ignore_loaded_modules + for (key, mod) in loaded_modules + if !(mod === Main || mod === Core || mod === Base) + push!(concrete_deps, key => module_build_id(mod)) + end end end # run the expression and cache the result From 549380d02215522e1c288cd4754429aaef8c04e7 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 7 Apr 2021 22:13:55 -0400 Subject: [PATCH 126/439] If module is missing a docstring show readme if available (#39093) * print available readme if no docstring for module * tweak search & print * handle pathless modules * limit readme print to first 200 lines * review changes * print message on single line * handle modules in sysimage that are missing src files * tweak formatting * fix docstring test --- stdlib/REPL/src/docview.jl | 44 ++++++++++++++++++++++++++++++++------ test/docs.jl | 6 ++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 7431906209baa..d6b523160da1e 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -243,10 +243,12 @@ end function summarize(binding::Binding, sig) io = IOBuffer() - println(io, "No documentation found.\n") if defined(binding) - summarize(io, resolve(binding), binding) + binding_res = resolve(binding) + !isa(binding_res, Module) && println(io, "No documentation found.\n") + summarize(io, binding_res, binding) else + println(io, "No documentation found.\n") quot = any(isspace, sprint(print, binding)) ? "'" : "" println(io, "Binding ", quot, "`", binding, "`", quot, " does not exist.") end @@ -313,16 +315,46 @@ function summarize(io::IO, TT::Type, binding::Binding) end end -function summarize(io::IO, m::Module, binding::Binding) - println(io, "No docstring found for module `", m, "`.\n") +function find_readme(m::Module)::Union{String, Nothing} + mpath = pathof(m) + isnothing(mpath) && return nothing + !isfile(mpath) && return nothing # modules in sysimage, where src files are omitted + path = dirname(mpath) + top_path = pkgdir(m) + while true + for file in readdir(path; join=true, sort=true) + isfile(file) && (basename(lowercase(file)) in ["readme.md", "readme"]) || continue + return file + end + path == top_path && break # go no further than pkgdir + path = dirname(path) # work up through nested modules + end + return nothing +end +function summarize(io::IO, m::Module, binding::Binding; nlines::Int = 200) + readme_path = find_readme(m) + if isnothing(readme_path) + println(io, "No docstring or readme file found for module `$m`.\n") + else + println(io, "No docstring found for module `$m`.") + end exports = filter!(!=(nameof(m)), names(m)) if isempty(exports) println(io, "Module does not export any names.") else - println(io, "# Exported names:") + println(io, "# Exported names") print(io, " `") join(io, exports, "`, `") - println(io, "`") + println(io, "`\n") + end + if !isnothing(readme_path) + readme_lines = readlines(readme_path) + isempty(readme_lines) && return # don't say we are going to print empty file + println(io, "# Displaying contents of readme found at `$(readme_path)`") + for line in first(readme_lines, nlines) + println(io, line) + end + length(readme_lines) > nlines && println(io, "\n[output truncated to first $nlines lines]") end end diff --git a/test/docs.jl b/test/docs.jl index da7a6f01f03e0..c7652bd73920e 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -863,11 +863,9 @@ undocumented(x,y) = 3 end # module doc_str = Markdown.parse(""" -No documentation found. - -No docstring found for module `$(curmod_prefix)Undocumented`. +No docstring or readme file found for module `$(curmod_prefix)Undocumented`. -# Exported names: +# Exported names `A`, `B`, `C`, `at0`, `pt2` """) From 61173883fc0764e74a6000b4402c728be3210fdc Mon Sep 17 00:00:00 2001 From: Sukera <11753998+Seelengrab@users.noreply.github.com> Date: Thu, 8 Apr 2021 04:58:13 +0200 Subject: [PATCH 127/439] Widen type signature of bytes2hex (#39710) and make it slightly faster! Also improves error message on hex2bytes! when passing a non-ASCII string, And ADD compat notice, fix implementation to be more generic in regards to AbstractString. --- NEWS.md | 1 + base/strings/util.jl | 99 +++++++++++++++++++++++++++----------------- test/strings/util.jl | 5 +++ 3 files changed, 68 insertions(+), 37 deletions(-) diff --git a/NEWS.md b/NEWS.md index 81565dba4d01d..9cc478b29cb48 100644 --- a/NEWS.md +++ b/NEWS.md @@ -45,6 +45,7 @@ New library features -------------------- * The optional keyword argument `context` of `sprint` can now be set to a tuple of `:key => value` pairs to specify multiple attributes. ([#39381]) +* `bytes2hex` and `hex2bytes` are no longer limited to arguments of type `Union{String,AbstractVector{UInt8}}` and now only require that they're iterable and have a length. ([#39710]) Standard library changes ------------------------ diff --git a/base/strings/util.jl b/base/strings/util.jl index 140c5a31194f1..5cea8d280f07c 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -595,15 +595,20 @@ replace(s::AbstractString, pat_f::Pair; count=typemax(Int)) = # hex <-> bytes conversion """ - hex2bytes(s::Union{AbstractString,AbstractVector{UInt8}}) + hex2bytes(itr) -Given a string or array `s` of ASCII codes for a sequence of hexadecimal digits, returns a +Given an iterable `itr` of ASCII codes for a sequence of hexadecimal digits, returns a `Vector{UInt8}` of bytes corresponding to the binary representation: each successive pair -of hexadecimal digits in `s` gives the value of one byte in the return vector. +of hexadecimal digits in `itr` gives the value of one byte in the return vector. -The length of `s` must be even, and the returned array has half of the length of `s`. +The length of `itr` must be even, and the returned array has half of the length of `itr`. See also [`hex2bytes!`](@ref) for an in-place version, and [`bytes2hex`](@ref) for the inverse. +!!! compat "Julia 1.7" + Calling hex2bytes with iterables producing UInt8 requires + version 1.7. In earlier versions, you can collect the iterable + before calling instead. + # Examples ```jldoctest julia> s = string(12345, base = 16) @@ -632,46 +637,64 @@ julia> hex2bytes(a) """ function hex2bytes end -hex2bytes(s::AbstractString) = hex2bytes(String(s)) -hex2bytes(s::Union{String,AbstractVector{UInt8}}) = hex2bytes!(Vector{UInt8}(undef, length(s) >> 1), s) +hex2bytes(s) = hex2bytes!(Vector{UInt8}(undef, length(s) >> 1), s) + +# special case - valid bytes are checked in the generic implementation +function hex2bytes!(dest::AbstractArray{UInt8}, s::String) + sizeof(s) != length(s) && throw(ArgumentError("input string must consist of hexadecimal characters only")) -_firstbyteidx(s::String) = 1 -_firstbyteidx(s::AbstractVector{UInt8}) = first(eachindex(s)) -_lastbyteidx(s::String) = sizeof(s) -_lastbyteidx(s::AbstractVector{UInt8}) = lastindex(s) + hex2bytes!(dest, transcode(UInt8, s)) +end """ - hex2bytes!(d::AbstractVector{UInt8}, s::Union{String,AbstractVector{UInt8}}) + hex2bytes!(dest::AbstractVector{UInt8}, itr) -Convert an array `s` of bytes representing a hexadecimal string to its binary +Convert an iterable `itr` of bytes representing a hexadecimal string to its binary representation, similar to [`hex2bytes`](@ref) except that the output is written in-place -in `d`. The length of `s` must be exactly twice the length of `d`. -""" -function hex2bytes!(d::AbstractVector{UInt8}, s::Union{String,AbstractVector{UInt8}}) - if 2length(d) != sizeof(s) - isodd(sizeof(s)) && throw(ArgumentError("input hex array must have even length")) - throw(ArgumentError("output array must be half length of input array")) +to `dest`. The length of `dest` must be half the length of `itr`. + +!!! compat "Julia 1.7" + Calling hex2bytes! with iterators producing UInt8 requires + version 1.7. In earlier versions, you can collect the iterable + before calling instead. +""" +function hex2bytes!(dest::AbstractArray{UInt8}, itr) + isodd(length(itr)) && throw(ArgumentError("length of iterable must be even")) + @boundscheck 2*length(dest) != length(itr) && throw(ArgumentError("length of output array must be half of the length of input iterable")) + iszero(length(itr)) && return dest + + next = iterate(itr) + @inbounds for i in eachindex(dest) + x,state = next + y,state = iterate(itr, state) + next = iterate(itr, state) + dest[i] = number_from_hex(x) << 4 + number_from_hex(y) end - j = first(eachindex(d)) - 1 - for i = _firstbyteidx(s):2:_lastbyteidx(s) - @inbounds d[j += 1] = number_from_hex(_nthbyte(s,i)) << 4 + number_from_hex(_nthbyte(s,i+1)) - end - return d + + return dest end -@inline number_from_hex(c) = - (UInt8('0') <= c <= UInt8('9')) ? c - UInt8('0') : - (UInt8('A') <= c <= UInt8('F')) ? c - (UInt8('A') - 0x0a) : - (UInt8('a') <= c <= UInt8('f')) ? c - (UInt8('a') - 0x0a) : +@inline number_from_hex(c::AbstractChar) = number_from_hex(Char(c)) +@inline number_from_hex(c::Char) = number_from_hex(UInt8(c)) +@inline function number_from_hex(c::UInt8) + UInt8('0') <= c <= UInt8('9') && return c - UInt8('0') + c |= 0b0100000 + UInt8('a') <= c <= UInt8('f') && return c - UInt8('a') + 0x0a throw(ArgumentError("byte is not an ASCII hexadecimal digit")) +end """ - bytes2hex(a::AbstractArray{UInt8}) -> String - bytes2hex(io::IO, a::AbstractArray{UInt8}) + bytes2hex(itr) -> String + bytes2hex(io::IO, itr) + +Convert an iterator `itr` of bytes to its hexadecimal string representation, either +returning a `String` via `bytes2hex(itr)` or writing the string to an `io` stream +via `bytes2hex(io, itr)`. The hexadecimal characters are all lowercase. -Convert an array `a` of bytes to its hexadecimal string representation, either -returning a `String` via `bytes2hex(a)` or writing the string to an `io` stream -via `bytes2hex(io, a)`. The hexadecimal characters are all lowercase. +!!! compat "Julia 1.7" + Calling bytes2hex with iterators producing UInt8 requires + version 1.7. In earlier versions, you can collect the iterable + before calling instead. # Examples ```jldoctest @@ -689,17 +712,19 @@ julia> bytes2hex(b) """ function bytes2hex end -function bytes2hex(a::Union{Tuple{Vararg{UInt8}}, AbstractArray{UInt8}}) - b = Base.StringVector(2*length(a)) - @inbounds for (i, x) in enumerate(a) +function bytes2hex(itr) + eltype(itr) === UInt8 || throw(ArgumentError("eltype of iterator not UInt8")) + b = Base.StringVector(2*length(itr)) + @inbounds for (i, x) in enumerate(itr) b[2i - 1] = hex_chars[1 + x >> 4] b[2i ] = hex_chars[1 + x & 0xf] end return String(b) end -function bytes2hex(io::IO, a::Union{Tuple{Vararg{UInt8}}, AbstractArray{UInt8}}) - for x in a +function bytes2hex(io::IO, itr) + eltype(itr) === UInt8 || throw(ArgumentError("eltype of iterator not UInt8")) + for x in itr print(io, Char(hex_chars[1 + x >> 4]), Char(hex_chars[1 + x & 0xf])) end end diff --git a/test/strings/util.jl b/test/strings/util.jl index 617ff31106634..2ca6df529ba51 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -376,6 +376,11 @@ end #non-hex characters @test_throws ArgumentError hex2bytes(b"0123456789abcdefABCDEFGH") end + + @testset "Issue 39284" begin + @test "efcdabefcdab8967452301" == bytes2hex(Iterators.reverse(hex2bytes("0123456789abcdefABCDEF"))) + @test hex2bytes(Iterators.reverse(b"CE1A85EECc")) == UInt8[0xcc, 0xee, 0x58, 0xa1, 0xec] + end end # b"" should be immutable From b05f94d4170ecdc9d4159f702588b29c301ec876 Mon Sep 17 00:00:00 2001 From: ro-ble <31608174+ro-ble@users.noreply.github.com> Date: Thu, 8 Apr 2021 06:54:35 +0200 Subject: [PATCH 128/439] =?UTF-8?q?doc:=20hint=20on=20how=20to=20type=20th?= =?UTF-8?q?e=20=C3=B7=20sign=20(#38762)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ÷ sign is the only operator in this chapter which has no dedicated key on the keyboard. With the Unicode input being at the very end of the documentation, newcomers probably do not know how to write the integer division sign. Therefore, I added this short hint on how to type it. --- doc/src/manual/mathematical-operations.md | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 850c1f15bbd17..eff9b4f76221d 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -9,18 +9,18 @@ collection of standard mathematical functions. The following [arithmetic operators](https://en.wikipedia.org/wiki/Arithmetic#Arithmetic_operations) are supported on all primitive numeric types: -| Expression | Name | Description | -|:---------- |:-------------- |:-------------------------------------- | -| `+x` | unary plus | the identity operation | -| `-x` | unary minus | maps values to their additive inverses | -| `x + y` | binary plus | performs addition | -| `x - y` | binary minus | performs subtraction | -| `x * y` | times | performs multiplication | -| `x / y` | divide | performs division | -| `x ÷ y` | integer divide | x / y, truncated to an integer | -| `x \ y` | inverse divide | equivalent to `y / x` | -| `x ^ y` | power | raises `x` to the `y`th power | -| `x % y` | remainder | equivalent to `rem(x,y)` | +| Expression | Name | Description | +|:---------- |:-------------- |:----------------------------------------| +| `+x` | unary plus | the identity operation | +| `-x` | unary minus | maps values to their additive inverses | +| `x + y` | binary plus | performs addition | +| `x - y` | binary minus | performs subtraction | +| `x * y` | times | performs multiplication | +| `x / y` | divide | performs division | +| `x ÷ y` | integer divide | x / y, truncated to an integer | +| `x \ y` | inverse divide | equivalent to `y / x` | +| `x ^ y` | power | raises `x` to the `y`th power | +| `x % y` | remainder | equivalent to `rem(x,y)` | A numeric literal placed directly before an identifier or parentheses, e.g. `2x` or `2(x+y)`, is treated as a multiplication, except with higher precedence than other binary operations. See [Numeric Literal Coefficients](@ref man-numeric-literal-coefficients) for details. @@ -28,6 +28,8 @@ Julia's promotion system makes arithmetic operations on mixtures of argument typ naturally and automatically. See [Conversion and Promotion](@ref conversion-and-promotion) for details of the promotion system. +The ÷ sign can be conveniently typed by writing `\div` to the REPL or Julia IDE. See the [manual section on Unicode input](@ref Unicode-Input) for more information. + Here are some simple examples using arithmetic operators: ```jldoctest From 027bd4a4d17979e5f78ca6831cac456dc41d1db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 8 Apr 2021 06:56:34 +0200 Subject: [PATCH 129/439] Replace _iszero by iszerodefined && iszero (#38789) This PR defines an iszerodefined function that custom types implements in case iszero is well-defined even if zero is not defined. Take 2 of #36194 after it was reverted in #38764. What was missing in #36194 is that in case iszero is not working for a given type, we should drop the structure and fall back to an Array. --- .../LinearAlgebra/src/structuredbroadcast.jl | 26 +++++++++++++++--- .../LinearAlgebra/test/structuredbroadcast.jl | 27 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index f9416b4cf3557..95a1842702291 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -105,9 +105,29 @@ function isstructurepreserving(::typeof(Base.literal_pow), ::Ref{typeof(^)}, ::S end isstructurepreserving(f, args...) = false -_iszero(n::Number) = iszero(n) -_iszero(x) = x == 0 -fzeropreserving(bc) = (v = fzero(bc); !ismissing(v) && _iszero(v)) +""" + iszerodefined(T::Type) + +Return a `Bool` indicating whether `iszero` is well-defined for objects of type +`T`. By default, this function returns `false` unless `T <: Number`. Note that +this function may return `true` even if `zero(::T)` is not defined as long as +`iszero(::T)` has a method that does not requires `zero(::T)`. + +This function is used to determine if mapping the elements of an array with +a specific structure of nonzero elements preserve this structure. +For instance, it is used to determine whether the output of +`tuple.(Diagonal([1, 2]))` is `Diagonal([(1,), (2,)])` or +`[(1,) (0,); (0,) (2,)]`. For this, we need to determine whether `(0,)` is +considered to be zero. `iszero((0,))` falls back to `(0,) == zero((0,))` which +fails as `zero(::Tuple{Int})` is not defined. However, +`iszerodefined(::Tuple{Int})` is `false` hence we falls back to the comparison +`(0,) == 0` which returns `false` and decides that the correct output is +`[(1,) (0,); (0,) (2,)]`. +""" +iszerodefined(::Type) = false +iszerodefined(::Type{<:Number}) = true + +fzeropreserving(bc) = (v = fzero(bc); !ismissing(v) && (iszerodefined(typeof(v)) ? iszero(v) : v == 0)) # Like sparse matrices, we assume that the zero-preservation property of a broadcasted # expression is stable. We can test the zero-preservability by applying the function # in cases where all other arguments are known scalars against a zero from the structured diff --git a/stdlib/LinearAlgebra/test/structuredbroadcast.jl b/stdlib/LinearAlgebra/test/structuredbroadcast.jl index fea7fa08f0534..4aeca31a79a03 100644 --- a/stdlib/LinearAlgebra/test/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/test/structuredbroadcast.jl @@ -206,6 +206,33 @@ end end +struct Zero36193 end +Base.iszero(::Zero36193) = true +LinearAlgebra.iszerodefined(::Type{Zero36193}) = true +@testset "PR #36193" begin + f(::Union{Int, Zero36193}) = Zero36193() + function test(el) + M = [el el + el el] + v = [el, el] + U = UpperTriangular(M) + L = LowerTriangular(M) + D = Diagonal(v) + for (T, A) in [(UpperTriangular, U), (LowerTriangular, L), (Diagonal, D)] + @test identity.(A) isa typeof(A) + @test map(identity, A) isa typeof(A) + @test f.(A) isa T{Zero36193} + @test map(f, A) isa T{Zero36193} + end + end + # This should not need `zero(::Type{Zero36193})` to be defined + test(1) + Base.zero(::Type{Zero36193}) = Zero36193() + # This should not need `==(::Zero36193, ::Int)` to be defined as `iszerodefined` + # returns true. + test(Zero36193()) +end + # structured broadcast with function returning non-number type @test tuple.(Diagonal([1, 2])) == [(1,) (0,); (0,) (2,)] From cc1e70a6e7d53e64c3769b60de196dd332a06584 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 8 Apr 2021 11:37:31 -0400 Subject: [PATCH 130/439] fix #40337, no error info from serialized TaskFailedException (#40395) --- base/task.jl | 7 +++++- stdlib/Distributed/src/clusterserialize.jl | 24 --------------------- stdlib/Distributed/test/distributed_exec.jl | 2 +- stdlib/Serialization/src/Serialization.jl | 14 +++++++++--- 4 files changed, 18 insertions(+), 29 deletions(-) diff --git a/base/task.jl b/base/task.jl index f817fdaae9cae..87b354d052797 100644 --- a/base/task.jl +++ b/base/task.jl @@ -79,7 +79,12 @@ end function show_task_exception(io::IO, t::Task; indent = true) stack = catch_stack(t) b = IOBuffer() - show_exception_stack(IOContext(b, io), stack) + if isempty(stack) + # exception stack buffer not available; probably a serialized task + showerror(IOContext(b, io), t.result) + else + show_exception_stack(IOContext(b, io), stack) + end str = String(take!(b)) if indent str = replace(str, "\n" => "\n ") diff --git a/stdlib/Distributed/src/clusterserialize.jl b/stdlib/Distributed/src/clusterserialize.jl index 3fde2bb4c2bd6..e37987c5bf875 100644 --- a/stdlib/Distributed/src/clusterserialize.jl +++ b/stdlib/Distributed/src/clusterserialize.jl @@ -102,19 +102,6 @@ function serialize(s::ClusterSerializer, t::Core.TypeName) nothing end -function serialize(s::ClusterSerializer, t::Task) - serialize_cycle(s, t) && return - if istaskstarted(t) && !istaskdone(t) - error("cannot serialize a running Task") - end - writetag(s.io, TASK_TAG) - serialize(s, t.code) - serialize(s, t.storage) - serialize(s, t._state) - serialize(s, t.result) - serialize(s, t._isexception) -end - function serialize(s::ClusterSerializer, g::GlobalRef) # Record if required and then invoke the default GlobalRef serializer. sym = g.name @@ -244,17 +231,6 @@ function deserialize(s::ClusterSerializer, t::Type{<:CapturedException}) return CapturedException(capex, bt) end -function deserialize(s::ClusterSerializer, ::Type{Task}) - t = Task(nothing) - deserialize_cycle(s, t) - t.code = deserialize(s) - t.storage = deserialize(s) - t._state = deserialize(s)::UInt8 - t.result = deserialize(s) - t._isexception = deserialize(s) - t -end - """ clear!(syms, pids=workers(); mod=Main) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index c36a79600773c..606b7fa81c3e7 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -1675,7 +1675,7 @@ let e = @test_throws RemoteException pmap(1) do _ es = sprint(showerror, e.value) @test contains(es, ":\nTaskFailedException\nStacktrace:\n") @test contains(es, "\n\n nested task error:") - @test_broken contains(es, "\n\n nested task error: 42\n") + @test contains(es, "\n\n nested task error: 42\n") end # issue #27429, propagate relative `include` path to workers diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index cb3dc6a38600a..f644c73762c2f 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -458,11 +458,19 @@ function serialize(s::AbstractSerializer, t::Task) if istaskstarted(t) && !istaskdone(t) error("cannot serialize a running Task") end - state = [t.code, t.storage, t.state, t.result, t._isexception] writetag(s.io, TASK_TAG) - for fld in state - serialize(s, fld) + serialize(s, t.code) + serialize(s, t.storage) + serialize(s, t.state) + if t._isexception && (stk = Base.catch_stack(t); !isempty(stk)) + # the exception stack field is hidden inside the task, so if there + # is any information there make a CapturedException from it instead. + # TODO: Handle full exception chain, not just the first one. + serialize(s, CapturedException(stk[1][1], stk[1][2])) + else + serialize(s, t.result) end + serialize(s, t._isexception) end function serialize(s::AbstractSerializer, g::GlobalRef) From 0869969e9747ce4dec8e7e69647ee12db309cd9f Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 8 Apr 2021 09:05:57 -0700 Subject: [PATCH 131/439] Bump OpenBLAS_jll to `v0.3.13+5` (#40396) * Bump OpenBLAS_jll to `v0.3.13+5` This should fix the illegal instruction errors older processors are running into. * Fix doctests * Update checksums Co-authored-by: Viral B. Shah --- deps/checksums/openblas | 184 ++++++++++----------- deps/checksums/suitesparse | 1 - stdlib/LinearAlgebra/docs/src/index.md | 14 +- stdlib/LinearAlgebra/src/symmetriceigen.jl | 4 +- stdlib/LinearAlgebra/src/tridiag.jl | 8 +- stdlib/OpenBLAS_jll/Project.toml | 2 +- 6 files changed, 106 insertions(+), 107 deletions(-) diff --git a/deps/checksums/openblas b/deps/checksums/openblas index 05b7ab29f55b7..ad67b3b6a2fc6 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,94 +1,94 @@ openblas-d2b11c47774b9216660e76e2fc67e87079f26fa1.tar.gz/md5/d50510c8b60b477b1ece4abafe66bf4d openblas-d2b11c47774b9216660e76e2fc67e87079f26fa1.tar.gz/sha512/95ce349353bea5e9c30455410b92fa9ebc833e58163a53a65b396c76fddf19147a323a3c69eea5892354488c67b027e20dc9b03754a0988f3bc8a4e9ad446b8b -OpenBLAS.v0.3.13+4.aarch64-apple-darwin-libgfortran5.tar.gz/md5/4f2775159e7d83cd4447e3fd7868e7e1 -OpenBLAS.v0.3.13+4.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/f8bc618d335ac1782531784bcf4d76fea587142fb0546ccacaeb0fcfae1e8a59a5ef1afbba33277521a56fe580467b0574afa7c97ad82cd76f5e154d2a390557 -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran3.tar.gz/md5/4317a7a4f2bc43dac7e9853288143c9a -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/2e0dda3cfe8b2df6e652499c8ed5a21ebc02357bee555e121d516c8c1a015521034c5887907956e8fe3d1f9cf892e0cd6a8fe63cc97a60ee12e6ce1d501a56a5 -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran4.tar.gz/md5/4a91f26298c2f20930a2759da48cd565 -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/2005ce29bd7b35c828b672776a4a65e9555d7cdcbeb093220075a85f69cc3168bc669648ad2795c63f5c78c5c6495e0e3328741789b3360a4320689e83645315 -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran5.tar.gz/md5/3bd51556c64a5b2b1e1b556040462d17 -OpenBLAS.v0.3.13+4.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/b278d8d8e95e3e8c79167659144bb0d876cd086f8323324faa10f85f9f382e94e613b19e7f677b692b5402fb2d6c54ad134d8c55b7441c48f32e90272eeb884f -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran3.tar.gz/md5/db27b95b3dc9f9705910eaec615f3098 -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran3.tar.gz/sha512/e6b8d98b0b24e219df5cf53956b1f2aedb3ac65d362dffb714d7c9110dbcca4bf47576464c5b6a1309354eb6f2ba48a932d665e552b90f2f679d7a5f5bb7b4f3 -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran4.tar.gz/md5/66f42f04c7f9deda3440426685f60f5e -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran4.tar.gz/sha512/bedb7b3b7151bb3e4241d7e05271e0d0b6cbec0c4c8f4f8a5e32fdef753a3d34f5fb7c51a5e8d9e522fa4dd7a3eac6dfac75a9fef36175ef923a7b1e399f8818 -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran5.tar.gz/md5/1418bfbd20bf08cfc6e018f9e6534569 -OpenBLAS.v0.3.13+4.aarch64-linux-musl-libgfortran5.tar.gz/sha512/a78c8b68e418580a7d40c8be50a5abb06b4ca04a4e5daa5579db394da509119a417a1c191f1eccdd308559f81f7c1a8e324ecb0a86d74a6e68a4748a59b95643 -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/d8ba3b4c6e681e5ca74526b39389b762 -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/57cb062d9eb7b94934cd9448f2a92e5b5bfd28fd98aff2d94efb3e3aa40c2ae53a03c928babf266d46cd91d9ff9c5e51b7f8690b98136f511ab9374e1d16636a -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/0a6d019340b05ded69a11b0ae5be68d3 -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/bbcb4cde29c004e4f146cb31c95de10c900123483019888b0319be93882139416a03971dc8cca6c3c2b3419ea5f6f8108641b43caae63fd0b3db93cb24e17655 -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/f73dce27904ccc783ee8f3ce951c5d47 -OpenBLAS.v0.3.13+4.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/6f914e74c0c9279370515ee799696cb710ecf79cd9685652b78a0d3deffd39783327b67d305d041454f083fd744eb80cc242a1de8d0c60cdb905e0da200a22d0 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/4ea568b64c1afc936dbc74ffe024fdf9 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/6fdf28b89b78aa06fe715258920ab0d2a142f3b134eaebcddae8f5c5bcb4e2e33009934840ec5d0ccbfd6b33c5f3f46e7b99d8d73afe14ba420b096caa1778e0 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/e0ac5999379580d28c739c28f53eb3b0 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/20641f43324267db53b9593bd7ed08909499838679344af99767cd56e7e47a223a0ca7c5d5b9857d8c09e8b044228d10e828a55167f93bea4f48bd523029fac3 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/a2f55bd99b92e9a4dbb8cac2d67da859 -OpenBLAS.v0.3.13+4.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/ba2529bf0387019a2749dca1c3ef1b85226ce10624e52d5422bb998178d2d7a4c2015a62f93288bde7fded6edc65c5e148d606dea5901f4d21d8d1a34f49fdeb -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/2f4ed5c58bed415739fdf0fb8e322ed5 -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/1900cd263760c5deecd097b24e1b60d9082deaf68e5173c77a2b750188b51ed6611f157f06861be76c0796d08ab8f177024d0725435c15fe10c857a7fb384fa7 -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/246b3797012725bfc3de103432d7681c -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/3909bb3ef6e7212df4535198b0027a45804079eabf8bbf17b8826a85f30c55cbb36f63859b036bc27b9231a8697ac2fb5411fafca886e720d8246bc81dd14a6c -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/0e9f2ed5aa7b218037187346d8981112 -OpenBLAS.v0.3.13+4.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/26a57c52159c16d7886e25ce4e8a4bc21c903eda09f7720cb5bfb3d7757cd6f9aa0502c4dbb36ca03697937d92ab4f5a98394dc1b950d580806991494327ec68 -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/1590ae03eaa30cb72599513bc826da3d -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/1d12d05e8a60dcaf311e72d5303e4d150dd552c0e8df653bf6f1cc643b6b695c47d2f97a8096c029ef6d45be1d83664040964ab06f9f16f01f51cf1d6b515ee8 -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/c36b060c2fc5913d0e67b466eb023616 -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/921e6d07063a5823529d45830f58437889d63c17c39110a60a37a703fe60d9ba40cd28a703e8f2cfc40825a9a2fc0afb0d39ba985522f8b2a70beb6be7366dbd -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/1c30ccf8a80a0762e5866003667aa219 -OpenBLAS.v0.3.13+4.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/c1109c32b2468d4d47cbe3c972330e66671e1e35cae358addf3017df2a4912e36f0f9a8113929f67422034c64935e363e6d4a259dc67b0467b7d5ac7d287cf55 -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran3.tar.gz/md5/f1fffae5cd41d0b275ca2364c4d37b9f -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran3.tar.gz/sha512/2da97e72d42649bbd8a03eda67659410ab99532fbdea3bf1b49298dbd3964c66e23eececcc58e943ed8cea239a0d089ede97720e9f46f1a3800843c41d290e33 -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran4.tar.gz/md5/7d8f65b490d9d2739090d4fff81c60fa -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran4.tar.gz/sha512/fceb132f445f6e596ae8473a14b0c4d23b8f16dea9ebf6df23a94c1343afe842ab3e40915d9d425e30d76950eee3bfdd7dd18ebf13352c5b46c2423c5719ecd6 -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran5.tar.gz/md5/bb2df68fe4f49ed1669450b4ef15843e -OpenBLAS.v0.3.13+4.i686-linux-gnu-libgfortran5.tar.gz/sha512/3d247832dba3ab2adbd9da9a79702bf64f227faba22bcb50828971299ef3f377ddbc424f9c3c625d159feca0dd781ca9de259317d8d7035ed60a45a4ff545c3f -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran3.tar.gz/md5/2609e74add74c2b36e3eb05ffe1639d0 -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran3.tar.gz/sha512/621ded00ea9708d520f18329bb649bbdb1b2e8a2c38a1b1611b39deb5e97443fcd9c5be2aaeed595c368e37f9d895c4bcb22a4544b1c3cde86d8c7de68ed403e -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran4.tar.gz/md5/a39578b29870bca9708882806c4f8309 -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran4.tar.gz/sha512/e2b79008d56c9afb685163186d40719fdb4cf62f2956c20d82d997549af447d936fdff2d2b232689d6a15840a72a6341e8a5962eeff11c748277de648d8c565b -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran5.tar.gz/md5/2d17bc3fcbb5dcef7f6d4613d67afcf9 -OpenBLAS.v0.3.13+4.i686-linux-musl-libgfortran5.tar.gz/sha512/8181ff5218b557a9bb5b25854b3d38e08730cda1c0a7396c13a3fd3c7583e04e843793d3fa1b17bfb58eed19c2e1d4b3867fd5df4651fe37d84bbf19c1362ee7 -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran3.tar.gz/md5/882e9ab41d7fe18e08530d3f4480fa03 -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran3.tar.gz/sha512/2243b59ea4c14f0611ac6dd6a7a9a8f2beed61f2a65084a89aeacf79c16ac198de508aa2f34ca586c8af7029bbde3f29b05b4e8e97777a1a8546afad1113fdd0 -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran4.tar.gz/md5/e14ce353b77e2e80063c9c07b77d4bd5 -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran4.tar.gz/sha512/a8e362f9dd9ca06ef6efc4927782e12e097941babc18b17c72f8d69aade416cc1886a89e34161dcda756ec3821a33f2bedf4dca4d641186a9e8e3db9486a56b4 -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran5.tar.gz/md5/f718d5df066df8998961c041fd53e35b -OpenBLAS.v0.3.13+4.i686-w64-mingw32-libgfortran5.tar.gz/sha512/6b5702c135a576915bc4cc6fc1127521bb2d10d28797d24941c15ae870b70fbb62a25e63842da35ab641346fae68368476edbd0751f8b6108db2e5457d507aef -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/6e294aa03b2e48913bee0b389ea93645 -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/4ddc7c0f3013f2069e5924f4f96f8d882b473b01e3dfbf7e865bf3a93fed94a57b4477c3fbfd4f2579f2ba78832bfbbe0c2d597e8d636aeb7dc283dd0514144b -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/8020654c032cd0e99630517e7f56e980 -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/92373120aaf73cdc6046e1c4a81541469a38025e181ec3fd7334d126fd78afb1db0342e431a293821a1226b30b20aa75aa60059cca11ee327ba452f7e378efe0 -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/8300b47873e3a81a61b8c280332e3764 -OpenBLAS.v0.3.13+4.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/163e35797e4a0f9ed15dd5d4707cb0ab54d0de548264c71c983050dc07015a8e329657429821a8a52a59805445169af80e12999fe61814ba5ab4685d66db9ad2 -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran3.tar.gz/md5/2459157e3b79311b181e88213d2afbf6 -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/723187b212869a4d9abbac586ee934b4d0cbb50430f336d7d9b7130207241189058abe324c6fe3a4ec9eb8007653d2fa548affbe7880f6aa3a2dd40d099f6fc5 -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran4.tar.gz/md5/5df3ecfad7ecc904852c1123b1e7c8cc -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/643d115abe50d10a09d2f02254b797ba2b81deb3173457a96c81d1f02036330c208b7ac545cf41838864ddd1be16567ad685cc2e5899df4993b423cf2c2ad34b -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran5.tar.gz/md5/3de8f778d3aa3102227fed3c0540843a -OpenBLAS.v0.3.13+4.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/69343d8baaa8c435e219d640df79f7a314dc67e494d50acb67fe13f8f5fd16d0bb84b19f575afc9ebb2db79d3e7dd08ccfda7a8143f80a00ecd5b8056ddac6b1 -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran3.tar.gz/md5/46114a6da46772f5a13330d1c4786f57 -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/a805be012462ed47bf153cbb7f2fe476e9988f57165927e4c6ce5e344c6580a6547f492d0df555e4f4f34c4a55efb179c32451f0c7143419543c9a10566a5fe6 -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran4.tar.gz/md5/84e64d74834762a018fa403c3bbe0f77 -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/112c073fa91a6a5e01092b0eba062ac9201e3ebbe875a98e5c214f45f05eb7ddc00939d3dd55954b136b6fbe532b7a8aa2dfa91b278d3202ebfc7d9a966fa37d -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran5.tar.gz/md5/020c74f778e0729d5dc1267f7c6a3fd4 -OpenBLAS.v0.3.13+4.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/1587083156596a8839972516fc96484dd58dbd5bd134ea3054a843f995f69c8a0a08d174ff2a6ec37961d825d5cc55f99e1daa7828587ee68669026e655c16f8 -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran3.tar.gz/md5/e179ad17125cd6726c641d30e3633edd -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran3.tar.gz/sha512/139f92f57d5c56970f741421d614b2c0c8f2fced0c19ac5615cdd8f84b8c3fda96a56f938a64ccc1431d1938c15ce86fd19b5465b79e814f39e8afdf624068b4 -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran4.tar.gz/md5/a19460cdfb1ab3e334c4a23a7fa40aa8 -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran4.tar.gz/sha512/702ded70c3195ad624b0e03f9bdadc9be8cc5e991b26bb2d863458a908e17d27bcfcee71eec2547e4e43c8afa204103ff6fe2eefe07db4f031d757f4367d9755 -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran5.tar.gz/md5/eba567bf765f5e438e8fee579c1f91b5 -OpenBLAS.v0.3.13+4.x86_64-linux-musl-libgfortran5.tar.gz/sha512/8e02ac4b56b2634e6c9481bba7ca8878ae1dd9f0c153975f7983e6aeab5cb3a03409ee3c237e066bef2da41b8f36483c3a5026b6acc85a77071e73c342cec4bc -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/321c44260b7d2443a177a9839bd5a7a6 -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/ac2f99d265bc44d61d2d7422afc790f9e52d8309e07c810fabab6951dd50993652f2271f591677bfe0d9ba123e7375382b59ce477b8a05d916efa093eb83cdda -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/9e650bc22e9b14320396c5621e25960d -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/847a6d689e81b7296ab08b4ff9881ce1a26af39b76199189b31d10fc0a18a24b9ffafb47c3d81c285a78691fba3c823dbf4a9aa5940b65331a10cc2eaff1b7d7 -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/65e2f7649e70277f90165a97eb19a67d -OpenBLAS.v0.3.13+4.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/62602e42c89805ab3963dc2989545a8a0f17ace7193bab527b54c2ca4c5066eefc0f6ef110c0a5e43fd4d6c9e7922be7e40a1ac9813b7fd1b3873756d9785675 -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/ad7ad7a00aae93c8347171c2319895ed -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/a87c5e5c7917885916cd38379944f9eb4830748d5488037834cfd6f87e50b35133a94906c56fd4f9c3716e8c3ea4f00ae214b3edbad86f0a4ccf89653eba5c7b -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/ab072184c8caf97ad243937701bfbeb8 -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/0ed921eda9756e262a840bdc4ec4f91c419f18efc15511b3ab5eb4407bade5b73cfdc8b9e8c2d42c1cd500a98729d452040bd41fe3080d5fdec30e12841fe975 -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/532b261f05ee1c0f131a55ba138df9c6 -OpenBLAS.v0.3.13+4.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/407279412cc912cf56cdafd5569eddfdca92dc01a045fb3450b9cedb9c9d2efbcf01d44bf8de94c197c4bad398e911ad651ac08a3ccd3741c1ad30661451471a +OpenBLAS.v0.3.13+5.aarch64-apple-darwin-libgfortran5.tar.gz/md5/bd8b87e018af8cf4da8440d9c2d7ea4b +OpenBLAS.v0.3.13+5.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/b066b590037a2ac6e8cd859ec642a330b4d058b60da2d071353c6dbe7691a8bb31a13fe36a03be3f1db5066ddd636c39911cb827aecb3811b5ff47de6ba3d3d3 +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran3.tar.gz/md5/0bfab1cdeab001382fbc6216a509532f +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/6137d4e861e61ad4ec6e871e7d24bf30979f701e27517b4b93cfea6230f34b70860d2bad8c8adadf426efce49d3348c1970d3bc85072c99aa255fcd6032450c0 +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran4.tar.gz/md5/ca0a14f775d18ef9313fc5a3d1ba36ad +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/74eb80e9f81519c514ddc09940c3ac6d79788ee0de3384e10039f836b806a7d4e521b25095606c366af1b84ef05aea47f6a6e9fb437b3297a4594c3507b36fc3 +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran5.tar.gz/md5/ad2976c0c5e7d5aa9b8d87cc23e9650d +OpenBLAS.v0.3.13+5.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/2eda1e20468ea51d8196e8d2063cd709579aef33dd180957adf749e6a460330d47561b368885444be8a5eaca8c711058769fb8ebdcb9d7e5d7f55649e74c3677 +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran3.tar.gz/md5/9f102704c8730df892ca4cb75d78d2a7 +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran3.tar.gz/sha512/07345f12b03c004ec84e92ba2e4685478e09e13348b6a6c4faf41ddea7ec2bc11e9fbb2234865b931be880ff5a056f4ffa21d01706af46ce983597bddb56f340 +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran4.tar.gz/md5/3d6132e2ec95f7c5d952e512b095abeb +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran4.tar.gz/sha512/b7b4c62ae8040b9290487f3399fdf6fff40c5172e8830d46e7c2d35f1eeae90c54d3a93d297d8e3bb70c8e251cb7ab83fee454b3876443d97cedd8c566325d88 +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran5.tar.gz/md5/8a6e784e1194eee29bc0077b9d9c431d +OpenBLAS.v0.3.13+5.aarch64-linux-musl-libgfortran5.tar.gz/sha512/732cfbf3663717aedb70b9b14041b520a0281e3a8597018205a0dd96d89fc8f307bcb9ed1158da50bf643af6f1518e1cb7c1734ac7966611a4a6e181f1f3ec80 +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/64ef9d054ac9090d44c250d5ac773a71 +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/92cace617a0ca6c06fea90848a1b8d5719e5f7ef62112b2c0ffdd34199e3153759a57c8cdd3f26893d880ddb5db2cf9e57963d758a9dc2d8cad3346cf6b5caae +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/d9d069d165541e1717e0f4bd2cd7018f +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/6b640b432ff56495610555f6f4cec897c25898e8625f8028dc11e3400bf099533e4a88628de85a852c6c10e76e8defd69cd3b6b5b53a072362fab38dfafebd08 +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/d557c68c9d6e619f240239c1e3bdda6f +OpenBLAS.v0.3.13+5.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/a9ee8ed000eb862bc10578526f311cd578d2cb59976b404d370150b97e84348b094852fae000dba4aa83d88b45bd50129da661cde7a1f8120dd1e29db66342cd +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/7570b2ae804f57605715f31ca5144ce2 +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/87f169e260093a9652a299ae9b042fab015a21b67bae285bd425bd02471ebe41634f843be18bb4d8cb2fbe2f2ffb062b7de63148ed64fe66f4ba48dd622dd615 +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/d2959f5bcb95f9ce759da9941b89dafc +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/dd4b0572c5165e511537f223e2bd2ff9b9c3f9ea241e8fe5c2863064f9dde37245c0e6cb331cd3ac6f02f15b4708bf53dcdd98daeb17f50eecb3abfbfb17a954 +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/aa42183091223699052c4011b546f399 +OpenBLAS.v0.3.13+5.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/b465abdcf5e876f2faa091927bd40da8a3c99a64d13ebbb1154a9c5d73652791db1b58564ea7bb0b0801af0ff239c8f3530c7784b91c6e2d770258108458c9fc +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/9ddcfad4d2a2678acad7af0bd802ab94 +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/6803844189ae00891559ad0dc624e8253c05c0a27b8bf589539164dacb5251f22e6829fade408d1f64e39dd0979fb0be0993da4c96ae91e76e962e9f0f023de2 +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/91d4df8a78d2f6295cdd597ff6f3beea +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/670d8bd3e49fc53d68dba3675f1962a01bbb396fe4e36b5169016f61fe4f8528876d0ed88ed4830714029e73e62b49cafbae2ad384eebf90eee1e6f558abd514 +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/d08af1ab6eac6b37a9565080d9179616 +OpenBLAS.v0.3.13+5.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/12f2e08fa4c5d040f0992ba99fd19342d27999ffbdd3df4a1b2981a852caf7148b9b6d17747a61a961da427840f77c8867ed82df6a8fe395e54e92f68739afd0 +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/db725dfb473c4cda573950b955415102 +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/d9be3863df5dd3ea5282a52489814db24f1a53fc76aaf323aaf6034637053b490dd927b37e71f29ad68cc4a825982d7e846ebe7fc5206d68ba2a74e411afb493 +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/8668cfc1158871e4815fc0e169cabcf3 +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/6b345f776f853df1c69f73afeb67e35dc7c928ade07b24b561d238fdde2270c054083b7a3e216ec20071f34fa945141fc5b38af84ce42e57cf9e3a0f1bfea4cd +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/00a1d20c390ea1eb8d1005ec9c26e809 +OpenBLAS.v0.3.13+5.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/2d0e0880e36be4761f61b27da16b644cb097012ed2b03141b1646f0b1ceed6176030cfb31a45e7a0d5ded99a2d6a8e472bf2e2c5f5e4260ed997e9e88cdc1b70 +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran3.tar.gz/md5/8d67cca00f231c01330b993f1c2b9b39 +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran3.tar.gz/sha512/abbd1b89f7a40b1b72aa9b0a9d57688e5d6d385029e7e2016d31eda866898c42686f1ad1a47d69213c7e79e0e85c1ab74dc5eb467eb07c286ef3153a7dd33113 +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran4.tar.gz/md5/9473d3d6bd2ff41ce7a9bd70077aa884 +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran4.tar.gz/sha512/3a3da3b01dad7b0171e1ecc18bf274a2c9043c756b06da0f140db68342d8fcbd9afcfd1b1b05aa9d3f3c8fa4ce1915ed25dc38671adcf98fef969a106e49470c +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran5.tar.gz/md5/d64ccb11a8ea4c4dba5778f754e3e8f5 +OpenBLAS.v0.3.13+5.i686-linux-gnu-libgfortran5.tar.gz/sha512/8b4759484d705aae68d65a0785af9788c86d3766285c6fe3985837b9320f864be32f09e98707fa6d8614a702d44154019818fa4c44bafb9c54828e25555a4ac2 +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran3.tar.gz/md5/02c1652b95583156ea798d0e0241b979 +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran3.tar.gz/sha512/c9c7ed980170e5b4c23684d3979a972c47ed06c19ef582cbee7130b84511ca110af3408ae5b161162552a55611d7de6007c2a1d6adb4f872f1ccec4f6a3d38cd +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran4.tar.gz/md5/92a0082208291ead889f38ee4eeda56e +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran4.tar.gz/sha512/68cab863ca08fcde9aa75ccf8f34c49bdc4ff48089c982f2c00506765c7d37beaeddfb65e7d31847f1c61ef6390f6ce6fe307c7cf069ef7189ec55d38a56ddd3 +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran5.tar.gz/md5/60e2bb9badf6121387d87bd8b88a63e9 +OpenBLAS.v0.3.13+5.i686-linux-musl-libgfortran5.tar.gz/sha512/13f7aaa870e9d7811ee79f1b8133345e0aa0d0bf4ad20d39acb43723b2bda1b11efaa2c6fec3cd8e2bc83b411be926fa74b39a8fcab1af92ccd0665435b22007 +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran3.tar.gz/md5/f9e29157a222ec195f5d42dbe0472f8d +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran3.tar.gz/sha512/a3b0875554a063a966e03d4a2f3d2dfecd44b049b93a9b627aa0491b70fbe4d1ba04f8b939dd402e22fa6f650cc1d0bf0d5375c4453bf3b8f6a097ec8faf3993 +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran4.tar.gz/md5/ada7c84a9ba17f2af1e54afb65d51790 +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran4.tar.gz/sha512/0ca3f30c5c56c1d3da850f2c077ed76ea27782013d3a5b5253879ed55078a2435d862278bb5021def8d52e4bc2cbd202ba9d8a8f676afef14bac56cd2d5a6f5a +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran5.tar.gz/md5/42944f897776c8f0034fc31d74d1babe +OpenBLAS.v0.3.13+5.i686-w64-mingw32-libgfortran5.tar.gz/sha512/bb3823fc50440a4a3b6624bfd12b9c1018220345ee3a3d7a7f7b84c75812c8f97bd1403aa88754155b3aa52fa0e70435eebea171969f8c4a79b76c582266a764 +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/238e8a32a24c6ffb6881866182588846 +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/9da4452924a8513f5f40c1c9350fdda30833a7ac9755421363e74f557944a5022df98881ccb1f9c468481550f8e4cc894d3963df57371a4d8c0dd0ee8cb1de70 +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/6d27131cf20d9172ee8486776a768ec1 +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/a10ecd91b98cf33e5541b64a5e4cd26cb7738d751f7c40c8e0ad337214ac9c15101f012c37ac9724c5414bea8f1bec5342c33e9ed1f7ae5f3e3a90e29cada89d +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/35d5f8477ea0ac0ce609785811d04164 +OpenBLAS.v0.3.13+5.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/77148afb919ece259c35e383e432cebabb65651fdcce00f8f15ec9d8f8805ea0a5615258b400f7ce73ed44405cd9f671b87c8aa015df4c7d417f9b2ee89e06dc +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran3.tar.gz/md5/5b8910928fdf38f2dca382a3ca583414 +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/65303a748366432ac1723009abdcd51674af2e6452522a813b32bd928bbae44de96c9e7279b9cf8e403fdb5adc8a323b1e383275ec5162aaca957fa9e7983116 +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran4.tar.gz/md5/a62af36a018e5e695476bedeb189db4c +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/594cd0536a3200bc452a7c1e26e0f179ba75f86f0ccd17ebc0816ff6bdd70ef4d367c6e68d173fa220cb092c4c65f0ceceaf55aa783032e28c465c060ead63d5 +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran5.tar.gz/md5/aedbf36e1e5e4aff51c7188c9d52c7f6 +OpenBLAS.v0.3.13+5.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/504afca82f8f30b7a93f0fc9fd9fdb2dbcb74b058fde3c3633b2462deb8b45f4c2f4caca5abf644196ac534799e07e1b7b55ce92ba395ff8e851c27d26113a42 +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran3.tar.gz/md5/9fc6ee1c8399a399dc5e6039bd99a3be +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/83896931f1e1f21a3c46a420238d4db2d633402cd72bb15f24d00359d7ff27cfd21f1e51a2e1e1cc95c90cf14ca6181060681784e14ae41d06857e5c732427fe +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran4.tar.gz/md5/e2c0cf837ba543048e66563f339ba674 +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/e63eb5501daadf460288aaab8d75ecfe4c321f775c25bf77836a0fb20cdd98f81adb8660e2b9465278fb0f002ed397f07399a93299b4373d571017511f474637 +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran5.tar.gz/md5/3301d928cce10270fe57dd9e1a83b9cc +OpenBLAS.v0.3.13+5.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/2e2db27c44ca65b428cb081a0f6ad441cba91ac67e7309007870e4811398038bd0fc6db494d200cfa14b624797835fdf4f08fb21a34e3a61ca013e64e259fc9a +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran3.tar.gz/md5/384fbb41d82460762349990c60900fc2 +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran3.tar.gz/sha512/05dceac3d28ab52d5becf51bca4b6696848902e70c44cbc3cc237fe761dea92b44d82b463671cd656ea0b82628c4c4eb7f2cf136f9c653e594bb8f349b46850f +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran4.tar.gz/md5/04e92d94fa5190e6915ff739a723ab54 +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran4.tar.gz/sha512/c49f57d5d35adae65db8a5bb6829b2d3fa806c2232698796d1a7769845f122b1d34a5aa409199fd514364a99d854fa8f8369b0f7445a3a22a828d997a8d9e487 +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran5.tar.gz/md5/26f0bb722acde07d05ea1c35cd976781 +OpenBLAS.v0.3.13+5.x86_64-linux-musl-libgfortran5.tar.gz/sha512/29ba655390118eadd760c2e46a0ad4dd8ed6776a8185e3a6acb5b3fa3542b454f7caf3d3b183ec04ad8cecde774e182d4400be875ff349b00880352a4e4dcc32 +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/0d08d7b22e4d6d6a844653718a6beb35 +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/08625e91f84243317e881a798e5c0c9f59ac19ec46c592d15ea105d1c24634fa17e66cfb9ac98a87a1bef14d3f550d278cde31e2cc62855288eb027778044a6f +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/5a2484aaedea160beafa0ae928f98bce +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/c5561a01275430fa6361da34f11f0478b343946c08428617d106e36e8ba1514b59628ad2fd798fdd78c0ed79e0d0014da8b08166182bcf88044dedd3357c5026 +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/c6f17657a15f180dfe9d911c0b41a244 +OpenBLAS.v0.3.13+5.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/3dc411b0914734ec10d89d6acbb5ed70fc80ad8fc48fbdfa8c56dd209cb4c1251060b441d420bf2deb9cc81dc07605fc4036d7ae37d786a1069716f9bbb5870d +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/5e1451e34917819fa100a92dffeafea5 +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/eea215ae37897fd03e0acd7b32547d33ee880ee000836632be637d503159bce5d8093a34d588ad4e9b9fa9b75ecebfeb09f633a8266db202076a4eda57be954b +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/a34a631f7c912ef84ac9a53720b8f2b4 +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/78ceb1b14d89fb8ada27a1ce195d9e011a592c41079a7790df8cb9c88df57c798883967ee47ecd633d1eb281d3b751e3e41e4a0394b37d9ef511ec032d2ce299 +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/fbfdf0d564cb892aa7d62f9874aad2d7 +OpenBLAS.v0.3.13+5.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/361d1e38445cad0ccd15bb886c7c3a45655ccd83b621cb8d7a50cc5061a05ade9d797f9011894ceede9c782f210c8f320eb1803b4d4620db6087d1bb6e192160 diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 82e4a00578de6..4cf1787854293 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -26,7 +26,6 @@ SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/md5/d266370cc574c8ca8b2b8a94d6b8 SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/sha512/2377d662f91d01229e3c44ec1c5624b6361e823ff90d625acc3bab8f68ada1b3b7b67f4e56c8896f890e5780bd2fcb494b5a1f91c9c7803715eac2a2a4bb938f SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index e71ac571d0b9b..48d44d98f7ca0 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -31,20 +31,20 @@ julia> inv(A) As well as other useful operations, such as finding eigenvalues or eigenvectors: ```jldoctest -julia> A = [-4. -9.; 2. 2.] +julia> A = [-4. -17.; 2. 2.] 2×2 Matrix{Float64}: - -4.0 -9.0 - 2.0 2.0 + -4.0 -17.0 + 2.0 2.0 julia> eigvals(A) 2-element Vector{ComplexF64}: - -1.0 - 3.0im - -1.0 + 3.0im + -1.0 - 5.0im + -1.0 + 5.0im julia> eigvecs(A) 2×2 Matrix{ComplexF64}: - 0.904534-0.0im 0.904534+0.0im - -0.301511+0.301511im -0.301511-0.301511im + 0.945905-0.0im 0.945905+0.0im + -0.166924+0.278207im -0.166924-0.278207im ``` In addition, Julia provides many [factorizations](@ref man-linalg-factorizations) which can be used to diff --git a/stdlib/LinearAlgebra/src/symmetriceigen.jl b/stdlib/LinearAlgebra/src/symmetriceigen.jl index e98f46d13dcd1..0f18d290b4d62 100644 --- a/stdlib/LinearAlgebra/src/symmetriceigen.jl +++ b/stdlib/LinearAlgebra/src/symmetriceigen.jl @@ -99,7 +99,7 @@ julia> eigvals(A, 2:2) julia> eigvals(A) 3-element Vector{Float64}: - -2.140054944640259 + -2.1400549446402604 1.0000000000000002 5.140054944640259 ``` @@ -139,7 +139,7 @@ julia> eigvals(A, -1, 2) julia> eigvals(A) 3-element Vector{Float64}: - -2.140054944640259 + -2.1400549446402604 1.0000000000000002 5.140054944640259 ``` diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index b19e2b5de1efb..8420750f8f4a1 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -330,15 +330,15 @@ julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.]) julia> eigvals(A) 3-element Vector{Float64}: - -2.140054944640259 + -2.1400549446402604 1.0000000000000002 5.140054944640259 julia> eigvecs(A) 3×3 Matrix{Float64}: - 0.418304 0.83205 0.364299 - -0.656749 8.21121e-16 0.754109 - 0.627457 -0.5547 0.546448 + 0.418304 -0.83205 0.364299 + -0.656749 -7.39009e-16 0.754109 + 0.627457 0.5547 0.546448 julia> eigvecs(A, [1.]) 3×1 Matrix{Float64}: diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index b3bf88b2afb57..b236ed0809eec 100644 --- a/stdlib/OpenBLAS_jll/Project.toml +++ b/stdlib/OpenBLAS_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenBLAS_jll" uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.13+4" +version = "0.3.13+5" [deps] CompilerSupportLibraries_jll = "e66e0078-7015-5450-92f7-15fbd957f2ae" From fe09ad9e0587a1b2f228aef727f6d1495efea98c Mon Sep 17 00:00:00 2001 From: Samuel Ainsworth Date: Thu, 8 Apr 2021 09:34:12 -0700 Subject: [PATCH 132/439] Add comments to runtests.jl to explain the `net_on`/loopback situation (#40359) --- test/runtests.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index ad029557a3377..ec4427d99b197 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -91,6 +91,16 @@ prepend!(tests, linalg_tests) import LinearAlgebra cd(@__DIR__) do + # `net_on` implies that we have access to the loopback interface which is + # necessary for Distributed multi-processing. There are some test + # environments that do not allow access to loopback, so we must disable + # addprocs when `net_on` is false. Note that there exist build environments, + # including Nix, where `net_on` is false but we still have access to the + # loopback interface. It would be great to make this check more specific to + # identify those situations somehow. See + # * https://github.com/JuliaLang/julia/issues/6722 + # * https://github.com/JuliaLang/julia/pull/29384 + # * https://github.com/JuliaLang/julia/pull/40348 n = 1 if net_on n = min(Sys.CPU_THREADS, length(tests)) From 3060edb80f534ca4d629bbb3674c521da6122c58 Mon Sep 17 00:00:00 2001 From: jmert <2965436+jmert@users.noreply.github.com> Date: Thu, 8 Apr 2021 11:46:02 -0500 Subject: [PATCH 133/439] fix #33413, crash with `cglobal(dlsym(...))` (#37910) --- src/julia-syntax.scm | 16 ++++++++++------ test/ccall.jl | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index aeb6ba49ea34f..fb34bd4bbe840 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -4068,13 +4068,14 @@ f(x) = yt(x) (else #f))) (case (car e) ((call new splatnew foreigncall cfunction new_opaque_closure) + (define (atom-or-not-tuple-call? fptr) + (or (atom? fptr) + (not (tuple-call? fptr)))) (let* ((args (cond ((eq? (car e) 'foreigncall) ;; NOTE: 2nd to 5th arguments of ccall must be left in place ;; the 1st should be compiled if an atom. - (append (if (let ((fptr (cadr e))) - (or (atom? fptr) - (not (tuple-call? fptr)))) + (append (if (atom-or-not-tuple-call? (cadr e)) (compile-args (list (cadr e)) break-labels) (list (cadr e))) (list-head (cddr e) 4) @@ -4093,12 +4094,15 @@ f(x) = yt(x) (compile-args (list-head (cdr e) 4) break-labels) (list (append (butlast oc_method) (list lambda))) (compile-args (list-tail (cdr e) 5) break-labels)))) - ;; TODO: evaluate first argument to cglobal some other way + ;; NOTE: 1st argument to cglobal treated same as for ccall ((and (length> e 2) (or (eq? (cadr e) 'cglobal) (equal? (cadr e) '(outerref cglobal)))) - (list* (cadr e) (caddr e) - (compile-args (cdddr e) break-labels))) + (append (list (cadr e)) + (if (atom-or-not-tuple-call? (caddr e)) + (compile-args (list (caddr e)) break-labels) + (list (caddr e))) + (compile-args (cdddr e) break-labels))) (else (compile-args (cdr e) break-labels)))) (callex (cons (car e) args))) diff --git a/test/ccall.jl b/test/ccall.jl index 88f693150eead..b7367c96549a5 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1770,3 +1770,47 @@ ccall_with_undefined_lib() = ccall((:time, xx_nOt_DeFiNeD_xx), Cint, (Ptr{Cvoid} b16 = transcode(UInt16, b8) @test b16 == b end + +# issue 33413 +@testset "cglobal lowering" begin + # crash in cglobal33413_ptrinline[_notype]() specifically requires the library pointer be + # retrieved inside the function; using global pointer variable doesn't trigger the crash + function cglobal33413_ptrvar() + libh = Libdl.dlopen(libccalltest) + sym = Libdl.dlsym(libh, :global_var) + return cglobal(sym, Cint) + end + function cglobal33413_ptrvar_notype() + libh = Libdl.dlopen(libccalltest) + sym = Libdl.dlsym(libh, :global_var) + return cglobal(sym) + end + function cglobal33413_ptrinline() + libh = Libdl.dlopen(libccalltest) + return cglobal(Libdl.dlsym(libh, :global_var), Cint) + end + function cglobal33413_ptrinline_notype() + libh = Libdl.dlopen(libccalltest) + return cglobal(Libdl.dlsym(libh, :global_var)) + end + function cglobal33413_tupleliteral() + return cglobal((:global_var, libccalltest), Cint) + end + function cglobal33413_tupleliteral_notype() + return cglobal((:global_var, libccalltest)) + end + function cglobal33413_literal() + return cglobal(:sin, Cint) + end + function cglobal33413_literal_notype() + return cglobal(:sin) + end + @test unsafe_load(cglobal33413_ptrvar()) == 1 + @test unsafe_load(cglobal33413_ptrinline()) == 1 + @test unsafe_load(cglobal33413_tupleliteral()) == 1 + @test unsafe_load(convert(Ptr{Cint}, cglobal33413_ptrvar_notype())) == 1 + @test unsafe_load(convert(Ptr{Cint}, cglobal33413_ptrinline_notype())) == 1 + @test unsafe_load(convert(Ptr{Cint}, cglobal33413_tupleliteral_notype())) == 1 + @test cglobal33413_literal() != C_NULL + @test cglobal33413_literal_notype() != C_NULL +end From 35157d96a4b537ba1114a3395ffd59e8c12e142f Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Thu, 8 Apr 2021 12:53:44 -0400 Subject: [PATCH 134/439] doc: clarify example returning a tuple (#40353) --- doc/src/manual/faq.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 1cd8ec849434b..c6bcd69424c7a 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -293,23 +293,23 @@ julia> threefloat() and similarly: ```jldoctest -julia> function threetup() - x, y = [3, 3] +julia> function twothreetup() + x, y = [2, 3] # assigns 2 to x and 3 to y x, y # returns a tuple end -threetup (generic function with 1 method) +twothreetup (generic function with 1 method) -julia> function threearr() - x, y = [3, 3] # returns an array +julia> function twothreearr() + x, y = [2, 3] # returns an array end -threearr (generic function with 1 method) +twothreearr (generic function with 1 method) -julia> threetup() -(3, 3) +julia> twothreetup() +(2, 3) -julia> threearr() +julia> twothreearr() 2-element Vector{Int64}: - 3 + 2 3 ``` From 9814bd6f9cabef85d38b647c891124fe24f8d9f3 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 8 Apr 2021 18:54:19 +0200 Subject: [PATCH 135/439] Avoid AbstractString in GitError struct to make extraction inferred. (#40402) This significantly reduces the number of invalidated methods when loading ProgressLogging. --- stdlib/LibGit2/src/error.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LibGit2/src/error.jl b/stdlib/LibGit2/src/error.jl index 3e56999d5a52c..3dbc92947fcb2 100644 --- a/stdlib/LibGit2/src/error.jl +++ b/stdlib/LibGit2/src/error.jl @@ -77,7 +77,7 @@ end struct GitError <: Exception class::Class code::Code - msg::AbstractString + msg::String end Base.show(io::IO, err::GitError) = print(io, "GitError(Code:$(err.code), Class:$(err.class), $(err.msg))") From b373a9a6093f91a508a8f53db5461089ac71cf06 Mon Sep 17 00:00:00 2001 From: Federico Stra Date: Thu, 8 Apr 2021 18:58:18 +0200 Subject: [PATCH 136/439] Fix signed integer overflow in `mapreduce_impl` (#38643) This PR solves #38627 as regards the code in reducedim.jl, reduce.jl and reinterpretarray.jl. It does not yet solve all the relevant issues with missing.jl: in the code there for _mapreduce and mapreduce_impl, there are still several instances of the construct: ``` while i <= ilast ... i += 1 end ``` This overflows when ilast == typemax(Int). More seriously, inside the while loops there is often `@inbounds A[i]`, which is then an out-of-bounds read! --- base/missing.jl | 45 +++++++++++++++++++++------------------- base/reduce.jl | 4 ++-- base/reinterpretarray.jl | 4 ++-- test/missing.jl | 16 ++++++++++++++ test/reduce.jl | 10 +++++++++ 5 files changed, 54 insertions(+), 25 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index 343e8014bbb0e..b89c394bea046 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -281,24 +281,24 @@ mapreduce(f, op, itr::SkipMissing{<:AbstractArray}) = function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}) A = itr.x - local ai + ai = missing inds = LinearIndices(A) i = first(inds) ilast = last(inds) - while i <= ilast + for outer i in i:ilast @inbounds ai = A[i] - ai === missing || break - i += 1 + ai !== missing && break end - i > ilast && return mapreduce_empty(f, op, eltype(itr)) + ai === missing && return mapreduce_empty(f, op, eltype(itr)) a1::eltype(itr) = ai + i == typemax(typeof(i)) && return mapreduce_first(f, op, a1) i += 1 - while i <= ilast + ai = missing + for outer i in i:ilast @inbounds ai = A[i] - ai === missing || break - i += 1 + ai !== missing && break end - i > ilast && return mapreduce_first(f, op, a1) + ai === missing && return mapreduce_first(f, op, a1) # We know A contains at least two non-missing entries: the result cannot be nothing something(mapreduce_impl(f, op, itr, first(inds), last(inds))) end @@ -312,32 +312,35 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = @noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray}, ifirst::Integer, ilast::Integer, blksize::Int) A = itr.x - if ifirst == ilast + if ifirst > ilast + return nothing + elseif ifirst == ilast @inbounds a1 = A[ifirst] if a1 === missing return nothing else return Some(mapreduce_first(f, op, a1)) end - elseif ifirst + blksize > ilast + elseif ilast - ifirst < blksize # sequential portion - local ai + ai = missing i = ifirst - while i <= ilast + for outer i in i:ilast @inbounds ai = A[i] - ai === missing || break - i += 1 + ai !== missing && break end - i > ilast && return nothing + ai === missing && return nothing a1 = ai::eltype(itr) + i == typemax(typeof(i)) && return Some(mapreduce_first(f, op, a1)) i += 1 - while i <= ilast + ai = missing + for outer i in i:ilast @inbounds ai = A[i] - ai === missing || break - i += 1 + ai !== missing && break end - i > ilast && return Some(mapreduce_first(f, op, a1)) + ai === missing && return Some(mapreduce_first(f, op, a1)) a2 = ai::eltype(itr) + i == typemax(typeof(i)) && return Some(op(f(a1), f(a2))) i += 1 v = op(f(a1), f(a2)) @simd for i = i:ilast @@ -349,7 +352,7 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = return Some(v) else # pairwise portion - imid = (ifirst + ilast) >> 1 + imid = ifirst + (ilast - ifirst) >> 1 v1 = mapreduce_impl(f, op, itr, ifirst, imid, blksize) v2 = mapreduce_impl(f, op, itr, imid+1, ilast, blksize) if v1 === nothing && v2 === nothing diff --git a/base/reduce.jl b/base/reduce.jl index 185a158893daa..66fb9bd45de87 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -237,7 +237,7 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) if ifirst == ilast @inbounds a1 = A[ifirst] return mapreduce_first(f, op, a1) - elseif ifirst + blksize > ilast + elseif ilast - ifirst < blksize # sequential portion @inbounds a1 = A[ifirst] @inbounds a2 = A[ifirst+1] @@ -249,7 +249,7 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) return v else # pairwise portion - imid = (ifirst + ilast) >> 1 + imid = ifirst + (ilast - ifirst) >> 1 v1 = mapreduce_impl(f, op, A, ifirst, imid, blksize) v2 = mapreduce_impl(f, op, A, imid+1, ilast, blksize) return op(v1, v2) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index c49c566ae65e5..3fec3452def86 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -683,7 +683,7 @@ end @noinline function mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, ifirst::SCI, ilast::SCI, blksize::Int) where {F,OP,SCI<:SCartesianIndex2{K}} where K - if ifirst.j + blksize > ilast.j + if ilast.j - ifirst.j < blksize # sequential portion @inbounds a1 = A[ifirst] @inbounds a2 = A[SCI(2,ifirst.j)] @@ -702,7 +702,7 @@ end return v else # pairwise portion - jmid = (ifirst.j + ilast.j) >> 1 + jmid = ifirst.j + (ilast.j - ifirst.j) >> 1 v1 = mapreduce_impl(f, op, A, ifirst, SCI(K,jmid), blksize) v2 = mapreduce_impl(f, op, A, SCI(1,jmid+1), ilast, blksize) return op(v1, v2) diff --git a/test/missing.jl b/test/missing.jl index 4c704c4ce64f8..2864c1f67cb5c 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -1,5 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +isdefined(Main, :OffsetArrays) || @eval Main include("testhelpers/OffsetArrays.jl") +using .Main.OffsetArrays + @testset "MissingException" begin @test sprint(showerror, MissingException("test")) == "MissingException: test" end @@ -504,6 +507,19 @@ end nt = NamedTuple{(:x, :y),Tuple{Union{Missing, Int},Union{Missing, Float64}}}( (missing, missing)) @test sum(skipmissing(nt)) === 0 + + # issues #38627 and #124 + @testset for len in [1, 2, 15, 16, 1024, 1025] + v = repeat(Union{Int,Missing}[1], len) + oa = OffsetArray(v, typemax(Int)-length(v)) + sm = skipmissing(oa) + @test sum(sm) == len + + v = repeat(Union{Int,Missing}[missing], len) + oa = OffsetArray(v, typemax(Int)-length(v)) + sm = skipmissing(oa) + @test sum(sm) == 0 + end end @testset "filter" begin diff --git a/test/reduce.jl b/test/reduce.jl index 7f3963590fbe0..5d49c47204484 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -646,3 +646,13 @@ end # issue #39281 @test @inferred(extrema(rand(2), dims=1)) isa Vector{Tuple{Float64,Float64}} + +# issue #38627 +@testset "overflow in mapreduce" begin + # at len = 16 and len = 1025 there is a change in codepath + for len in [0, 1, 15, 16, 1024, 1025, 2048, 2049] + oa = OffsetArray(repeat([1], len), typemax(Int)-len) + @test sum(oa) == reduce(+, oa) == len + @test mapreduce(+, +, oa, oa) == 2len + end +end From 41857b5d002086c3004c89b4ddf1684c69f09c65 Mon Sep 17 00:00:00 2001 From: jaakkor2 Date: Thu, 8 Apr 2021 20:07:31 +0300 Subject: [PATCH 137/439] Bump MACOSX_VERSION_MIN from 10.9 to 10.10 (#40400) Fixes #39363 (BinaryBuilder already made this change) --- Make.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Make.inc b/Make.inc index 04181edf07596..a3718833fb706 100644 --- a/Make.inc +++ b/Make.inc @@ -472,13 +472,13 @@ USEGCC := 0 USECLANG := 1 endif -# Note: Supporting only macOS Mavericks and above +# Note: Supporting only macOS Yosemite and above ifeq ($(OS), Darwin) APPLE_ARCH := $(shell uname -m) USEGCC := 0 USECLANG := 1 ifneq ($(APPLE_ARCH),arm64) -MACOSX_VERSION_MIN := 10.9 +MACOSX_VERSION_MIN := 10.10 else MACOSX_VERSION_MIN := 11.0 endif From f021c67fe9aba889f015b66c6d5bf6394762c60d Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 8 Apr 2021 19:45:20 +0200 Subject: [PATCH 138/439] Fix temp install of BugReporting.jl (#40403) Fixes #40398 --- stdlib/InteractiveUtils/src/InteractiveUtils.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index 9d989148878fb..c0c6f2df05215 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -396,9 +396,12 @@ function report_bug(kind) mktempdir() do tmp old_load_path = copy(LOAD_PATH) push!(empty!(LOAD_PATH), joinpath(tmp, "Project.toml")) + old_active_project = Base.ACTIVE_PROJECT[] + Base.ACTIVE_PROJECT[] = nothing Pkg.add(Pkg.PackageSpec(BugReportingId.name, BugReportingId.uuid)) BugReporting = Base.require(BugReportingId) append!(empty!(LOAD_PATH), old_load_path) + Base.ACTIVE_PROJECT[] = old_active_project end end else From 5b6edad71900b3a2a206a0583953eceaa06a2f89 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Apr 2021 15:43:01 -0400 Subject: [PATCH 139/439] avoid calling dlerror unless absolutely necessary (#40392) Most platforms implement this sensibly, but POSIX does not require that, so FreeBSD does not implement this sensibly. But we can mostly avoid the problems on FreeBSD by avoiding calling it unless we absolutely must. Fixes #39582 --- src/dlload.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/dlload.c b/src/dlload.c index ecb34d2be57e3..62f28d583a85a 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -120,7 +120,6 @@ JL_DLLEXPORT void *jl_dlopen(const char *filename, unsigned flags) JL_NOTSAFEPOI needsSymRefreshModuleList = 1; return lib; #else - dlerror(); /* Reset error status. */ return dlopen(filename, (flags & JL_RTLD_NOW ? RTLD_NOW : RTLD_LAZY) | JL_RTLD(flags, LOCAL) @@ -144,11 +143,15 @@ JL_DLLEXPORT void *jl_dlopen(const char *filename, unsigned flags) JL_NOTSAFEPOI JL_DLLEXPORT int jl_dlclose(void *handle) JL_NOTSAFEPOINT { #ifdef _OS_WINDOWS_ - if (!handle) return -1; + if (!handle) { + return -1; + } return !FreeLibrary((HMODULE) handle); #else - dlerror(); /* Reset error status. */ - if (!handle) return -1; + if (!handle) { + dlerror(); /* Reset error status. */ + return -1; + } return dlclose(handle); #endif } @@ -291,19 +294,26 @@ JL_DLLEXPORT int jl_dlsym(void *handle, const char *symbol, void ** value, int t #ifdef _OS_WINDOWS_ *value = GetProcAddress((HMODULE) handle, symbol); #else - dlerror(); /* Reset error status. */ *value = dlsym(handle, symbol); #endif - /* Next, check for errors. On Windows, a NULL pointer means the symbol - * was not found. On everything else, we can have NULL symbols, so we check - * for non-NULL returns from dlerror(). Note that means we unconditionally - * call dlerror() on POSIX systems.*/ -#ifdef _OS_WINDOWS_ + /* Next, check for errors. On Windows, a NULL pointer means the symbol was + * not found. On everything else, we can have NULL symbols, so we check for + * non-NULL returns from dlerror(). Since POSIX doesn't require `dlerror` + * to be implemented safely, FreeBSD doesn't (unlike everyone else, who + * realized decades ago that threads are here to stay), so we avoid calling + * `dlerror` unless we need to get the error message. + * https://github.com/freebsd/freebsd-src/blob/12db51d20823a5e3b9e5f8a2ea73156fe1cbfc28/libexec/rtld-elf/rtld.c#L198 + */ symbol_found = *value != NULL; -#else - const char *err = dlerror(); - symbol_found = err == NULL; +#ifndef _OS_WINDOWS_ + const char *err; + if (!symbol_found) { + dlerror(); /* Reset error status. */ + *value = dlsym(handle, symbol); + err = dlerror(); + symbol_found = *value != NULL || err == NULL; + } #endif if (!symbol_found && throw_err) { From 1defc11510a4816d9ebf8efa6b796aa77802c0d7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 8 Apr 2021 15:59:27 -0400 Subject: [PATCH 140/439] remove method definition for `Int` in test/core.jl (#40380) --- test/core.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/core.jl b/test/core.jl index 04c261e861ab2..d617f14c7eb01 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2389,19 +2389,14 @@ let ex = Expr(:(=), :(f8338(x;y=4)), :(x*y)) end # call overloading (#2403) -(x::Int)(y::Int) = x + 3y issue2403func(f) = f(7) -let x = 10 - @test x(3) == 19 - @test x((3,)...) == 19 - @test issue2403func(x) == 31 -end mutable struct Issue2403 x end (i::Issue2403)(y) = i.x + 2y let x = Issue2403(20) @test x(3) == 26 + @test x((3,)...) == 26 @test issue2403func(x) == 34 end From 7d6dfe1ec94dbf5ba52a2109c3c3f8c0ef555c43 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Thu, 8 Apr 2021 15:04:14 -0500 Subject: [PATCH 141/439] faster expm1 (#37440) Faster and slightly more accurate (and all Julia). --- base/math.jl | 31 +++++++------- base/special/exp.jl | 85 +++++++++++++++++++++++++++++++++++++- base/special/hyperbolic.jl | 16 +------ 3 files changed, 98 insertions(+), 34 deletions(-) diff --git a/base/math.jl b/base/math.jl index 42f10760ed4fb..b66a058e5ae9e 100644 --- a/base/math.jl +++ b/base/math.jl @@ -241,6 +241,20 @@ macro evalpoly(z, p...) :(evalpoly($zesc, ($(pesc...),))) end +# polynomial evaluation using compensated summation. +# much more accurate, especially when lo can be combined with other rounding errors +@inline function exthorner(x, p::Tuple) + hi, lo = p[end], zero(x) + for i in length(p)-1:-1:1 + pi = p[i] + prod = hi*x + err = fma(hi, x, -prod) + hi = pi+prod + lo = fma(lo, x, prod - (hi - pi) + err) + end + return hi, lo +end + """ rad2deg(x) @@ -365,23 +379,6 @@ Compute the inverse hyperbolic sine of `x`. """ asinh(x::Number) -""" - expm1(x) - -Accurately compute ``e^x-1``. It avoids the loss of precision involved in the direct -evaluation of exp(x)-1 for small values of x. -# Examples -```jldoctest -julia> expm1(1e-16) -1.0e-16 - -julia> exp(1e-16) - 1 -0.0 -``` -""" -expm1(x) -expm1(x::Float64) = ccall((:expm1,libm), Float64, (Float64,), x) -expm1(x::Float32) = ccall((:expm1f,libm), Float32, (Float32,), x) # utility for converting NaN return to DomainError # the branch in nan_dom_err prevents its callers from inlining, so be sure to force it diff --git a/base/special/exp.jl b/base/special/exp.jl index 5dffcde385812..e10fdf243055c 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -205,7 +205,7 @@ for (func, base) in (:exp2=>Val(2), :exp=>Val(:ℯ), :exp10=>Val(10)) @eval begin function ($func)(x::T) where T<:Float64 N_float = muladd(x, LogBo256INV($base, T), MAGIC_ROUND_CONST(T)) - N = reinterpret(uinttype(T), N_float) % Int32 + N = reinterpret(UInt64, N_float) % Int32 N_float -= MAGIC_ROUND_CONST(T) #N_float now equals round(x*LogBo256INV($base, T)) r = muladd(N_float, LogBo256U($base, T), x) r = muladd(N_float, LogBo256L($base, T), r) @@ -273,7 +273,6 @@ julia> exp(1.0) ``` """ exp(x::Real) - """ exp2(x) @@ -314,3 +313,85 @@ exp10(x) reinterpret(Float64, (exponent_bias(Float64) + (x % Int64)) << (significand_bits(Float64) % UInt)) end end + +# min and max arguments by base and type +MAX_EXP(::Type{Float64}) = 709.7827128933845 # log 2^1023*(2-2^-52) +MIN_EXP(::Type{Float64}) = -37.42994775023705 # log 2^-54 +MAX_EXP(::Type{Float32}) = 88.72284f0 # log 2^127 *(2-2^-23) +MIN_EXP(::Type{Float32}) = -17.32868f0 # log 2^-25 + +Ln2INV(::Type{Float64}) = 1.4426950408889634 +Ln2(::Type{Float64}) = -0.6931471805599453 + +# log(.75) <= x <= log(1.25) +function expm1_small(x::Float32) + p = evalpoly(x, (0.16666666f0, 0.041666627f0, 0.008333682f0, + 0.0013908712f0, 0.0001933096f0)) + p2 = exthorner(x, (1f0, .5f0, p)) + return fma(x, p2[1], x*p2[2]) +end +@inline function expm1_small(x::Float64) + p = evalpoly(x, (0.16666666666666632, 0.04166666666666556, 0.008333333333401227, + 0.001388888889068783, 0.00019841269447671544, 2.480157691845342e-5, + 2.7558212415361945e-6, 2.758218402815439e-7, 2.4360682937111612e-8)) + p2 = exthorner(x, (1.0, .5, p)) + return fma(x, p2[1], x*p2[2]) +end + +@inline function expm1(x::Float64) + T=Float64 + if -0.2876820724517809 <= x <= 0.22314355131420976 + return expm1_small(x) + elseif !(abs(x)<=MIN_EXP(Float64)) + isnan(x) && return x + x > MAX_EXP(Float64) && return Inf + x < MIN_EXP(Float64) && return -1.0 + end + + N_float = muladd(x, LogBo256INV(Val(:ℯ), T), MAGIC_ROUND_CONST(T)) + N = reinterpret(UInt64, N_float) % Int32 + N_float -= MAGIC_ROUND_CONST(T) #N_float now equals round(x*LogBo256INV(Val(:ℯ), T)) + r = muladd(N_float, LogBo256U(Val(:ℯ), T), x) + r = muladd(N_float, LogBo256L(Val(:ℯ), T), r) + k = Int64(N >> 8) + jU, jL = table_unpack(N&255 +1) + p = expm1b_kernel(Val(:ℯ), r) + twopk = reinterpret(Float64, (1023+k) << 52) + twopnk = reinterpret(Float64, (1023-k) << 52) + k>=106 && return reinterpret(Float64, (1022+k) << 52)*(jU + muladd(jU, p, jL))*2 + k>=53 && return twopk*(jU + muladd(jU, p, (jL-twopnk))) + k<=-2 && return twopk*(jU + muladd(jU, p, jL))-1 + return twopk*((jU-twopnk) + fma(jU, p, jL)) +end + +@inline function expm1(x::Float32) + if -0.2876821f0 <=x <= 0.22314355f0 + return expm1_small(x) + end + x = Float64(x) + N_float = round(x*Ln2INV(Float64)) + N = unsafe_trunc(UInt64, N_float) + r = muladd(N_float, Ln2(Float64), x) + hi = evalpoly(r, (1.0, .5, 0.16666667546642386, 0.041666183019487026, + 0.008332997481506921, 0.0013966479175977883, 0.0002004037059220124)) + small_part = r*hi + twopk = reinterpret(Float64, (N+1023) << 52) + x > MAX_EXP(Float32) && return Inf32 + return Float32(muladd(twopk, small_part, twopk-1.0)) +end + +""" + expm1(x) + +Accurately compute ``e^x-1``. It avoids the loss of precision involved in the direct +evaluation of exp(x)-1 for small values of x. +# Examples +```jldoctest +julia> expm1(1e-16) +1.0e-16 + +julia> exp(1e-16) - 1 +0.0 +``` +""" +expm1(x) diff --git a/base/special/hyperbolic.jl b/base/special/hyperbolic.jl index 1fee6e2879220..f6ff43d900b1b 100644 --- a/base/special/hyperbolic.jl +++ b/base/special/hyperbolic.jl @@ -14,20 +14,6 @@ # is preserved. # ==================================================== -@inline function exthorner(x, p::Tuple) - # polynomial evaluation using compensated summation. - # much more accurate, especially when lo can be combined with other rounding errors - hi, lo = p[end], zero(x) - for i in length(p)-1:-1:1 - pi = p[i] - prod = hi*x - err = fma(hi, x, -prod) - hi = pi+prod - lo = fma(lo, x, prod - (hi - pi) + err) - end - return hi, lo -end - # Hyperbolic functions # sinh methods H_SMALL_X(::Type{Float64}) = 2.0^-28 @@ -112,7 +98,7 @@ function cosh(x::T) where T<:Union{Float32,Float64} # return cosh(x) = = (exp(x) + exp(-x))/2 # e) H_LARGE_X <= x # return cosh(x) = exp(x/2)/2 * exp(x/2) - # Note that this branch automatically deals with Infs and NaNs + # Note that this branch automatically deals with Infs and NaNs absx = abs(x) if absx <= COSH_SMALL_X(T) From b5391980f0a1fb7e862b8fc78a31758c1ca4a4ca Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Thu, 8 Apr 2021 17:08:24 -0400 Subject: [PATCH 142/439] docs: more scope lawyering (re #40238) (#40394) --- doc/src/manual/variables-and-scoping.md | 89 ++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 906a6c6d06b43..2b0b23d95597a 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -103,14 +103,37 @@ Note that the interactive prompt (aka REPL) is in the global scope of the module ## Local Scope -A new local scope is introduced by most code blocks (see above [table](@ref man-scope-table) for a -complete list). Some programming languages require explicitly declaring new variables before using -them. Explicit declaration works in Julia too: in any local scope, writing `local x` declares a new -local variable in that scope, regardless of whether there is already a variable named `x` in an -outer scope or not. Declaring each new local like this is somewhat verbose and tedious, however, so -Julia, like many other languages, considers assignment to a new variable in a local scope to -implicitly declare that variable as a new local. Mostly this is pretty intuitive, but as with many -things that behave intuitively, the details are more subtle than one might naïvely imagine. +A new local scope is introduced by most code blocks (see above [table](@ref +man-scope-table) for a complete list). If such a block is syntactically nested +inside of another local scope, the scope it creates is nested inside of all the +local scopes that it appears within, which are all ultimately nested inside of +the global scope of the module in which the code is evaluated. Variables in +outer scopes are visible from any scope they contain — meaning that they can be +read and written in inner scopes — unless there is a local variable with the +same name that "shadows" the outer variable of the same name. This is true even +if the outer local is declared after (in the sense of textually below) an inner +block. When we say that a variable "exists" in a given scope, this means that a +variable by that name exists in any of the scopes that the current scope is +nested inside of, including the current one. + +Some programming languages require explicitly declaring new variables before +using them. Explicit declaration works in Julia too: in any local scope, writing +`local x` declares a new local variable in that scope, regardless of whether +there is already a variable named `x` in an outer scope or not. Declaring each +new variable like this is somewhat verbose and tedious, however, so Julia, like +many other languages, considers assignment to a variable name that doesn't +already exist to implicitly declare that variable. If the current scope is +global, the new variable is global; if the current scope is local, the new +variable is local to the innermost local scope and will be visible inside of +that scope but not outside of it. If you assign to an existing local, it +_always_ updates that existing local: you can only shadow a local by explicitly +declaring a new local in a nested scope with the `local` keyword. In particular, +this applies to variables assigned in inner functions, which may surprise users +coming from Python where assignment in an inner function creates a new local +unless the variable is explictly declared to be non-local. + +Mostly this is pretty intuitive, but as with many things that behave +intuitively, the details are more subtle than one might naïvely imagine. When `x = ` occurs in a local scope, Julia applies the following rules to decide what the expression means based on where the assignment expression occurs and what `x` already refers to at @@ -183,9 +206,15 @@ Since the `x` in `greet` is local, the value (or lack thereof) of the global `x` calling `greet`. The hard scope rule doesn't care whether a global named `x` exists or not: assignment to `x` in a hard scope is local (unless `x` is declared global). -The next clear cut situation we'll consider is when there is already a local variable named `x`, in -which case `x = ` always assigns to this existing local `x`. The function `sum_to` computes -the sum of the numbers from one up to `n`: +The next clear cut situation we'll consider is when there is already a local +variable named `x`, in which case `x = ` always assigns to this existing +local `x`. This is true whether the assignment occurs in the same local scope, +an inner local scope in the same function body, or in the body of a function +nested inside of another function, also known as a +[closure](https://en.wikipedia.org/wiki/Closure_(computer_programming)). + +We'll use the `sum_to` function, which computes the sum of integers from one up +to `n`, as an example: ```julia function sum_to(n) @@ -252,6 +281,44 @@ introduces a hard scope, the assignment causes `t` to become a new local variabl where it appears, i.e. inside of the loop body. Even if there were a global named `t`, it would make no difference—the hard scope rule isn't affected by anything in global scope. +Note that the local scope of a for loop body is no different from the local +scope of an inner function. This means that we could rewrite this example so +that the loop body is implemented as a call to an inner helper function and it +behaves the same way: + +```jldoctest +julia> function sum_to_def_closure(n) + function loop_body(i) + t = s + i # new local `t` + s = t # assign same local `s` as below + end + s = 0 # new local + for i = 1:n + loop_body(i) + end + return s, @isdefined(t) + end +sum_to_def_closure (generic function with 1 method) + +julia> sum_to_def_closure(10) +(55, false) +``` + +This example illustrates a couple of key points: + +1. Inner function scopes are just like any other nested local scope. In + particular, if a variable is already a local outside of an inner function and + you assign to it in the inner function, the outer local variable is updated. + +2. It doesn't matter if the definition of an outer local happens below where it + is updated, the rule remains the same. The entire enclosing local scope is + parsed and its locals determined before inner local meanings are resolved. + +This design means that you can generally move code in or out of an inner +function without changing its meaning, which facilitates a number of common +idioms in the language using closures (see [do blocks](@ref +Do-Block-Syntax-for-Function-Arguments)). + Let's move onto some more ambiguous cases covered by the soft scope rule. We'll explore this by extracting the bodies of the `greet` and `sum_to_def` functions into soft scope contexts. First, let's put the body of `greet` in a `for` loop—which is soft, rather than hard—and evaluate it in the REPL: From c2ec70cd1842b53f45ac72ea74c94f008adbc7b3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Apr 2021 23:10:57 -0400 Subject: [PATCH 143/439] inference: limit single-level nested `Type` signature (#40379) Previously `type_more_complex` returns `false` for `Type{Type{...}}` compared against `Type{...}`. Per comment there, this should return `true`, but the code was ordered incorrect (it was also missing support for Vararg, after the recent changes). Fixes #40336 Co-authored-by: Shuhei Kadowaki --- base/compiler/typelimits.jl | 44 ++++++++++++++++++------------------- test/compiler/inference.jl | 35 +++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index cb584a6788f59..2eb2d6f542377 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -128,7 +128,15 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec end return Vararg{VaT} elseif isa(t, DataType) - if isa(c, DataType) + if isa(c, Core.TypeofVararg) + # Tuple{Vararg{T}} --> Tuple{T} is OK + return _limit_type_size(t, c.T, sources, depth, 0) + elseif isType(t) # allow taking typeof as Type{...}, but ensure it doesn't start nesting + tt = unwrap_unionall(t.parameters[1]) + (!isa(tt, DataType) || isType(tt)) && (depth += 1) + is_derived_type_from_any(tt, sources, depth) && return t + return Type + elseif isa(c, DataType) tP = t.parameters cP = c.parameters if t.name === c.name && !isempty(cP) @@ -158,15 +166,6 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec return Tuple{Q...} end end - elseif isa(c, Core.TypeofVararg) - # Tuple{Vararg{T}} --> Tuple{T} is OK - return _limit_type_size(t, c.T, sources, depth, 0) - end - if isType(t) # allow taking typeof as Type{...}, but ensure it doesn't start nesting - tt = unwrap_unionall(t.parameters[1]) - if isa(tt, DataType) && !isType(tt) - is_derived_type_from_any(tt, sources, depth) && return t - end end if allowed_tuplelen < 1 && t.name === Tuple.name return Any @@ -226,9 +225,19 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe return t !== 1 && !(0 <= t < c) # alternatively, could use !(abs(t) <= abs(c) || abs(t) < n) for some n end # base case for data types - if isa(t, DataType) + if isa(t, Core.TypeofVararg) + if isa(c, Core.TypeofVararg) + return type_more_complex(unwrapva(t), unwrapva(c), sources, depth + 1, tupledepth, 0) + end + elseif isa(t, DataType) tP = t.parameters - if isa(c, DataType) && t.name === c.name + if isa(c, Core.TypeofVararg) + return type_more_complex(t, unwrapva(c), sources, depth, tupledepth, 0) + elseif isType(t) # allow taking typeof any source type anywhere as Type{...}, as long as it isn't nesting Type{Type{...}} + tt = unwrap_unionall(t.parameters[1]) + (!isa(tt, DataType) || isType(tt)) && (depth += 1) + return !is_derived_type_from_any(tt, sources, depth) + elseif isa(c, DataType) && t.name === c.name cP = c.parameters length(cP) < length(tP) && return true length(cP) > length(tP) && !isvarargtype(tP[end]) && depth == 1 && return false @@ -236,7 +245,7 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe # allow creating variation within a nested tuple, but only so deep if t.name === Tuple.name && tupledepth > 0 tupledepth -= 1 - elseif !isvarargtype(t) + else tupledepth = 0 end isgenerator = (t.name.name === :Generator && t.name.module === _topmod(t.name.module)) @@ -258,15 +267,6 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe type_more_complex(tPi, cPi, sources, depth + 1, tupledepth, 0) && return true end return false - elseif isvarargtype(c) - return type_more_complex(t, unwrapva(c), sources, depth, tupledepth, 0) - end - if isType(t) # allow taking typeof any source type anywhere as Type{...}, as long as it isn't nesting Type{Type{...}} - tt = unwrap_unionall(t.parameters[1]) - if isa(tt, DataType) && !isType(tt) - is_derived_type_from_any(tt, sources, depth) || return true - return false - end end end return true diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 754fd7a3f5ce8..b6eb4acb3cf1d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -44,6 +44,13 @@ let t = Tuple{Ref{T},T,T} where T, c = Tuple{Ref, T, T} where T # #36407 @test t <: Core.Compiler.limit_type_size(t, c, Union{}, 1, 100) end +let # 40336 + t = Type{Type{Int}} + c = Type{Int} + r = Core.Compiler.limit_type_size(t, c, c, 100, 100) + @test t !== r && t <: r +end + @test Core.Compiler.unionlen(Union{}) == 1 @test Core.Compiler.unionlen(Int8) == 1 @test Core.Compiler.unionlen(Union{Int8, Int16}) == 2 @@ -3171,8 +3178,6 @@ end end @testset "constant prop' for union split signature" begin - anonymous_module() = Core.eval(@__MODULE__, :(module $(gensym()) end))::Module - # indexing into tuples really relies on constant prop', and we will get looser result # (`Union{Int,String,Char}`) if constant prop' doesn't happen for splitunion signatures tt = (Union{Tuple{Int,String},Tuple{Int,Char}},) @@ -3191,7 +3196,7 @@ end b end == Any[Union{String,Char}] - @test (@eval anonymous_module() begin + @test (@eval Module() begin struct F32 val::Float32 _v::Int @@ -3205,7 +3210,7 @@ end end end) == Any[Union{Float32,Float64}] - @test (@eval anonymous_module() begin + @test (@eval Module() begin struct F32 val::Float32 _v @@ -3243,3 +3248,25 @@ end Some(0x2) end end == [Union{Some{Float64}, Some{Int}, Some{UInt8}}] + +# https://github.com/JuliaLang/julia/issues/40336 +@testset "make sure a call with signatures with recursively nested Types terminates" begin + @test @eval Module() begin + f(@nospecialize(t)) = f(Type{t}) + + code_typed() do + f(Int) + end + true + end + + @test @eval Module() begin + f(@nospecialize(t)) = tdepth(t) == 10 ? t : f(Type{t}) + tdepth(@nospecialize(t)) = isempty(t.parameters) ? 1 : 1+tdepth(t.parameters[1]) + + code_typed() do + f(Int) + end + true + end +end From 40e57aa927f40b7389a811104fc060cf8c500ea1 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 8 Apr 2021 23:48:12 -0400 Subject: [PATCH 144/439] Dot-broadcasting for short-circuiting ops .&& and .|| (#39594) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have long wanted a proper fix for issue #5187. It was the very first Julia issue I filed. This is a shot at such a fix. This PR: * Enables parsing for `.&&` and `.||`. They are parsed into `Expr(:call, :.&&, ...)` expressions at the same precedence as their respective `&&` and `||`: ```julia-repl julia> Meta.show_sexpr(:(a .&& b)) (:call, :.&&, :a, :b) ``` * Unlike all other dotted operators `.op` (like `.+`), the `op`-alone part (`var"&&"`) is not an exported name from Base. As such, this effectively lowers to `broadcasted((x,y)->x && y, ...)`, but instead of using an anonymous function I've named it `Base.andand` and `Base.oror`: ```julia-repl julia> Meta.@lower a .&& b :($(Expr(:thunk, CodeInfo( @ none within `top-level scope' 1 ─ %1 = Base.broadcasted(Base.andand, a, b) │ %2 = Base.materialize(%1) └── return %2 )))) ``` * I've used a named function to enable short-circuiting behavior _within the broadcast kernel itself_. In the case that the second argument is a part of the same fused broadcast kernel, it will only evaluate if required: ```julia-repl julia> mutable struct F5187; x; end julia> (f::F5187)(x) = (f.x += x) julia> (iseven.(1:4) .|| (F5187(0)).(ones(4))) 4-element Vector{Real}: 1.0 true 2.0 true ``` Co-authored-by: Simeon Schaub --- NEWS.md | 2 ++ base/broadcast.jl | 29 +++++++++++++++++++---------- src/julia-parser.scm | 8 ++++---- src/julia-syntax.scm | 9 +++++++++ test/broadcast.jl | 29 +++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 14 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9cc478b29cb48..8b3f4e9a76794 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,8 @@ New language features * `(; a, b) = x` can now be used to destructure properties `a` and `b` of `x`. This syntax is equivalent to `a = getproperty(x, :a)` and similarly for `b`. ([#39285]) * Implicit multiplication by juxtaposition is now allowed for radical symbols (e.g., `x√y` and `x∛y`). ([#40173]) +* The short-circuiting operators `&&` and `||` can now be dotted to participate in broadcast fusion + as `.&&` and `.||`. ([#39594]) Language changes ---------------- diff --git a/base/broadcast.jl b/base/broadcast.jl index c6d079d318acf..fd3fcba74fb57 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -11,7 +11,7 @@ using .Base.Cartesian using .Base: Indices, OneTo, tail, to_shape, isoperator, promote_typejoin, @pure, _msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, unalias import .Base: copy, copyto!, axes -export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, broadcast_preserving_zero_d, BroadcastFunction +export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, broadcast_preserving_zero_d, BroadcastFunction, andand, oror ## Computing the result's axes: deprecated name const broadcast_axes = axes @@ -179,6 +179,21 @@ function Broadcasted{Style}(f::F, args::Args, axes=nothing) where {Style, F, Arg Broadcasted{Style, typeof(axes), Core.Typeof(f), Args}(f, args, axes) end +struct AndAnd end +andand = AndAnd() +broadcasted(::AndAnd, a, b) = broadcasted((a, b) -> a && b, a, b) +function broadcasted(::AndAnd, a, bc::Broadcasted) + bcf = flatten(bc) + broadcasted((a, args...) -> a && bcf.f(args...), a, bcf.args...) +end +struct OrOr end +const oror = OrOr() +broadcasted(::OrOr, a, b) = broadcasted((a, b) -> a || b, a, b) +function broadcasted(::OrOr, a, bc::Broadcasted) + bcf = flatten(bc) + broadcasted((a, args...) -> a || bcf.f(args...), a, bcf.args...) +end + Base.convert(::Type{Broadcasted{NewStyle}}, bc::Broadcasted{Style,Axes,F,Args}) where {NewStyle,Style,Axes,F,Args} = Broadcasted{NewStyle,Axes,F,Args}(bc.f, bc.args, bc.axes) @@ -1257,15 +1272,9 @@ function __dot__(x::Expr) tmp = x.head === :(<:) ? :.<: : :.>: Expr(:call, tmp, dotargs...) else - if x.head === :&& || x.head === :|| - error(""" - Using `&&` and `||` is disallowed in `@.` expressions. - Use `&` or `|` for elementwise logical operations. - """) - end - head = string(x.head) - if last(head) == '=' && first(head) != '.' - Expr(Symbol('.',head), dotargs...) + head = String(x.head)::String + if last(head) == '=' && first(head) != '.' || head == "&&" || head == "||" + Expr(Symbol('.', head), dotargs...) else Expr(x.head, dotargs...) end diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 9e279fead3fd2..afff8d23054ee 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -11,8 +11,8 @@ (define prec-pair (add-dots '(=>))) (define prec-conditional '(?)) (define prec-arrow (add-dots '(← → ↔ ↚ ↛ ↞ ↠ ↢ ↣ ↦ ↤ ↮ ⇎ ⇍ ⇏ ⇐ ⇒ ⇔ ⇴ ⇶ ⇷ ⇸ ⇹ ⇺ ⇻ ⇼ ⇽ ⇾ ⇿ ⟵ ⟶ ⟷ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿ ⤀ ⤁ ⤂ ⤃ ⤄ ⤅ ⤆ ⤇ ⤌ ⤍ ⤎ ⤏ ⤐ ⤑ ⤔ ⤕ ⤖ ⤗ ⤘ ⤝ ⤞ ⤟ ⤠ ⥄ ⥅ ⥆ ⥇ ⥈ ⥊ ⥋ ⥎ ⥐ ⥒ ⥓ ⥖ ⥗ ⥚ ⥛ ⥞ ⥟ ⥢ ⥤ ⥦ ⥧ ⥨ ⥩ ⥪ ⥫ ⥬ ⥭ ⥰ ⧴ ⬱ ⬰ ⬲ ⬳ ⬴ ⬵ ⬶ ⬷ ⬸ ⬹ ⬺ ⬻ ⬼ ⬽ ⬾ ⬿ ⭀ ⭁ ⭂ ⭃ ⭄ ⭇ ⭈ ⭉ ⭊ ⭋ ⭌ ← → ⇜ ⇝ ↜ ↝ ↩ ↪ ↫ ↬ ↼ ↽ ⇀ ⇁ ⇄ ⇆ ⇇ ⇉ ⇋ ⇌ ⇚ ⇛ ⇠ ⇢ ↷ ↶ ↺ ↻ --> <-- <-->))) -(define prec-lazy-or '(|\|\||)) -(define prec-lazy-and '(&&)) +(define prec-lazy-or (add-dots '(|\|\||))) +(define prec-lazy-and (add-dots '(&&))) (define prec-comparison (append! '(in isa) (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≂ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂ <: >:)))) @@ -111,8 +111,8 @@ ; operators that are special forms, not function names (define syntactic-operators - (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=)) - '(:= $= && |\|\|| |.| ... ->))) + (append! (add-dots '(&& |\|\|| = += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=)) + '(:= $= |.| ... ->))) (define syntactic-unary-operators '($ & |::|)) (define syntactic-op? (Set syntactic-operators)) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index fb34bd4bbe840..ca274ef552f5b 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1804,6 +1804,10 @@ e)))) ((and (pair? e) (eq? (car e) 'comparison)) (dot-to-fuse (expand-compare-chain (cdr e)) top)) + ((and (pair? e) (eq? (car e) '.&&)) + (make-fuse '(top andand) (cdr e))) + ((and (pair? e) (eq? (car e) '|.\|\||)) + (make-fuse '(top oror) (cdr e))) (else e))) (let ((e (dot-to-fuse rhs #t)) ; an expression '(fuse func args) if expr is a dot call (lhs-view (ref-to-view lhs))) ; x[...] expressions on lhs turn in to view(x, ...) to update x in-place @@ -2125,6 +2129,11 @@ ;; e = (|.| f x) (expand-fuse-broadcast '() e))) + '.&& + (lambda (e) (expand-fuse-broadcast '() e)) + '|.\|\|| + (lambda (e) (expand-fuse-broadcast '() e)) + '.= (lambda (e) (expand-fuse-broadcast (cadr e) (caddr e))) diff --git a/test/broadcast.jl b/test/broadcast.jl index 28c56b2c2e636..4c2b92a39bb9f 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -951,6 +951,35 @@ p0 = copy(p) @test repr(.!) == "Base.Broadcast.BroadcastFunction(!)" @test eval(:(.+)) == Base.BroadcastFunction(+) +@testset "Issue #5187: Broadcasting of short-circuiting ops" begin + ex = Meta.parse("A .< 1 .|| A .> 2") + @test ex == :((A .< 1) .|| (A .> 2)) + @test ex.head == :.|| + ex = Meta.parse("A .< 1 .&& A .> 2") + @test ex == :((A .< 1) .&& (A .> 2)) + @test ex.head == :.&& + + A = -1:4 + @test (A .< 1 .|| A .> 2) == [true, true, false, false, true, true] + @test (A .>= 1 .&& A .<= 2) == [false, false, true, true, false, false] + + mutable struct F5187; x; end + (f::F5187)(x) = (f.x += x) + @test (iseven.(1:4) .&& (F5187(0)).(ones(4))) == [false, 1, false, 2] + @test (iseven.(1:4) .|| (F5187(0)).(ones(4))) == [1, true, 2, true] + r = 1:4; o = ones(4); f = F5187(0); + @test (@. iseven(r) && f(o)) == [false, 1, false, 2] + @test (@. iseven(r) || f(o)) == [3, true, 4, true] + + @test (iseven.(1:8) .&& iseven.((F5187(0)).(ones(8))) .&& (F5187(0)).(ones(8))) == [false,false,false,1,false,false,false,2] + @test (iseven.(1:8) .|| iseven.((F5187(0)).(ones(8))) .|| (F5187(0)).(ones(8))) == [1,true,true,true,2,true,true,true] + r = 1:8; o = ones(8); f1 = F5187(0); f2 = F5187(0) + @test (@. iseven(r) && iseven(f1(o)) && f2(o)) == [false,false,false,1,false,false,false,2] + @test (@. iseven(r) || iseven(f1(o)) || f2(o)) == [3,true,true,true,4,true,true,true] + @test (iseven.(1:8) .&& iseven.((F5187(0)).(ones(8))) .&& (F5187(0)).(ones(8))) == [false,false,false,1,false,false,false,2] + @test (iseven.(1:8) .|| iseven.((F5187(0)).(ones(8))) .|| (F5187(0)).(ones(8))) == [1,true,true,true,2,true,true,true] +end + @testset "Issue #28382: inferrability of broadcast with Union eltype" begin @test isequal([1, 2] .+ [3.0, missing], [4.0, missing]) @test Core.Compiler.return_type(broadcast, Tuple{typeof(+), Vector{Int}, From 752e4594eef41bc1f6fa11dbad53c8c98eae1d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 9 Apr 2021 12:19:05 +0200 Subject: [PATCH 145/439] Introduce ArrayContainer in performance tips (#36542) --- doc/src/manual/performance-tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 9f0a0b9ff4f4c..8535028c0fa3c 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1514,7 +1514,7 @@ The following examples may help you interpret expressions marked as containing n element accesses * `Base.getfield(%%x, :(:data))::ARRAY{FLOAT64,N} WHERE N` - * Interpretation: getting a field that is of non-leaf type. In this case, `ArrayContainer` had a + * Interpretation: getting a field that is of non-leaf type. In this case, the type of `x`, say `ArrayContainer`, had a field `data::Array{T}`. But `Array` needs the dimension `N`, too, to be a concrete type. * Suggestion: use concrete types like `Array{T,3}` or `Array{T,N}`, where `N` is now a parameter of `ArrayContainer` From 90bea0319ec29e09123ab4c678fa6a30753c8849 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 9 Apr 2021 07:19:38 -0400 Subject: [PATCH 146/439] remove unnecessary `@generated` from literal_pow (#40408) This was added before the Compiler could constant-prop, now it will just get in the way of general inferability. --- base/intfuncs.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 35140a81367e6..7070aa9d13579 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -303,8 +303,7 @@ end const HWReal = Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64} const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}} -# Core.Compiler has complicated logic to inline x^2 and x^3 for -# numeric types. In terms of Val we can do it much more simply. +# Inline x^2 and x^3 for Val # (The first argument prevents unexpected behavior if a function ^ # is defined that is not equal to Base.^) @inline literal_pow(::typeof(^), x::HWNumber, ::Val{0}) = one(x) @@ -318,11 +317,11 @@ const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}} # for other types, define x^-n as inv(x)^n so that negative literal powers can # be computed in a type-stable way even for e.g. integers. -@inline @generated function literal_pow(f::typeof(^), x, ::Val{p}) where {p} +@inline function literal_pow(f::typeof(^), x, ::Val{p}) where {p} if p < 0 - :(literal_pow(^, inv(x), $(Val{-p}()))) + literal_pow(^, inv(x), Val(-p)) else - :(f(x,$p)) + f(x, p) end end From b838cdfbb54515f8007a2958ebcdd58b76513db5 Mon Sep 17 00:00:00 2001 From: Arvind Ganesh Date: Fri, 9 Apr 2021 09:16:03 -0500 Subject: [PATCH 147/439] Implemented bitwise nand and nor (#40339) --- base/bitarray.jl | 2 + base/bool.jl | 68 +++++++++++++++++++++++ base/exports.jl | 4 ++ base/gmp.jl | 2 +- base/operators.jl | 2 + doc/src/base/math.md | 2 + doc/src/manual/mathematical-operations.md | 14 +++++ stdlib/REPL/src/latex_symbols.jl | 4 ++ test/bitarray.jl | 36 ++++++++++++ test/gmp.jl | 6 ++ test/missing.jl | 26 ++++++++- test/numbers.jl | 18 ++++++ 12 files changed, 182 insertions(+), 2 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 6175a492cac75..1db84cad37a1c 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1707,6 +1707,8 @@ map!(::typeof(identity), dest::BitArray, A::BitArray) = copyto!(dest, A) for (T, f) in ((:(Union{typeof(&), typeof(*), typeof(min)}), :(&)), (:(Union{typeof(|), typeof(max)}), :(|)), (:(Union{typeof(xor), typeof(!=)}), :xor), + (:(typeof(nand)), :nand), + (:(typeof(nor)), :nor), (:(Union{typeof(>=), typeof(^)}), :((p, q) -> p | ~q)), (:(typeof(<=)), :((p, q) -> ~p | q)), (:(typeof(==)), :((p, q) -> ~xor(p, q))), diff --git a/base/bool.jl b/base/bool.jl index 92a27543d2fbc..297aa1863a64e 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -70,6 +70,74 @@ julia> [true; true; false] .⊻ [true; false; false] """ xor(x::Bool, y::Bool) = (x != y) +""" + nand(x, y) + ⊼(x, y) + +Bitwise nand (not and) of `x` and `y`. Implements +[three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic), +returning [`missing`](@ref) if one of the arguments is `missing`. + +The infix operation `a ⊼ b` is a synonym for `nand(a,b)`, and +`⊼` can be typed by tab-completing `\\nand` or `\\barwedge` in the Julia REPL. + +# Examples +```jldoctest +julia> nand(true, false) +true + +julia> nand(true, true) +false + +julia> nand(true, missing) +missing + +julia> false ⊼ false +true + +julia> [true; true; false] .⊼ [true; false; false] +3-element BitVector: + 0 + 1 + 1 +``` +""" +nand(x...) = ~(&)(x...) + +""" + nor(x, y) + ⊽(x, y) + +Bitwise nor (not or) of `x` and `y`. Implements +[three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic), +returning [`missing`](@ref) if one of the arguments is `missing`. + +The infix operation `a ⊽ b` is a synonym for `nor(a,b)`, and +`⊽` can be typed by tab-completing `\\nor` or `\\veebar` in the Julia REPL. + +# Examples +```jldoctest +julia> nor(true, false) +false + +julia> nor(true, true) +false + +julia> nor(true, missing) +false + +julia> false ⊽ false +true + +julia> [true; true; false] .⊽ [true; false; false] +3-element BitVector: + 0 + 0 + 1 +``` +""" +nor(x...) = ~(|)(x...) + >>(x::Bool, c::UInt) = Int(x) >> c <<(x::Bool, c::UInt) = Int(x) << c >>>(x::Bool, c::UInt) = Int(x) >>> c diff --git a/base/exports.jl b/base/exports.jl index 2a8ed97d4598f..9a6cdce86b38c 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -169,6 +169,10 @@ export ≢, xor, ⊻, + nand, + nor, + ⊼, + ⊽, %, ÷, &, diff --git a/base/gmp.jl b/base/gmp.jl index d0446e7d3d169..b957ab22a4bea 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -4,7 +4,7 @@ module GMP export BigInt -import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, +import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, trailing_zeros, trailing_ones, count_ones, tryparse_internal, diff --git a/base/operators.jl b/base/operators.jl index 58f6024f71176..8d7d8180c5cde 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -578,6 +578,8 @@ identity(x) = x xor(x::Integer) = x const ⊻ = xor +const ⊼ = nand +const ⊽ = nor # foldl for argument lists. expand fully up to a point, then # switch to a loop. this allows small cases like `a+b+c+d` to be managed diff --git a/doc/src/base/math.md b/doc/src/base/math.md index e0f094572a398..8f8a038df83c0 100644 --- a/doc/src/base/math.md +++ b/doc/src/base/math.md @@ -49,6 +49,8 @@ Base.:(~) Base.:(&) Base.:(|) Base.xor +Base.nand +Base.nor Base.:(!) && || diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index eff9b4f76221d..4d1ebc726fa6d 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -84,6 +84,8 @@ are supported on all primitive integer types: | `x & y` | bitwise and | | `x \| y` | bitwise or | | `x ⊻ y` | bitwise xor (exclusive or) | +| `x ⊼ y` | bitwise nand (not and) | +| `x ⊽ y` | bitwise nor (not or) | | `x >>> y` | [logical shift](https://en.wikipedia.org/wiki/Logical_shift) right | | `x >> y` | [arithmetic shift](https://en.wikipedia.org/wiki/Arithmetic_shift) right | | `x << y` | logical/arithmetic shift left | @@ -106,6 +108,18 @@ julia> 123 ⊻ 234 julia> xor(123, 234) 145 +julia> nand(123, 123) +-124 + +julia> 123 ⊼ 123 +-124 + +julia> nor(123, 124) +-128 + +julia> 123 ⊽ 124 +-128 + julia> ~UInt32(123) 0xffffff84 diff --git a/stdlib/REPL/src/latex_symbols.jl b/stdlib/REPL/src/latex_symbols.jl index 57e41ed670538..bfd2e1fbbb015 100644 --- a/stdlib/REPL/src/latex_symbols.jl +++ b/stdlib/REPL/src/latex_symbols.jl @@ -110,6 +110,8 @@ const latex_symbols = Dict( "\\backpprime" => "‶", "\\backppprime" => "‷", "\\xor" => "⊻", + "\\nand" => "⊼", + "\\nor" => "⊽", "\\iff" => "⟺", "\\implies" => "⟹", "\\impliedby" => "⟸", @@ -2651,4 +2653,6 @@ const symbols_latex_canonical = Dict( "→" => "\\to", "ε" => "\\varepsilon", "⊻" => "\\xor", + "⊼" => "\\nand", + "⊽" => "\\nor", ) diff --git a/test/bitarray.jl b/test/bitarray.jl index a5591fca26de7..cee7624d9a81a 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -832,6 +832,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, b1, b2) BitMatrix @check_bit_operation broadcast(|, b1, b2) BitMatrix @check_bit_operation broadcast(xor, b1, b2) BitMatrix + @check_bit_operation broadcast(nand, b1, b2) BitMatrix + @check_bit_operation broadcast(nor, b1, b2) BitMatrix @check_bit_operation (+)(b1, b2) Matrix{Int} @check_bit_operation (-)(b1, b2) Matrix{Int} @check_bit_operation broadcast(*, b1, b2) BitMatrix @@ -861,6 +863,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, b0, b0) BitVector @check_bit_operation broadcast(|, b0, b0) BitVector @check_bit_operation broadcast(xor, b0, b0) BitVector + @check_bit_operation broadcast(nand, b0, b0) BitVector + @check_bit_operation broadcast(nor, b0, b0) BitVector @check_bit_operation broadcast(*, b0, b0) BitVector @check_bit_operation (*)(b0, b0') BitMatrix end @@ -871,6 +875,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, b1, i2) Matrix{Int} @check_bit_operation broadcast(|, b1, i2) Matrix{Int} @check_bit_operation broadcast(xor, b1, i2) Matrix{Int} + @check_bit_operation broadcast(nand, b1, i2) Matrix{Int} + @check_bit_operation broadcast(nor, b1, i2) Matrix{Int} @check_bit_operation (+)(b1, i2) Matrix{Int} @check_bit_operation (-)(b1, i2) Matrix{Int} @check_bit_operation broadcast(*, b1, i2) Matrix{Int} @@ -902,6 +908,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, i1, b2) Matrix{Int} @check_bit_operation broadcast(|, i1, b2) Matrix{Int} @check_bit_operation broadcast(xor, i1, b2) Matrix{Int} + @check_bit_operation broadcast(nand, i1, b2) Matrix{Int} + @check_bit_operation broadcast(nor, i1, b2) Matrix{Int} @check_bit_operation broadcast(+, i1, b2) Matrix{Int} @check_bit_operation broadcast(-, i1, b2) Matrix{Int} @check_bit_operation broadcast(*, i1, b2) Matrix{Int} @@ -909,6 +917,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, u1, b2) Matrix{UInt8} @check_bit_operation broadcast(|, u1, b2) Matrix{UInt8} @check_bit_operation broadcast(xor, u1, b2) Matrix{UInt8} + @check_bit_operation broadcast(nand, u1, b2) Matrix{UInt8} + @check_bit_operation broadcast(nor, u1, b2) Matrix{UInt8} @check_bit_operation broadcast(+, u1, b2) Matrix{UInt8} @check_bit_operation broadcast(-, u1, b2) Matrix{UInt8} @check_bit_operation broadcast(*, u1, b2) Matrix{UInt8} @@ -986,6 +996,14 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(xor, b1, false) BitMatrix @check_bit_operation broadcast(xor, true, b1) BitMatrix @check_bit_operation broadcast(xor, false, b1) BitMatrix + @check_bit_operation broadcast(nand, b1, true) BitMatrix + @check_bit_operation broadcast(nand, b1, false) BitMatrix + @check_bit_operation broadcast(nand, true, b1) BitMatrix + @check_bit_operation broadcast(nand, false, b1) BitMatrix + @check_bit_operation broadcast(nor, b1, true) BitMatrix + @check_bit_operation broadcast(nor, b1, false) BitMatrix + @check_bit_operation broadcast(nor, true, b1) BitMatrix + @check_bit_operation broadcast(nor, false, b1) BitMatrix @check_bit_operation broadcast(+, b1, true) Matrix{Int} @check_bit_operation broadcast(+, b1, false) Matrix{Int} @check_bit_operation broadcast(-, b1, true) Matrix{Int} @@ -1002,12 +1020,18 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, b1, b2) BitMatrix @check_bit_operation broadcast(|, b1, b2) BitMatrix @check_bit_operation broadcast(xor, b1, b2) BitMatrix + @check_bit_operation broadcast(nand, b1, b2) BitMatrix + @check_bit_operation broadcast(nor, b1, b2) BitMatrix @check_bit_operation broadcast(&, b2, b1) BitMatrix @check_bit_operation broadcast(|, b2, b1) BitMatrix @check_bit_operation broadcast(xor, b2, b1) BitMatrix + @check_bit_operation broadcast(nand, b2, b1) BitMatrix + @check_bit_operation broadcast(nor, b2, b1) BitMatrix @check_bit_operation broadcast(&, b1, i2) Matrix{Int} @check_bit_operation broadcast(|, b1, i2) Matrix{Int} @check_bit_operation broadcast(xor, b1, i2) Matrix{Int} + @check_bit_operation broadcast(nand, b1, i2) Matrix{Int} + @check_bit_operation broadcast(nor, b1, i2) Matrix{Int} @check_bit_operation broadcast(+, b1, i2) Matrix{Int} @check_bit_operation broadcast(-, b1, i2) Matrix{Int} @check_bit_operation broadcast(*, b1, i2) Matrix{Int} @@ -1018,6 +1042,8 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(&, b1, u2) Matrix{UInt8} @check_bit_operation broadcast(|, b1, u2) Matrix{UInt8} @check_bit_operation broadcast(xor, b1, u2) Matrix{UInt8} + @check_bit_operation broadcast(nand, b1, u2) Matrix{UInt8} + @check_bit_operation broadcast(nor, b1, u2) Matrix{UInt8} @check_bit_operation broadcast(+, b1, u2) Matrix{UInt8} @check_bit_operation broadcast(-, b1, u2) Matrix{UInt8} @check_bit_operation broadcast(*, b1, u2) Matrix{UInt8} @@ -1086,6 +1112,14 @@ timesofar("unary arithmetic") @check_bit_operation broadcast(xor, b1, transpose(b3)) BitMatrix @check_bit_operation broadcast(xor, b2, b1) BitMatrix @check_bit_operation broadcast(xor, transpose(b3), b1) BitMatrix + @check_bit_operation broadcast(nand, b1, b2) BitMatrix + @check_bit_operation broadcast(nand, b1, transpose(b3)) BitMatrix + @check_bit_operation broadcast(nand, b2, b1) BitMatrix + @check_bit_operation broadcast(nand, transpose(b3), b1) BitMatrix + @check_bit_operation broadcast(nor, b1, b2) BitMatrix + @check_bit_operation broadcast(nor, b1, transpose(b3)) BitMatrix + @check_bit_operation broadcast(nor, b2, b1) BitMatrix + @check_bit_operation broadcast(nor, transpose(b3), b1) BitMatrix @check_bit_operation broadcast(+, b1, b2) Matrix{Int} @check_bit_operation broadcast(+, b1, transpose(b3)) Matrix{Int} @check_bit_operation broadcast(+, b2, b1) Matrix{Int} @@ -1390,6 +1424,8 @@ timesofar("reductions") @test map(&, b1, b2) == map((x,y)->x&y, b1, b2) == broadcast(&, b1, b2) @test map(|, b1, b2) == map((x,y)->x|y, b1, b2) == broadcast(|, b1, b2) @test map(⊻, b1, b2) == map((x,y)->x⊻y, b1, b2) == broadcast(⊻, b1, b2) == broadcast(xor, b1, b2) + @test map(⊼, b1, b2) == map((x,y)->x⊼y, b1, b2) == broadcast(⊼, b1, b2) == broadcast(nand, b1, b2) + @test map(⊽, b1, b2) == map((x,y)->x⊽y, b1, b2) == broadcast(⊽, b1, b2) == broadcast(nor, b1, b2) @test map(^, b1, b2) == map((x,y)->x^y, b1, b2) == b1 .^ b2 @test map(*, b1, b2) == map((x,y)->x*y, b1, b2) == b1 .* b2 diff --git a/test/gmp.jl b/test/gmp.jl index 96ffdedb7a93c..3d7317b37bacc 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -241,6 +241,12 @@ end @test xor(a, b, c, d, f) == parse(BigInt,"-2413804710837418037418307081437316711364709261074607933698") @test xor(a, b, c, d, f, g) == parse(BigInt,"2413804710837418037418307081437316711364709261074607933697") + @test nand(a, b) == parse(BigInt,"-125") + @test ⊼(a, b) == parse(BigInt,"-125") + + @test nor(a, b) == parse(BigInt,"-327424") + @test ⊽(a, b) == parse(BigInt,"-327424") + @test (&)(a, b) == parse(BigInt,"124") @test (&)(a, b, c) == parse(BigInt,"72") @test (&)(a, b, c, d) == parse(BigInt,"8") diff --git a/test/missing.jl b/test/missing.jl index 2864c1f67cb5c..ae08c37b25949 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -86,7 +86,7 @@ end arithmetic_operators = [+, -, *, /, ^, Base.div, Base.mod, Base.fld, Base.rem] # All unary operators return missing when evaluating missing - for f in [!, ~, +, -, *, &, |, xor] + for f in [!, ~, +, -, *, &, |, xor, nand, nor] @test ismissing(f(missing)) end @@ -131,6 +131,22 @@ end @test ismissing(xor(true, missing)) @test ismissing(xor(missing, false)) @test ismissing(xor(false, missing)) + @test ismissing(nand(missing, true)) + @test ismissing(nand(true, missing)) + @test nand(missing, false) == true + @test nand(false, missing) == true + @test ismissing(⊼(missing, true)) + @test ismissing(⊼(true, missing)) + @test ⊼(missing, false) == true + @test ⊼(false, missing) == true + @test nor(missing, true) == false + @test nor(true, missing) == false + @test ismissing(nor(missing, false)) + @test ismissing(nor(false, missing)) + @test ⊽(missing, true) == false + @test ⊽(true, missing) == false + @test ismissing(⊽(missing, false)) + @test ismissing(⊽(false, missing)) @test ismissing(missing & 1) @test ismissing(1 & missing) @@ -138,6 +154,14 @@ end @test ismissing(1 | missing) @test ismissing(xor(missing, 1)) @test ismissing(xor(1, missing)) + @test ismissing(nand(missing, 1)) + @test ismissing(nand(1, missing)) + @test ismissing(⊼(missing, 1)) + @test ismissing(⊼(1, missing)) + @test ismissing(nor(missing, 1)) + @test ismissing(nor(1, missing)) + @test ismissing(⊽(missing, 1)) + @test ismissing(⊽(1, missing)) end @testset "* string concatenation" begin diff --git a/test/numbers.jl b/test/numbers.jl index a76f5726492df..e62e1a798221d 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -38,6 +38,24 @@ const ≣ = isequal # convenient for comparing NaNs @test xor(true, false) == true @test xor(false, true) == true @test xor(true, true) == false + + @test false ⊼ false == true + @test true ⊼ false == true + @test false ⊼ true == true + @test true ⊼ true == false + @test nand(false, false) == true + @test nand(true, false) == true + @test nand(false, true) == true + @test nand(true, true) == false + + @test false ⊽ false == true + @test true ⊽ false == false + @test false ⊽ true == false + @test true ⊽ true == false + @test nor(false, false) == true + @test nor(true, false) == false + @test nor(false, true) == false + @test nor(true, true) == false end @testset "bool operator" begin @test Bool(false) == false From 4996445df37e526dac2772e333caf82f1ea987f0 Mon Sep 17 00:00:00 2001 From: Jonas Schulze Date: Fri, 9 Apr 2021 16:19:28 +0200 Subject: [PATCH 148/439] =?UTF-8?q?Add=20U+2AEA=20(=E2=AB=AA)=20and=20U+2A?= =?UTF-8?q?EB=20(=E2=AB=AB)=20to=20binary=20operators=20(#39403)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NEWS.md | 2 ++ src/julia-parser.scm | 2 +- stdlib/REPL/src/latex_symbols.jl | 9 ++++++++- test/syntax.jl | 6 ++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8b3f4e9a76794..0b493a9e8f1c7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,8 @@ New language features * Implicit multiplication by juxtaposition is now allowed for radical symbols (e.g., `x√y` and `x∛y`). ([#40173]) * The short-circuiting operators `&&` and `||` can now be dotted to participate in broadcast fusion as `.&&` and `.||`. ([#39594]) +* `⫪` (U+2AEA, `\Top`, `\downvDash`) and `⫫` (U+2AEB, `\Bot`, `\upvDash`, `\indep`) + may now be used as binary operators with comparison precedence. ([#39403]) Language changes ---------------- diff --git a/src/julia-parser.scm b/src/julia-parser.scm index afff8d23054ee..60cd047d12c76 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -15,7 +15,7 @@ (define prec-lazy-and (add-dots '(&&))) (define prec-comparison (append! '(in isa) - (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≂ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂ <: >:)))) + (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≂ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂ ⫪ ⫫ <: >:)))) (define prec-pipe< '(|.<\|| |<\||)) (define prec-pipe> '(|.\|>| |\|>|)) (define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) diff --git a/stdlib/REPL/src/latex_symbols.jl b/stdlib/REPL/src/latex_symbols.jl index bfd2e1fbbb015..237aba92c45c7 100644 --- a/stdlib/REPL/src/latex_symbols.jl +++ b/stdlib/REPL/src/latex_symbols.jl @@ -671,8 +671,13 @@ const latex_symbols = Dict( "\\dashv" => "⊣", "\\top" => "⊤", "\\bot" => "⊥", + "\\Top" => "⫪", + "\\Bot" => "⫫", + "\\indep" => "⫫", "\\models" => "⊧", "\\vDash" => "⊨", + "\\downvDash" => "⫪", + "\\upvDash" => "⫫", "\\Vdash" => "⊩", "\\Vvdash" => "⊪", "\\VDash" => "⊫", @@ -2624,13 +2629,14 @@ const latex_symbols = Dict( # Canonical reverse mapping for symbols that have several completions (#39148). # -# These duplicate mappings can be investigated with the folllowing commands: +# These duplicate mappings can be investigated with the following commands: #= ls = REPL.REPLCompletions.latex_symbols; symbols = values(ls) duplicates = [v for v in unique(symbols) if count(==(v), symbols) > 1] [(v, REPL.symbol_latex(v)) => findall(==(v), ls) for v in duplicates] =# const symbols_latex_canonical = Dict( + "⫫" => "\\Bot", "ð" => "\\dh", "…" => "\\ldots", "∅" => "\\emptyset", @@ -2651,6 +2657,7 @@ const symbols_latex_canonical = Dict( "√" => "\\sqrt", "̶" => "\\sout", "→" => "\\to", + "⫪" => "\\Top", "ε" => "\\varepsilon", "⊻" => "\\xor", "⊼" => "\\nand", diff --git a/test/syntax.jl b/test/syntax.jl index bfd7beacb89c6..6c2cfb465abd1 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2157,6 +2157,12 @@ end @test Meta.parse("a ⟂ b ⟂ c") == Expr(:comparison, :a, :⟂, :b, :⟂, :c) @test Meta.parse("a ⟂ b ∥ c") == Expr(:comparison, :a, :⟂, :b, :∥, :c) +# issue 39350 +@testset "binary ⫪ and ⫫" begin + @test Meta.parse("a ⫪ b") == Expr(:call, :⫪, :a, :b) + @test Meta.parse("a ⫫ b") == Expr(:call, :⫫, :a, :b) +end + # only allow certain characters after interpolated vars (#25231) @test Meta.parse("\"\$x෴ \"",raise=false) == Expr(:error, "interpolated variable \$x ends with invalid character \"෴\"; use \"\$(x)\" instead.") @test Base.incomplete_tag(Meta.parse("\"\$foo", raise=false)) == :string From 54c7002892d1b0260890848397e4ba1e2d2506d1 Mon Sep 17 00:00:00 2001 From: quildtide <42811940+quildtide@users.noreply.github.com> Date: Fri, 9 Apr 2021 14:18:09 -0400 Subject: [PATCH 149/439] Improve flow of documentation for non-standard strings (#40057) --- doc/src/manual/metaprogramming.md | 35 +++++++++++++++++-------------- doc/src/manual/strings.md | 15 +++++++------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 9880bf4417867..fe9604183bcaf 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -981,13 +981,13 @@ block: end ``` -## Non-Standard String Literals +## [Non-Standard String Literals](@id meta-non-standard-string-literals) Recall from [Strings](@ref non-standard-string-literals) that string literals prefixed by an identifier are called non-standard string literals, and can have different semantics than un-prefixed string literals. For example: - * `r"^\s*(?:#|$)"` produces a regular expression object rather than a string - * `b"DATA\xff\u2200"` is a byte array literal for `[68,65,84,65,255,226,136,128]`. + * `r"^\s*(?:#|$)"` produces a [regular expression object](@ref man-regex-literals) rather than a string + * `b"DATA\xff\u2200"` is a [byte array literal](@ref man-byte-array-literals) for `[68,65,84,65,255,226,136,128]`. Perhaps surprisingly, these behaviors are not hard-coded into the Julia parser or compiler. Instead, they are custom behaviors provided by a general mechanism that anyone can use: prefixed string @@ -1051,20 +1051,9 @@ constructed on each iteration. In the vast majority of use cases, however, regul are not constructed based on run-time data. In this majority of cases, the ability to write regular expressions as compile-time values is invaluable. -Like non-standard string literals, non-standard command literals exist using a prefixed variant -of the command literal syntax. The command literal ```custom`literal` ``` is parsed as `@custom_cmd "literal"`. -Julia itself does not contain any non-standard command literals, but packages can make use of -this syntax. Aside from the different syntax and the `_cmd` suffix instead of the `_str` suffix, -non-standard command literals behave exactly like non-standard string literals. - -In the event that two modules provide non-standard string or command literals with the same name, -it is possible to qualify the string or command literal with a module name. For instance, if both -`Foo` and `Bar` provide non-standard string literal `@x_str`, then one can write `Foo.x"literal"` -or `Bar.x"literal"` to disambiguate between the two. - The mechanism for user-defined string literals is deeply, profoundly powerful. Not only are Julia's -non-standard literals implemented using it, but also the command literal syntax (``` `echo "Hello, $person"` ```) -is implemented with the following innocuous-looking macro: +non-standard literals implemented using it, but the command literal syntax (``` `echo "Hello, $person"` ```) +is also implemented using the following innocuous-looking macro: ```julia macro cmd(str) @@ -1077,6 +1066,20 @@ but they are just functions, written entirely in Julia. You can read their sourc what they do -- and all they do is construct expression objects to be inserted into your program's syntax tree. +Like string literals, command literals can also be prefixed by an identifier +to form what are called non-standard command literals. These command literals are parsed +as calls to specially-named macros. For example, the syntax ```custom`literal` ``` is parsed +as `@custom_cmd "literal"`. +Julia itself does not contain any non-standard command literals, but packages can make use of +this syntax. Aside from the different syntax and the `_cmd` suffix instead of the `_str` suffix, +non-standard command literals behave exactly like non-standard string literals. + +In the event that two modules provide non-standard string or command literals with the same name, +it is possible to qualify the string or command literal with a module name. For instance, if both +`Foo` and `Bar` provide non-standard string literal `@x_str`, then one can write `Foo.x"literal"` +or `Bar.x"literal"` to disambiguate between the two. + + Another way to define a macro would be like this: ```julia diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index f65a5526a8551..743ce3caa3c0d 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -739,13 +739,16 @@ Some other useful functions include: There are situations when you want to construct a string or use string semantics, but the behavior of the standard string construct is not quite what is needed. For these kinds of situations, Julia -provides [non-standard string literals](@ref). A non-standard string literal looks like a regular -double-quoted string literal, but is immediately prefixed by an identifier, and doesn't behave -quite like a normal string literal. Regular expressions, byte array literals and version number -literals, as described below, are some examples of non-standard string literals. Other examples -are given in the [Metaprogramming](@ref) section. +provides non-standard string literals. A non-standard string literal looks like a regular +double-quoted string literal, +but is immediately prefixed by an identifier, and may behave differently from a normal string literal. -## Regular Expressions +[Regular expressions](@ref man-regex-literals), [byte array literals](@ref man-byte-array-literals), +and [version number literals](@ref man-version-number-literals), as described below, +are some examples of non-standard string literals. Users and packages may also define new non-standard string literals. +Further documentation is given in the [Metaprogramming](@ref meta-non-standard-string-literals) section. + +## [Regular Expressions](@id man-regex-literals) Julia has Perl-compatible regular expressions (regexes), as provided by the [PCRE](http://www.pcre.org/) library (a description of the syntax can be found [here](http://www.pcre.org/current/doc/html/pcre2syntax.html)). Regular expressions are related to strings in two ways: the obvious connection is that From 2f0156a6c79566bf265397641effa17a202f7ab4 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Fri, 9 Apr 2021 22:26:20 +0000 Subject: [PATCH 150/439] [automated] Bump the Tar stdlib from ac4d442 to 86825ec (#40421) Co-authored-by: Dilum Aluthge --- .../Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/md5 | 1 + .../Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/sha512 | 1 + .../Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/md5 | 1 - .../Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/sha512 | 1 - stdlib/Tar.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/md5 create mode 100644 deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/sha512 delete mode 100644 deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/md5 delete mode 100644 deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/sha512 diff --git a/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/md5 b/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/md5 new file mode 100644 index 0000000000000..30d64c2600751 --- /dev/null +++ b/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/md5 @@ -0,0 +1 @@ +e2b8b646355ba71a6e30dbe9c0fdc6ac diff --git a/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/sha512 b/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/sha512 new file mode 100644 index 0000000000000..be161a529bc83 --- /dev/null +++ b/deps/checksums/Tar-86825ecf1e8b6f57105bf0632e93c532cee200a4.tar.gz/sha512 @@ -0,0 +1 @@ +db66086d531bbf2210207449ac464d4e865562a849f8a4197feca4636c90ca577140977daf3d0fb4c4c61240866934a10ccc6120b7bc95b1a18ff16f9491aed9 diff --git a/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/md5 b/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/md5 deleted file mode 100644 index 5f1a8151702d6..0000000000000 --- a/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -8e142a0c1761068128b4ac229aae584d diff --git a/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/sha512 b/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/sha512 deleted file mode 100644 index 0c3dd7423504f..0000000000000 --- a/deps/checksums/Tar-ac4d442266a676ce2d1a43acb55fc07d1edc6566.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -d899b09c3ab4d94605297c716838f21dae7f1467b2785c9fff960ddad645161148fcdb2bc114e94da24f567098af4abce49960986f91eb26a2c234928fe6bdc9 diff --git a/stdlib/Tar.version b/stdlib/Tar.version index 0ab47a82fd468..2997467cdd1bd 100644 --- a/stdlib/Tar.version +++ b/stdlib/Tar.version @@ -1,2 +1,2 @@ TAR_BRANCH = master -TAR_SHA1 = ac4d442266a676ce2d1a43acb55fc07d1edc6566 +TAR_SHA1 = 86825ecf1e8b6f57105bf0632e93c532cee200a4 From 21eb1b6628a88cd013931fd49c95b45eb036b143 Mon Sep 17 00:00:00 2001 From: felix Date: Sat, 10 Apr 2021 00:09:35 +0100 Subject: [PATCH 151/439] add some assorted subtyping tests (#20627) --- test/ambiguous.jl | 17 +++++++++++++++++ test/subtype.jl | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index bad5f19f389c9..8d0c2092f21c2 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -369,4 +369,21 @@ let ambig = Int32[0] @test ambig[1] == 1 end +# issue #11407 +f11407(::Dict{K,V}, ::Dict{Any,V}) where {K,V} = 1 +f11407(::Dict{K,V}, ::Dict{K,Any}) where {K,V} = 2 +@test_throws MethodError f11407(Dict{Any,Any}(), Dict{Any,Any}()) # ambiguous +@test f11407(Dict{Any,Int}(), Dict{Any,Int}()) == 1 +f11407(::Dict{Any,Any}, ::Dict{Any,Any}) where {K,V} = 3 +@test f11407(Dict{Any,Any}(), Dict{Any,Any}()) == 3 + +# issue #12814 +abstract type A12814{N, T} end +struct B12814{N, T} <: A12814{N, T} + x::NTuple{N, T} +end +(::Type{T})(x::X) where {T <: A12814, X <: Array} = 1 +@test_throws MethodError B12814{3, Float64}([1, 2, 3]) # ambiguous +@test B12814{3,Float64}((1, 2, 3)).x === (1.0, 2.0, 3.0) + nothing diff --git a/test/subtype.jl b/test/subtype.jl index 6956c212301ea..244ce3c4b7900 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1901,3 +1901,16 @@ let A = Tuple{Array{Pair{T, JT} where JT<:Ref{T}, 1} where T, Vector}, @test_broken I <: A @test_broken !Base.has_free_typevars(I) end + +# issue #8915 +struct D8915{T<:Union{Float32,Float64}} + D8915{T}(a) where {T} = 1 + D8915{T}(a::Int) where {T} = 2 +end +@test D8915{Float64}(1) == 2 +@test D8915{Float64}(1.0) == 1 + +# issue #18985 +f18985(x::T, y...) where {T<:Union{Int32,Int64}} = (length(y), f18985(y[1], y[2:end]...)...) +f18985(x::T) where {T<:Union{Int32,Int64}} = 100 +@test f18985(1, 2, 3) == (2, 1, 100) From 722f90f17fab62578a6e82a7c8c121830d147ff3 Mon Sep 17 00:00:00 2001 From: Michael Hatherly Date: Sat, 10 Apr 2021 00:13:07 +0100 Subject: [PATCH 152/439] [REPL] Implement basic pager using TerminalMenus (#38956) --- stdlib/REPL/src/TerminalMenus/Pager.jl | 40 +++++++++++++++++++ .../REPL/src/TerminalMenus/TerminalMenus.jl | 2 + stdlib/REPL/test/TerminalMenus/pager.jl | 39 ++++++++++++++++++ stdlib/REPL/test/TerminalMenus/runtests.jl | 1 + 4 files changed, 82 insertions(+) create mode 100644 stdlib/REPL/src/TerminalMenus/Pager.jl create mode 100644 stdlib/REPL/test/TerminalMenus/pager.jl diff --git a/stdlib/REPL/src/TerminalMenus/Pager.jl b/stdlib/REPL/src/TerminalMenus/Pager.jl new file mode 100644 index 0000000000000..af49c3aa63440 --- /dev/null +++ b/stdlib/REPL/src/TerminalMenus/Pager.jl @@ -0,0 +1,40 @@ +mutable struct Pager{C} <: _ConfiguredMenu{C} + lines::Vector{String} + pagesize::Int + pageoffset::Int + selected::Nothing + config::C +end + +function Pager(text::AbstractString; pagesize::Int=10, kwargs...) + lines = readlines(IOBuffer(text)) + return Pager(lines, pagesize, 0, nothing, Config(; kwargs...)) +end + +function header(p::Pager) + total = length(p.lines) + current = min(p.pageoffset + p.pagesize, total) + percent = round(Int, (current / total) * 100) + return "($(lpad(current, ndigits(total))) / $total) $(lpad(percent, 3))%" +end + +options(p::Pager) = p.lines + +cancel(::Pager) = nothing + +pick(::Pager, ::Int) = true + +function writeline(buf::IOBuffer, pager::Pager{Config}, idx::Int, iscursor::Bool) + print(buf, pager.lines[idx]) +end + +function pager(terminal, object) + lines, columns = displaysize(terminal)::Tuple{Int,Int} + columns -= 3 + buffer = IOBuffer() + ctx = IOContext(buffer, :color => REPL.Terminals.hascolor(terminal), :displaysize => (lines, columns)) + show(ctx, "text/plain", object) + pager = Pager(String(take!(buffer)); pagesize = div(lines, 2)) + return request(terminal, pager) +end +pager(object) = pager(terminal, object) diff --git a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl index d9d3dc8598f7d..87869e84d9838 100644 --- a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl +++ b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl @@ -17,10 +17,12 @@ include("config.jl") include("AbstractMenu.jl") include("RadioMenu.jl") include("MultiSelectMenu.jl") +include("Pager.jl") export RadioMenu, MultiSelectMenu, + Pager, request # TODO: remove in Julia 2.0 diff --git a/stdlib/REPL/test/TerminalMenus/pager.jl b/stdlib/REPL/test/TerminalMenus/pager.jl new file mode 100644 index 0000000000000..1d6579b8f5fc9 --- /dev/null +++ b/stdlib/REPL/test/TerminalMenus/pager.jl @@ -0,0 +1,39 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +content = + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Arcu non sodales neque sodales. + Placerat orci nulla pellentesque dignissim enim sit amet venenatis. Mauris + augue neque gravida in fermentum et sollicitudin. Amet venenatis urna cursus + eget. Enim praesent elementum facilisis leo vel fringilla est. Vitae sapien + pellentesque habitant morbi tristique. Ornare lectus sit amet est placerat in. + Leo urna molestie at elementum eu facilisis. Aliquam vestibulum morbi blandit + cursus risus at ultrices. Id aliquet lectus proin nibh. Facilisi etiam + dignissim diam quis enim lobortis scelerisque fermentum. Pretium lectus quam id + leo in vitae turpis massa sed. Elementum facilisis leo vel fringilla est. + Vulputate ut pharetra sit amet aliquam. Quis enim lobortis scelerisque + fermentum dui faucibus in ornare. Cursus turpis massa tincidunt dui ut. + + A arcu cursus vitae congue mauris rhoncus. Tellus rutrum tellus pellentesque + eu. Fringilla phasellus faucibus scelerisque eleifend donec pretium. Aliquam + etiam erat velit scelerisque. Volutpat lacus laoreet non curabitur gravida. + Felis imperdiet proin fermentum leo vel orci. Viverra tellus in hac habitasse + platea dictumst vestibulum rhoncus est. Ullamcorper dignissim cras tincidunt + lobortis feugiat vivamus. Sit amet luctus venenatis lectus. Odio facilisis + mauris sit amet massa vitae tortor condimentum. Purus sit amet volutpat + consequat mauris nunc congue. Enim nunc faucibus a pellentesque sit amet. Purus + non enim praesent elementum facilisis leo vel fringilla est. + """ |> strip + +let p = Pager(content) + @test p.pagesize == 10 + @test length(p.lines) == 22 + @test startswith(content, p.lines[1]) + @test endswith(content, p.lines[end]) + buffer = IOBuffer() + TerminalMenus.printmenu(buffer, p, 1) + str = String(take!(buffer)) + @test contains(str, "(10 / 22) 45%") + @test endswith(str, "leo in vitae turpis massa sed. Elementum facilisis leo vel fringilla est.") +end diff --git a/stdlib/REPL/test/TerminalMenus/runtests.jl b/stdlib/REPL/test/TerminalMenus/runtests.jl index fab105244d0a1..62a91cc0a1256 100644 --- a/stdlib/REPL/test/TerminalMenus/runtests.jl +++ b/stdlib/REPL/test/TerminalMenus/runtests.jl @@ -25,6 +25,7 @@ include("radio_menu.jl") include("multiselect_menu.jl") include("dynamic_menu.jl") include("multiselect_with_skip_menu.jl") +include("pager.jl") # Legacy tests include("legacytests/old_radio_menu.jl") From bb608e592b14d84cbe1f6ab78bbc678d2f19715e Mon Sep 17 00:00:00 2001 From: Thibaut Lienart Date: Sat, 10 Apr 2021 01:17:33 +0200 Subject: [PATCH 153/439] regex: remove error when accessing an unset group (#40391) closes #31456 --- base/pcre.jl | 5 ++++- base/regex.jl | 2 ++ test/strings/util.jl | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/pcre.jl b/base/pcre.jl index e52bea2869eb7..a8edaaa089c31 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -228,7 +228,10 @@ function substring_length_bynumber(match_data, number) s = RefValue{Csize_t}() rc = ccall((:pcre2_substring_length_bynumber_8, PCRE_LIB), Cint, (Ptr{Cvoid}, Cint, Ref{Csize_t}), match_data, number, s) - rc < 0 && error("PCRE error: $(err_message(rc))") + if rc < 0 + rc == ERROR_UNSET && return 0 + error("PCRE error: $(err_message(rc))") + end return Int(s[]) end diff --git a/base/regex.jl b/base/regex.jl index a79f51995fab3..7fae9326c231b 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -528,6 +528,8 @@ replace_err(repl) = error("Bad replacement string: $repl") function _write_capture(io, re::RegexAndMatchData, group) len = PCRE.substring_length_bynumber(re.match_data, group) + # in the case of an optional group that doesn't match, len == 0 + len == 0 && return ensureroom(io, len+1) PCRE.substring_copy_bynumber(re.match_data, group, pointer(io.data, io.ptr), len+1) diff --git a/test/strings/util.jl b/test/strings/util.jl index 2ca6df529ba51..e8ea3b643fcda 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -275,6 +275,11 @@ end # Issue 13332 @test replace("abc", 'b' => 2.1) == "a2.1c" + # Issue 31456 + @test replace("The fox.", r"fox(es)?" => s"bus\1") == "The bus." + @test replace("The foxes.", r"fox(es)?" => s"bus\1") == "The buses." + @test replace("The quick fox quickly.", r"(quick)?\sfox(es)?\s(run)?" => s"\1 bus\2 \3") == "The quick bus quickly." + # test replace with a count for String and GenericString # check that replace is a no-op if count==0 for s in ["aaa", Test.GenericString("aaa")] From fc69c9aef38a1b53324abe9a715514f9716d270b Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Sat, 10 Apr 2021 03:59:56 +0200 Subject: [PATCH 154/439] Allow any f for sum/minimum/maximum(f, v::AbstractSparseVector) (#29884) * sum/minimum/maximum(f, v::AbstractSparseVector) generalize sum/minimum/maximum(abs/abs2, v::AbstractSparseVector) to arbitrary f * add broken sum(f, [])==0 tests for reference --- stdlib/SparseArrays/src/sparsevector.jl | 52 ++++++++++++++++-------- stdlib/SparseArrays/test/sparsevector.jl | 28 +++++++++++++ 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 777be897ea7df..3bb3e2ddec05f 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -1354,34 +1354,50 @@ end ### Reduction +function _sum(f, x::AbstractSparseVector) + n = length(x) + n > 0 || return sum(f, nonzeros(x)) # return zero() of proper type + m = nnz(x) + (m == 0 ? n * f(zero(eltype(x))) : + m == n ? sum(f, nonzeros(x)) : + Base.add_sum((n - m) * f(zero(eltype(x))), sum(f, nonzeros(x)))) +end + +sum(f::Union{Function, Type}, x::AbstractSparseVector) = _sum(f, x) # resolve ambiguity +sum(f, x::AbstractSparseVector) = _sum(f, x) sum(x::AbstractSparseVector) = sum(nonzeros(x)) -function maximum(x::AbstractSparseVector{T}) where T<:Real +function _maximum(f, x::AbstractSparseVector) n = length(x) - n > 0 || throw(ArgumentError("maximum over empty array is not allowed.")) + if n == 0 + if f === abs || f === abs2 + return zero(eltype(x)) # preserving maximum(abs/abs2, x) behaviour in 1.0.x + else + throw(ArgumentError("maximum over an empty array is not allowed.")) + end + end m = nnz(x) - (m == 0 ? zero(T) : - m == n ? maximum(nonzeros(x)) : - max(zero(T), maximum(nonzeros(x))))::T + (m == 0 ? f(zero(eltype(x))) : + m == n ? maximum(f, nonzeros(x)) : + max(f(zero(eltype(x))), maximum(f, nonzeros(x)))) end -function minimum(x::AbstractSparseVector{T}) where T<:Real +maximum(f::Union{Function, Type}, x::AbstractSparseVector) = _maximum(f, x) # resolve ambiguity +maximum(f, x::AbstractSparseVector) = _maximum(f, x) +maximum(x::AbstractSparseVector) = maximum(identity, x) + +function _minimum(f, x::AbstractSparseVector) n = length(x) - n > 0 || throw(ArgumentError("minimum over empty array is not allowed.")) + n > 0 || throw(ArgumentError("minimum over an empty array is not allowed.")) m = nnz(x) - (m == 0 ? zero(T) : - m == n ? minimum(nonzeros(x)) : - min(zero(T), minimum(nonzeros(x))))::T + (m == 0 ? f(zero(eltype(x))) : + m == n ? minimum(f, nonzeros(x)) : + min(f(zero(eltype(x))), minimum(f, nonzeros(x)))) end -for f in [:sum, :maximum, :minimum], op in [:abs, :abs2] - SV = :AbstractSparseVector - if f === :minimum - @eval ($f)(::typeof($op), x::$SV{T}) where {T<:Number} = nnz(x) < length(x) ? ($op)(zero(T)) : ($f)($op, nonzeros(x)) - else - @eval ($f)(::typeof($op), x::$SV) = ($f)($op, nonzeros(x)) - end -end +minimum(f::Union{Function, Type}, x::AbstractSparseVector) = _minimum(f, x) # resolve ambiguity +minimum(f, x::AbstractSparseVector) = _minimum(f, x) +minimum(x::AbstractSparseVector) = minimum(identity, x) norm(x::SparseVectorUnion, p::Real=2) = norm(nonzeros(x), p) diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 79c952620050c..55df1fb65393c 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -789,6 +789,19 @@ end @test sum(x) == 4.0 @test sum(abs, x) == 5.5 @test sum(abs2, x) == 14.375 + @test @inferred(sum(t -> true, x)) === 8 + @test @inferred(sum(t -> abs(t) + one(t), x)) == 13.5 + + @test @inferred(sum(t -> true, spzeros(Float64, 8))) === 8 + @test @inferred(sum(t -> abs(t) + one(t), spzeros(Float64, 8))) === 8.0 + + # reducing over an empty collection + # FIXME sum(f, []) throws, should be fixed both for generic and sparse vectors + @test_broken sum(t -> true, zeros(Float64, 0)) === 0 + @test_broken sum(t -> true, spzeros(Float64, 0)) === 0 + @test @inferred(sum(abs2, spzeros(Float64, 0))) === 0.0 + @test_broken sum(t -> abs(t) + one(t), zeros(Float64, 0)) === 0.0 + @test_broken sum(t -> abs(t) + one(t), spzeros(Float64, 0)) === 0.0 @test norm(x) == sqrt(14.375) @test norm(x, 1) == 5.5 @@ -802,6 +815,12 @@ end @test minimum(x) == -0.75 @test maximum(abs, x) == 3.5 @test minimum(abs, x) == 0.0 + @test @inferred(minimum(t -> true, x)) === true + @test @inferred(maximum(t -> true, x)) === true + @test @inferred(minimum(t -> abs(t) + one(t), x)) == 1.0 + @test @inferred(maximum(t -> abs(t) + one(t), x)) == 4.5 + @test @inferred(minimum(t -> t + one(t), x)) == 0.25 + @test @inferred(maximum(t -> -abs(t) + one(t), x)) == 1.0 end let x = abs.(spv_x1) @@ -826,6 +845,15 @@ end @test minimum(x) == 0.0 @test maximum(abs, x) == 0.0 @test minimum(abs, x) == 0.0 + @test @inferred(minimum(t -> true, x)) === true + @test @inferred(maximum(t -> true, x)) === true + @test @inferred(minimum(t -> abs(t) + one(t), x)) === 1.0 + @test @inferred(maximum(t -> abs(t) + one(t), x)) === 1.0 + end + + let x = spzeros(Float64, 0) + @test_throws ArgumentError minimum(t -> true, x) + @test_throws ArgumentError maximum(t -> true, x) end end From 008275c8d7fd11d60699e76d1a02cfa474df08f5 Mon Sep 17 00:00:00 2001 From: kimikage Date: Sat, 10 Apr 2021 19:18:38 +0900 Subject: [PATCH 155/439] doc: fix examples with invalid MIME type (#40427) --- base/multimedia.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/multimedia.jl b/base/multimedia.jl index 45e6b9532e9fa..5d9e3e807d159 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -69,7 +69,7 @@ methods; for example, if the available MIME formats depend on the *value* of `x` julia> showable(MIME("text/plain"), rand(5)) true -julia> showable("img/png", rand(5)) +julia> showable("image/png", rand(5)) false ``` """ @@ -176,7 +176,7 @@ data except for a set of types known to be text data (possibly Unicode). julia> istextmime(MIME("text/plain")) true -julia> istextmime(MIME("img/png")) +julia> istextmime(MIME("image/png")) false ``` """ From e260f2bccada3ef162c1f322bd80581a3d95fb64 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 10 Apr 2021 18:32:45 +0200 Subject: [PATCH 156/439] fix a typo in TOML error message (#40428) * fix a typo in TOML error message --- base/toml_parser.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/toml_parser.jl b/base/toml_parser.jl index 956c62196d6b8..916a93fdf0d22 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -242,7 +242,7 @@ const err_message = Dict( ErrExpectedEqualAfterKey => "expected equal sign after key", ErrNoTrailingDigitAfterDot => "expected digit after dot", ErrOverflowError => "overflowed when parsing integer", - ErrInvalidUnicodeScalar => "invalid uncidode scalar", + ErrInvalidUnicodeScalar => "invalid unicode scalar", ErrInvalidEscapeCharacter => "invalid escape character", ErrUnexpectedEofExpectedValue => "unexpected end of file, expected a value" ) From f9c6d9848164669fbb44a4f8b2ee56ae80ffbd00 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sat, 10 Apr 2021 13:55:41 -0400 Subject: [PATCH 157/439] Add LBT checksums and bump versions in all the places. (#40429) * Add LBT checksums * remove old checksums * Change LBT version in various places --- deps/Versions.make | 2 +- deps/blastrampoline.version | 4 +-- deps/checksums/blastrampoline | 64 +++++++++++++++++------------------ 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/deps/Versions.make b/deps/Versions.make index 9d19790e945e6..8501acd31f4f7 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -74,7 +74,7 @@ OBJCONV_JLL_NAME := Objconv OBJCONV_JLL_VER := 2.49.1+0 # blastrampoline -BLASTRAMPOLINE_VER := 3.0.2 +BLASTRAMPOLINE_VER := 3.0.4 BLASTRAMPOLINE_JLL_NAME := libblastrampoline # OpenBLAS diff --git a/deps/blastrampoline.version b/deps/blastrampoline.version index 905164db9e272..86d77ab5bf293 100644 --- a/deps/blastrampoline.version +++ b/deps/blastrampoline.version @@ -1,2 +1,2 @@ -BLASTRAMPOLINE_BRANCH=main -BLASTRAMPOLINE_SHA1=5882fdf6395afb1ed01a8a10db94b7b3cbd39e16 +BLASTRAMPOLINE_BRANCH=v3.0.4 +BLASTRAMPOLINE_SHA1=23de7a09bf354fe6f655c457bab5bf47fdd2486d diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index 02049d4752096..1d371bee78d16 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,34 +1,34 @@ blastrampoline-5882fdf6395afb1ed01a8a10db94b7b3cbd39e16.tar.gz/md5/e0d62a761862e4331e39f3a863558b15 blastrampoline-5882fdf6395afb1ed01a8a10db94b7b3cbd39e16.tar.gz/sha512/b0637d903183b42ad7fff0e7c6e2c9feda0082d31d6a86926586c56437fc91041b5fea2c4cd4f5b588e8f86e71fdbf4ac216fa6862a1df360faa77c8966e7b0e -libblastrampoline.v3.0.2+0.aarch64-apple-darwin.tar.gz/md5/4f7ba7d67f6fc8148f5be9f125b09628 -libblastrampoline.v3.0.2+0.aarch64-apple-darwin.tar.gz/sha512/e1b950317edbfa5fa91c343ff99b008db82f2a7f2c4a19a51b4c9b36faf8f9c1d11453d8b3234eb29ee30adeca10877098ce456d181b9c068ba086a59792165f -libblastrampoline.v3.0.2+0.aarch64-linux-gnu.tar.gz/md5/ba18ed1a8db10a2e630a8c09b4911af3 -libblastrampoline.v3.0.2+0.aarch64-linux-gnu.tar.gz/sha512/242bd84474827725f45faa1e52ecc1f8f1d9d0abd9fa8f0f994557d0a508b5959f10c098d9ede579f9421fa8c7559a9ab3ef01e71aa44fd1f691dc8f96d1f4bd -libblastrampoline.v3.0.2+0.aarch64-linux-musl.tar.gz/md5/6296dad440625727da3a167a4dcb9d14 -libblastrampoline.v3.0.2+0.aarch64-linux-musl.tar.gz/sha512/0f7975b008003575ba499b6c98ae2231d6bd5d3831f0b737ea0019b63d6ddb8bfd526350390a4727569181accd895e0f82f00c23cdb2aa11e5eafba046c1224a -libblastrampoline.v3.0.2+0.armv6l-linux-gnueabihf.tar.gz/md5/3dc56056be7f96e39a25bf1e2413e1f6 -libblastrampoline.v3.0.2+0.armv6l-linux-gnueabihf.tar.gz/sha512/e1c66d40ff078736502597cf2e06165741ac387d987b5c5c96053f632b74ee80bf0df0318da15f87833a9a096b36113b4bd882c4f4c90810a389015efb66a1d6 -libblastrampoline.v3.0.2+0.armv6l-linux-musleabihf.tar.gz/md5/fb2db3dfc963ac7fe78b738bfbc68d8a -libblastrampoline.v3.0.2+0.armv6l-linux-musleabihf.tar.gz/sha512/14878afb19bc1925e9d8f5d4586ce03c8b248bbf669e367b5114c3d289f99340c1cf002e5b030e4ca8272021c0173bc39faeddf3c4d8ce890590d94d28b73149 -libblastrampoline.v3.0.2+0.armv7l-linux-gnueabihf.tar.gz/md5/216eca57cb50379ec2766b59d66014b3 -libblastrampoline.v3.0.2+0.armv7l-linux-gnueabihf.tar.gz/sha512/478cac263aa42db5800d3d70efba81f3111ef371ba0f9940cc64a4a0b8306751ab4f517dc42a136b5c3e3a50cdf25ab0ad769e9eb854de812fba47e54f0c0f16 -libblastrampoline.v3.0.2+0.armv7l-linux-musleabihf.tar.gz/md5/6896c312111b20b6b9c45398991a4309 -libblastrampoline.v3.0.2+0.armv7l-linux-musleabihf.tar.gz/sha512/43241768dff5f3b4bec18ac72cfb328dc6498ddfb1b0ed98b5a2e4052ea7bb1d1e7a669910a1edb50fcb938dd460578bee268baf28a9eb69426c053259272a74 -libblastrampoline.v3.0.2+0.i686-linux-gnu.tar.gz/md5/9ab7739ae2816070d7bd57cacc2ae5b1 -libblastrampoline.v3.0.2+0.i686-linux-gnu.tar.gz/sha512/de747d285db84ccd5983e2acef4b98d03d209fe2454ac48142190be28db655c62e6c6d4041c56b227cae4f247276ad6f0491add09c07bc46dc4cb171030cff63 -libblastrampoline.v3.0.2+0.i686-linux-musl.tar.gz/md5/0621e71f25a3a69dc06acc845fb89999 -libblastrampoline.v3.0.2+0.i686-linux-musl.tar.gz/sha512/bb80afabf0525ab11beec9829097498a1501cd2f51d83f0599d17d40a684ec2ac3d7a61150cfec6b2464872184b435d0fd912fd6d4a4cd5d286a029a2633961d -libblastrampoline.v3.0.2+0.i686-w64-mingw32.tar.gz/md5/a03bd4ea83d040dfc3658be3bf089210 -libblastrampoline.v3.0.2+0.i686-w64-mingw32.tar.gz/sha512/0585aad4e9fd0b2722ed3b4693b41ceeeef18b34f00246f98352556ff17e1213342f457916a5fcf53d0d87a93be1ad22af17c9d4a3b1fec80ad21ef964cde1db -libblastrampoline.v3.0.2+0.powerpc64le-linux-gnu.tar.gz/md5/89ac3a8c5b0fb9b02b14d61f7b8e5055 -libblastrampoline.v3.0.2+0.powerpc64le-linux-gnu.tar.gz/sha512/3f0bf8921a8574cbea0d4a3a7e9a521b9e318acfbe0476b01e4266a9c674995f8ad9d21a05976b65c04dce99afd2d96d50d8a3da0ca53ce3cf843e78a7d19871 -libblastrampoline.v3.0.2+0.x86_64-apple-darwin.tar.gz/md5/0da14952e48c982321a63a0877b4a685 -libblastrampoline.v3.0.2+0.x86_64-apple-darwin.tar.gz/sha512/8aa97721c77a310864632c54a46768ad62507a40c1dc36fc240bf409cc25db3b443270b3cdbce6a7794bc6e59e492220adb69d90a2804c32d0d7a41a7712366a -libblastrampoline.v3.0.2+0.x86_64-linux-gnu.tar.gz/md5/a8884383157ee9dc33f8d885510d806a -libblastrampoline.v3.0.2+0.x86_64-linux-gnu.tar.gz/sha512/5f0d8a2d36778c08b46769f4eeae2bad03c0763dd84c94531911e5979eecad816b198ee3cadf0d03d4339bcbef28ed5d20e2799d00f13b0bc818f94fb7521675 -libblastrampoline.v3.0.2+0.x86_64-linux-musl.tar.gz/md5/1f59ccb2555dd76d92f4d779029bfccc -libblastrampoline.v3.0.2+0.x86_64-linux-musl.tar.gz/sha512/c631648a90306d11aa80880ed857de7cdc40d354f9a26979e71fbc44fa5517596a68af53f651a683307fb8112abd439b335ad1df18c0301afc7f7f24f380a97a -libblastrampoline.v3.0.2+0.x86_64-unknown-freebsd.tar.gz/md5/2dfab8bbdcfcdb02f1bacac6c2317587 -libblastrampoline.v3.0.2+0.x86_64-unknown-freebsd.tar.gz/sha512/d93b277a51e43d150d1af781ddc122a8e093450a83ce376a37e1f32d0eaf382a6a852722181a11765cfbbd514287854937eab88e9bb09688da0d323ede46e1b3 -libblastrampoline.v3.0.2+0.x86_64-w64-mingw32.tar.gz/md5/e233f526a30b02d8d486918607af44d6 -libblastrampoline.v3.0.2+0.x86_64-w64-mingw32.tar.gz/sha512/25ca3feb99157f80dc45661319a2c5a00ea7943830905d7530a9053b89d47e4e4c4efbe7b374bf9b7e7c44774fc2b2061c4b2b7f09f6cc3e14aa1867039f15be +libblastrampoline.v3.0.4+0.aarch64-apple-darwin.tar.gz/md5/0ea485b558637933f039d8793b3aa6c6 +libblastrampoline.v3.0.4+0.aarch64-apple-darwin.tar.gz/sha512/bc7d4edd90f0f01cbc23cdce38bf3fa550ce988790fc63d8c84951b884465cc4f2d591d91a119e5cf8ce6b3161da6e09dc3689d52b4e71175be0d21afba00319 +libblastrampoline.v3.0.4+0.aarch64-linux-gnu.tar.gz/md5/a175724976338ad493b200194687f63a +libblastrampoline.v3.0.4+0.aarch64-linux-gnu.tar.gz/sha512/30164779760514f0395daad24e9c4c457b1428f9532a47c1d5cc64c5843f3c392505825c70fdd6f0953c4b064b1a9fdb0834d4901b88244f1b31b49cb9baacdf +libblastrampoline.v3.0.4+0.aarch64-linux-musl.tar.gz/md5/f73b62096c9b3a128749179be29e2503 +libblastrampoline.v3.0.4+0.aarch64-linux-musl.tar.gz/sha512/7cb42503ad8d7103c1187e8ee163324cf28c54b38dde535f7ca5e1ef7c29be187a11d10cc451baebf74327d48010bb6b6638fcf5c31418f47f853bbea2d8b7f6 +libblastrampoline.v3.0.4+0.armv6l-linux-gnueabihf.tar.gz/md5/436323431e54429f35128f6f404771bf +libblastrampoline.v3.0.4+0.armv6l-linux-gnueabihf.tar.gz/sha512/760a5c35c17c70f5ae0d8cb543a982435f999662382d78070cc2b16f11000ed03e5de60944da67f959ef978f35bb033981a0a65460dddfd0f9bc146ff34e4e87 +libblastrampoline.v3.0.4+0.armv6l-linux-musleabihf.tar.gz/md5/370ba82c807bb041d7f015b4f5ee8c48 +libblastrampoline.v3.0.4+0.armv6l-linux-musleabihf.tar.gz/sha512/79be4403f2c3afd58103a6bb14bf42087f3c9b6737ece01d6abc339844d6b4b5f3e42ab6dd9d418e7f949cd2c1bbd8b934193763c1eb261298d9a0ce04c82019 +libblastrampoline.v3.0.4+0.armv7l-linux-gnueabihf.tar.gz/md5/3ea77545ee850be82d497753360671b7 +libblastrampoline.v3.0.4+0.armv7l-linux-gnueabihf.tar.gz/sha512/4dd1562f003c846fb84454ad2f6a0d6ae02d9662974d360d2d5ce6422a2c22d1f80e84ca500571cf391689d614c352288e1e4ef51392eb8438990a0ed96e66ae +libblastrampoline.v3.0.4+0.armv7l-linux-musleabihf.tar.gz/md5/b12cdf35ebe3eaa4c71db76be589d860 +libblastrampoline.v3.0.4+0.armv7l-linux-musleabihf.tar.gz/sha512/b389958b71c0e31d60c69492055c2fe3eb6cb1c2ae1e99c55fee7768dd1c40c07b8d25c6525fddb60806c4d98731a20f851c790ddb3c6030f16a82a9c89b3336 +libblastrampoline.v3.0.4+0.i686-linux-gnu.tar.gz/md5/078924f3c57310602aca1ac0063236ac +libblastrampoline.v3.0.4+0.i686-linux-gnu.tar.gz/sha512/7c37fff276943d32a7dfa9beb819569000ffb067b53a3dffa1752a9f40b29a10f87193ea5fb49d8fa3ac17a812a9c897c3fe8f89294e9aed1bac6bb3cf87eaac +libblastrampoline.v3.0.4+0.i686-linux-musl.tar.gz/md5/eb7c4a8454e9e5bdf84d8ce36dc6c6ed +libblastrampoline.v3.0.4+0.i686-linux-musl.tar.gz/sha512/01580512c9d7827ac0218ca43a546e595da0c2588b0dd60a7538b7c3e91ffce9aba3572eb5b682caa6f159b3453954169fc3a17f440a5a3057ad31c8094105f3 +libblastrampoline.v3.0.4+0.i686-w64-mingw32.tar.gz/md5/ce9c539cd80f4ed80a76fdff81a5d8ee +libblastrampoline.v3.0.4+0.i686-w64-mingw32.tar.gz/sha512/0fb5452b3ee1d9a78f74ad5a95bca1049b903f37eb6b64f47479592d87a24e2b12d1838a7f2c5b3cede7d5e4c5d76f599cf47cfc7559f7ef01ba34acbf60a832 +libblastrampoline.v3.0.4+0.powerpc64le-linux-gnu.tar.gz/md5/10239f0598e486969d882001c458a148 +libblastrampoline.v3.0.4+0.powerpc64le-linux-gnu.tar.gz/sha512/85bf61041c7c1e7efa6405c16892dac342a88f94a3c8a03696044ddf32a65e94217bfa09165cf532f2adbea3c8ee9ed3ecdf7401d5d3d4a886c29879fb6c4116 +libblastrampoline.v3.0.4+0.x86_64-apple-darwin.tar.gz/md5/a6dec79d2442617c03a32b69a2a5b1bf +libblastrampoline.v3.0.4+0.x86_64-apple-darwin.tar.gz/sha512/493b522b86568b82e3011518bdfd234d3a1f04fecd687f2a44d3a6037ff00d45e122d700ad41b434c3aeab2f9668f04afcc999236958e137fe1ab8660187a719 +libblastrampoline.v3.0.4+0.x86_64-linux-gnu.tar.gz/md5/69fa36c363904e71dc7bd5c08a63c0a8 +libblastrampoline.v3.0.4+0.x86_64-linux-gnu.tar.gz/sha512/c5563205653fc2d8c3efbf1449d3777a202e902f611febf5d8973a8b6247e6229cb9e3c30d9dd84d0bcafaa0ea9b85f433d6b0806e1e755c8ec3ba51e2efa125 +libblastrampoline.v3.0.4+0.x86_64-linux-musl.tar.gz/md5/32f12ef8e1ad8b8ed4338bb5666c10ae +libblastrampoline.v3.0.4+0.x86_64-linux-musl.tar.gz/sha512/dce53f14bbcab1fd4c1836308b13fc38de6043f62fe74fcada894a725efad520153375bebdea8a48b8ae9edfb813c2f03ec194361f4556e6ed51238fbe8919ae +libblastrampoline.v3.0.4+0.x86_64-unknown-freebsd.tar.gz/md5/75dfdd1264f58b8ef43021bdd0ff6656 +libblastrampoline.v3.0.4+0.x86_64-unknown-freebsd.tar.gz/sha512/9a14a89c82a93e23dbbf226cfe58bca2847a3eb66a9e2f552dc1598d721b837ed8ce3f9bc617266591872169dcd3728ff7ab251882de4230d6ce00c6f791c821 +libblastrampoline.v3.0.4+0.x86_64-w64-mingw32.tar.gz/md5/3bf231ab990147d315ed6c243e35135b +libblastrampoline.v3.0.4+0.x86_64-w64-mingw32.tar.gz/sha512/9ae053f60060dccf78c2d77716d0dc8d6720799e2d92410e0de1412c1c7ddaf8523405994a9f0949c795da2d68f85056e851e17f3fd0a2f2aa4dc0be32f9caf7 From c87d85feaf547f763c5dee64c1be163b02df210d Mon Sep 17 00:00:00 2001 From: Logan Kilpatrick <23kilpatrick23@gmail.com> Date: Sat, 10 Apr 2021 10:58:39 -0700 Subject: [PATCH 158/439] Update contributing guide with new video links (#40426) * Update contributing guide with new links * Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbca229de0d45..83d9bdd48f3a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ If you are already familiar with Julia itself, this blog post by Katharine Hyatt ## Learning Julia -[The learning page](https://julialang.org/learning) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](https://docs.julialang.org) covers the language and core library features, and is searchable. +[The learning page](https://julialang.org/learning) has a great list of resources for new and experienced users alike. ## Before filing an issue From 5b7f4c5bc98f101fd4b38f61e9cbcaf41dd46a6c Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 11 Apr 2021 01:42:03 -0400 Subject: [PATCH 159/439] Fix eigvals(:::SymTridagonal) with longer off-diagonal vector (#40165) * Fix eigvals(:::SymTridagonal) with longer off-diagonal vector * Update tridiag.jl * Update lapack.jl * Revert "Update lapack.jl" This reverts commit 5c4047689c42a6fb4292aa3e6ceff3506e770142. * Update lapack.jl --- stdlib/LinearAlgebra/src/lapack.jl | 4 ++-- stdlib/LinearAlgebra/test/lapack.jl | 2 +- stdlib/LinearAlgebra/test/tridiag.jl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index e0d86c67de31e..0dd1f86db5459 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -3775,8 +3775,8 @@ for (stev, stebz, stegr, stein, elty) in require_one_based_indexing(dv, ev) chkstride1(dv, ev) n = length(dv) - if length(ev) != n - 1 - throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) + if length(ev) != n - 1 && length(ev) != n + throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than or equal to dv's length, $n)")) end Zmat = similar(dv, $elty, (n, job != 'N' ? n : 0)) work = Vector{$elty}(undef, max(1, 2n-2)) diff --git a/stdlib/LinearAlgebra/test/lapack.jl b/stdlib/LinearAlgebra/test/lapack.jl index ccf8cf980f1c1..c8e2c82e97150 100644 --- a/stdlib/LinearAlgebra/test/lapack.jl +++ b/stdlib/LinearAlgebra/test/lapack.jl @@ -407,7 +407,7 @@ end @testset for elty in (Float32, Float64) d = rand(elty,10) e = rand(elty,9) - @test_throws DimensionMismatch LAPACK.stev!('U',d,rand(elty,10)) + @test_throws DimensionMismatch LAPACK.stev!('U',d,rand(elty,11)) @test_throws DimensionMismatch LAPACK.stebz!('A','B',zero(elty),zero(elty),0,0,-1.,d,rand(elty,10)) @test_throws DimensionMismatch LAPACK.stegr!('N','A',d,rand(elty,11),zero(elty),zero(elty),0,0) @test_throws DimensionMismatch LAPACK.stein!(d,zeros(elty,10),zeros(elty,10),zeros(BlasInt,10),zeros(BlasInt,10)) diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index ec777bcd46222..e310766b2a66c 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -589,7 +589,7 @@ end A2 = SymTridiagonal(fill(1.0, 3), fill(-1.0, 2)) F2 = eigen(A2) test_approx_eq_modphase(F.vectors, F2.vectors) - @test F.values ≈ F2.values + @test F.values ≈ F2.values ≈ eigvals(A) ≈ eigvals(A2) end @testset "non-commutative algebra (#39701)" begin From 684425998e8334ba3267fdce39d6456dfead9174 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Sun, 11 Apr 2021 13:52:37 +0200 Subject: [PATCH 160/439] Preserve Hessenberg shape when possible (#40039) * Preserve Hessenberg shape when possible * Remove obsolete comments * Add NEWS * Support for unitful Hessenberg matrices * Mark some tests for unitful matrices as broken --- NEWS.md | 1 + stdlib/LinearAlgebra/src/hessenberg.jl | 91 +++++++++++++++++++++++-- stdlib/LinearAlgebra/test/hessenberg.jl | 52 ++++++++++++++ test/testhelpers/Furlongs.jl | 1 + 4 files changed, 139 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0b493a9e8f1c7..0a560a9643ce3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -93,6 +93,7 @@ Standard library changes * On aarch64, OpenBLAS now uses an ILP64 BLAS like all other 64-bit platforms. ([#39436]) * OpenBLAS is updated to 0.3.13. ([#39216]) * SuiteSparse is updated to 5.8.1. ([#39455]) +* The shape of an `UpperHessenberg` matrix is preserved under certain arithmetic operations, e.g. when multiplying or dividing by an `UpperTriangular` matrix. ([#40039]) * `cis(A)` now supports matrix arguments ([#40194]). #### Markdown diff --git a/stdlib/LinearAlgebra/src/hessenberg.jl b/stdlib/LinearAlgebra/src/hessenberg.jl index b284b4f940085..ffd12f39eafe2 100644 --- a/stdlib/LinearAlgebra/src/hessenberg.jl +++ b/stdlib/LinearAlgebra/src/hessenberg.jl @@ -94,17 +94,96 @@ Base.copy(A::Transpose{<:Any,<:UpperHessenberg}) = tril!(transpose!(similar(A.pa rmul!(H::UpperHessenberg, x::Number) = (rmul!(H.data, x); H) lmul!(x::Number, H::UpperHessenberg) = (lmul!(x, H.data); H) -# (future: we could also have specialized routines for UpperHessenberg * UpperTriangular) - fillstored!(H::UpperHessenberg, x) = (fillband!(H.data, x, -1, size(H,2)-1); H) +(A::UpperHessenberg, B::UpperHessenberg) = UpperHessenberg(A.data+B.data) -(A::UpperHessenberg, B::UpperHessenberg) = UpperHessenberg(A.data-B.data) -# (future: we could also have specialized routines for UpperHessenberg ± UpperTriangular) -# shift Hessenberg by λI -+(H::UpperHessenberg, J::UniformScaling) = UpperHessenberg(H.data + J) --(J::UniformScaling, H::UpperHessenberg) = UpperHessenberg(J - H.data) +for T = (:UniformScaling, :Diagonal, :Bidiagonal, :Tridiagonal, :SymTridiagonal, + :UpperTriangular, :UnitUpperTriangular) + for op = (:+, :-) + @eval begin + $op(H::UpperHessenberg, x::$T) = UpperHessenberg($op(H.data, x)) + $op(x::$T, H::UpperHessenberg) = UpperHessenberg($op(x, H.data)) + end + end +end + +for T = (:Number, :UniformScaling, :Diagonal) + @eval begin + *(H::UpperHessenberg, x::$T) = UpperHessenberg(H.data * x) + *(x::$T, H::UpperHessenberg) = UpperHessenberg(x * H.data) + /(H::UpperHessenberg, x::$T) = UpperHessenberg(H.data / x) + \(x::$T, H::UpperHessenberg) = UpperHessenberg(x \ H.data) + end +end + +function *(H::UpperHessenberg, U::UpperOrUnitUpperTriangular) + T = typeof(oneunit(eltype(H))*oneunit(eltype(U))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + rmul!(HH, U) + UpperHessenberg(HH) +end +function *(U::UpperOrUnitUpperTriangular, H::UpperHessenberg) + T = typeof(oneunit(eltype(H))*oneunit(eltype(U))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + lmul!(U, HH) + UpperHessenberg(HH) +end + +function /(H::UpperHessenberg, U::UpperTriangular) + T = typeof(oneunit(eltype(H))/oneunit(eltype(U))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + rdiv!(HH, U) + UpperHessenberg(HH) +end +function /(H::UpperHessenberg, U::UnitUpperTriangular) + T = typeof(oneunit(eltype(H))/oneunit(eltype(U))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + rdiv!(HH, U) + UpperHessenberg(HH) +end + +function \(U::UpperTriangular, H::UpperHessenberg) + T = typeof(oneunit(eltype(U))\oneunit(eltype(H))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + ldiv!(U, HH) + UpperHessenberg(HH) +end +function \(U::UnitUpperTriangular, H::UpperHessenberg) + T = typeof(oneunit(eltype(U))\oneunit(eltype(H))) + HH = similar(H.data, T, size(H)) + copyto!(HH, H) + ldiv!(U, HH) + UpperHessenberg(HH) +end + +function *(H::UpperHessenberg, B::Bidiagonal) + TS = promote_op(matprod, eltype(H), eltype(B)) + if B.uplo == 'U' + A_mul_B_td!(UpperHessenberg(zeros(TS, size(H)...)), H, B) + else + A_mul_B_td!(zeros(TS, size(H)...), H, B) + end +end +function *(B::Bidiagonal, H::UpperHessenberg) + TS = promote_op(matprod, eltype(B), eltype(H)) + if B.uplo == 'U' + A_mul_B_td!(UpperHessenberg(zeros(TS, size(B)...)), B, H) + else + A_mul_B_td!(zeros(TS, size(B)...), B, H) + end +end + +function /(H::UpperHessenberg, B::Bidiagonal) + A = Base.@invoke /(H::AbstractMatrix, B::Bidiagonal) + B.uplo == 'U' ? UpperHessenberg(A) : A +end # Solving (H+µI)x = b: we can do this in O(m²) time and O(m) memory # (in-place in x) by the RQ algorithm from: diff --git a/stdlib/LinearAlgebra/test/hessenberg.jl b/stdlib/LinearAlgebra/test/hessenberg.jl index 62cafecb57609..dd6a131a6ae1e 100644 --- a/stdlib/LinearAlgebra/test/hessenberg.jl +++ b/stdlib/LinearAlgebra/test/hessenberg.jl @@ -4,6 +4,10 @@ module TestHessenberg using Test, LinearAlgebra, Random +const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") +isdefined(Main, :Furlongs) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "Furlongs.jl")) +using .Main.Furlongs + # for tuple tests below ≅(x,y) = all(p -> p[1] ≈ p[2], zip(x,y)) @@ -55,6 +59,54 @@ let n = 10 H = UpperHessenberg(Areal) @test Array(Hc + H) == Array(Hc) + Array(H) @test Array(Hc - H) == Array(Hc) - Array(H) + @testset "Preserve UpperHessenberg shape (issue #39388)" begin + for H = (UpperHessenberg(Areal), UpperHessenberg(Furlong.(Areal))) + if eltype(H) <: Furlong + A = Furlong.(rand(n,n)) + d = Furlong.(rand(n)) + dl = Furlong.(rand(n-1)) + du = Furlong.(rand(n-1)) + us = Furlong(1)*I + else + A = rand(n,n) + d = rand(n) + dl = rand(n-1) + du = rand(n-1) + us = 1*I + end + @testset "$op" for op = (+,-) + for x = (us, Diagonal(d), Bidiagonal(d,dl,:U), Bidiagonal(d,dl,:L), + Tridiagonal(dl,d,du), SymTridiagonal(d,dl), + UpperTriangular(A), UnitUpperTriangular(A)) + @test op(H,x) == op(Array(H),x) + @test op(x,H) == op(x,Array(H)) + @test op(H,x) isa UpperHessenberg + @test op(x,H) isa UpperHessenberg + end + end + A = randn(n,n) + d = randn(n) + dl = randn(n-1) + @testset "Multiplication/division" begin + for x = (5, 5I, Diagonal(d), Bidiagonal(d,dl,:U), + UpperTriangular(A), UnitUpperTriangular(A)) + @test H*x == Array(H)*x broken = eltype(H) <: Furlong && x isa Bidiagonal + @test x*H == x*Array(H) broken = eltype(H) <: Furlong && x isa Bidiagonal + @test H/x == Array(H)/x broken = eltype(H) <: Furlong && x isa Union{Bidiagonal, Diagonal, UpperTriangular} + @test x\H == x\Array(H) broken = eltype(H) <: Furlong && x isa Union{Bidiagonal, Diagonal, UpperTriangular} + @test H*x isa UpperHessenberg broken = eltype(H) <: Furlong && x isa Bidiagonal + @test x*H isa UpperHessenberg broken = eltype(H) <: Furlong && x isa Bidiagonal + @test H/x isa UpperHessenberg broken = eltype(H) <: Furlong && x isa Union{Bidiagonal, Diagonal} + @test x\H isa UpperHessenberg broken = eltype(H) <: Furlong && x isa Union{Bidiagonal, Diagonal} + end + x = Bidiagonal(d, dl, :L) + @test H*x == Array(H)*x + @test x*H == x*Array(H) + @test H/x == Array(H)/x broken = eltype(H) <: Furlong + @test_broken x\H == x\Array(H) # issue 40037 + end + end + end end @testset for eltya in (Float32, Float64, ComplexF32, ComplexF64, Int), herm in (false, true) diff --git a/test/testhelpers/Furlongs.jl b/test/testhelpers/Furlongs.jl index 8abe583925d93..73d23a39d2d7b 100644 --- a/test/testhelpers/Furlongs.jl +++ b/test/testhelpers/Furlongs.jl @@ -36,6 +36,7 @@ Base.floatmin(::Type{Furlong{p,T}}) where {p,T<:AbstractFloat} = Furlong{p}(floa Base.floatmin(::Furlong{p,T}) where {p,T<:AbstractFloat} = floatmin(Furlong{p,T}) Base.floatmax(::Type{Furlong{p,T}}) where {p,T<:AbstractFloat} = Furlong{p}(floatmax(T)) Base.floatmax(::Furlong{p,T}) where {p,T<:AbstractFloat} = floatmax(Furlong{p,T}) +Base.conj(x::Furlong{p,T}) where {p,T} = Furlong{p,T}(conj(x.val)) # convert Furlong exponent p to a canonical form. This # is not type stable, but it doesn't matter since it is used From d29126a43ee289fc5ab8fcb3dc0e03f514605950 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Sun, 11 Apr 2021 20:54:40 +0900 Subject: [PATCH 161/439] doc: fix typo in io.jl (#40433) --- base/strings/io.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 6003a6d503b90..f80479dd79f90 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -540,7 +540,7 @@ macro raw_str(s); s; end Escape a string in the manner used for parsing raw string literals. For each double-quote (`"`) character in input string `s`, this -function counts the number _n_ of preceeding backslash (`\\`) characters, +function counts the number _n_ of preceding backslash (`\\`) characters, and then increases there the number of backslashes from _n_ to 2_n_+1 (even for _n_ = 0). It also doubles a sequence of backslashes at the end of the string. From 0a6ea9f5a6eefa2c144dab7453c3a28f01507282 Mon Sep 17 00:00:00 2001 From: jz2903 <33365321+jz2903@users.noreply.github.com> Date: Sun, 11 Apr 2021 23:08:45 +0800 Subject: [PATCH 162/439] fix some typos (#40434) Fix typos in comments --- base/binaryplatforms.jl | 2 +- base/compiler/methodtable.jl | 2 +- base/compiler/ssair/domtree.jl | 2 +- base/compiler/ssair/inlining.jl | 2 +- base/compiler/ssair/show.jl | 4 ++-- base/compiler/typelattice.jl | 2 +- base/show.jl | 2 +- base/toml_parser.jl | 2 +- contrib/add_license_to_files.jl | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 8c9c6768090e0..aff1de4a80993 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -141,7 +141,7 @@ function Base.setindex!(p::AbstractPlatform, v::String, k::String) return p end -# Hash definitino to ensure that it's stable +# Hash definition to ensure that it's stable function Base.hash(p::Platform, h::UInt) h += 0x506c6174666f726d % UInt h = hash(p.tags, h) diff --git a/base/compiler/methodtable.jl b/base/compiler/methodtable.jl index 1a0b4076f3ed9..cff9e21fccb41 100644 --- a/base/compiler/methodtable.jl +++ b/base/compiler/methodtable.jl @@ -47,7 +47,7 @@ CachedMethodTable(table::T) where T = Find all methods in the given method table `view` that are applicable to the given signature `sig`. If no applicable methods are found, an empty result is -returned. If the number of applicable methods exeeded the specified limit, +returned. If the number of applicable methods exceeded the specified limit, `missing` is returned. """ function findall(@nospecialize(sig::Type{<:Tuple}), table::InternalMethodTable; limit::Int=typemax(Int)) diff --git a/base/compiler/ssair/domtree.jl b/base/compiler/ssair/domtree.jl index 1ab2876b769da..c2f056a0c027b 100644 --- a/base/compiler/ssair/domtree.jl +++ b/base/compiler/ssair/domtree.jl @@ -244,7 +244,7 @@ function update_level!(nodes::Vector{DomTreeNode}, node::BBNumber, level::Int) end """ -The main Semi-NCA algrithm. Matches Figure 2.8 in [LG05]. Note that the +The main Semi-NCA algorithm. Matches Figure 2.8 in [LG05]. Note that the pseudocode in [LG05] is not entirely accurate. The best way to understand what's happening is to read [LT79], then the description of SLT in [LG05] (warning: inconsistent notation), then the description of Semi-NCA. diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index f95ff55b75e84..c07e2b8365d51 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -103,7 +103,7 @@ function CFGInliningState(ir::IRCode) end # Tells the inliner that we're now inlining into block `block`, meaning -# all previous blocks have been proceesed and can be added to the new cfg +# all previous blocks have been processed and can be added to the new cfg function inline_into_block!(state::CFGInliningState, block::Int) if state.first_bb != block new_range = state.first_bb+1:block diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 1f822ee687214..64477354ffc9d 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -192,7 +192,7 @@ example (taken from `@code_typed sin(1.0)`): ``` The three annotations are indicated with `*`. The first one is the line number of the -active function (printed once whenver the outer most line number changes). The second +active function (printed once whenever the outer most line number changes). The second is the inlining indicator. The number of lines indicate the level of nesting, with a half-size line (╷) indicating the start of a scope and a full size line (│) indicating a continuing scope. The last annotation is the most complicated one. It is a heuristic @@ -201,7 +201,7 @@ scope that hasn't been printed before. Let's work a number of examples to see th and tradeoffs involved. ``` -f() = leaf_function() # Delibarately not defined to end up in the IR verbatim +f() = leaf_function() # Deliberately not defined to end up in the IR verbatim g() = f() h() = g() top_function() = h() diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index e2668e15c9e2c..0f3dd7b4a84ed 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -19,7 +19,7 @@ import Core: Const, PartialStruct # The type of this value might be Bool. -# However, to enable a limited amount of back-propagagation, +# However, to enable a limited amount of back-propagation, # we also keep some information about how this Bool value was created. # In particular, if you branch on this value, then may assume that in # the true branch, the type of `var` will be limited by `vtype` and in diff --git a/base/show.jl b/base/show.jl index 4ff7d6916f0de..c98637a026112 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1264,7 +1264,7 @@ const ExprNode = Union{Expr, QuoteNode, Slot, LineNumberNode, SSAValue, # IOContext(io, :unquote_fallback => false) tells show_unquoted to treat any # Expr whose head is :$ as if it is inside a quote, preventing fallback to the # "unhandled" case: this is used by print/string to be lawful to Rule 1 above. -# On the countrary, show/repr have to follow Rule 2, requiring any Expr whose +# On the contrary, show/repr have to follow Rule 2, requiring any Expr whose # head is :$ and which is not inside a quote to fallback to the "unhandled" case: # this is behavior is triggered by IOContext(io, :unquote_fallback => true) print( io::IO, ex::ExprNode) = (show_unquoted(IOContext(io, :unquote_fallback => false), ex, 0, -1); nothing) diff --git a/base/toml_parser.jl b/base/toml_parser.jl index 916a93fdf0d22..041211a72e869 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -751,7 +751,7 @@ isvalid_binary(c::Char) = '0' <= c <= '1' const ValidSigs = Union{typeof.([isvalid_hex, isvalid_oct, isvalid_binary, isdigit])...} # This function eats things accepted by `f` but also allows eating `_` in between -# digits. Retruns if it ate at lest one character and if it ate an underscore +# digits. Returns if it ate at lest one character and if it ate an underscore function accept_batch_underscore(l::Parser, f::ValidSigs, fail_if_underscore=true)::Err{Tuple{Bool, Bool}} contains_underscore = false at_least_one = false diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index eecca7dc3f464..c5aa0f49d99d3 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -20,7 +20,7 @@ const rootdirs = [ "../stdlib", ] -# to exculde whole sub directories +# to exclude whole sub directories const excludedirs = [ # see: https://github.com/JuliaLang/julia/pull/11073#issuecomment-98090053 "../base/ryu", From 8fc38a4d57e465b6dfb9479fe665c1d2e1d1308d Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sun, 11 Apr 2021 17:18:58 +0000 Subject: [PATCH 163/439] [automated] Bump the Pkg stdlib from 74098fe7 to 879c21d9 (#40422) --- .../Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 | 1 - .../Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 | 1 - .../Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 | 1 + .../Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 create mode 100644 deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 diff --git a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 deleted file mode 100644 index ab9c27e3272bc..0000000000000 --- a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ae890308e62884dac6aaa69ba45ec1a1 diff --git a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 b/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 deleted file mode 100644 index b3959f1dd6a87..0000000000000 --- a/deps/checksums/Pkg-74098fe713066b8d6e4d8159c80a305b7a8fd408.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -2517ad47694a55eb009fde46b4d7bf70c82a2ace15145f61b6fd925c4ce34ead336f8c1be8edf872b89c6a43cdfdd90ea2c3a54a87f9beba1aa7cefa5f3b59dd diff --git a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 new file mode 100644 index 0000000000000..ac19c43317da9 --- /dev/null +++ b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 @@ -0,0 +1 @@ +c529f61ceca38c5acf28e5ba57bd8b4d diff --git a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 new file mode 100644 index 0000000000000..3d042f16d8793 --- /dev/null +++ b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 @@ -0,0 +1 @@ +921e9dc6d422d90f722d6145182c0bccc2cf9be4653b1ed37084baf569a1f4d534fd78a50d3f0a9350ad5e7f0e49f1b3a32acb543749b8230a713688a8000bbf diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 33ecf13468d35..3f85f57b2a693 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 74098fe713066b8d6e4d8159c80a305b7a8fd408 +PKG_SHA1 = 879c21d938d3d898539903bb3e381ef8cee21f1d From c3c8ffa8d4e7b1c91106952dfe1965a278ba4610 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 11 Apr 2021 16:39:33 -0400 Subject: [PATCH 164/439] fix #32843, codegen attempting `typeof(NULL)` for some union tags (#40365) also fixes part of #40065 --- src/cgutils.cpp | 30 +++++++++++++++++++++++++++--- src/codegen.cpp | 6 ++++-- test/compiler/codegen.jl | 8 ++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index bb0e15ed7363c..58bfb958a917c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2472,6 +2472,27 @@ static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype, jl_value_t return tindex; } +// Returns typeof(v), or null if v is a null pointer at run time. +// This is used when the value might have come from an undefined variable, +// yet we try to read its type to compute a union index when moving the value. +static Value *emit_typeof_or_null(jl_codectx_t &ctx, Value *v) +{ + BasicBlock *nonnull = BasicBlock::Create(jl_LLVMContext, "nonnull", ctx.f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "postnull", ctx.f); + Value *isnull = ctx.builder.CreateICmpEQ(v, Constant::getNullValue(v->getType())); + ctx.builder.CreateCondBr(isnull, postBB, nonnull); + BasicBlock *entry = ctx.builder.GetInsertBlock(); + ctx.builder.SetInsertPoint(nonnull); + Value *typof = emit_typeof(ctx, v); + ctx.builder.CreateBr(postBB); + nonnull = ctx.builder.GetInsertBlock(); // could have changed + ctx.builder.SetInsertPoint(postBB); + PHINode *ti = ctx.builder.CreatePHI(typof->getType(), 2); + ti->addIncoming(Constant::getNullValue(typof->getType()), entry); + ti->addIncoming(typof, nonnull); + return ti; +} + // get the runtime tindex value, assuming val is already converted to type typ if it has a TIndex static Value *compute_tindex_unboxed(jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ) { @@ -2482,9 +2503,12 @@ static Value *compute_tindex_unboxed(jl_codectx_t &ctx, const jl_cgval_t &val, j if (val.TIndex) return ctx.builder.CreateAnd(val.TIndex, ConstantInt::get(T_int8, 0x7f)); - if (val.isboxed) - return compute_box_tindex(ctx, emit_typeof_boxed(ctx, val), val.typ, typ); - return compute_box_tindex(ctx, emit_typeof_boxed(ctx, val), val.typ, typ); + Value *typof; + if (val.isboxed && !jl_is_concrete_type(val.typ) && !jl_is_type_type(val.typ)) + typof = emit_typeof_or_null(ctx, val.V); + else + typof = emit_typeof_boxed(ctx, val); + return compute_box_tindex(ctx, typof, val.typ, typ); } static void union_alloca_type(jl_uniontype_t *ut, diff --git a/src/codegen.cpp b/src/codegen.cpp index b3acb943b3150..4be8510adcbea 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1504,11 +1504,13 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & // actually need it. Value *union_box_dt = NULL; BasicBlock *union_isaBB = NULL; + BasicBlock *post_union_isaBB = NULL; auto maybe_setup_union_isa = [&]() { if (!union_isaBB) { union_isaBB = BasicBlock::Create(jl_LLVMContext, "union_isa", ctx.f); ctx.builder.SetInsertPoint(union_isaBB); - union_box_dt = emit_typeof(ctx, v.Vboxed); + union_box_dt = emit_typeof_or_null(ctx, v.Vboxed); + post_union_isaBB = ctx.builder.GetInsertBlock(); } }; @@ -1540,7 +1542,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & ctx.builder.SetInsertPoint(postBB); PHINode *tindex_phi = ctx.builder.CreatePHI(T_int8, 2); tindex_phi->addIncoming(new_tindex, currBB); - tindex_phi->addIncoming(union_box_tindex, union_isaBB); + tindex_phi->addIncoming(union_box_tindex, post_union_isaBB); new_tindex = tindex_phi; } } diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 47f419d9937a2..97a9d45d7ecf3 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -553,3 +553,11 @@ end end @test occursin("llvm.julia.gc_preserve_begin", get_llvm(f4, Tuple{Bool}, true, false, false)) end + +# issue #32843 +function f32843(vals0, v) + (length(vals0) > 1) && (vals = v[1]) + (length(vals0) == 1 && vals0[1]==1) && (vals = 1:2) + vals +end +@test_throws UndefVarError f32843([6], Vector[[1]]) From c649ebb50c1c40d36472c37893564ad151c60271 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 12 Apr 2021 14:36:46 -0400 Subject: [PATCH 165/439] fix #39982, reduce cursor artifacts in REPL after #39538 (#40411) --- stdlib/REPL/src/LineEdit.jl | 8 ++++++-- stdlib/REPL/src/options.jl | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index a8a1f5ef03912..c80273e2d6ca0 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -790,10 +790,12 @@ function edit_insert(s::PromptState, c::StringLike) offset = s.ias.curs_row == 1 || s.indent < 0 ? sizeof(prompt_string(s.p.prompt)::String) : s.indent offset += position(buf) - beginofline(buf) # size of current line + spinner = true if offset + textwidth(str) <= w # Avoid full update when appending characters to the end # and an update of curs_row isn't necessary (conservatively estimated) write(termbuf, str) + spinner = false elseif after == 0 refresh_line(s) delayup = false @@ -801,8 +803,10 @@ function edit_insert(s::PromptState, c::StringLike) delayup = true end if delayup - write(termbuf, spin_seq[mod1(position(buf) - w, length(spin_seq))]) - cmove_left(termbuf) + if spinner + write(termbuf, spin_seq[mod1(position(buf) - w, length(spin_seq))]) + cmove_left(termbuf) + end s.refresh_wait = Timer(after) do t s.refresh_wait === t || return s.refresh_wait = nothing diff --git a/stdlib/REPL/src/options.jl b/stdlib/REPL/src/options.jl index 09e3f4265fabe..3ce0ab6ff00dc 100644 --- a/stdlib/REPL/src/options.jl +++ b/stdlib/REPL/src/options.jl @@ -46,7 +46,7 @@ Options(; auto_indent_tmp_off = false, auto_indent_bracketed_paste = false, auto_indent_time_threshold = 0.005, - auto_refresh_time_delay = 0.05, + auto_refresh_time_delay = Sys.iswindows() ? 0.05 : 0.0, iocontext = Dict{Symbol,Any}()) = Options(hascolor, extra_keymap, tabwidth, kill_ring_max, region_animation_duration, From 011d6f05709a8dffc6c929e65c5fae80f77b564f Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Mon, 12 Apr 2021 21:06:11 +0200 Subject: [PATCH 166/439] fix verbose IRCode printing with long file names (#40437) --- base/compiler/ssair/show.jl | 4 +++- test/show.jl | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 64477354ffc9d..3137571081536 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -721,7 +721,9 @@ function ircode_verbose_linfo_printer(code::IRCode, used::BitSet) print(io, indent) ssa_guard = " "^(maxlength_idx + 4 + i) entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) " - hline = string("─"^(start_column-length(entry_label)-length(_strip_color(indent))+max_depth-i), "┐") + width_hline = start_column - length(entry_label) - length(_strip_color(indent)) + max_depth - i + width_hline = max(width_hline, 0) # don't error on overlong method/file names + hline = string("─"^width_hline, "┐") printstyled(io, string(entry_label, hline), "\n"; color=:light_black) end end diff --git a/test/show.jl b/test/show.jl index ff007ec63be23..8e022f581bf06 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1904,7 +1904,7 @@ h_line() = f_line() @test sprint(Base.show_unquoted, Core.Compiler.Argument(-2)) == "_-2" -eval(Meta.parse("""function my_fun28173(x) +eval(Meta._parse_string("""function my_fun28173(x) y = if x == 1 "HI" elseif x == 2 @@ -1921,7 +1921,7 @@ eval(Meta.parse("""function my_fun28173(x) "three" end return y -end""")) # use parse to control the line numbers +end""", "a"^80, 1, :statement)[1]) # use parse to control the line numbers let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] ir = Core.Compiler.inflate_ir(src) fill!(src.codelocs, 0) # IRCode printing is only capable of printing partial line info @@ -1960,7 +1960,7 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] io = IOBuffer() Base.IRShow.show_ir(io, ir; verbose_linetable=true) seekstart(io) - @test count(contains(r"my_fun28173 at none:\d+"), eachline(io)) == 9 + @test count(contains(r"my_fun28173 at a{80}:\d+"), eachline(io)) == 9 end # Verify that extra instructions at the end of the IR From 53603f6b74b81807fb48e0bd5f7d65e4a708d49f Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 12 Apr 2021 19:24:42 -0400 Subject: [PATCH 167/439] Fix wine bootstrap (#40425) * Fix wine bootstrap Fixes #39124 Closes #39022 * fix cross-build, and other build issues * this should probably be part of spawn, if it is needed * Revert "this should probably be part of spawn, if it is needed" This reverts commit eb88a9cf06308a1edb27b15cf1dbb0aff8ae980a. Seems to be needed * fixup! fix cross-build, and other build issues Co-authored-by: Jameson Nash --- Make.inc | 23 +++++++++++++---------- Makefile | 3 ++- base/Makefile | 6 ------ base/env.jl | 2 +- cli/Makefile | 13 +++---------- cli/list_strip_symbols.h | 7 +++++++ src/Makefile | 6 ++++-- sysimage.mk | 8 +++++--- 8 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 cli/list_strip_symbols.h diff --git a/Make.inc b/Make.inc index a3718833fb706..207308b34b82a 100644 --- a/Make.inc +++ b/Make.inc @@ -587,6 +587,12 @@ endif #USEMSVC RANLIB := $(CROSS_COMPILE)ranlib OBJCOPY := $(CROSS_COMPILE)objcopy +ifneq ($(USEMSVC), 1) +CPP_STDOUT := $(CPP) -P +else +CPP_STDOUT := $(CPP) -E +endif + # file extensions ifeq ($(OS), WINNT) SHLIB_EXT := dll @@ -1024,22 +1030,18 @@ JCPPFLAGS+=-DSYSTEM_LLVM endif # SYSTEM_LLVM # Windows builds need a little help finding the LLVM libraries for llvm-config -LLVM_CONFIG_PATH_FIX := +# use delayed expansion (= not :=) because spawn isn't defined until later +# WINEPATH is only needed for a wine-based cross compile +LLVM_CONFIG_PATH_FIX = ifeq ($(OS),WINNT) -LLVM_CONFIG_PATH_FIX := PATH="$(build_bindir):$(PATH)" +LLVM_CONFIG_PATH_FIX = PATH="$(build_bindir):$(PATH)" WINEPATH="$(call cygpath_w,$(build_bindir));$(WINEPATH)" endif ifeq ($(BUILD_OS),$(OS)) -LLVM_CONFIG_HOST := $(LLVM_CONFIG) +LLVM_CONFIG_HOST = $(LLVM_CONFIG_PATH_FIX) $(LLVM_CONFIG) else LLVM_CONFIG_HOST := $(basename $(LLVM_CONFIG))-host$(BUILD_EXE) -ifeq (exists, $(shell [ -f '$(LLVM_CONFIG_HOST)' ] && echo exists )) -ifeq ($(shell $(LLVM_CONFIG_PATH_FIX) $(LLVM_CONFIG_HOST) --version),3.3) -# llvm-config-host <= 3.3 is broken, use llvm-config instead (in an emulator) -# use delayed expansion (= not :=) because spawn isn't defined until later -LLVM_CONFIG_HOST = $(LLVM_CONFIG_PATH_FIX) $(call spawn,$(LLVM_CONFIG)) -endif -else +ifneq (exists, $(shell [ -f '$(LLVM_CONFIG_HOST)' ] && echo exists )) # llvm-config-host does not exist (cmake build) LLVM_CONFIG_HOST = $(LLVM_CONFIG_PATH_FIX) $(call spawn,$(LLVM_CONFIG)) endif @@ -1570,6 +1572,7 @@ PRINT_FLISP = echo '$(subst ','\'',$(1))'; $(1) PRINT_JULIA = echo '$(subst ','\'',$(1))'; $(1) endif + # Makefile debugging trick: # call print-VARIABLE to see the runtime value of any variable # (hardened against any special characters appearing in the output) diff --git a/Makefile b/Makefile index f7bad6350c77e..d16cf2855087b 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,8 @@ $(build_depsbindir)/stringreplace: $(JULIAHOME)/contrib/stringreplace.c | $(buil @$(call PRINT_CC, $(HOSTCC) -o $(build_depsbindir)/stringreplace $(JULIAHOME)/contrib/stringreplace.c) julia-base-cache: julia-sysimg-$(JULIA_BUILD_MODE) | $(DIRS) $(build_datarootdir)/julia - @JULIA_BINDIR=$(call cygpath_w,$(build_bindir)) $(call spawn, $(JULIA_EXECUTABLE) --startup-file=no $(call cygpath_w,$(JULIAHOME)/etc/write_base_cache.jl) \ + @JULIA_BINDIR=$(call cygpath_w,$(build_bindir)) WINEPATH="$(call cygpath_w,$(build_bindir));$$WINEPATH" \ + $(call spawn, $(JULIA_EXECUTABLE) --startup-file=no $(call cygpath_w,$(JULIAHOME)/etc/write_base_cache.jl) \ $(call cygpath_w,$(build_datarootdir)/julia/base.cache)) # public libraries, that are installed in $(prefix)/lib diff --git a/base/Makefile b/base/Makefile index 2bef6aab7f1f4..5c6540331a880 100644 --- a/base/Makefile +++ b/base/Makefile @@ -6,12 +6,6 @@ include $(JULIAHOME)/Make.inc TAGGED_RELEASE_BANNER := "" -ifneq ($(USEMSVC), 1) -CPP_STDOUT := $(CPP) -P -else -CPP_STDOUT := $(CPP) -E -endif - all: $(addprefix $(BUILDDIR)/,pcre_h.jl errno_h.jl build_h.jl.phony features_h.jl file_constants.jl uv_constants.jl version_git.jl.phony) PCRE_CONST := 0x[0-9a-fA-F]+|[0-9]+|\([\-0-9]+\) diff --git a/base/env.jl b/base/env.jl index 63b2df9c9acc8..7d47a4de090a3 100644 --- a/base/env.jl +++ b/base/env.jl @@ -32,7 +32,7 @@ if Sys.iswindows() function _unsetenv(svar::AbstractString) var = cwstring(svar) ret = ccall(:SetEnvironmentVariableW,stdcall,Int32,(Ptr{UInt16},Ptr{UInt16}),var,C_NULL) - windowserror(:setenv, ret == 0) + windowserror(:setenv, ret == 0 && Libc.GetLastError() != ERROR_ENVVAR_NOT_FOUND) end else # !windows _getenv(var::AbstractString) = ccall(:getenv, Cstring, (Cstring,), var) diff --git a/cli/Makefile b/cli/Makefile index 03261c386d2d0..b998462db9a32 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -100,17 +100,10 @@ libjulia-debug: $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT) ifeq ($(OS),WINNT) # On Windows we need to strip out exported functions from the generated import library. -# On i686, there's an extra underscore at the beginning -ifeq ($(ARCH),i686) -ABI_UNDERSCORE := _\#\# -else -ABI_UNDERSCORE := -endif -EXPORTED_FUNCS := $(shell echo -e "#include \"jl_exported_funcs.inc\"\n#define XX(x) $(ABI_UNDERSCORE)x\nJL_EXPORTED_FUNCS(XX)" | $(CPP) -I$(JULIAHOME)/src - | tail -n 1) -STRIP_EXPORTED_FUNCS := $(patsubst %,--strip-symbol=%,$(EXPORTED_FUNCS)) +STRIP_EXPORTED_FUNCS := $(shell $(CPP_STDOUT) -I$(JULIAHOME)/src $(SRCDIR)/list_strip_symbols.h) endif -$(build_shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_OBJS) | $(build_shlibdir) $(build_libdir) +$(build_shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_OBJS) $(SRCDIR)/list_strip_symbols.h | $(build_shlibdir) $(build_libdir) @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -DLIBRARY_EXPORTS -shared $(SHIPFLAGS) $(LIB_OBJS) -o $@ \ $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(RPATH_LIB) $(call SONAME_FLAGS,libjulia.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia.$(SHLIB_EXT) $@ @@ -120,7 +113,7 @@ ifeq ($(OS), WINNT) @$(call PRINT_ANALYZE, $(OBJCOPY) $(build_libdir)/$(notdir $@).tmp.a $(STRIP_EXPORTED_FUNCS) $(build_libdir)/$(notdir $@).a && rm $(build_libdir)/$(notdir $@).tmp.a) endif -$(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_DOBJS) | $(build_shlibdir) $(build_libdir) +$(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_DOBJS) $(SRCDIR)/list_strip_symbols.h | $(build_shlibdir) $(build_libdir) @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -DLIBRARY_EXPORTS -shared $(DEBUGFLAGS) $(LIB_DOBJS) -o $@ \ $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(RPATH_LIB) $(call SONAME_FLAGS,libjulia-debug.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-debug.$(SHLIB_EXT) $@.tmp diff --git a/cli/list_strip_symbols.h b/cli/list_strip_symbols.h new file mode 100644 index 0000000000000..e1a96261fe05a --- /dev/null +++ b/cli/list_strip_symbols.h @@ -0,0 +1,7 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include "jl_exported_funcs.inc" +#include "trampolines/common.h" +#define XX(x) --strip-symbol=CNAME(x) +JL_EXPORTED_FUNCS(XX) +#undef XX diff --git a/src/Makefile b/src/Makefile index 6f2ee2960c7a2..89aa3fc44f49a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -140,11 +140,13 @@ DEBUGFLAGS += "-DJL_LIBJULIA_SONAME=\"libjulia-debug.$(JL_MAJOR_SHLIB_EXT)\"" "- ifeq ($(USE_CROSS_FLISP), 1) FLISPDIR := $(BUILDDIR)/flisp/host +FLISP_EXECUTABLE_debug := $(FLISPDIR)/flisp-debug$(BUILD_EXE) +FLISP_EXECUTABLE_release := $(FLISPDIR)/flisp$(BUILD_EXE) else FLISPDIR := $(BUILDDIR)/flisp +FLISP_EXECUTABLE_debug := $(FLISPDIR)/flisp-debug$(EXE) +FLISP_EXECUTABLE_release := $(FLISPDIR)/flisp$(EXE) endif -FLISP_EXECUTABLE_debug := $(FLISPDIR)/flisp-debug$(BUILD_EXE) -FLISP_EXECUTABLE_release := $(FLISPDIR)/flisp$(BUILD_EXE) ifeq ($(OS),WINNT) FLISP_EXECUTABLE := $(FLISP_EXECUTABLE_release) else diff --git a/sysimage.mk b/sysimage.mk index ebc991bdd40f0..de5c3e22f253a 100644 --- a/sysimage.mk +++ b/sysimage.mk @@ -65,7 +65,8 @@ $(build_private_libdir)/corecompiler.ji: $(COMPILER_SRCS) $(build_private_libdir)/sys.ji: $(build_private_libdir)/corecompiler.ji $(JULIAHOME)/VERSION $(BASE_SRCS) $(STDLIB_SRCS) @$(call PRINT_JULIA, cd $(JULIAHOME)/base && \ - if ! JULIA_BINDIR=$(call cygpath_w,$(build_bindir)) $(call spawn, $(JULIA_EXECUTABLE)) -g1 -O0 -C "$(JULIA_CPU_TARGET)" --output-ji $(call cygpath_w,$@).tmp $(JULIA_SYSIMG_BUILD_FLAGS) \ + if ! JULIA_BINDIR=$(call cygpath_w,$(build_bindir)) WINEPATH="$(call cygpath_w,$(build_bindir));$$WINEPATH" \ + $(call spawn, $(JULIA_EXECUTABLE)) -g1 -O0 -C "$(JULIA_CPU_TARGET)" --output-ji $(call cygpath_w,$@).tmp $(JULIA_SYSIMG_BUILD_FLAGS) \ --startup-file=no --warn-overwrite=yes --sysimage $(call cygpath_w,$<) sysimg.jl $(RELBUILDROOT); then \ echo '*** This error might be fixed by running `make clean`. If the error persists$(COMMA) try `make cleanall`. ***'; \ false; \ @@ -75,8 +76,9 @@ $(build_private_libdir)/sys.ji: $(build_private_libdir)/corecompiler.ji $(JULIAH define sysimg_builder $$(build_private_libdir)/sys$1-o.a $$(build_private_libdir)/sys$1-bc.a : $$(build_private_libdir)/sys$1-%.a : $$(build_private_libdir)/sys.ji @$$(call PRINT_JULIA, cd $$(JULIAHOME)/base && \ - if ! JULIA_BINDIR=$$(call cygpath_w,$(build_bindir)) $$(call spawn, $3) $2 -C "$$(JULIA_CPU_TARGET)" --output-$$* $$(call cygpath_w,$$@).tmp $$(JULIA_SYSIMG_BUILD_FLAGS) \ - --startup-file=no --warn-overwrite=yes --sysimage $$(call cygpath_w,$$<) $$(call cygpath_w,$$(JULIAHOME)/contrib/generate_precompile.jl) $(JULIA_PRECOMPILE); then \ + if ! JULIA_BINDIR=$$(call cygpath_w,$(build_bindir)) WINEPATH="$$(call cygpath_w,$$(build_bindir));$$$$WINEPATH" \ + $$(call spawn, $3) $2 -C "$$(JULIA_CPU_TARGET)" --output-$$* $$(call cygpath_w,$$@).tmp $$(JULIA_SYSIMG_BUILD_FLAGS) \ + --startup-file=no --warn-overwrite=yes --sysimage $$(call cygpath_w,$$<) $$(call cygpath_w,$$(JULIAHOME)/contrib/generate_precompile.jl) $(JULIA_PRECOMPILE); then \ echo '*** This error is usually fixed by running `make clean`. If the error persists$$(COMMA) try `make cleanall`. ***'; \ false; \ fi ) From 2646c43fb73a07abf80aaafef4a5956298d499e1 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 12 Apr 2021 20:36:04 -0400 Subject: [PATCH 168/439] Update `perf` docs `-k 1` must be passed for jit injection to work later. --- doc/src/manual/profile.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/profile.md b/doc/src/manual/profile.md index 8afadf959dbf1..b736c46f90282 100644 --- a/doc/src/manual/profile.md +++ b/doc/src/manual/profile.md @@ -341,7 +341,7 @@ For example with `OProfile` you can try a simple recording : Or similary with `perf` : ``` -$ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf ./julia /test/fastmath.jl +$ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf -k 1 ./julia /test/fastmath.jl $ perf inject --jit --input /tmp/perf.data --output /tmp/perf-jit.data $ perf report --call-graph -G -i /tmp/perf-jit.data ``` From 4a19b753804ed0b06fab9681309941862eaa7227 Mon Sep 17 00:00:00 2001 From: Jonas Schulze Date: Tue, 13 Apr 2021 10:31:47 +0200 Subject: [PATCH 169/439] Add vim bindings to TerminalMenus (#37940) * `k` to move up * `j` to move down * `` as an alternative to `` --- stdlib/REPL/src/TerminalMenus/AbstractMenu.jl | 6 +++--- stdlib/REPL/test/TerminalMenus/runtests.jl | 20 +++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl index f01df5c389324..ee5bd4d426795 100644 --- a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl +++ b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl @@ -203,9 +203,9 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio lastoption = numoptions(m) c = readkey(term.in_stream) - if c == Int(ARROW_UP) + if c == Int(ARROW_UP) || c == Int('k') cursor[] = move_up!(m, cursor[], lastoption) - elseif c == Int(ARROW_DOWN) + elseif c == Int(ARROW_DOWN) || c == Int('j') cursor[] = move_down!(m, cursor[], lastoption) elseif c == Int(PAGE_UP) cursor[] = page_up!(m, cursor[], lastoption) @@ -217,7 +217,7 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio elseif c == Int(END_KEY) cursor[] = lastoption m.pageoffset = lastoption - m.pagesize - elseif c == 13 # + elseif c == 13 || c == Int(' ') # or # will break if pick returns true pick(m, cursor[]) && break elseif c == UInt32('q') diff --git a/stdlib/REPL/test/TerminalMenus/runtests.jl b/stdlib/REPL/test/TerminalMenus/runtests.jl index 62a91cc0a1256..ac577dfd9ab27 100644 --- a/stdlib/REPL/test/TerminalMenus/runtests.jl +++ b/stdlib/REPL/test/TerminalMenus/runtests.jl @@ -6,10 +6,22 @@ using Test function simulate_input(expected, menu::TerminalMenus.AbstractMenu, keys...; kwargs...) - keydict = Dict(:up => "\e[A", - :down => "\e[B", - :enter => "\r") + keydict = Dict(:up => "\e[A", + :down => "\e[B", + :enter => "\r") + vimdict = Dict(:up => "k", + :down => "j", + :enter => " ") + errs = [] + got = _simulate_input(keydict, deepcopy(menu), keys...; kwargs...) + got == expected || push!(errs, :arrows => got) + got = _simulate_input(vimdict, menu, keys...; kwargs...) + got == expected || push!(errs, :vim => got) + isempty(errs) || return errs +end +function _simulate_input(keydict, menu::TerminalMenus.AbstractMenu, keys...; + kwargs...) for key in keys if isa(key, Symbol) write(stdin.buffer, keydict[key]) @@ -18,7 +30,7 @@ function simulate_input(expected, menu::TerminalMenus.AbstractMenu, keys...; end end - request(menu; suppress_output=true, kwargs...) == expected + request(menu; suppress_output=true, kwargs...) end include("radio_menu.jl") From 9300073eb46e515a2362f918a2cb4478e35823db Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 13 Apr 2021 15:56:44 -0400 Subject: [PATCH 170/439] Allow use of 32 element tuples without dynamic allocation --- base/combinatorics.jl | 4 ++-- base/operators.jl | 20 ++++++++++++++++++-- base/tuple.jl | 36 +++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index d966065852b3a..7411de5b40043 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -91,7 +91,7 @@ function isperm(P::Tuple) end end -isperm(P::Any16) = _isperm(P) +isperm(P::Any32) = _isperm(P) # swap columns i and j of a, in-place function swapcols!(a::AbstractMatrix, i, j) @@ -286,7 +286,7 @@ function invperm(P::Tuple) end end -invperm(P::Any16) = Tuple(invperm(collect(P))) +invperm(P::Any32) = Tuple(invperm(collect(P))) #XXX This function should be moved to Combinatorics.jl but is currently used by Base.DSP. """ diff --git a/base/operators.jl b/base/operators.jl index 8d7d8180c5cde..fcd32cb0206ec 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -590,7 +590,7 @@ afoldl(op, a) = a function afoldl(op, a, bs...) l = length(bs) i = 0; y = a; l == i && return y - #@nexprs 15 i -> (y = op(y, bs[i]); l == i && return y) + #@nexprs 31 i -> (y = op(y, bs[i]); l == i && return y) i = 1; y = op(y, bs[i]); l == i && return y i = 2; y = op(y, bs[i]); l == i && return y i = 3; y = op(y, bs[i]); l == i && return y @@ -606,12 +606,28 @@ function afoldl(op, a, bs...) i = 13; y = op(y, bs[i]); l == i && return y i = 14; y = op(y, bs[i]); l == i && return y i = 15; y = op(y, bs[i]); l == i && return y + i = 16; y = op(y, bs[i]); l == i && return y + i = 17; y = op(y, bs[i]); l == i && return y + i = 18; y = op(y, bs[i]); l == i && return y + i = 19; y = op(y, bs[i]); l == i && return y + i = 20; y = op(y, bs[i]); l == i && return y + i = 21; y = op(y, bs[i]); l == i && return y + i = 22; y = op(y, bs[i]); l == i && return y + i = 23; y = op(y, bs[i]); l == i && return y + i = 24; y = op(y, bs[i]); l == i && return y + i = 25; y = op(y, bs[i]); l == i && return y + i = 26; y = op(y, bs[i]); l == i && return y + i = 27; y = op(y, bs[i]); l == i && return y + i = 28; y = op(y, bs[i]); l == i && return y + i = 29; y = op(y, bs[i]); l == i && return y + i = 30; y = op(y, bs[i]); l == i && return y + i = 31; y = op(y, bs[i]); l == i && return y for i in (i + 1):l y = op(y, bs[i]) end return y end -typeof(afoldl).name.mt.max_args = 18 +typeof(afoldl).name.mt.max_args = 34 for op in (:+, :*, :&, :|, :xor, :min, :max, :kron) @eval begin diff --git a/base/tuple.jl b/base/tuple.jl index d0b849f3a9803..3894ec83139fc 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -215,11 +215,17 @@ map(f, t::Tuple{Any, Any}) = (@_inline_meta; (f(t[1]), f(t[2]))) map(f, t::Tuple{Any, Any, Any}) = (@_inline_meta; (f(t[1]), f(t[2]), f(t[3]))) map(f, t::Tuple) = (@_inline_meta; (f(t[1]), map(f,tail(t))...)) # stop inlining after some number of arguments to avoid code blowup -const Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any, - Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}} -const All16{T,N} = Tuple{T,T,T,T,T,T,T,T, - T,T,T,T,T,T,T,T,Vararg{T,N}} -function map(f, t::Any16) +const Any32{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any, + Any,Any,Any,Any,Any,Any,Any,Any, + Any,Any,Any,Any,Any,Any,Any,Any, + Any,Any,Any,Any,Any,Any,Any,Any, + Vararg{Any,N}} +const All32{T,N} = Tuple{T,T,T,T,T,T,T,T, + T,T,T,T,T,T,T,T, + T,T,T,T,T,T,T,T, + T,T,T,T,T,T,T,T, + Vararg{T,N}} +function map(f, t::Any32) n = length(t) A = Vector{Any}(undef, n) for i=1:n @@ -235,7 +241,7 @@ function map(f, t::Tuple, s::Tuple) @_inline_meta (f(t[1],s[1]), map(f, tail(t), tail(s))...) end -function map(f, t::Any16, s::Any16) +function map(f, t::Any32, s::Any32) n = length(t) A = Vector{Any}(undef, n) for i = 1:n @@ -251,7 +257,7 @@ function map(f, t1::Tuple, t2::Tuple, ts::Tuple...) @_inline_meta (f(heads(t1, t2, ts...)...), map(f, tails(t1, t2, ts...)...)...) end -function map(f, t1::Any16, t2::Any16, ts::Any16...) +function map(f, t1::Any32, t2::Any32, ts::Any32...) n = length(t1) A = Vector{Any}(undef, n) for i = 1:n @@ -317,8 +323,8 @@ function _totuple(T, itr, s...) end # use iterative algorithm for long tuples -function _totuple(T::Type{All16{E,N}}, itr) where {E,N} - len = N+16 +function _totuple(T::Type{All32{E,N}}, itr) where {E,N} + len = N+32 elts = collect(E, Iterators.take(itr,len)) if length(elts) != len _totuple_err(T) @@ -342,7 +348,7 @@ end filter(f, xs::Tuple) = afoldl((ys, x) -> f(x) ? (ys..., x) : ys, (), xs...) # use Array for long tuples -filter(f, t::Any16) = Tuple(filter(f, collect(t))) +filter(f, t::Any32) = Tuple(filter(f, collect(t))) ## comparison ## @@ -350,7 +356,7 @@ isequal(t1::Tuple, t2::Tuple) = (length(t1) == length(t2)) && _isequal(t1, t2) _isequal(t1::Tuple{}, t2::Tuple{}) = true _isequal(t1::Tuple{Any}, t2::Tuple{Any}) = isequal(t1[1], t2[1]) _isequal(t1::Tuple, t2::Tuple) = isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2)) -function _isequal(t1::Any16, t2::Any16) +function _isequal(t1::Any32, t2::Any32) for i = 1:length(t1) if !isequal(t1[i], t2[i]) return false @@ -380,7 +386,7 @@ function _eq_missing(t1::Tuple, t2::Tuple) return _eq_missing(tail(t1), tail(t2)) end end -function _eq(t1::Any16, t2::Any16) +function _eq(t1::Any32, t2::Any32) anymissing = false for i = 1:length(t1) eq = (t1[i] == t2[i]) @@ -396,7 +402,7 @@ end const tuplehash_seed = UInt === UInt64 ? 0x77cfa1eef01bca90 : 0xf01bca90 hash(::Tuple{}, h::UInt) = h + tuplehash_seed hash(t::Tuple, h::UInt) = hash(t[1], hash(tail(t), h)) -function hash(t::Any16, h::UInt) +function hash(t::Any32, h::UInt) out = h + tuplehash_seed for i = length(t):-1:1 out = hash(t[i], out) @@ -417,7 +423,7 @@ function <(t1::Tuple, t2::Tuple) end return tail(t1) < tail(t2) end -function <(t1::Any16, t2::Any16) +function <(t1::Any32, t2::Any32) n1, n2 = length(t1), length(t2) for i = 1:min(n1, n2) a, b = t1[i], t2[i] @@ -444,7 +450,7 @@ function isless(t1::Tuple, t2::Tuple) a, b = t1[1], t2[1] isless(a, b) || (isequal(a, b) && isless(tail(t1), tail(t2))) end -function isless(t1::Any16, t2::Any16) +function isless(t1::Any32, t2::Any32) n1, n2 = length(t1), length(t2) for i = 1:min(n1, n2) a, b = t1[i], t2[i] From d88ed01ba90d57f1c7c387a81b4657fd8e6eed08 Mon Sep 17 00:00:00 2001 From: Lea Kapelevich Date: Tue, 13 Apr 2021 16:46:49 -0400 Subject: [PATCH 171/439] define dot between AbstractMatrix and UniformScaling (#40250) * define dot between AbstractMatrix and UniformScaling * fix equality check * fix for complex * add news entry --- NEWS.md | 1 + stdlib/LinearAlgebra/src/uniformscaling.jl | 3 +++ stdlib/LinearAlgebra/test/uniformscaling.jl | 14 ++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0a560a9643ce3..b4f09d1b1d106 100644 --- a/NEWS.md +++ b/NEWS.md @@ -95,6 +95,7 @@ Standard library changes * SuiteSparse is updated to 5.8.1. ([#39455]) * The shape of an `UpperHessenberg` matrix is preserved under certain arithmetic operations, e.g. when multiplying or dividing by an `UpperTriangular` matrix. ([#40039]) * `cis(A)` now supports matrix arguments ([#40194]). +* `dot` now supports `UniformScaling` with `AbstractMatrix` ([#40250]). #### Markdown diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 13acea982e7e0..71dd11a2f9e87 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -480,6 +480,9 @@ Array(s::UniformScaling, dims::Dims{2}) = Matrix(s, dims) Diagonal{T}(s::UniformScaling, m::Integer) where {T} = Diagonal{T}(fill(T(s.λ), m)) Diagonal(s::UniformScaling, m::Integer) = Diagonal{eltype(s)}(s, m) +dot(A::AbstractMatrix, J::UniformScaling) = dot(tr(A), J.λ) +dot(J::UniformScaling, A::AbstractMatrix) = dot(J.λ, tr(A)) + dot(x::AbstractVector, J::UniformScaling, y::AbstractVector) = dot(x, J.λ, y) dot(x::AbstractVector, a::Number, y::AbstractVector) = sum(t -> dot(t[1], a, t[2]), zip(x, y)) dot(x::AbstractVector, a::Union{Real,Complex}, y::AbstractVector) = a*dot(x, y) diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 0f86f0555cba7..4eea74b12ff15 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -462,6 +462,20 @@ end @test I(3) == [1 0 0; 0 1 0; 0 0 1] end +@testset "dot" begin + A = randn(3, 3) + λ = randn() + J = UniformScaling(λ) + @test dot(A, J) ≈ dot(J, A) + @test dot(A, J) ≈ tr(A' * J) + + A = rand(ComplexF64, 3, 3) + λ = randn() + im * randn() + J = UniformScaling(λ) + @test dot(A, J) ≈ conj(dot(J, A)) + @test dot(A, J) ≈ tr(A' * J) +end + @testset "generalized dot" begin x = rand(-10:10, 3) y = rand(-10:10, 3) From 45c518d5628f8c2975c81b674bb1189936d6eade Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Tue, 13 Apr 2021 16:25:29 -0500 Subject: [PATCH 172/439] improve fastmath for `exp` and friends (#40223) * improve fastmath for scalars * fix typo in exp_impl_fast(::Float64) * fix whitespace * Rebase on master * Update base/special/exp.jl Co-authored-by: Mustafa M * Update base/special/exp.jl Co-authored-by: Mustafa M * address review Co-authored-by: Mustafa M --- base/fastmath.jl | 25 +------- base/special/exp.jl | 147 +++++++++++++++++++++++++++----------------- 2 files changed, 93 insertions(+), 79 deletions(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index a7d8b86fcb26a..c01a8a5b225f7 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -273,6 +273,9 @@ end # Math functions +exp2_fast(x::Union{Float32,Float64}) = Base.Math.exp2_fast(x) +exp_fast(x::Union{Float32,Float64}) = Base.Math.exp_fast(x) +exp10_fast(x::Union{Float32,Float64}) = Base.Math.exp10_fast(x) # builtins @@ -282,28 +285,6 @@ pow_fast(x::FloatTypes, ::Val{p}) where {p} = pow_fast(x, p) # inlines already v @inline pow_fast(x, v::Val) = Base.literal_pow(^, x, v) sqrt_fast(x::FloatTypes) = sqrt_llvm_fast(x) - -# libm - -const libm = Base.libm_name - -for f in (:acosh, :asinh, :atanh, :cbrt, - :cosh, :exp2, :expm1, :log10, :log1p, :log2, - :log, :sinh, :tanh) - f_fast = fast_op[f] - @eval begin - $f_fast(x::Float32) = - ccall(($(string(f,"f")),libm), Float32, (Float32,), x) - $f_fast(x::Float64) = - ccall(($(string(f)),libm), Float64, (Float64,), x) - end -end - -pow_fast(x::Float32, y::Float32) = - ccall(("powf",libm), Float32, (Float32,Float32), x, y) -pow_fast(x::Float64, y::Float64) = - ccall(("pow",libm), Float64, (Float64,Float64), x, y) - sincos_fast(v::FloatTypes) = sincos(v) @inline function sincos_fast(v::Float16) diff --git a/base/special/exp.jl b/base/special/exp.jl index e10fdf243055c..5591f3603eee2 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -9,7 +9,7 @@ MAGIC_ROUND_CONST(::Type{Float32}) = 1.048576f7 MAX_EXP(n::Val{2}, ::Type{Float32}) = 128.0f0 MAX_EXP(n::Val{2}, ::Type{Float64}) = 1024.0 MAX_EXP(n::Val{:ℯ}, ::Type{Float32}) = 88.72284f0 -MAX_EXP(n::Val{:ℯ}, ::Type{Float64}) = 709.782712893384 +MAX_EXP(n::Val{:ℯ}, ::Type{Float64}) = 709.7827128933841 MAX_EXP(n::Val{10}, ::Type{Float32}) = 38.53184f0 MAX_EXP(n::Val{10}, ::Type{Float64}) = 308.25471555991675 @@ -198,69 +198,102 @@ end # # 2. Approximate b^r by 7th-degree minimax polynomial p_b(r) on the interval [-log(b,2)/2, log(b,2)/2]. # 3. Scale back: b^x = 2^N * p_b(r) - # For both, a little extra care needs to be taken if b^r is subnormal. # The solution is to do the scaling back in 2 steps as just messing with the exponent wouldn't work. -for (func, base) in (:exp2=>Val(2), :exp=>Val(:ℯ), :exp10=>Val(10)) - @eval begin - function ($func)(x::T) where T<:Float64 - N_float = muladd(x, LogBo256INV($base, T), MAGIC_ROUND_CONST(T)) - N = reinterpret(UInt64, N_float) % Int32 - N_float -= MAGIC_ROUND_CONST(T) #N_float now equals round(x*LogBo256INV($base, T)) - r = muladd(N_float, LogBo256U($base, T), x) - r = muladd(N_float, LogBo256L($base, T), r) - k = N >> 8 - jU, jL = table_unpack(N&255 +1) - small_part = muladd(jU, expm1b_kernel($base, r), jL) + jU - - if !(abs(x) <= SUBNORM_EXP($base, T)) - x >= MAX_EXP($base, T) && return Inf - x <= MIN_EXP($base, T) && return 0.0 - if k <= -53 - # The UInt64 forces promotion. (Only matters for 32 bit systems.) - twopk = (k + UInt64(53)) << 52 - return reinterpret(T, twopk + reinterpret(UInt64, small_part))*(2.0^-53) - end - end - twopk = Int64(k) << 52 - return reinterpret(T, twopk + reinterpret(Int64, small_part)) - end - function ($func)(x::T) where T<:Float32 - N_float = round(x*LogBINV($base, T)) - N = unsafe_trunc(Int32, N_float) - r = muladd(N_float, LogBU($base, T), x) - r = muladd(N_float, LogBL($base, T), r) - small_part = expb_kernel($base, r) - if !(abs(x) <= SUBNORM_EXP($base, T)) - x > MAX_EXP($base, T) && return Inf32 - x < MIN_EXP($base, T) && return 0.0f0 - if N<=Int32(-24) - twopk = reinterpret(T, (N+Int32(151)) << Int32(23)) - return (twopk*small_part)*(2f0^(-24)) - end - N == (exponent_max(T)+1) && return small_part * T(2.0) * T(2.0)^exponent_max(T) - end - twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) - return twopk*small_part +@inline function exp_impl(x::Float64, base) + T = Float64 + N_float = muladd(x, LogBo256INV(base, T), MAGIC_ROUND_CONST(T)) + N = reinterpret(UInt64, N_float) % Int32 + N_float -= MAGIC_ROUND_CONST(T) #N_float now equals round(x*LogBo256INV(base, T)) + r = muladd(N_float, LogBo256U(base, T), x) + r = muladd(N_float, LogBo256L(base, T), r) + k = N >> 8 + jU, jL = table_unpack(N&255 + 1) + small_part = muladd(jU, expm1b_kernel(base, r), jL) + jU + + if !(abs(x) <= SUBNORM_EXP(base, T)) + x >= MAX_EXP(base, T) && return Inf + x <= MIN_EXP(base, T) && return 0.0 + if k <= -53 + # The UInt64 forces promotion. (Only matters for 32 bit systems.) + twopk = (k + UInt64(53)) << 52 + return reinterpret(T, twopk + reinterpret(UInt64, small_part))*(2.0^-53) end + #k == 1024 && return (small_part * 2.0) * 2.0^1023 + end + twopk = Int64(k) << 52 + return reinterpret(T, twopk + reinterpret(Int64, small_part)) +end +@inline function exp_impl_fast(x::Float64, base) + T = Float64 + N_float = muladd(x, LogBo256INV(base, T), MAGIC_ROUND_CONST(T)) + N = reinterpret(UInt64, N_float) % Int32 + N_float -= MAGIC_ROUND_CONST(T) #N_float now equals round(x*LogBo256INV(base, T)) + r = muladd(N_float, LogBo256U(base, T), x) + r = muladd(N_float, LogBo256L(base, T), r) + k = N >> 8 + jU = reinterpret(Float64, JU_CONST | (@inbounds J_TABLE[N&255 + 1] & JU_MASK)) + small_part = muladd(jU, expm1b_kernel(base, r), jU) + twopk = Int64(k) << 52 + return reinterpret(T, twopk + reinterpret(Int64, small_part)) +end - function ($func)(a::Float16) - T = Float32 - x = T(a) - N_float = round(x*LogBINV($base, T)) - N = unsafe_trunc(Int32, N_float) - r = muladd(N_float, LogB($base, Float16), x) - small_part = expb_kernel($base, r) - if !(abs(x) <= SUBNORM_EXP($base, T)) - x > MAX_EXP($base, T) && return Inf16 - N<=Int32(-24) && return zero(Float16) - end - twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) - return Float16(twopk*small_part) +@inline function exp_impl(x::Float32, base) + T = Float32 + N_float = round(x*LogBINV(base, T)) + N = unsafe_trunc(Int32, N_float) + r = muladd(N_float, LogBU(base, T), x) + r = muladd(N_float, LogBL(base, T), r) + small_part = expb_kernel(base, r) + if !(abs(x) <= SUBNORM_EXP(base, T)) + x > MAX_EXP(base, T) && return Inf32 + x < MIN_EXP(base, T) && return 0.0f0 + if N <= Int32(-24) + twopk = reinterpret(T, (N+Int32(151)) << Int32(23)) + return (twopk*small_part)*(2f0^(-24)) end + N == 128 && return small_part * T(2.0) * T(2.0)^127 + end + twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) + return twopk*small_part +end + +@inline function exp_impl_fast(x::Float32, base) + T = Float32 + N_float = round(x*LogBINV(base, T)) + N = unsafe_trunc(Int32, N_float) + r = muladd(N_float, LogBU(base, T), x) + r = muladd(N_float, LogBL(base, T), r) + small_part = expb_kernel(base, r) + twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) + return twopk*small_part +end + +@inline function exp_impl(a::Float16, base) + T = Float32 + x = T(a) + N_float = round(x*LogBINV(base, T)) + N = unsafe_trunc(Int32, N_float) + r = muladd(N_float, LogB(base, Float16), x) + small_part = expb_kernel(base, r) + if !(abs(x) <= SUBNORM_EXP(base, T)) + x > MAX_EXP(base, T) && return Inf16 + N<=Int32(-24) && return zero(Float16) end + twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) + return Float16(twopk*small_part) end + +for (func, fast_func, base) in ((:exp2, :exp2_fast, Val(2)), + (:exp, :exp_fast, Val(:ℯ)), + (:exp10, :exp10_fast, Val(10))) + @eval begin + $func(x::Union{Float16,Float32,Float64}) = exp_impl(x, $base) + $fast_func(x::Union{Float32,Float64}) = exp_impl_fast(x, $base) + end +end + @doc """ exp(x) @@ -339,7 +372,7 @@ end end @inline function expm1(x::Float64) - T=Float64 + T = Float64 if -0.2876820724517809 <= x <= 0.22314355131420976 return expm1_small(x) elseif !(abs(x)<=MIN_EXP(Float64)) From 7112c89f625b1cced5943613f98f2dbdecdfe5b6 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 13 Apr 2021 19:47:46 -0700 Subject: [PATCH 173/439] Always trigger a safepoint in process_events (#40473) yield is already a potential safepoint, this just ensures it is always one --- src/jl_uv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jl_uv.c b/src/jl_uv.c index 35f83b3314e91..78238bf07e8eb 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -207,14 +207,15 @@ JL_DLLEXPORT int jl_process_events(void) { jl_ptls_t ptls = jl_get_ptls_states(); uv_loop_t *loop = jl_io_loop; + jl_gc_safepoint_(ptls); if (loop && (_threadedregion || ptls->tid == 0)) { - jl_gc_safepoint_(ptls); if (jl_atomic_load(&jl_uv_n_waiters) == 0 && jl_mutex_trylock(&jl_uv_mutex)) { loop->stop_flag = 0; int r = uv_run(loop, UV_RUN_NOWAIT); JL_UV_UNLOCK(); return r; } + jl_gc_safepoint_(ptls); } return 0; } From 2fed7c34739cfe97610fa648b8ddc29b3c5141d6 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 14 Apr 2021 09:28:12 +0200 Subject: [PATCH 174/439] further parametrize IRShow (#40459) Ref https://github.com/JuliaDebug/Cthulhu.jl/issues/149. This allows Ctulhu to further customize how line annotations are printed. Also moves a hook to skip printing some statements into `show_ir`, which previously Cthulhu had to duplicate. Since Cthulhu seems to be the only downstream consumer of `show_ir` https://juliahub.com/ui/RepoSearch?q=show_ir&r=true, I don't expect this change to be major. I did also try to keep compatibility for `show_ir_stmt`, which seems to be more commonly used. --- base/compiler/ssair/show.jl | 108 +++++++++++++++--------- base/reflection.jl | 6 +- base/show.jl | 2 +- stdlib/InteractiveUtils/src/codeview.jl | 3 +- test/show.jl | 8 +- 5 files changed, 81 insertions(+), 46 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 3137571081536..72f17e5505324 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -487,6 +487,25 @@ function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false) return emit_lineinfo_update end +# line_info_preprinter(io::IO, indent::String, idx::Int) may print relevant info +# at the beginning of the line, and should at least print `indent`. It returns a +# string that will be printed after the final basic-block annotation. +# line_info_postprinter(io::IO, typ, used::Bool) prints the type-annotation at the end +# of the statement +# should_print_stmt(idx::Int) -> Bool: whether the statement at index `idx` should be +# printed as part of the IR or not +# bb_color: color used for printing the basic block brackets on the left +struct IRShowConfig + line_info_preprinter + line_info_postprinter + should_print_stmt + bb_color::Symbol + function IRShowConfig(line_info_preprinter, line_info_postprinter=default_expr_type_printer; + should_print_stmt=Returns(true), bb_color::Symbol=:light_black) + return new(line_info_preprinter, line_info_postprinter, should_print_stmt, bb_color) + end +end + struct _UNDEF global const UNDEF = _UNDEF.instance end @@ -510,7 +529,7 @@ function _type(code::CodeInfo, idx::Int) return isassigned(types, idx) ? types[idx] : UNDEF end -function statement_indices_to_labels(@nospecialize(stmt), cfg::CFG) +function statement_indices_to_labels(stmt, cfg::CFG) # convert statement index to labels, as expected by print_stmt if stmt isa Expr if stmt.head === :enter && length(stmt.args) == 1 && stmt.args[1] isa Int @@ -529,16 +548,17 @@ end # Show a single statement, code.stmts[idx]/code.code[idx], in the context of the whole IRCode/CodeInfo. # Returns the updated value of bb_idx. -# line_info_preprinter(io::IO, indent::String, idx::Int) may print relevant info -# at the beginning of the line, and should at least print `indent`. It returns a -# string that will be printed after the final basic-block annotation. -# line_info_postprinter(io::IO, typ, used::Bool) prints the type-annotation at the end -# of the statement # pop_new_node!(idx::Int) -> (node_idx, new_node_inst, new_node_type) may return a new # node at the current index `idx`, which is printed before the statement at index # `idx`. This function is repeatedly called until it returns `nothing` +function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo}, idx::Int, config::IRShowConfig, + used::BitSet, cfg::CFG, bb_idx::Int; pop_new_node! = Returns(nothing)) + return show_ir_stmt(io, code, idx, config.line_info_preprinter, config.line_info_postprinter, + used, cfg, bb_idx; pop_new_node!, config.bb_color) +end + function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo}, idx::Int, line_info_preprinter, line_info_postprinter, - used::BitSet, cfg::CFG, bb_idx::Int, pop_new_node! = _ -> nothing; bb_color=:light_black) + used::BitSet, cfg::CFG, bb_idx::Int; pop_new_node! = Returns(nothing), bb_color=:light_black) stmt = _stmt(code, idx) type = _type(code, idx) max_bb_idx_size = length(string(length(cfg.blocks))) @@ -653,8 +673,8 @@ function ircode_new_nodes_iter(code::IRCode) end end -# corresponds to `verbose_linetable=false` -function ircode_default_linfo_printer(code::IRCode) +# print only line numbers on the left, some of the method names and nesting depth on the right +function inline_linfo_printer(code::IRCode) loc_annotations, loc_methods, loc_lineno = compute_ir_line_annotations(code) max_loc_width = maximum(length, loc_annotations) max_lineno_width = maximum(length, loc_lineno) @@ -693,10 +713,11 @@ end _strip_color(s::String) = replace(s, r"\e\[\d+m" => "") # corresponds to `verbose_linetable=true` -function ircode_verbose_linfo_printer(code::IRCode, used::BitSet) +function ircode_verbose_linfo_printer(code::IRCode) stmts = code.stmts max_depth = maximum(compute_inlining_depth(code.linetable, stmts[i][:line]) for i in 1:length(stmts.line)) last_stack = Ref(Int[]) + used = stmts_used(code, false) maxlength_idx = if isempty(used) 0 else @@ -733,16 +754,27 @@ function ircode_verbose_linfo_printer(code::IRCode, used::BitSet) end end -function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_printer; verbose_linetable=false) +function statementidx_lineinfo_printer(f, code::IRCode) + printer = f(code.linetable) + function (io::IO, indent::String, idx::Int) + printer(io, indent, idx > 0 ? code.stmts[idx][:line] : typemin(Int32)) + end +end +function statementidx_lineinfo_printer(f, code::CodeInfo) + printer = f(code.linetable) + function (io::IO, indent::String, idx::Int) + printer(io, indent, idx > 0 ? code.codelocs[idx] : typemin(Int32)) + end +end +statementidx_lineinfo_printer(code) = statementidx_lineinfo_printer(DILineInfoPrinter, code) + +function stmts_used(code::IRCode, warn_unset_entry=true) stmts = code.stmts - isempty(stmts) && return # unlikely, but avoid errors from reducing over empty sets used = BitSet() - cfg = code.cfg for stmt in stmts scan_ssa_use!(push!, used, stmt[:inst]) end new_nodes = code.new_nodes.stmts - warn_unset_entry = true for nn in 1:length(new_nodes) if isassigned(new_nodes.inst, nn) scan_ssa_use!(push!, used, new_nodes[nn][:inst]) @@ -751,44 +783,42 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print warn_unset_entry = false end end - bb_idx = 1 - - pop_new_node! = ircode_new_nodes_iter(code) - - if verbose_linetable - line_info_preprinter = ircode_verbose_linfo_printer(code, used) - else - line_info_preprinter = ircode_default_linfo_printer(code) - end - - for idx in 1:length(stmts) - bb_idx = show_ir_stmt(io, code, idx, line_info_preprinter, expr_type_printer, - used, cfg, bb_idx, pop_new_node!; bb_color=:normal) - end - nothing -end - -function statementidx_lineinfo_printer(f, code::CodeInfo) - printer = f(code.linetable) - return (io::IO, indent::String, idx::Int) -> printer(io, indent, idx > 0 ? code.codelocs[idx] : typemin(Int32)) + return used end -statementidx_lineinfo_printer(code::CodeInfo) = statementidx_lineinfo_printer(DILineInfoPrinter, code) -function show_ir(io::IO, code::CodeInfo, line_info_preprinter=statementidx_lineinfo_printer(code), line_info_postprinter=default_expr_type_printer) +function stmts_used(code::CodeInfo) stmts = code.code used = BitSet() - cfg = compute_basic_blocks(stmts) for stmt in stmts scan_ssa_use!(push!, used, stmt) end + return used +end + +function default_config(code::IRCode; verbose_linetable=false) + return IRShowConfig(verbose_linetable ? ircode_verbose_linfo_printer(code) + : inline_linfo_printer(code); + bb_color=:normal) +end +default_config(code::CodeInfo) = IRShowConfig(statementidx_lineinfo_printer(code)) + +function show_ir(io::IO, code::Union{IRCode, CodeInfo}, config::IRShowConfig=default_config(code); + pop_new_node! = code isa IRCode ? ircode_new_nodes_iter(code) : Returns(nothing)) + stmts = code isa IRCode ? code.stmts : code.code + used = stmts_used(code) + cfg = code isa IRCode ? code.cfg : compute_basic_blocks(stmts) bb_idx = 1 for idx in 1:length(stmts) - bb_idx = show_ir_stmt(io, code, idx, line_info_preprinter, line_info_postprinter, used, cfg, bb_idx) + if config.should_print_stmt(code, idx, used) + bb_idx = show_ir_stmt(io, code, idx, config, used, cfg, bb_idx; pop_new_node!) + elseif bb_idx <= length(cfg.blocks) && idx == cfg.blocks[bb_idx].stmts.stop + bb_idx += 1 + end end max_bb_idx_size = length(string(length(cfg.blocks))) - line_info_preprinter(io, " "^(max_bb_idx_size + 2), 0) + config.line_info_preprinter(io, " "^(max_bb_idx_size + 2), 0) nothing end diff --git a/base/reflection.jl b/base/reflection.jl index bfed4154cd7d8..d9cd893474364 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1262,7 +1262,11 @@ function print_statement_costs(io::IO, @nospecialize(tt::Type); maxcost = Core.Compiler.statement_costs!(cst, code.code, code, Any[match.sparams...], false, params) nd = ndigits(maxcost) println(io, meth) - IRShow.show_ir(io, code, (io, linestart, idx) -> (print(io, idx > 0 ? lpad(cst[idx], nd+1) : " "^(nd+1), " "); return "")) + irshow_config = IRShow.IRShowConfig() do io, linestart, idx + print(io, idx > 0 ? lpad(cst[idx], nd+1) : " "^(nd+1), " ") + return "" + end + IRShow.show_ir(io, code, irshow_config) println(io) end end diff --git a/base/show.jl b/base/show.jl index c98637a026112..a601007eeedef 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2476,7 +2476,7 @@ function show(io::IO, src::CodeInfo; debuginfo::Symbol=:source) # TODO: static parameter values? # only accepts :source or :none, we can't have a fallback for default since # that would break code_typed(, debuginfo=:source) iff IRShow.default_debuginfo[] = :none - IRShow.show_ir(lambda_io, src, IRShow.__debuginfo[debuginfo](src)) + IRShow.show_ir(lambda_io, src, IRShow.IRShowConfig(IRShow.__debuginfo[debuginfo](src))) else # this is a CodeInfo that has not been used as a method yet, so its locations are still LineNumberNodes body = Expr(:block) diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index da72fae8daeb0..e11a8d1ec6433 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -127,7 +127,8 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(t); debuginfo::Sy print(io, "Body") warntype_type_printer(io, rettype, true) println(io) - Base.IRShow.show_ir(lambda_io, src, lineprinter(src), warntype_type_printer) + irshow_config = Base.IRShow.IRShowConfig(lineprinter(src), warntype_type_printer) + Base.IRShow.show_ir(lambda_io, src, irshow_config) println(io) end nothing diff --git a/test/show.jl b/test/show.jl index 8e022f581bf06..65b5441841f9c 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1931,13 +1931,13 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] @test repr(src) == repr_ir end lines1 = split(repr(ir), '\n') - @test isempty(pop!(lines1)) + @test all(isspace, pop!(lines1)) Core.Compiler.insert_node!(ir, 1, Core.Compiler.NewInstruction(QuoteNode(1), Val{1}), false) Core.Compiler.insert_node!(ir, 1, Core.Compiler.NewInstruction(QuoteNode(2), Val{2}), true) Core.Compiler.insert_node!(ir, length(ir.stmts.inst), Core.Compiler.NewInstruction(QuoteNode(3), Val{3}), false) Core.Compiler.insert_node!(ir, length(ir.stmts.inst), Core.Compiler.NewInstruction(QuoteNode(4), Val{4}), true) lines2 = split(repr(ir), '\n') - @test isempty(pop!(lines2)) + @test all(isspace, pop!(lines2)) @test popfirst!(lines2) == "2 1 ── $(QuoteNode(1))" @test popfirst!(lines2) == " │ $(QuoteNode(2))" # TODO: this should print after the next statement let line1 = popfirst!(lines1) @@ -1958,7 +1958,7 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] # verbose linetable io = IOBuffer() - Base.IRShow.show_ir(io, ir; verbose_linetable=true) + Base.IRShow.show_ir(io, ir, Base.IRShow.default_config(ir; verbose_linetable=true)) seekstart(io) @test count(contains(r"my_fun28173 at a{80}:\d+"), eachline(io)) == 9 end @@ -1970,7 +1970,7 @@ let src = code_typed(gcd, (Int, Int), debuginfo=:source)[1][1] ir = Core.Compiler.inflate_ir(src) push!(ir.stmts.inst, Core.Compiler.ReturnNode()) lines = split(sprint(show, ir), '\n') - @test isempty(pop!(lines)) + @test all(isspace, pop!(lines)) @test pop!(lines) == " !!! ── unreachable::#UNDEF" end From b10f9cf489abcc9001562a54c3aa3c8fb851eb7e Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 14 Apr 2021 19:17:21 +0200 Subject: [PATCH 175/439] fix #40478: MethodError hint printed twice (#40479) https://github.com/JuliaLang/julia/pull/40304 accidentally registered the error hint every time the error was printed. --- base/errorshow.jl | 3 ++- test/errorshow.jl | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index d11130523a88f..e52fde76ab96e 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -313,7 +313,6 @@ function showerror(io::IO, ex::MethodError) "\nYou can convert to a column vector with the vec() function.") end end - Experimental.register_error_hint(noncallable_number_hint_handler, MethodError) Experimental.show_error_hints(io, ex, arg_types_param, kwargs) try show_method_candidates(io, ex, kwargs) @@ -885,3 +884,5 @@ function noncallable_number_hint_handler(io, ex, arg_types, kwargs) print(io, "?") end end + +Experimental.register_error_hint(noncallable_number_hint_handler, MethodError) diff --git a/test/errorshow.jl b/test/errorshow.jl index 4a6796a454f78..d219df3b12d64 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -638,7 +638,10 @@ struct ANumber <: Number end let err_str err_str = @except_str ANumber()(3 + 4) MethodError @test occursin("objects of type $(curmod_prefix)ANumber are not callable", err_str) - @test occursin("Maybe you forgot to use an operator such as *, ^, %, / etc. ?", err_str) + @test count(==("Maybe you forgot to use an operator such as *, ^, %, / etc. ?"), split(err_str, '\n')) == 1 + # issue 40478 + err_str = @except_str ANumber()(3 + 4) MethodError + @test count(==("Maybe you forgot to use an operator such as *, ^, %, / etc. ?"), split(err_str, '\n')) == 1 end # Execute backtrace once before checking formatting, see #38858 From 8ecb30667165c273ac59096b43a97ad37328af03 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 14 Apr 2021 17:35:12 -0400 Subject: [PATCH 176/439] fix #39982, remove cursor artifacts in REPL after #40411 (#40452) --- stdlib/REPL/src/LineEdit.jl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index c80273e2d6ca0..9a6160c960fe3 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -786,25 +786,30 @@ function edit_insert(s::PromptState, c::StringLike) after = options(s).auto_refresh_time_delay termbuf = terminal(s) w = width(termbuf) - delayup = !eof(buf) || old_wait offset = s.ias.curs_row == 1 || s.indent < 0 ? sizeof(prompt_string(s.p.prompt)::String) : s.indent offset += position(buf) - beginofline(buf) # size of current line - spinner = true - if offset + textwidth(str) <= w + spinner = '\0' + delayup = !eof(buf) || old_wait + if offset + textwidth(str) <= w && !(after == 0 && delayup) # Avoid full update when appending characters to the end # and an update of curs_row isn't necessary (conservatively estimated) write(termbuf, str) - spinner = false + spinner = ' ' # temporarily clear under the cursor elseif after == 0 refresh_line(s) delayup = false - else + else # render a spinner for each key press + if old_wait || length(str) != 1 + spinner = spin_seq[mod1(position(buf) - w, length(spin_seq))] + else + spinner = str[end] + end delayup = true end if delayup - if spinner - write(termbuf, spin_seq[mod1(position(buf) - w, length(spin_seq))]) + if spinner != '\0' + write(termbuf, spinner) cmove_left(termbuf) end s.refresh_wait = Timer(after) do t From 5e93c29dde1001bc823f3e781f1f221aac320d27 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 15 Apr 2021 06:41:36 +0900 Subject: [PATCH 177/439] improve various inferrabilities, fix some errors (#40463) --- base/compiler/ssair/inlining.jl | 11 ++++++----- base/compiler/ssair/verify.jl | 2 +- base/deprecated.jl | 12 +++++++----- base/iterators.jl | 2 +- base/loading.jl | 8 +++++--- base/strings/basic.jl | 2 +- base/strings/util.jl | 4 ++-- base/toml_parser.jl | 2 +- base/version.jl | 2 +- stdlib/Distributed/src/cluster.jl | 2 +- stdlib/Distributed/src/remotecall.jl | 2 +- stdlib/LibGit2/src/error.jl | 4 ++-- 12 files changed, 29 insertions(+), 24 deletions(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index c07e2b8365d51..0420d137da69e 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -710,7 +710,7 @@ function compileable_specialization(et::Union{EdgeTracker, Nothing}, match::Meth end function compileable_specialization(et::Union{EdgeTracker, Nothing}, result::InferenceResult) - mi = specialize_method(result.linfo.def, result.linfo.specTypes, + mi = specialize_method(result.linfo.def::Method, result.linfo.specTypes, result.linfo.sparam_vals, false, true) mi !== nothing && et !== nothing && push!(et, mi::MethodInstance) return mi @@ -746,8 +746,10 @@ function resolve_todo(todo::InliningTodo, state::InliningState) end end - if isconst && state.et !== nothing - push!(state.et, todo.mi) + et = state.et + + if isconst && et !== nothing + push!(et, todo.mi) return ConstantCase(src) end @@ -756,14 +758,13 @@ function resolve_todo(todo::InliningTodo, state::InliningState) end if src === nothing - return compileable_specialization(state.et, spec.match) + return compileable_specialization(et, spec.match) end if isa(src, IRCode) src = copy(src) end - et = state.et et !== nothing && push!(et, todo.mi) return InliningTodo(todo.mi, src) end diff --git a/base/compiler/ssair/verify.jl b/base/compiler/ssair/verify.jl index 6c2953c12c505..653923ace6e8e 100644 --- a/base/compiler/ssair/verify.jl +++ b/base/compiler/ssair/verify.jl @@ -111,7 +111,7 @@ function verify_ir(ir::IRCode, print::Bool=true) end elseif isexpr(terminator, :enter) @label enter_check - if length(block.succs) != 2 || (block.succs != [terminator.args[1], idx+1] && block.succs != [idx+1, terminator.args[1]]) + if length(block.succs) != 2 || (block.succs != Int[terminator.args[1], idx+1] && block.succs != Int[idx+1, terminator.args[1]]) @verify_error "Block $idx successors ($(block.succs)), does not match :enter terminator" error("") end diff --git a/base/deprecated.jl b/base/deprecated.jl index 45adac55a355c..f64bd38779994 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -117,12 +117,14 @@ function firstcaller(bt::Vector, funcsyms) end found = lkup.func in funcsyms # look for constructor type name - if !found && lkup.linfo isa Core.MethodInstance + if !found li = lkup.linfo - ft = ccall(:jl_first_argument_datatype, Any, (Any,), li.def.sig) - if isa(ft, DataType) && ft.name === Type.body.name - ft = unwrap_unionall(ft.parameters[1]) - found = (isa(ft, DataType) && ft.name.name in funcsyms) + if li isa Core.MethodInstance + ft = ccall(:jl_first_argument_datatype, Any, (Any,), (li.def::Method).sig) + if isa(ft, DataType) && ft.name === Type.body.name + ft = unwrap_unionall(ft.parameters[1]) + found = (isa(ft, DataType) && ft.name.name in funcsyms) + end end end end diff --git a/base/iterators.jl b/base/iterators.jl index 2eb944c929b64..618c3e04547cf 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1316,7 +1316,7 @@ See also: [`first`](@ref), [`last`](@ref). @boundscheck if i === nothing throw(ArgumentError("Collection is empty, must contain exactly 1 element")) end - (ret, state) = i + (ret, state) = i::NTuple{2,Any} @boundscheck if iterate(x, state) !== nothing throw(ArgumentError("Collection has multiple elements, must contain exactly 1 element")) end diff --git a/base/loading.jl b/base/loading.jl index fc4b1b2f1b687..94cf9623353f3 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -312,8 +312,9 @@ function pathof(m::Module) pkgid === nothing && return nothing origin = get(Base.pkgorigins, pkgid, nothing) origin === nothing && return nothing - origin.path === nothing && return nothing - return fixup_stdlib_path(origin.path) + path = origin.path + path === nothing && return nothing + return fixup_stdlib_path(path) end """ @@ -563,7 +564,8 @@ function explicit_manifest_entry_path(manifest_file::String, pkg::PkgId, entry:: hash === nothing && return nothing hash = SHA1(hash) # Keep the 4 since it used to be the default - for slug in (version_slug(pkg.uuid, hash, 4), version_slug(pkg.uuid, hash)) + uuid = pkg.uuid::UUID # checked within `explicit_manifest_uuid_path` + for slug in (version_slug(uuid, hash, 4), version_slug(uuid, hash)) for depot in DEPOT_PATH path = abspath(depot, "packages", pkg.name, slug) ispath(path) && return path diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 750c6e83df99b..0b7a4ae8345e6 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -183,7 +183,7 @@ isempty(s::AbstractString) = iszero(ncodeunits(s)::Int) function getindex(s::AbstractString, i::Integer) @boundscheck checkbounds(s, i) - @inbounds return isvalid(s, i) ? iterate(s, i)[1] : string_index_err(s, i) + @inbounds return isvalid(s, i) ? (iterate(s, i)::NTuple{2,Any})[1] : string_index_err(s, i) end getindex(s::AbstractString, i::Colon) = s diff --git a/base/strings/util.jl b/base/strings/util.jl index 5cea8d280f07c..2d043b5a360a9 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -665,8 +665,8 @@ function hex2bytes!(dest::AbstractArray{UInt8}, itr) next = iterate(itr) @inbounds for i in eachindex(dest) - x,state = next - y,state = iterate(itr, state) + x,state = next::NTuple{2,Any} + y,state = iterate(itr, state)::NTuple{2,Any} next = iterate(itr, state) dest[i] = number_from_hex(x) << 4 + number_from_hex(y) end diff --git a/base/toml_parser.jl b/base/toml_parser.jl index 041211a72e869..8fcfc4ca0c29c 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -321,7 +321,7 @@ function Base.showerror(io::IO, err::ParserError) printstyled(io, " error: "; color=Base.error_color()) println(io, format_error_message_for_err_type(err)) # In this case we want the arrow to point one character - pos = err.pos + pos = err.pos::Int err.type == ErrUnexpectedEofExpectedValue && (pos += 1) str1, err1 = point_to_line(err.str, pos, pos, io) @static if VERSION <= v"1.6.0-DEV.121" diff --git a/base/version.jl b/base/version.jl index 86343dcddabf4..f3dda52c4ea10 100644 --- a/base/version.jl +++ b/base/version.jl @@ -110,7 +110,7 @@ function tryparse(::Type{VersionNumber}, v::AbstractString) m = match(VERSION_REGEX, v) m === nothing && return nothing major, minor, patch, minus, prerl, plus, build = m.captures - major = parse(VInt, major) + major = parse(VInt, major::AbstractString) minor = minor !== nothing ? parse(VInt, minor) : VInt(0) patch = patch !== nothing ? parse(VInt, patch) : VInt(0) if prerl !== nothing && !isempty(prerl) && prerl[1] == '-' diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 482e7da44390d..8b68287aad8d7 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -171,7 +171,7 @@ function check_worker_state(w::Worker) end end -exec_conn_func(id::Int) = exec_conn_func(worker_from_id(id)) +exec_conn_func(id::Int) = exec_conn_func(worker_from_id(id)::Worker) function exec_conn_func(w::Worker) try f = notnothing(w.conn_func) diff --git a/stdlib/Distributed/src/remotecall.jl b/stdlib/Distributed/src/remotecall.jl index 9b2127d4f499a..91e5de36736bd 100644 --- a/stdlib/Distributed/src/remotecall.jl +++ b/stdlib/Distributed/src/remotecall.jl @@ -259,7 +259,7 @@ function send_del_client(rr) if rr.where == myid() del_client(rr) elseif id_in_procs(rr.where) # process only if a valid worker - w = worker_from_id(rr.where) + w = worker_from_id(rr.where)::Worker push!(w.del_msgs, (remoteref_id(rr), myid())) w.gcflag = true notify(any_gc_flag) diff --git a/stdlib/LibGit2/src/error.jl b/stdlib/LibGit2/src/error.jl index 3dbc92947fcb2..d742cde1605b8 100644 --- a/stdlib/LibGit2/src/error.jl +++ b/stdlib/LibGit2/src/error.jl @@ -95,8 +95,8 @@ function last_error() return (err_class, err_msg) end -function GitError(code::Integer) - err_code = Code(code) +GitError(err_code::Integer) = GitError(Code(err_code)) +function GitError(err_code::Code) err_class, err_msg = last_error() return GitError(err_class, err_code, err_msg) end From aa7d8797223422a31573b0593ce7267b6c0ea63a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 15 Apr 2021 09:59:40 +0200 Subject: [PATCH 178/439] prevent conj! into uninitialized memory (#40481) --- stdlib/LinearAlgebra/src/matmul.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/matmul.jl b/stdlib/LinearAlgebra/src/matmul.jl index 27bd9c2f23b15..e755cc88c6572 100644 --- a/stdlib/LinearAlgebra/src/matmul.jl +++ b/stdlib/LinearAlgebra/src/matmul.jl @@ -683,7 +683,7 @@ function copyto!(B::AbstractVecOrMat, ir_dest::UnitRange{Int}, jr_dest::UnitRang copyto!(B, ir_dest, jr_dest, M, ir_src, jr_src) else LinearAlgebra.copy_transpose!(B, ir_dest, jr_dest, M, jr_src, ir_src) - tM == 'C' && conj!(B) + tM == 'C' && conj!(@view B[ir_dest, jr_dest]) end B end @@ -693,7 +693,7 @@ function copy_transpose!(B::AbstractMatrix, ir_dest::UnitRange{Int}, jr_dest::Un LinearAlgebra.copy_transpose!(B, ir_dest, jr_dest, M, ir_src, jr_src) else copyto!(B, ir_dest, jr_dest, M, jr_src, ir_src) - tM == 'C' && conj!(B) + tM == 'C' && conj!(@view B[ir_dest, jr_dest]) end B end From 17ede14702b2ce32f4acd74952011660d71530d0 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Thu, 15 Apr 2021 23:51:29 +0900 Subject: [PATCH 179/439] fix %a/%A format for zeros --- stdlib/Printf/src/Printf.jl | 5 ++++- stdlib/Printf/test/runtests.jl | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index e00b6becbb0f1..f77fa89aa1fe5 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -425,7 +425,7 @@ const __BIG_FLOAT_MAX__ = 8192 x = round(x, sigdigits=prec) newpos = Ryu.writeshortest(buf, pos, x, plus, space, hash, prec, T == Val{'g'} ? UInt8('e') : UInt8('E'), true, UInt8('.')) elseif T == Val{'a'} || T == Val{'A'} - x, neg = x < 0 ? (-x, true) : (x, false) + x, neg = x < 0 || x === -Base.zero(x) ? (-x, true) : (x, false) newpos = pos if neg buf[newpos] = UInt8('-') @@ -456,6 +456,8 @@ const __BIG_FLOAT_MAX__ = 8192 buf[newpos] = UInt8('0') newpos += 1 if prec > 0 + buf[newpos] = UInt8('.') + newpos += 1 while prec > 0 buf[newpos] = UInt8('0') newpos += 1 @@ -465,6 +467,7 @@ const __BIG_FLOAT_MAX__ = 8192 buf[newpos] = T <: Val{'a'} ? UInt8('p') : UInt8('P') buf[newpos + 1] = UInt8('+') buf[newpos + 2] = UInt8('0') + newpos += 3 else if prec > -1 s, p = frexp(x) diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index f6645464b4797..5fd9d9fd2eef5 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -27,6 +27,9 @@ end @testset "%a" begin # hex float + @test (Printf.@sprintf "%a" 0.0) == "0x0p+0" + @test (Printf.@sprintf "%a" -0.0) == "-0x0p+0" + @test (Printf.@sprintf "%.3a" 0.0) == "0x0.000p+0" @test (Printf.@sprintf "%a" 1.5) == "0x1.8p+0" @test (Printf.@sprintf "%a" 1.5f0) == "0x1.8p+0" @test (Printf.@sprintf "%a" big"1.5") == "0x1.8p+0" From b6735765cacda66fd1a4cb045165efb234d6df8b Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Thu, 15 Apr 2021 17:15:01 +0100 Subject: [PATCH 180/439] Relax constrain on `lq` to allwo `AbstractMatrix` (#32120) Co-authored-by: Jameson Nash --- stdlib/LinearAlgebra/src/lq.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lq.jl b/stdlib/LinearAlgebra/src/lq.jl index 21ba6a27ac580..35f1dd56dc045 100644 --- a/stdlib/LinearAlgebra/src/lq.jl +++ b/stdlib/LinearAlgebra/src/lq.jl @@ -107,8 +107,10 @@ julia> l == S.L && q == S.Q true ``` """ -lq(A::StridedMatrix{<:BlasFloat}) = lq!(copy(A)) -lq(x::Number) = lq(fill(x,1,1)) +lq(A::AbstractMatrix{T}) where {T} = lq!(copy_oftype(A, lq_eltype(T))) +lq(x::Number) = lq!(fill(convert(lq_eltype(typeof(x)), x), 1, 1)) + +lq_eltype(::Type{T}) where {T} = typeof(zero(T) / sqrt(abs2(one(T)))) copy(A::LQ) = LQ(copy(A.factors), copy(A.τ)) From ed7b069f9c857ab0eec7972350b21d9e92d696cc Mon Sep 17 00:00:00 2001 From: Logan Kilpatrick <23kilpatrick23@gmail.com> Date: Thu, 15 Apr 2021 13:12:19 -0700 Subject: [PATCH 181/439] Add examples for `@text_str` and `@html_str` (#38254) Co-authored-by: Max Horn --- base/docs/utils.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 841af2d2c2b9b..cac029295d81e 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -43,6 +43,12 @@ show(io::IO, ::MIME"text/html", h::HTML{<:Function}) = h.content(io) @html_str -> Docs.HTML Create an `HTML` object from a literal string. + +# Examples +```jldoctest +julia> html"Julia" +HTML{String}("Julia") +``` """ macro html_str(s) :(HTML($s)) @@ -89,6 +95,12 @@ hash(t::T, h::UInt) where {T<:Union{HTML,Text}} = hash(T, hash(t.content, h)) @text_str -> Docs.Text Create a `Text` object from a literal string. + +# Examples +```jldoctest +julia> text"Julia" +Julia +``` """ macro text_str(s) :(Text($s)) From 29d5158d27ddc3983ae2e373c4cd05569b9ead6c Mon Sep 17 00:00:00 2001 From: Logan Kilpatrick <23kilpatrick23@gmail.com> Date: Thu, 15 Apr 2021 13:13:33 -0700 Subject: [PATCH 182/439] Add docstring example to VecOrMat (#38253) Co-authored-by: kimikage --- base/array.jl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index afaa3b5f19d6b..7fd3ea8fb0bc2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -64,10 +64,23 @@ Two-dimensional dense array with elements of type `T`, often used to represent a mathematical matrix. Alias for [`Array{T,2}`](@ref). """ const Matrix{T} = Array{T,2} + """ VecOrMat{T} -Union type of [`Vector{T}`](@ref) and [`Matrix{T}`](@ref). +Union type of [`Vector{T}`](@ref) and [`Matrix{T}`](@ref) which allows functions to accept either a Matrix or a Vector. + +# Examples +```jldoctest +julia> Vector{Float64} <: VecOrMat{Float64} +true + +julia> Matrix{Float64} <: VecOrMat{Float64} +true + +julia> Array{Float64, 3} <: VecOrMat{Float64} +false +``` """ const VecOrMat{T} = Union{Vector{T}, Matrix{T}} From 67f29d8aa4e7e5e9ffdfc0c2f783c455469e4ca0 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 16 Apr 2021 12:42:17 -0400 Subject: [PATCH 183/439] [CLI] error on not finding symbol (#38994) Also removes some excess exports that are not in julia.h, including intrinsics and the unused `jl_cpuid` function (only defined on Intel processors). --- cli/loader_lib.c | 7 +- src/jl_exported_funcs.inc | 222 +------------------------------------- src/threading.c | 4 + 3 files changed, 11 insertions(+), 222 deletions(-) diff --git a/cli/loader_lib.c b/cli/loader_lib.c index 0249c11f3f6c3..ba00516d6b916 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -160,7 +160,12 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { // Once we have libjulia-internal loaded, re-export its symbols: for (unsigned int symbol_idx=0; jl_exported_func_names[symbol_idx] != NULL; ++symbol_idx) { - (*jl_exported_func_addrs[symbol_idx]) = lookup_symbol(libjulia_internal, jl_exported_func_names[symbol_idx]); + void *addr = lookup_symbol(libjulia_internal, jl_exported_func_names[symbol_idx]); + if (addr == NULL) { + jl_loader_print_stderr3("ERROR: Unable to load ", jl_exported_func_names[symbol_idx], " from libjulia-internal"); + exit(1); + } + (*jl_exported_func_addrs[symbol_idx]) = addr; } } diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index bf56eb19564a5..8a23a0f5e9b65 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -1,12 +1,6 @@ #define JL_EXPORTED_FUNCS(XX) \ - XX(jl_) \ - XX(jl_abs_float) \ - XX(jl_abs_float_withtype) \ XX(jl_active_task_stack) \ - XX(jl_add_float) \ - XX(jl_add_int) \ XX(jl_add_optimization_passes) \ - XX(jl_add_ptr) \ XX(jl_add_standard_imports) \ XX(jl_alignment) \ XX(jl_alloc_array_1d) \ @@ -16,7 +10,6 @@ XX(jl_alloc_svec) \ XX(jl_alloc_svec_uninit) \ XX(jl_alloc_vec_any) \ - XX(jl_and_int) \ XX(jl_apply_array_type) \ XX(jl_apply_generic) \ XX(jl_apply_tuple_type) \ @@ -50,7 +43,6 @@ XX(jl_array_to_string) \ XX(jl_array_typetagdata) \ XX(jl_arrayunset) \ - XX(jl_ashr_int) \ XX(jl_astaggedvalue) \ XX(jl_atexit_hook) \ XX(jl_backtrace_from_here) \ @@ -81,8 +73,6 @@ XX(jl_box_uint8) \ XX(jl_box_uint8pointer) \ XX(jl_box_voidpointer) \ - XX(jl_breakpoint) \ - XX(jl_bswap_int) \ XX(jl_call) \ XX(jl_call0) \ XX(jl_call1) \ @@ -96,16 +86,6 @@ XX(jl_cglobal) \ XX(jl_cglobal_auto) \ XX(jl_checked_assignment) \ - XX(jl_checked_sadd_int) \ - XX(jl_checked_sdiv_int) \ - XX(jl_checked_smul_int) \ - XX(jl_checked_srem_int) \ - XX(jl_checked_ssub_int) \ - XX(jl_checked_uadd_int) \ - XX(jl_checked_udiv_int) \ - XX(jl_checked_umul_int) \ - XX(jl_checked_urem_int) \ - XX(jl_checked_usub_int) \ XX(jl_clear_implicit_imports) \ XX(jl_clear_malloc_data) \ XX(jl_clock_now) \ @@ -117,9 +97,6 @@ XX(jl_compute_fieldtypes) \ XX(jl_copy_ast) \ XX(jl_copy_code_info) \ - XX(jl_copysign_float) \ - XX(jl_cpuid) \ - XX(jl_cpuidex) \ XX(jl_cpu_pause) \ XX(jl_cpu_threads) \ XX(jl_cpu_wake) \ @@ -127,15 +104,11 @@ XX(jl_create_native) \ XX(jl_create_system_image) \ XX(jl_cstr_to_string) \ - XX(jl_ctlz_int) \ - XX(jl_ctpop_int) \ - XX(jl_cttz_int) \ XX(jl_current_exception) \ XX(jl_debug_method_invalidation) \ XX(jl_declare_constant) \ XX(jl_defines_or_exports_p) \ XX(jl_deprecate_binding) \ - XX(jl_div_float) \ XX(jl_dlclose) \ XX(jl_dlopen) \ XX(jl_dlsym) \ @@ -154,8 +127,6 @@ XX(jl_enter_threaded_region) \ XX(jl_environ) \ XX(jl_eof_error) \ - XX(jl_eq_float) \ - XX(jl_eq_int) \ XX(jl_eqtable_get) \ XX(jl_eqtable_nextind) \ XX(jl_eqtable_pop) \ @@ -178,83 +149,6 @@ XX(jl_expand_with_loc) \ XX(jl_expand_with_loc_warn) \ XX(jl_extern_c) \ - XX(jl_f__abstracttype) \ - XX(jl_f__apply) \ - XX(jl_f__apply_iterate) \ - XX(jl_f__apply_pure) \ - XX(jl_f__call_in_world) \ - XX(jl_f__call_latest) \ - XX(jl_f_applicable) \ - XX(jl_f_apply_type) \ - XX(jl_f_arrayref) \ - XX(jl_f_arrayset) \ - XX(jl_f_arraysize) \ - XX(jl_f_const_arrayref) \ - XX(jl_f__equiv_typedef) \ - XX(jl_f__expr) \ - XX(jl_f_fieldtype) \ - XX(jl_f_getfield) \ - XX(jl_field_index) \ - XX(jl_field_isdefined) \ - XX(jl_f_ifelse) \ - XX(jl_finalize) \ - XX(jl_finalize_th) \ - XX(jl_find_free_typevars) \ - XX(jl_f_intrinsic_call) \ - XX(jl_f_invoke) \ - XX(jl_f_invoke_kwsorter) \ - XX(jl_first_argument_datatype) \ - XX(jl_f_is) \ - XX(jl_f_isa) \ - XX(jl_f_isdefined) \ - XX(jl_f_issubtype) \ - XX(jl_flipsign_int) \ - XX(jl_floor_llvm) \ - XX(jl_floor_llvm_withtype) \ - XX(jl_fl_parse) \ - XX(jl_flush_cstdio) \ - XX(jl_fma_float) \ - XX(jl_f_new_module) \ - XX(jl_f_nfields) \ - XX(jl_forceclose_uv) \ - XX(jl_format_filename) \ - XX(jl_fpext) \ - XX(jl_fpiseq) \ - XX(jl_fpislt) \ - XX(jl_f__primitivetype) \ - XX(jl_fptosi) \ - XX(jl_fptoui) \ - XX(jl_fptr_args) \ - XX(jl_fptr_const_return) \ - XX(jl_fptr_interpret_call) \ - XX(jl_fptr_sparam) \ - XX(jl_fptrunc) \ - XX(jl_free) \ - XX(jl_free_stack) \ - XX(jl_fs_access) \ - XX(jl_fs_chmod) \ - XX(jl_fs_chown) \ - XX(jl_fs_close) \ - XX(jl_f_setfield) \ - XX(jl_f__setsuper) \ - XX(jl_f_sizeof) \ - XX(jl_fs_read) \ - XX(jl_fs_read_byte) \ - XX(jl_fs_rename) \ - XX(jl_fs_sendfile) \ - XX(jl_fs_symlink) \ - XX(jl_fstat) \ - XX(jl_f__structtype) \ - XX(jl_fs_unlink) \ - XX(jl_f_svec) \ - XX(jl_fs_write) \ - XX(jl_f_throw) \ - XX(jl_ftruncate) \ - XX(jl_f_tuple) \ - XX(jl_f_typeassert) \ - XX(jl_f__typebody) \ - XX(jl_f_typeof) \ - XX(jl_f__typevar) \ XX(jl_gc_add_finalizer) \ XX(jl_gc_add_finalizer_th) \ XX(jl_gc_add_ptr_finalizer) \ @@ -311,7 +205,6 @@ XX(jl_generating_output) \ XX(jl_generic_function_def) \ XX(jl_gensym) \ - XX(jl_getaddrinfo) \ XX(jl_getallocationgranularity) \ XX(jl_get_ARCH) \ XX(jl_get_backtrace) \ @@ -419,12 +312,7 @@ XX(jl_is_unary_and_binary_operator) \ XX(jl_is_unary_operator) \ XX(jl_lazy_load_and_lookup) \ - XX(jl_le_float) \ XX(jl_lisp_prompt) \ - XX(jl_LLVMCreateDisasm) \ - XX(jl_LLVMDisasmInstruction) \ - XX(jl_LLVMFlipSign) \ - XX(jl_LLVMSMod) \ XX(jl_load) \ XX(jl_load_) \ XX(jl_load_and_lookup) \ @@ -432,9 +320,7 @@ XX(jl_load_file_string) \ XX(jl_lookup_code_address) \ XX(jl_lseek) \ - XX(jl_lshr_int) \ XX(jl_lstat) \ - XX(jl_lt_float) \ XX(jl_macroexpand) \ XX(jl_macroexpand1) \ XX(jl_malloc) \ @@ -449,7 +335,6 @@ XX(jl_method_table_insert) \ XX(jl_methtable_lookup) \ XX(jl_mi_cache_insert) \ - XX(jl_mmap) \ XX(jl_module_build_id) \ XX(jl_module_export) \ XX(jl_module_exports_p) \ @@ -462,16 +347,8 @@ XX(jl_module_using) \ XX(jl_module_usings) \ XX(jl_module_uuid) \ - XX(jl_muladd_float) \ - XX(jl_mul_float) \ - XX(jl_mul_int) \ XX(jl_native_alignment) \ XX(jl_nb_available) \ - XX(jl_ne_float) \ - XX(jl_neg_float) \ - XX(jl_neg_float_withtype) \ - XX(jl_neg_int) \ - XX(jl_ne_int) \ XX(jl_new_array) \ XX(jl_new_bits) \ XX(jl_new_code_info_uninit) \ @@ -493,13 +370,11 @@ XX(jl_next_from_addrinfo) \ XX(jl_no_exc_handler) \ XX(jl_normalize_to_compilable_sig) \ - XX(jl_not_int) \ XX(jl_object_id) \ XX(jl_object_id_) \ XX(jl_obvious_subtype) \ XX(jl_operator_precedence) \ XX(jl_op_suffix_char) \ - XX(jl_or_int) \ XX(jl_parse) \ XX(jl_parse_all) \ XX(jl_parse_input_line) \ @@ -527,15 +402,12 @@ XX(jl_ptrarrayref) \ XX(jl_ptr_to_array) \ XX(jl_ptr_to_array_1d) \ - XX(jl_pwrite) \ XX(jl_queue_work) \ XX(jl_raise_debugger) \ XX(jl_readuntil) \ XX(jl_read_verify_header) \ XX(jl_realloc) \ XX(jl_register_newmeth_tracer) \ - XX(jl_rem_float) \ - XX(jl_repl_raise_sigtstp) \ XX(jl_reshape_array) \ XX(jl_restore_excstack) \ XX(jl_restore_incremental) \ @@ -545,14 +417,11 @@ XX(jl_rethrow) \ XX(jl_rethrow_other) \ XX(jl_rettype_inferred) \ - XX(jl_rint_llvm) \ - XX(jl_rint_llvm_withtype) \ XX(jl_running_on_valgrind) \ XX(jl_safe_printf) \ XX(jl_save_incremental) \ XX(jl_save_system_image) \ XX(jl_SC_CLK_TCK) \ - XX(jl_sdiv_int) \ XX(jl_set_ARGS) \ XX(jl_set_const) \ XX(jl_set_errno) \ @@ -571,52 +440,14 @@ XX(jl_set_task_tid) \ XX(jl_set_typeinf_func) \ XX(jl_set_zero_subnormals) \ - XX(jl_sext_int) \ - XX(jl_shl_int) \ XX(jl_sigatomic_begin) \ XX(jl_sigatomic_end) \ XX(jl_sig_throw) \ - XX(jl_sitofp) \ - XX(jl_sizeof_ios_t) \ - XX(jl_sizeof_jl_options) \ - XX(jl_sizeof_mode_t) \ - XX(jl_sizeof_off_t) \ - XX(jl_sizeof_stat) \ - XX(jl_sizeof_uv_fs_t) \ - XX(jl_sle_int) \ - XX(jl_slt_int) \ - XX(jl_smod_int) \ - XX(jl_sockaddr_from_addrinfo) \ - XX(jl_sockaddr_host4) \ - XX(jl_sockaddr_host6) \ - XX(jl_sockaddr_is_ip4) \ - XX(jl_sockaddr_is_ip6) \ - XX(jl_sockaddr_port4) \ - XX(jl_sockaddr_port6) \ - XX(jl_sockaddr_set_port) \ XX(jl_spawn) \ XX(jl_specializations_get_linfo) \ XX(jl_specializations_lookup) \ - XX(jl_sqrt_llvm) \ - XX(jl_sqrt_llvm_fast) \ - XX(jl_sqrt_llvm_fast_withtype) \ - XX(jl_sqrt_llvm_withtype) \ - XX(jl_srem_int) \ - XX(jl_stat) \ - XX(jl_stat_blksize) \ - XX(jl_stat_blocks) \ - XX(jl_stat_ctime) \ - XX(jl_stat_dev) \ - XX(jl_stat_gid) \ XX(jl_static_show) \ XX(jl_static_show_func_sig) \ - XX(jl_stat_ino) \ - XX(jl_stat_mode) \ - XX(jl_stat_mtime) \ - XX(jl_stat_nlink) \ - XX(jl_stat_rdev) \ - XX(jl_stat_size) \ - XX(jl_stat_uid) \ XX(jl_stderr_obj) \ XX(jl_stderr_stream) \ XX(jl_stdin_stream) \ @@ -627,9 +458,6 @@ XX(jl_string_to_array) \ XX(jl_strtod_c) \ XX(jl_strtof_c) \ - XX(jl_sub_float) \ - XX(jl_sub_int) \ - XX(jl_sub_ptr) \ XX(jl_substrtod) \ XX(jl_substrtof) \ XX(jl_subtype) \ @@ -653,12 +481,6 @@ XX(jl_take_buffer) \ XX(jl_task_get_next) \ XX(jl_task_stack_buffer) \ - XX(jl_tcp_bind) \ - XX(jl_tcp_connect) \ - XX(jl_tcp_getpeername) \ - XX(jl_tcp_getsockname) \ - XX(jl_tcp_quickack) \ - XX(jl_tcp_reuseport) \ XX(jl_test_cpu_feature) \ XX(jl_threadid) \ XX(jl_threading_enabled) \ @@ -668,9 +490,6 @@ XX(jl_too_many_args) \ XX(jl_toplevel_eval) \ XX(jl_toplevel_eval_in) \ - XX(jl_trunc_int) \ - XX(jl_trunc_llvm) \ - XX(jl_trunc_llvm_withtype) \ XX(jl_try_substrtod) \ XX(jl_try_substrtof) \ XX(jl_tty_set_mode) \ @@ -683,7 +502,6 @@ XX(jl_typeinf_end) \ XX(jl_type_intersection) \ XX(jl_type_intersection_with_env) \ - XX(jl_typemax_uint) \ XX(jl_type_morespecific) \ XX(jl_type_morespecific_no_subtype) \ XX(jl_typename_str) \ @@ -693,12 +511,6 @@ XX(jl_type_to_llvm) \ XX(jl_type_union) \ XX(jl_type_unionall) \ - XX(jl_udiv_int) \ - XX(jl_udp_bind) \ - XX(jl_udp_send) \ - XX(jl_uitofp) \ - XX(jl_ule_int) \ - XX(jl_ult_int) \ XX(jl_unbox_bool) \ XX(jl_unbox_float32) \ XX(jl_unbox_float64) \ @@ -716,36 +528,6 @@ XX(jl_uncompress_argnames) \ XX(jl_uncompress_ir) \ XX(jl_undefined_var_error) \ - XX(jl_urem_int) \ - XX(jl_uv_associate_julia_struct) \ - XX(jl_uv_buf_base) \ - XX(jl_uv_buf_len) \ - XX(jl_uv_buf_set_base) \ - XX(jl_uv_buf_set_len) \ - XX(jl_uv_connect_handle) \ - XX(jl_uv_disassociate_julia_struct) \ - XX(jl_uv_file_handle) \ - XX(jl_uv_flush) \ - XX(jl_uv_fs_t_path) \ - XX(jl_uv_fs_t_ptr) \ - XX(jl_uv_handle) \ - XX(jl_uv_handle_data) \ - XX(jl_uv_handle_type) \ - XX(jl_uv_interface_addresses) \ - XX(jl_uv_interface_address_is_internal) \ - XX(jl_uv_interface_address_sockaddr) \ - XX(jl_uv_process_data) \ - XX(jl_uv_process_pid) \ - XX(jl_uv_putb) \ - XX(jl_uv_putc) \ - XX(jl_uv_puts) \ - XX(jl_uv_req_data) \ - XX(jl_uv_req_set_data) \ - XX(jl_uv_sizeof_interface_address) \ - XX(jl_uv_unix_fd_is_watched) \ - XX(jl_uv_write) \ - XX(jl_uv_writecb) \ - XX(jl_uv_write_handle) \ XX(jl_valueof) \ XX(jl_value_ptr) \ XX(jl_ver_is_release) \ @@ -756,6 +538,4 @@ XX(jl_vexceptionf) \ XX(jl_vprintf) \ XX(jl_wakeup_thread) \ - XX(jl_xor_int) \ - XX(jl_yield) \ - XX(jl_zext_int) + XX(jl_yield) diff --git a/src/threading.c b/src/threading.c index bffc1b02d909a..85855ed5b7e09 100644 --- a/src/threading.c +++ b/src/threading.c @@ -81,6 +81,8 @@ jl_get_ptls_states_func jl_get_ptls_states_getter(void) // for codegen return &jl_get_ptls_states_fast; } + +JL_DLLEXPORT void jl_set_ptls_states_getter(jl_get_ptls_states_func f) { } #elif defined(_OS_WINDOWS_) // Apparently windows doesn't have a static TLS model (or one that can be // reliably used from a shared library) either..... Use `TLSAlloc` instead. @@ -138,6 +140,8 @@ jl_get_ptls_states_func jl_get_ptls_states_getter(void) // for codegen return &jl_get_ptls_states; } + +JL_DLLEXPORT void jl_set_ptls_states_getter(jl_get_ptls_states_func f) { } #else // We use the faster static version in the main executable to replace // the slower version in the shared object. The code in different libraries From d41fac3c9388dc620361217606a120b811d5efe5 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 16 Apr 2021 18:43:13 +0200 Subject: [PATCH 184/439] document how to use `@test_logs` to check for no warnings (#39025) closes #37307 Co-authored-by: Jameson Nash --- stdlib/Test/src/logging.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index 7e8659a4c2f2a..f7ecf90e2bc7f 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -135,21 +135,26 @@ We can test the info message using If we also wanted to test the debug messages, these need to be enabled with the `min_level` keyword: - @test_logs (:info,"Doing foo with n=2") (:debug,"Iteration 1") (:debug,"Iteration 2") min_level=Debug foo(2) + @test_logs (:info,"Doing foo with n=2") (:debug,"Iteration 1") (:debug,"Iteration 2") min_level=Logging.Debug foo(2) If you want to test that some particular messages are generated while ignoring the rest, you can set the keyword `match_mode=:any`: - @test_logs (:info,) (:debug,"Iteration 42") min_level=Debug match_mode=:any foo(100) + @test_logs (:info,) (:debug,"Iteration 42") min_level=Logging.Debug match_mode=:any foo(100) The macro may be chained with `@test` to also test the returned value: @test (@test_logs (:info,"Doing foo with n=2") foo(2)) == 42 -If you want to test an absence of logger messages, you can pass no log_patterns: +If you want to test for the absence of warnings, you can omit specifying log +patterns and set the `min_level` accordingly: - @test_logs min_level=Logging.Warn f() # test `f` logs no messages when the logger level is warn. + # test that the expression logs no messages when the logger level is warn: + @test_logs min_level=Logging.Warn @info("Some information") # passes + @test_logs min_level=Logging.Warn @warn("Some information") # fails +If you want to test the absence of warnings (or error messages) in +[`stderr`](@ref) which are not generated by `@warn`, see [`@test_nowarn`](@ref). """ macro test_logs(exs...) length(exs) >= 1 || throw(ArgumentError("""`@test_logs` needs at least one arguments. @@ -265,4 +270,3 @@ macro test_deprecated(exs...) res.args[4].args[3].args[2].args[2].args[2] = __source__ res end - From 9d3a7c47df972b1108b5a49d2c5ce493635bbadf Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Fri, 16 Apr 2021 18:45:32 +0200 Subject: [PATCH 185/439] Extend `Eigen` to keep additional information from `geevx` (#38483) Closes #13307 Fixes #38335 --- stdlib/LinearAlgebra/src/eigen.jl | 115 ++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 22 deletions(-) diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 3a423a87295f3..9cd1c9bc20f4b 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -17,7 +17,7 @@ Iterating the decomposition produces the components `F.values` and `F.vectors`. # Examples ```jldoctest julia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) -Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}} +Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}, Vector{Float64}} values: 3-element Vector{Float64}: 1.0 @@ -47,14 +47,18 @@ julia> vals == F.values && vecs == F.vectors true ``` """ -struct Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} +struct Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector,R<:AbstractVector} <: Factorization{T} values::U vectors::S - Eigen{T,V,S,U}(values::AbstractVector{V}, vectors::AbstractMatrix{T}) where {T,V,S,U} = - new(values, vectors) + vectorsl::S + unitary::Bool + rconde::R + rcondv::R + Eigen{T,V,S,U,R}(values::AbstractVector{V}, vectors::AbstractMatrix{T}, vectorsl::AbstractMatrix{T}, unitary::Bool, rconde::R, rcondv::R) where {T,V,S,U,R} = + new(values, vectors, vectorsl, unitary, rconde, rcondv) end -Eigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) where {T,V} = - Eigen{T,V,typeof(vectors),typeof(values)}(values, vectors) +Eigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}, vectorsl=vectors, uni=true, rce=zeros(real(T),0), rcv=zeros(real(T), 0)) where {T,V} = + Eigen{T,V,typeof(vectors),typeof(values),typeof(rce)}(values, vectors, vectorsl, uni, rce, rcv) # Generalized eigenvalue problem. """ @@ -133,24 +137,55 @@ function sorteig!(λ::AbstractVector, X::AbstractMatrix, sortby::Union{Function, if sortby !== nothing && !issorted(λ, by=sortby) p = sortperm(λ; alg=QuickSort, by=sortby) permute!(λ, p) - Base.permutecols!!(X, p) + !isempty(X) && Base.permutecols!!(X, copy(p)) end return λ, X end +function sorteig!(λ::AbstractVector, X::AbstractMatrix, sortby::Union{Function,Nothing}, Y::AbstractMatrix, rconde::AbstractVector, rcondv::AbstractVector) + if sortby !== nothing && !issorted(λ, by=sortby) + p = sortperm(λ; alg=QuickSort, by=sortby) + permute!(λ, p) + !isempty(rconde) && permute!(rconde, p) + !isempty(rcondv) && permute!(rcondv, p) + !isempty(X) && Base.permutecols!!(X, copy(p)) + !isempty(Y) && X !== Y && Base.permutecols!!(Y, p) + end + return λ, X, Y, false, rconde, rcondv +end sorteig!(λ::AbstractVector, sortby::Union{Function,Nothing}=eigsortby) = sortby === nothing ? λ : sort!(λ, by=sortby) """ eigen!(A, [B]; permute, scale, sortby) -Same as [`eigen`](@ref), but saves space by overwriting the input `A` (and +came as [`eigen`](@ref), but saves space by overwriting the input `A` (and `B`), instead of creating a copy. """ -function eigen!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby) where T<:BlasReal +function eigen!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby, jvl::Bool=false, jvr::Bool=true, jce::Bool=false, jcv::Bool=false) where T<:BlasReal n = size(A, 2) n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) issymmetric(A) && return eigen!(Symmetric(A), sortby=sortby) - A, WR, WI, VL, VR, _ = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A) - iszero(WI) && return Eigen(sorteig!(WR, VR, sortby)...) + + balance = permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N') + jobvl = jvl || jce ? 'V' : 'N' + jobvr = jvr || jce ? 'V' : 'N' + sense = jce && jcv ? 'B' : jce ? 'E' : jcv ? 'V' : 'N' + A, WR, WI, VL, VR, _, _, scale, abnrm, rconde, rcondv = LAPACK.geevx!(balance, jobvl, jobvr, sense, A) + if iszero(WI) + evecr = VR + evecl = VL + evals = WR + else + evecr = complexeig(WI, VR) + evecl = complexeig(WI, VL) + evals = complex.(WR, WI) + end + rconde = jce ? inv.(rconde) : zeros(T, 0) + rcondv = jcv ? inv.(rcondv) : zeros(T, 0) + return Eigen(sorteig!(evals, evecr, sortby, evecl, rconde, rcondv)...) +end + +function complexeig(WI::Vector{T}, VR::Matrix{T}) where T + n = min(size(VR)...) evec = zeros(Complex{T}, n, n) j = 1 while j <= n @@ -165,15 +200,19 @@ function eigen!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true, sortb end j += 1 end - return Eigen(sorteig!(complex.(WR, WI), evec, sortby)...) + evec end -function eigen!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby) where T<:BlasComplex +function eigen!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby, jvl::Bool=false, jvr::Bool=true, jce::Bool=false, jcv::Bool=false) where T<:BlasComplex n = size(A, 2) n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) ishermitian(A) && return eigen!(Hermitian(A), sortby=sortby) - eval, evec = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A)[[2,4]] - return Eigen(sorteig!(eval, evec, sortby)...) + balance = permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N') + jobvl = jvl || jce ? 'V' : 'N' + jobvr = jvr || jce ? 'V' : 'N' + sense = jce && jcv ? 'B' : jce ? 'E' : jcv ? 'V' : 'N' + A, W, VL, VR, _, _, scale, abnrm, rconde, rcondv = LAPACK.geevx!(balance, jobvl, jobvr, sense, A) + return Eigen(sorteig!(W, VR, sortby, VL, rconde, rcondv)...) end """ @@ -201,7 +240,7 @@ accept a `sortby` keyword. # Examples ```jldoctest julia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) -Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}} +Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}, Vector{Float64}} values: 3-element Vector{Float64}: 1.0 @@ -231,10 +270,10 @@ julia> vals == F.values && vecs == F.vectors true ``` """ -function eigen(A::AbstractMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby) where T +function eigen(A::AbstractMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby, jvl::Bool=false, jvr::Bool=true, jce::Bool=false, jcv::Bool=false) where T AA = copy_oftype(A, eigtype(T)) isdiag(AA) && return eigen(Diagonal(AA); permute=permute, scale=scale, sortby=sortby) - return eigen!(AA; permute=permute, scale=scale, sortby=sortby) + return eigen!(AA; permute=permute, scale=scale, sortby=sortby, jvl=jvl, jvr=jvr, jce=jce, jcv=jcv) end eigen(x::Number) = Eigen([x], fill(one(x), 1, 1)) @@ -420,7 +459,19 @@ function eigmin(A::Union{Number, AbstractMatrix}; minimum(v) end -inv(A::Eigen) = A.vectors * inv(Diagonal(A.values)) / A.vectors +""" + spectral(f, F::Eigen) + +Construct a matrix from an eigen-decomposition `F` by applying the function to +the spectrum (diagonal) of `F`. +""" +function spectral(f, A::Eigen) + d = Diagonal(f.(A.values)) + v = A.vectors + vd = v * d + A.unitary ? vd * v' : vd / v +end +inv(A::Eigen) = spectral(inv, A) det(A::Eigen) = prod(A.values) # Generalized eigenproblem @@ -610,14 +661,34 @@ function show(io::IO, mime::MIME{Symbol("text/plain")}, F::Union{Eigen,Generaliz summary(io, F); println(io) println(io, "values:") show(io, mime, F.values) - println(io, "\nvectors:") - show(io, mime, F.vectors) + if !isdefined(F, :vectorsl) || (!isempty(F.vectors) && (F.vectors === F.vectorsl || isempty(F.vectorsl))) + println(io, "\nvectors:") + show(io, mime, F.vectors) + else + if !isempty(F.vectors) + println(io, "\nright vectors:") + show(io, mime, F.vectors) + end + if !isempty(F.vectorsl) + println(io, "\nleft vectors:") + show(io, mime, F.vectorsl) + end + end + if isdefined(F, :rconde) && !isempty(F.rconde) + println(io, "\ncondition values:") + show(io, mime, F.rconde) + end + if isdefined(F, :rcondv) && !isempty(F.rcondv) + println(io, "\ncondition vectors:") + show(io, mime, F.rcondv) + end + nothing end # Conversion methods ## Can we determine the source/result is Real? This is not stored in the type Eigen -AbstractMatrix(F::Eigen) = F.vectors * Diagonal(F.values) / F.vectors +AbstractMatrix(F::Eigen) = spectral(identity, F) AbstractArray(F::Eigen) = AbstractMatrix(F) Matrix(F::Eigen) = Array(AbstractArray(F)) Array(F::Eigen) = Matrix(F) From 07bf9da07824891bde01f1f8cdbada904054c1dd Mon Sep 17 00:00:00 2001 From: bramtayl Date: Fri, 16 Apr 2021 14:16:27 -0400 Subject: [PATCH 186/439] no LoadError wrapper in macroexpand errors (#38379) --- NEWS.md | 2 +- base/docs/basedocs.jl | 3 +++ src/ast.c | 30 +++++++++++++++--------------- stdlib/Test/src/Test.jl | 19 ++++++++++++++++++- stdlib/Test/test/runtests.jl | 20 ++++++++++++++++++++ test/core.jl | 6 ++---- test/docs.jl | 9 +-------- test/errorshow.jl | 6 ------ test/simdloop.jl | 13 ------------- test/syntax.jl | 7 ++----- test/threads_exec.jl | 3 +-- 11 files changed, 63 insertions(+), 55 deletions(-) diff --git a/NEWS.md b/NEWS.md index b4f09d1b1d106..eed4172c5a31e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,7 +14,7 @@ New language features Language changes ---------------- - +* `macroexpand`, `@macroexpand`, and `@macroexpand1` no longer wrap errors in a `LoadError`. To reduce breakage, `@test_throws` has been modified so that many affected tests will still pass ([#38379]]. Compiler/Runtime improvements ----------------------------- diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 5233b08e0ead3..99a08b03f4d0b 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -2276,6 +2276,9 @@ AssertionError An error occurred while [`include`](@ref Base.include)ing, [`require`](@ref Base.require)ing, or [`using`](@ref) a file. The error specifics should be available in the `.error` field. + +!!! compat "Julia 1.7" + LoadErrors are no longer emitted by `@macroexpand`, `@macroexpand1`, and `macroexpand` as of Julia 1.7. """ LoadError diff --git a/src/ast.c b/src/ast.c index cb96ec51976d3..307d731109933 100644 --- a/src/ast.c +++ b/src/ast.c @@ -135,7 +135,7 @@ struct macroctx_stack { static jl_value_t *scm_to_julia(fl_context_t *fl_ctx, value_t e, jl_module_t *mod); static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v); -static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world); +static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world, int throw_load_error); static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { @@ -1031,7 +1031,7 @@ int jl_has_meta(jl_array_t *body, jl_sym_t *sym) JL_NOTSAFEPOINT return 0; } -static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule, jl_module_t **ctx, size_t world) +static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule, jl_module_t **ctx, size_t world, int throw_load_error) { jl_ptls_t ptls = jl_get_ptls_states(); JL_TIMING(MACRO_INVOCATION); @@ -1066,7 +1066,7 @@ static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule result = jl_invoke(margs[0], &margs[1], nargs - 1, mfunc); } JL_CATCH { - if (jl_loaderror_type == NULL) { + if ((jl_loaderror_type == NULL) || !throw_load_error) { jl_rethrow(); } else { @@ -1086,7 +1086,7 @@ static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule return result; } -static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world) +static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world, int throw_load_error) { if (!expr || !jl_is_expr(expr)) return expr; @@ -1100,7 +1100,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str if (e->head == quote_sym && jl_expr_nargs(e) == 1) { expr = jl_call_scm_on_ast("julia-bq-macro", jl_exprarg(e, 0), inmodule); JL_GC_PUSH1(&expr); - expr = jl_expand_macros(expr, inmodule, macroctx, onelevel, world); + expr = jl_expand_macros(expr, inmodule, macroctx, onelevel, world, throw_load_error); JL_GC_POP(); return expr; } @@ -1110,7 +1110,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str JL_TYPECHK(hygienic-scope, module, (jl_value_t*)newctx.m); newctx.parent = macroctx; jl_value_t *a = jl_exprarg(e, 0); - jl_value_t *a2 = jl_expand_macros(a, inmodule, &newctx, onelevel, world); + jl_value_t *a2 = jl_expand_macros(a, inmodule, &newctx, onelevel, world, throw_load_error); if (a != a2) jl_array_ptr_set(e->args, 0, a2); return expr; @@ -1119,7 +1119,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str struct macroctx_stack newctx; newctx.m = macroctx ? macroctx->m : inmodule; newctx.parent = macroctx; - jl_value_t *result = jl_invoke_julia_macro(e->args, inmodule, &newctx.m, world); + jl_value_t *result = jl_invoke_julia_macro(e->args, inmodule, &newctx.m, world, throw_load_error); jl_value_t *wrap = NULL; JL_GC_PUSH3(&result, &wrap, &newctx.m); // copy and wrap the result in `(hygienic-scope ,result ,newctx) @@ -1129,7 +1129,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str wrap = (jl_value_t*)jl_exprn(hygienicscope_sym, 2); result = jl_copy_ast(result); if (!onelevel) - result = jl_expand_macros(result, inmodule, wrap ? &newctx : macroctx, onelevel, world); + result = jl_expand_macros(result, inmodule, wrap ? &newctx : macroctx, onelevel, world, throw_load_error); if (wrap) { jl_exprargset(wrap, 0, result); jl_exprargset(wrap, 1, newctx.m); @@ -1151,7 +1151,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str for (j = 2; j < nm; j++) { jl_exprargset(mc2, j+1, jl_exprarg(mc, j)); } - jl_value_t *ret = jl_expand_macros((jl_value_t*)mc2, inmodule, macroctx, onelevel, world); + jl_value_t *ret = jl_expand_macros((jl_value_t*)mc2, inmodule, macroctx, onelevel, world, throw_load_error); JL_GC_POP(); return ret; } @@ -1162,7 +1162,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str size_t i; for (i = 0; i < jl_array_len(e->args); i++) { jl_value_t *a = jl_array_ptr_ref(e->args, i); - jl_value_t *a2 = jl_expand_macros(a, inmodule, macroctx, onelevel, world); + jl_value_t *a2 = jl_expand_macros(a, inmodule, macroctx, onelevel, world, throw_load_error); if (a != a2) jl_array_ptr_set(e->args, i, a2); } @@ -1174,7 +1174,7 @@ JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr, jl_module_t *inmodule) JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0, jl_world_counter); + expr = jl_expand_macros(expr, inmodule, NULL, 0, jl_world_counter, 0); expr = jl_call_scm_on_ast("jl-expand-macroscope", expr, inmodule); JL_GC_POP(); return expr; @@ -1185,7 +1185,7 @@ JL_DLLEXPORT jl_value_t *jl_macroexpand1(jl_value_t *expr, jl_module_t *inmodule JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 1, jl_world_counter); + expr = jl_expand_macros(expr, inmodule, NULL, 1, jl_world_counter, 0); expr = jl_call_scm_on_ast("jl-expand-macroscope", expr, inmodule); JL_GC_POP(); return expr; @@ -1211,7 +1211,7 @@ JL_DLLEXPORT jl_value_t *jl_expand_in_world(jl_value_t *expr, jl_module_t *inmod JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0, world); + expr = jl_expand_macros(expr, inmodule, NULL, 0, world, 1); expr = jl_call_scm_on_ast_and_loc("jl-expand-to-thunk", expr, inmodule, file, line); JL_GC_POP(); return expr; @@ -1224,7 +1224,7 @@ JL_DLLEXPORT jl_value_t *jl_expand_with_loc_warn(jl_value_t *expr, jl_module_t * JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0, 1); jl_ast_context_t *ctx = jl_ast_ctx_enter(); fl_context_t *fl_ctx = &ctx->fl; JL_AST_PRESERVE_PUSH(ctx, old_roots, inmodule); @@ -1245,7 +1245,7 @@ JL_DLLEXPORT jl_value_t *jl_expand_stmt_with_loc(jl_value_t *expr, jl_module_t * JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0, 1); expr = jl_call_scm_on_ast_and_loc("jl-expand-to-thunk-stmt", expr, inmodule, file, line); JL_GC_POP(); return expr; diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 74531b482524f..43d4ae689b5b5 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -669,6 +669,8 @@ macro test_throws(extype, ex) :(do_test_throws($result, $orig_ex, $(esc(extype)))) end +const MACROEXPAND_LIKE = Symbol.(("@macroexpand", "@macroexpand1", "macroexpand")) + # An internal function, called by the code generated by @test_throws # to evaluate and catch the thrown exception - if it exists function do_test_throws(result::ExecutionResult, orig_expr, extype) @@ -676,9 +678,24 @@ function do_test_throws(result::ExecutionResult, orig_expr, extype) # Check that the right type of exception was thrown success = false exc = result.exception + # NB: Throwing LoadError from macroexpands is deprecated, but in order to limit + # the breakage in package tests we add extra logic here. + from_macroexpand = + orig_expr isa Expr && + orig_expr.head in (:call, :macrocall) && + orig_expr.args[1] in MACROEXPAND_LIKE if isa(extype, Type) - success = isa(exc, extype) + success = + if from_macroexpand && extype == LoadError && exc isa Exception + Base.depwarn("macroexpand no longer throw a LoadError so `@test_throws LoadError ...` is deprecated and passed without checking the error type!", :do_test_throws) + true + else + isa(exc, extype) + end else + if extype isa LoadError && !(exc isa LoadError) && typeof(extype.error) == typeof(exc) + extype = extype.error # deprecated + end if isa(exc, typeof(extype)) success = true for fld in 1:nfields(extype) diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index b4d7f6afc2391..88179ebbfb554 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -1150,3 +1150,23 @@ let errors = @testset NoThrowTestSet begin @test occursin("Expression: !(1 < 2 < missing < 4)", str) end end + +macro test_macro_throw_1() + throw(ErrorException("Real error")) +end +macro test_macro_throw_2() + throw(LoadError("file", 111, ErrorException("Real error"))) +end + +@testset "Soft deprecation of @test_throws LoadError [@]macroexpand[1]" begin + # If a macroexpand was detected, undecorated LoadErrors can stand in for any error. + # This will throw a deprecation warning. + @test_deprecated (@test_throws LoadError macroexpand(@__MODULE__, :(@test_macro_throw_1))) + @test_deprecated (@test_throws LoadError @macroexpand @test_macro_throw_1) + # Decorated LoadErrors are unwrapped if the actual exception matches the inner, but not the outer, exception, regardless of whether or not a macroexpand is detected. + # This will not throw a deprecation warning. + @test_throws LoadError("file", 111, ErrorException("Real error")) macroexpand(@__MODULE__, :(@test_macro_throw_1)) + @test_throws LoadError("file", 111, ErrorException("Real error")) @macroexpand @test_macro_throw_1 + # Decorated LoadErrors are not unwrapped if a LoadError was thrown. + @test_throws LoadError("file", 111, ErrorException("Real error")) @macroexpand @test_macro_throw_2 +end diff --git a/test/core.jl b/test/core.jl index d617f14c7eb01..5036df4ec8218 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5646,11 +5646,9 @@ f_isdefined_unionvar(y, t) = (t > 0 && (x = (t == 1 ? 1 : y)); @isdefined x) @test !f_isdefined_unionvar(1, 0) f_isdefined_splat(x...) = @isdefined x @test f_isdefined_splat(1, 2, 3) -let err = try; @macroexpand @isdefined :x; false; catch ex; ex; end, +let e = try; @macroexpand @isdefined :x; false; catch ex; ex; end, __source__ = LineNumberNode(@__LINE__() - 1, Symbol(@__FILE__)) - @test err.file === string(__source__.file) - @test err.line === __source__.line - e = err.error::MethodError + e::MethodError @test e.f === getfield(@__MODULE__, Symbol("@isdefined")) @test e.args === (__source__, @__MODULE__, :(:x)) end diff --git a/test/docs.jl b/test/docs.jl index c7652bd73920e..05442df9d4cbe 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -793,14 +793,7 @@ end # Issue #13905. let err = try; @macroexpand(@doc "" f() = @x); false; catch ex; ex; end - __source__ = LineNumberNode(@__LINE__() - 1, Symbol(@__FILE__)) - err::LoadError - @test err.file === string(__source__.file) - @test err.line === __source__.line - err = err.error::LoadError - @test err.file === string(__source__.file) - @test err.line === __source__.line - err = err.error::UndefVarError + err::UndefVarError @test err.var == Symbol("@x") end diff --git a/test/errorshow.jl b/test/errorshow.jl index d219df3b12d64..3bcf3df514c64 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -475,12 +475,6 @@ let @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) let err = try; @macroexpand @doc "" f() = @x; catch ex; ex; end - file, line = @__FILE__, @__LINE__() - 1 - err = err::LoadError - @test err.file == file && err.line == line - err = err.error::LoadError - @test err.file == file && err.line == line - err = err.error::UndefVarError @test err == UndefVarError(Symbol("@x")) end @test (@macroexpand @seven_dollar $bar) == 7 diff --git a/test/simdloop.jl b/test/simdloop.jl index 1920cfa6140b1..88e41364ef222 100644 --- a/test/simdloop.jl +++ b/test/simdloop.jl @@ -92,19 +92,6 @@ import Base.SimdLoop.SimdError # Test that @simd rejects inner loop body with invalid control flow statements # issue #8613 -macro test_throws(ty, ex) - return quote - Test.@test_throws $(esc(ty)) try - $(esc(ex)) - catch err - @test err isa LoadError - @test err.file === $(string(__source__.file)) - @test err.line === $(__source__.line + 1) - rethrow(err.error) - end - end -end - @test_throws SimdError("break is not allowed inside a @simd loop body") @macroexpand begin @simd for x = 1:10 x == 1 && break diff --git a/test/syntax.jl b/test/syntax.jl index 6c2cfb465abd1..ba71d750254e7 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -618,15 +618,12 @@ end @test A15838.@f() === nothing @test A15838.@f(1) === :b let ex = :(A15838.@f(1, 2)), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) - nometh = try + e = try macroexpand(@__MODULE__, ex) false catch ex ex - end::LoadError - @test nometh.file === string(__source__.file) - @test nometh.line === __source__.line - e = nometh.error::MethodError + end::MethodError @test e.f === getfield(A15838, Symbol("@f")) @test e.args === (__source__, @__MODULE__, 1, 2) end diff --git a/test/threads_exec.jl b/test/threads_exec.jl index 87b3edc7c8025..860f0e03e2f5e 100644 --- a/test/threads_exec.jl +++ b/test/threads_exec.jl @@ -738,8 +738,7 @@ end try @macroexpand @threads(for i = 1:10, j = 1:10; end) catch ex - @test ex isa LoadError - @test ex.error isa ArgumentError + @test ex isa ArgumentError end @testset "@spawn interpolation" begin From 2b4c088ee729228e6014a4973c3e9123044532b4 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Fri, 16 Apr 2021 16:37:10 -0400 Subject: [PATCH 187/439] simplify views of adjoint matrices (#39467) --- stdlib/LinearAlgebra/src/adjtrans.jl | 14 +++++++++++++ stdlib/LinearAlgebra/test/adjtrans.jl | 29 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 56942930d7aa7..44ceeb43ede2a 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -241,6 +241,20 @@ parent(A::AdjOrTrans) = A.parent vec(v::TransposeAbsVec) = parent(v) vec(v::AdjointAbsVec{<:Real}) = parent(v) +Base.reshape(v::TransposeAbsVec{<:Number}, ::Val{1}) = parent(v) +Base.reshape(v::AdjointAbsVec{<:Real}, ::Val{1}) = parent(v) + +# these make eachrow(A') produce simpler views +@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::Integer, j::AbstractArray) = + Base.unsafe_view(parent(A), j, i) +@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::AbstractArray, j::Integer) = + Base.unsafe_view(parent(A), j, i) + +@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::Integer, j::AbstractArray) = + Base.unsafe_view(parent(A), j, i) +@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::AbstractArray, j::Integer) = + Base.unsafe_view(parent(A), j, i) + ### concatenation # preserve Adjoint/Transpose wrapper around vectors # to retain the associated semantics post-concatenation diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index bb2e54d306224..61c914d1a7f9e 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -277,6 +277,35 @@ end @test vec(cvec')[1] == cvec[1]' end +@testset "Adjoint and Transpose view methods" begin + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + # overload of reshape(v, Val(1)) simplifies views of row vectors: + @test view(adjoint(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} + @test view(transpose(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} + cvec = [1, 2im, 3, 4im] + @test view(transpose(cvec), 2:3) === view(cvec, 2:3) + @test view(adjoint(cvec), 2:3) == conj(view(cvec, 2:3)) + + # vector slices of transposed matrices are simplified: + @test view(adjoint(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} + @test view(transpose(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} + @test view(adjoint(intmat), 1, :) == permutedims(intmat)[1, :] + @test view(transpose(intmat), 1:1, :) == permutedims(intmat)[1:1, :] # not simplified + @test view(adjoint(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} + @test view(transpose(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} + @test view(adjoint(intmat), :, 2) == permutedims(intmat)[:, 2] + @test view(transpose(intmat), :, 2:2) == permutedims(intmat)[:, 2:2] # not simplified + cmat = [1 2im 3; 4im 5 6im] + @test view(transpose(cmat), 1, :) isa SubArray{Complex{Int}, 1, Matrix{Complex{Int}}} + @test view(transpose(cmat), :, 2) == cmat[2, :] + @test view(adjoint(cmat), :, 2) == conj(cmat[2, :]) # not simplified + + # bounds checks happen before this + @test_throws BoundsError view(adjoint(intvec), 0:3) + @test_throws BoundsError view(transpose(cvec), 0:3) + @test_throws BoundsError view(adjoint(intmat), :, 3) +end + @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin # horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers # should preserve the Adjoint/Transpose-wrapper to preserve semantics downstream From 2f4775e2a969c73fa37546d009b25ab8e5ac30c2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 17 Apr 2021 02:37:55 -0400 Subject: [PATCH 188/439] Revert "simplify views of adjoint matrices (#39467)" (#40504) This reverts commit 2b4c088ee729228e6014a4973c3e9123044532b4. There seems to be an issue with #39301 causing now test failure, but this PR was newer and thus easier to revert while reviewing the causes. See discussion in #40504. --- stdlib/LinearAlgebra/src/adjtrans.jl | 14 ------------- stdlib/LinearAlgebra/test/adjtrans.jl | 29 --------------------------- 2 files changed, 43 deletions(-) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 44ceeb43ede2a..56942930d7aa7 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -241,20 +241,6 @@ parent(A::AdjOrTrans) = A.parent vec(v::TransposeAbsVec) = parent(v) vec(v::AdjointAbsVec{<:Real}) = parent(v) -Base.reshape(v::TransposeAbsVec{<:Number}, ::Val{1}) = parent(v) -Base.reshape(v::AdjointAbsVec{<:Real}, ::Val{1}) = parent(v) - -# these make eachrow(A') produce simpler views -@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::Integer, j::AbstractArray) = - Base.unsafe_view(parent(A), j, i) -@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::AbstractArray, j::Integer) = - Base.unsafe_view(parent(A), j, i) - -@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::Integer, j::AbstractArray) = - Base.unsafe_view(parent(A), j, i) -@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::AbstractArray, j::Integer) = - Base.unsafe_view(parent(A), j, i) - ### concatenation # preserve Adjoint/Transpose wrapper around vectors # to retain the associated semantics post-concatenation diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 61c914d1a7f9e..bb2e54d306224 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -277,35 +277,6 @@ end @test vec(cvec')[1] == cvec[1]' end -@testset "Adjoint and Transpose view methods" begin - intvec, intmat = [1, 2], [1 2 3; 4 5 6] - # overload of reshape(v, Val(1)) simplifies views of row vectors: - @test view(adjoint(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} - @test view(transpose(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} - cvec = [1, 2im, 3, 4im] - @test view(transpose(cvec), 2:3) === view(cvec, 2:3) - @test view(adjoint(cvec), 2:3) == conj(view(cvec, 2:3)) - - # vector slices of transposed matrices are simplified: - @test view(adjoint(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} - @test view(transpose(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} - @test view(adjoint(intmat), 1, :) == permutedims(intmat)[1, :] - @test view(transpose(intmat), 1:1, :) == permutedims(intmat)[1:1, :] # not simplified - @test view(adjoint(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} - @test view(transpose(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} - @test view(adjoint(intmat), :, 2) == permutedims(intmat)[:, 2] - @test view(transpose(intmat), :, 2:2) == permutedims(intmat)[:, 2:2] # not simplified - cmat = [1 2im 3; 4im 5 6im] - @test view(transpose(cmat), 1, :) isa SubArray{Complex{Int}, 1, Matrix{Complex{Int}}} - @test view(transpose(cmat), :, 2) == cmat[2, :] - @test view(adjoint(cmat), :, 2) == conj(cmat[2, :]) # not simplified - - # bounds checks happen before this - @test_throws BoundsError view(adjoint(intvec), 0:3) - @test_throws BoundsError view(transpose(cvec), 0:3) - @test_throws BoundsError view(adjoint(intmat), :, 3) -end - @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin # horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers # should preserve the Adjoint/Transpose-wrapper to preserve semantics downstream From f723667e4c943e1050709442d057155750981dae Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Sat, 17 Apr 2021 05:36:56 -0400 Subject: [PATCH 189/439] restrict vec(::Transpose) shortcut to numbers (#40502) --- stdlib/LinearAlgebra/src/adjtrans.jl | 2 +- stdlib/LinearAlgebra/test/adjtrans.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 56942930d7aa7..f3d08abc54b0e 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -238,7 +238,7 @@ similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, # sundry basic definitions parent(A::AdjOrTrans) = A.parent -vec(v::TransposeAbsVec) = parent(v) +vec(v::TransposeAbsVec{<:Number}) = parent(v) vec(v::AdjointAbsVec{<:Real}) = parent(v) ### concatenation diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index bb2e54d306224..e6f271b2b4650 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -275,6 +275,9 @@ end @test vec(Transpose(intvec)) === intvec cvec = [1 + 1im] @test vec(cvec')[1] == cvec[1]' + mvec = [[1 2; 3 4+5im]]; + @test vec(transpose(mvec))[1] == transpose(mvec[1]) + @test vec(adjoint(mvec))[1] == adjoint(mvec[1]) end @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin From b6c6bc0d0270ace768db1dbd9136a2ebbaef2a45 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sat, 17 Apr 2021 04:40:53 -0500 Subject: [PATCH 190/439] float16 cbrt, 50% faster (#39441) Co-authored-by: Kristoffer Carlsson --- base/special/cbrt.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/base/special/cbrt.jl b/base/special/cbrt.jl index 978f7cf89971e..9fda5c41fb09e 100644 --- a/base/special/cbrt.jl +++ b/base/special/cbrt.jl @@ -146,3 +146,20 @@ function cbrt(x::Union{Float32,Float64}) t = _approx_cbrt(x) return _improve_cbrt(x, t) end + +function cbrt(a::Float16) + if !isfinite(a) || iszero(a) + return a + end + x = Float32(a) + + # 5 bit approximation. Simpler than _approx_cbrt since subnormals can not appear + u = highword(x) & 0x7fff_ffff + v = div(u, UInt32(3)) + 0x2a5119f2 + t = copysign(fromhighword(Float32, v), x) + + # 2 newton iterations + t = 0.33333334f0 * (2f0*t + x/(t*t)) + t = 0.33333334f0 * (2f0*t + x/(t*t)) + return Float16(t) +end From be3603e736047ccc40f8742db41e8fa7854e35b8 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Sat, 17 Apr 2021 21:21:54 +0900 Subject: [PATCH 191/439] [CLI] Fix typo in loader_lib.c (#40506) initalize -> initialize --- cli/loader_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/loader_lib.c b/cli/loader_lib.c index ba00516d6b916..b56a4893ea66f 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -130,7 +130,7 @@ JL_DLLEXPORT const char * jl_get_libdir() void * libjulia_internal = NULL; __attribute__((constructor)) void jl_load_libjulia_internal(void) { - // Only initalize this once + // Only initialize this once if (libjulia_internal != NULL) { return; } From 0b0e8e598ad63467c878011492c80e5f12be4ad7 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Sat, 17 Apr 2021 18:42:35 +0200 Subject: [PATCH 192/439] Relax type restriction on `factors` field of `LQPackedQ` (#39665) --- stdlib/LinearAlgebra/src/lq.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lq.jl b/stdlib/LinearAlgebra/src/lq.jl index 35f1dd56dc045..f6a2d3e29f85f 100644 --- a/stdlib/LinearAlgebra/src/lq.jl +++ b/stdlib/LinearAlgebra/src/lq.jl @@ -56,12 +56,10 @@ Base.iterate(S::LQ) = (S.L, Val(:Q)) Base.iterate(S::LQ, ::Val{:Q}) = (S.Q, Val(:done)) Base.iterate(S::LQ, ::Val{:done}) = nothing -struct LQPackedQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} - factors::Matrix{T} +struct LQPackedQ{T,S<:AbstractMatrix{T}} <: AbstractMatrix{T} + factors::S τ::Vector{T} - LQPackedQ{T,S}(factors::AbstractMatrix{T}, τ::Vector{T}) where {T,S<:AbstractMatrix} = new(factors, τ) end -LQPackedQ(factors::AbstractMatrix{T}, τ::Vector{T}) where {T} = LQPackedQ{T,typeof(factors)}(factors, τ) """ From 3a6b2a1071563adba1d3760a589421d3ff7a17bd Mon Sep 17 00:00:00 2001 From: Daniel Bruegmann Date: Sat, 17 Apr 2021 19:12:23 +0200 Subject: [PATCH 193/439] Add references to Performance Tips and Workflow Tips to Getting Started. (#40464) I suspect that some people go to julialang.org, click 'Learn', click 'getting started guide', start reading, and never get to Performance Tips (or Workflow Tips) because they come quite late in the manual. (An alternative would be to link to the introduction which already has a link to Performance Tips. However, I like that the Getting Started page quickly gets to the REPL, so I don't want to change that.) --- doc/src/manual/getting-started.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index 9caa52792be93..8b13385e9ede7 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -103,3 +103,5 @@ command-line-options). ## Resources A curated list of useful learning resources to help new users get started can be found on the [learning](https://julialang.org/learning/) page of the main Julia web site. + +If you already know Julia a bit, you might want to peek ahead at [Performance Tips](@ref man-performance-tips) and [Workflow Tips](@ref man-workflow-tips). From 53dfc4b4275db960b67c1856401607a117bd800b Mon Sep 17 00:00:00 2001 From: Mustafa Mohamad Date: Sat, 17 Apr 2021 12:34:38 -0400 Subject: [PATCH 194/439] sign executables within installer --- contrib/windows/build-installer.iss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/windows/build-installer.iss b/contrib/windows/build-installer.iss index 6648d9e1f528a..4f5f0259d2f2c 100644 --- a/contrib/windows/build-installer.iss +++ b/contrib/windows/build-installer.iss @@ -103,7 +103,8 @@ Name: "addtopath"; Description: "Add {#AppName} to PATH"; GroupDescription: "{cm [Files] -Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "{#SourceDir}\*"; Excludes: "{#AppMainExeName}"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; +Source: "{#SourceDir}\{#AppMainExeName}"; DestDir: "{app}\bin"; Flags: ignoreversion sign; [Icons] From e580a57d09a6bb285b42e42fbacc95a91ecb093a Mon Sep 17 00:00:00 2001 From: Mustafa Mohamad Date: Sat, 17 Apr 2021 16:58:48 -0400 Subject: [PATCH 195/439] Update Julia year in exe --- contrib/windows/julia.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/windows/julia.rc b/contrib/windows/julia.rc index afef95ca4af0b..759b4f1b3023a 100644 --- a/contrib/windows/julia.rc +++ b/contrib/windows/julia.rc @@ -18,7 +18,7 @@ BEGIN VALUE "FileDescription", "Julia Programming Language" VALUE "FileVersion", JLVER_STR VALUE "InternalName", "julia" - VALUE "LegalCopyright", "(c) 2009-2020 Julia Language" + VALUE "LegalCopyright", "(c) 2009-2021 Julia Language" VALUE "OriginalFilename", "julia.exe" VALUE "ProductName", "Julia" VALUE "ProductVersion", JLVER_STR From 55dd2f4e921d97620b5eb8d911392d281bca8800 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 18 Apr 2021 00:05:06 -0400 Subject: [PATCH 196/439] Overload permutedims for Diagonal (#39447) Optimization for performance --- stdlib/LinearAlgebra/src/diagonal.jl | 2 ++ stdlib/LinearAlgebra/test/diagonal.jl | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index e83c5274ac3d6..3501937996716 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -552,6 +552,8 @@ transpose(D::Diagonal{<:Number}) = D transpose(D::Diagonal) = Diagonal(transpose.(D.diag)) adjoint(D::Diagonal{<:Number}) = conj(D) adjoint(D::Diagonal) = Diagonal(adjoint.(D.diag)) +Base.permutedims(D::Diagonal) = D +Base.permutedims(D::Diagonal, perm) = (Base.checkdims_perm(D, D, perm); D) function diag(D::Diagonal, k::Integer=0) # every branch call similar(..., ::Int) to make sure the diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 61090830a65e0..86ff2980876f2 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -740,6 +740,14 @@ end @test dot(zeros(Int32, 0), Diagonal(zeros(Int, 0)), zeros(Int16, 0)) === 0 end + +@testset "permutedims (#39447)" begin + for D in (Diagonal(zeros(5)), Diagonal(zeros(5) .+ 1im), Diagonal([[1,2],[3,4]])) + @test permutedims(D) === permutedims(D,(1,2)) === permutedims(D,(2,1)) === D + @test_throws ArgumentError permutedims(D,(1,3)) + end +end + @testset "Inner product" begin A = Diagonal(rand(10) .+ im) B = Diagonal(rand(10) .+ im) From 36a048ce6e13d890d184bb552c37b876a0e54cce Mon Sep 17 00:00:00 2001 From: Alfredo Braunstein Date: Sun, 18 Apr 2021 14:48:45 +0200 Subject: [PATCH 197/439] add spzeros(::Tuple{<:Integer}) (#40515) --- stdlib/SparseArrays/src/sparsevector.jl | 3 +++ stdlib/SparseArrays/test/sparsevector.jl | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 3bb3e2ddec05f..09696ab1e06c8 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -125,8 +125,11 @@ Base.unaliascopy(S::SparseVector) = typeof(S)(length(S), unaliascopy(nonzeroinds ### Construct empty sparse vector spzeros(len::Integer) = spzeros(Float64, len) +spzeros(dims::Tuple{<:Integer}) = spzeros(Float64, dims[1]) spzeros(::Type{T}, len::Integer) where {T} = SparseVector(len, Int[], T[]) +spzeros(::Type{T}, dims::Tuple{<:Integer}) where {T} = spzeros(T, dims[1]) spzeros(::Type{Tv}, ::Type{Ti}, len::Integer) where {Tv,Ti<:Integer} = SparseVector(len, Ti[], Tv[]) +spzeros(::Type{Tv}, ::Type{Ti}, dims::Tuple{<:Integer}) where {Tv,Ti<:Integer} = spzeros(Tv, Ti, dims[1]) LinearAlgebra.fillstored!(x::SparseVector, y) = (fill!(nonzeros(x), y); x) diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 55df1fb65393c..e141deea40517 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -75,7 +75,11 @@ end @testset "other constructors" begin # construct empty sparse vector - @test exact_equal(spzeros(Float64, 8), SparseVector(8, Int[], Float64[])) + for dims in (8, (8,)) + @test exact_equal(spzeros(dims), SparseVector(8, Int[], Float64[])) + @test exact_equal(spzeros(Float64, dims), SparseVector(8, Int[], Float64[])) + @test exact_equal(spzeros(Float64, Int16, dims), SparseVector(8, Int16[], Float64[])) + end @testset "from list of indices and values" begin @test exact_equal( From a20e547ae2d05543165415fefd8c84d5ee50e479 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Sun, 18 Apr 2021 14:50:25 +0200 Subject: [PATCH 198/439] Fix `kron` with `Diagonal` (#40509) --- stdlib/LinearAlgebra/src/diagonal.jl | 27 ++++++++++----------------- stdlib/LinearAlgebra/test/diagonal.jl | 4 ++++ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 3501937996716..e4a1899e16770 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -472,14 +472,13 @@ rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = invoke(\, Tuple{Union{QR,QRCompactWY,QRPivoted}, AbstractVecOrMat}, A, B) -@inline function kron!(C::AbstractMatrix{T}, A::Diagonal, B::Diagonal) where T - fill!(C, zero(T)) +@inline function kron!(C::AbstractMatrix, A::Diagonal, B::Diagonal) valA = A.diag; nA = length(valA) valB = B.diag; nB = length(valB) nC = checksquare(C) @boundscheck nC == nA*nB || throw(DimensionMismatch("expect C to be a $(nA*nB)x$(nA*nB) matrix, got size $(nC)x$(nC)")) - + isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) @inbounds for i = 1:nA, j = 1:nB idx = (i-1)*nB+j C[idx, idx] = valA[i] * valB[j] @@ -497,9 +496,12 @@ end @inline function kron!(C::AbstractMatrix, A::Diagonal, B::AbstractMatrix) Base.require_one_based_indexing(B) - (mA, nA) = size(A); (mB, nB) = size(B); (mC, nC) = size(C); + (mA, nA) = size(A) + (mB, nB) = size(B) + (mC, nC) = size(C) @boundscheck (mC, nC) == (mA * mB, nA * nB) || throw(DimensionMismatch("expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) + isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) m = 1 @inbounds for j = 1:nA A_jj = A[j,j] @@ -517,9 +519,12 @@ end @inline function kron!(C::AbstractMatrix, A::AbstractMatrix, B::Diagonal) require_one_based_indexing(A) - (mA, nA) = size(A); (mB, nB) = size(B); (mC, nC) = size(C); + (mA, nA) = size(A) + (mB, nB) = size(B) + (mC, nC) = size(C) @boundscheck (mC, nC) == (mA * mB, nA * nB) || throw(DimensionMismatch("expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) + isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) m = 1 @inbounds for j = 1:nA for l = 1:mB @@ -535,18 +540,6 @@ end return C end -function kron(A::Diagonal{T}, B::AbstractMatrix{S}) where {T<:Number, S<:Number} - (mA, nA) = size(A); (mB, nB) = size(B) - R = zeros(Base.promote_op(*, T, S), mA * mB, nA * nB) - return @inbounds kron!(R, A, B) -end - -function kron(A::AbstractMatrix{T}, B::Diagonal{S}) where {T<:Number, S<:Number} - (mA, nA) = size(A); (mB, nB) = size(B) - R = zeros(promote_op(*, T, S), mA * mB, nA * nB) - return @inbounds kron!(R, A, B) -end - conj(D::Diagonal) = Diagonal(conj(D.diag)) transpose(D::Diagonal{<:Number}) = D transpose(D::Diagonal) = Diagonal(transpose.(D.diag)) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 86ff2980876f2..0ae2920fc0e86 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -299,6 +299,10 @@ Random.seed!(1) M4 = rand(elty, n÷2, n÷2) @test kron(D3, M4) ≈ kron(DM3, M4) @test kron(M4, D3) ≈ kron(M4, DM3) + X = [ones(1,1) for i in 1:2, j in 1:2] + @test kron(I(2), X)[1,3] == zeros(1,1) + X = [ones(2,2) for i in 1:2, j in 1:2] + @test kron(I(2), X)[1,3] == zeros(2,2) end @testset "iszero, isone, triu, tril" begin Dzero = Diagonal(zeros(elty, 10)) From 671bccba27e69b40dabe73409df2b1feba25944c Mon Sep 17 00:00:00 2001 From: Simon Etter Date: Mon, 19 Apr 2021 00:02:16 +0800 Subject: [PATCH 199/439] Move CHOLMOD.common_struct from Vector{UInt8} to an actual struct (#38919) * Move common_struct from Vector{UInt8} to an actual struct * Compare full version numbers Co-authored-by: Simon Etter --- deps/SuiteSparse_wrapper.c | 157 ++++++++-- stdlib/SuiteSparse/src/cholmod.jl | 434 +++++++++++++++++----------- stdlib/SuiteSparse/src/spqr.jl | 12 +- stdlib/SuiteSparse/test/cholmod.jl | 39 ++- stdlib/SuiteSparse_jll/Project.toml | 2 +- 5 files changed, 433 insertions(+), 211 deletions(-) diff --git a/deps/SuiteSparse_wrapper.c b/deps/SuiteSparse_wrapper.c index fc8b612d7671b..63204ac80a665 100644 --- a/deps/SuiteSparse_wrapper.c +++ b/deps/SuiteSparse_wrapper.c @@ -7,10 +7,6 @@ #include #include -extern size_t jl_cholmod_common_size(void) { - return sizeof(cholmod_common); -} - extern size_t jl_cholmod_sizeof_long(void) { return sizeof(SuiteSparse_long); } @@ -24,24 +20,137 @@ extern int jl_cholmod_version(int *ver) { return CHOLMOD_VERSION; } -extern void jl_cholmod_common_offsets(size_t *vv) { - vv[0] = offsetof(cholmod_common, dbound); - vv[1] = offsetof(cholmod_common, maxrank); - vv[2] = offsetof(cholmod_common, supernodal_switch); - vv[3] = offsetof(cholmod_common, supernodal); - vv[4] = offsetof(cholmod_common, final_asis); - vv[5] = offsetof(cholmod_common, final_super); - vv[6] = offsetof(cholmod_common, final_ll); - vv[7] = offsetof(cholmod_common, final_pack); - vv[8] = offsetof(cholmod_common, final_monotonic); - vv[9] = offsetof(cholmod_common, final_resymbol); - vv[10] = offsetof(cholmod_common, prefer_zomplex); - vv[11] = offsetof(cholmod_common, prefer_upper); - vv[12] = offsetof(cholmod_common, print); - vv[13] = offsetof(cholmod_common, precise); - vv[14] = offsetof(cholmod_common, nmethods); - vv[15] = offsetof(cholmod_common, selected); - vv[16] = offsetof(cholmod_common, postorder); - vv[17] = offsetof(cholmod_common, itype); - vv[18] = offsetof(cholmod_common, dtype); +// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl +extern void jl_cholmod_method_offsets(size_t *v) { + size_t offset = offsetof(cholmod_common, method[0]); + v[ 0] = offsetof(cholmod_common, method[0].lnz) - offset; + v[ 1] = offsetof(cholmod_common, method[0].fl) - offset; + v[ 2] = offsetof(cholmod_common, method[0].prune_dense) - offset; + v[ 3] = offsetof(cholmod_common, method[0].prune_dense2) - offset; + v[ 4] = offsetof(cholmod_common, method[0].nd_oksep) - offset; + v[ 5] = offsetof(cholmod_common, method[0].other_1) - offset; + v[ 6] = offsetof(cholmod_common, method[0].nd_small) - offset; + v[ 7] = offsetof(cholmod_common, method[0].other_2) - offset; + v[ 8] = offsetof(cholmod_common, method[0].aggressive) - offset; + v[ 9] = offsetof(cholmod_common, method[0].order_for_lu) - offset; + v[10] = offsetof(cholmod_common, method[0].nd_compress) - offset; + v[11] = offsetof(cholmod_common, method[0].nd_camd) - offset; + v[12] = offsetof(cholmod_common, method[0].nd_components) - offset; + v[13] = offsetof(cholmod_common, method[0].ordering) - offset; + v[14] = offsetof(cholmod_common, method[0].other_3) - offset; +} + +// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl +extern void jl_cholmod_common_offsets(size_t *v) { + v[ 0] = offsetof(cholmod_common, dbound); + v[ 1] = offsetof(cholmod_common, grow0); + v[ 2] = offsetof(cholmod_common, grow1); + v[ 3] = offsetof(cholmod_common, grow2); + v[ 4] = offsetof(cholmod_common, maxrank); + v[ 5] = offsetof(cholmod_common, supernodal_switch); + v[ 6] = offsetof(cholmod_common, supernodal); + v[ 7] = offsetof(cholmod_common, final_asis); + v[ 8] = offsetof(cholmod_common, final_super); + v[ 9] = offsetof(cholmod_common, final_ll); + v[ 10] = offsetof(cholmod_common, final_pack); + v[ 11] = offsetof(cholmod_common, final_monotonic); + v[ 12] = offsetof(cholmod_common, final_resymbol); + v[ 13] = offsetof(cholmod_common, zrelax); + v[ 14] = offsetof(cholmod_common, nrelax); + v[ 15] = offsetof(cholmod_common, prefer_zomplex); + v[ 16] = offsetof(cholmod_common, prefer_upper); + v[ 17] = offsetof(cholmod_common, quick_return_if_not_posdef); + v[ 18] = offsetof(cholmod_common, prefer_binary); + v[ 19] = offsetof(cholmod_common, print); + v[ 20] = offsetof(cholmod_common, precise); + v[ 21] = offsetof(cholmod_common, try_catch); + v[ 22] = offsetof(cholmod_common, error_handler); + v[ 23] = offsetof(cholmod_common, nmethods); + v[ 24] = offsetof(cholmod_common, current); + v[ 25] = offsetof(cholmod_common, selected); + v[ 26] = offsetof(cholmod_common, method); + v[ 27] = offsetof(cholmod_common, postorder); + v[ 28] = offsetof(cholmod_common, default_nesdis); + v[ 29] = offsetof(cholmod_common, metis_memory); + v[ 30] = offsetof(cholmod_common, metis_dswitch); + v[ 31] = offsetof(cholmod_common, metis_nswitch); + v[ 32] = offsetof(cholmod_common, nrow); + v[ 33] = offsetof(cholmod_common, mark); + v[ 34] = offsetof(cholmod_common, iworksize); + v[ 35] = offsetof(cholmod_common, xworksize); + v[ 36] = offsetof(cholmod_common, Flag); + v[ 37] = offsetof(cholmod_common, Head); + v[ 38] = offsetof(cholmod_common, Xwork); + v[ 39] = offsetof(cholmod_common, Iwork); + v[ 40] = offsetof(cholmod_common, itype); + v[ 41] = offsetof(cholmod_common, dtype); + v[ 42] = offsetof(cholmod_common, no_workspace_reallocate); + v[ 43] = offsetof(cholmod_common, status); + v[ 44] = offsetof(cholmod_common, fl); + v[ 45] = offsetof(cholmod_common, lnz); + v[ 46] = offsetof(cholmod_common, anz); + v[ 47] = offsetof(cholmod_common, modfl); + v[ 48] = offsetof(cholmod_common, malloc_count); + v[ 49] = offsetof(cholmod_common, memory_usage); + v[ 50] = offsetof(cholmod_common, memory_inuse); + v[ 51] = offsetof(cholmod_common, nrealloc_col); + v[ 52] = offsetof(cholmod_common, nrealloc_factor); + v[ 53] = offsetof(cholmod_common, ndbounds_hit); + v[ 54] = offsetof(cholmod_common, rowfacfl); + v[ 55] = offsetof(cholmod_common, aatfl); + v[ 56] = offsetof(cholmod_common, called_nd); + v[ 57] = offsetof(cholmod_common, blas_ok); + v[ 58] = offsetof(cholmod_common, SPQR_grain); + v[ 59] = offsetof(cholmod_common, SPQR_small); + v[ 60] = offsetof(cholmod_common, SPQR_shrink); + v[ 61] = offsetof(cholmod_common, SPQR_nthreads); + v[ 62] = offsetof(cholmod_common, SPQR_flopcount); + v[ 63] = offsetof(cholmod_common, SPQR_analyze_time); + v[ 64] = offsetof(cholmod_common, SPQR_factorize_time); + v[ 65] = offsetof(cholmod_common, SPQR_solve_time); + v[ 66] = offsetof(cholmod_common, SPQR_flopcount_bound); + v[ 67] = offsetof(cholmod_common, SPQR_tol_used); + v[ 68] = offsetof(cholmod_common, SPQR_norm_E_fro); + v[ 69] = offsetof(cholmod_common, SPQR_istat); + v[ 70] = offsetof(cholmod_common, useGPU); + v[ 71] = offsetof(cholmod_common, maxGpuMemBytes); + v[ 72] = offsetof(cholmod_common, maxGpuMemFraction); + v[ 73] = offsetof(cholmod_common, gpuMemorySize); + v[ 74] = offsetof(cholmod_common, gpuKernelTime); + v[ 75] = offsetof(cholmod_common, gpuFlops); + v[ 76] = offsetof(cholmod_common, gpuNumKernelLaunches); + v[ 77] = offsetof(cholmod_common, cublasHandle); + v[ 78] = offsetof(cholmod_common, gpuStream); + v[ 79] = offsetof(cholmod_common, cublasEventPotrf); + v[ 80] = offsetof(cholmod_common, updateCKernelsComplete); + v[ 81] = offsetof(cholmod_common, updateCBuffersFree); + v[ 82] = offsetof(cholmod_common, dev_mempool); + v[ 83] = offsetof(cholmod_common, dev_mempool_size); + v[ 84] = offsetof(cholmod_common, host_pinned_mempool); + v[ 85] = offsetof(cholmod_common, host_pinned_mempool_size); + v[ 86] = offsetof(cholmod_common, devBuffSize); + v[ 87] = offsetof(cholmod_common, ibuffer); + v[ 88] = offsetof(cholmod_common, syrkStart); + v[ 89] = offsetof(cholmod_common, cholmod_cpu_gemm_time); + v[ 90] = offsetof(cholmod_common, cholmod_cpu_syrk_time); + v[ 91] = offsetof(cholmod_common, cholmod_cpu_trsm_time); + v[ 92] = offsetof(cholmod_common, cholmod_cpu_potrf_time); + v[ 93] = offsetof(cholmod_common, cholmod_gpu_gemm_time); + v[ 94] = offsetof(cholmod_common, cholmod_gpu_syrk_time); + v[ 95] = offsetof(cholmod_common, cholmod_gpu_trsm_time); + v[ 96] = offsetof(cholmod_common, cholmod_gpu_potrf_time); + v[ 97] = offsetof(cholmod_common, cholmod_assemble_time); + v[ 98] = offsetof(cholmod_common, cholmod_assemble_time2); + v[ 99] = offsetof(cholmod_common, cholmod_cpu_gemm_calls); + v[100] = offsetof(cholmod_common, cholmod_cpu_syrk_calls); + v[101] = offsetof(cholmod_common, cholmod_cpu_trsm_calls); + v[102] = offsetof(cholmod_common, cholmod_cpu_potrf_calls); + v[103] = offsetof(cholmod_common, cholmod_gpu_gemm_calls); + v[104] = offsetof(cholmod_common, cholmod_gpu_syrk_calls); + v[105] = offsetof(cholmod_common, cholmod_gpu_trsm_calls); + v[106] = offsetof(cholmod_common, cholmod_gpu_potrf_calls); +} + +extern size_t jl_cholmod_common_size() { + return sizeof(cholmod_common); } diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index cbfee4a30cb41..ef14709eb076c 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -40,44 +40,166 @@ include("cholmod_h.jl") const CHOLMOD_MIN_VERSION = v"2.1.1" -const common_struct = Vector{Vector{UInt8}}() - -const common_supernodal = Vector{Ptr{Cint}}() -const common_final_ll = Vector{Ptr{Cint}}() -const common_print = Vector{Ptr{Cint}}() -const common_itype = Vector{Ptr{Cint}}() -const common_dtype = Vector{Ptr{Cint}}() -const common_nmethods = Vector{Ptr{Cint}}() -const common_postorder = Vector{Ptr{Cint}}() - -### These offsets are defined in SuiteSparse_wrapper.c -const common_size = ccall((:jl_cholmod_common_size,:libsuitesparse_wrapper),Int,()) - -const cholmod_com_offsets = Vector{Csize_t}(undef, 19) -ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), - Nothing, (Ptr{Csize_t},), cholmod_com_offsets) - ## macro to generate the name of the C function according to the integer type macro cholmod_name(nm) string("cholmod_l_", nm) end -function start(a::Vector{UInt8}) - @isok ccall((@cholmod_name("start"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a +# Julia copy of the cholmod_method_struct +# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L655 +# Keep this synchronized with __init__() below and jl_cholmod_method_offsets in +# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c +struct Method + lnz::Cdouble + fl::Cdouble + prune_dense::Cdouble + prune_dense2::Cdouble + nd_oksep::Cdouble + other_1::NTuple{4,Cdouble} + nd_small::Csize_t + other_2::NTuple{4,Csize_t} + aggressive::Cint + order_for_lu::Cint + nd_compress::Cint + nd_camd::Cint + nd_components::Cint + ordering::Cint + other_3::NTuple{4,Csize_t} +end + +# Julia copy of the cholmod_common_struct +# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L414 +# Keep this synchronized with __init__() below and jl_cholmod_common_offsets in +# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c +mutable struct Common + dbound::Cdouble + grow0::Cdouble + grow1::Cdouble + grow2::Csize_t + maxrank::Csize_t + supernodal_switch::Cdouble + supernodal::Cint + final_asis::Cint + final_super::Cint + final_ll::Cint + final_pack::Cint + final_monotonic::Cint + final_resymbol::Cint + zrelax::NTuple{3,Cdouble} + nrelax::NTuple{3,Csize_t} + prefer_zomplex::Cint + prefer_upper::Cint + quick_return_if_not_posdef::Cint + prefer_binary::Cint + print::Cint + precise::Cint + try_catch::Cint + error_handler::Ptr{Nothing} + nmethods::Cint + current::Cint + selected::Cint + method::NTuple{10,Method} + postorder::Cint + default_nesdis::Cint + metis_memory::Cdouble + metis_dswitch::Cdouble + metis_nswitch::Csize_t + nrow::Csize_t + mark::SuiteSparse_long + iworksize::Csize_t + xworksize::Csize_t + Flag::Ptr{Nothing} + Head::Ptr{Nothing} + Xwork::Ptr{Nothing} + Iwork::Ptr{Nothing} + itype::Cint + dtype::Cint + no_workspace_reallocate::Cint + status::Cint + fl::Cdouble + lnz::Cdouble + anz::Cdouble + modfl::Cdouble + malloc_count::Csize_t + memory_usage::Csize_t + memory_inuse::Csize_t + nrealloc_col::Cdouble + nrealloc_factor::Cdouble + ndbounds_hit::Cdouble + rowfacfl::Cdouble + aatfl::Cdouble + called_nd::Cint + blas_ok::Cint + SPQR_grain::Cdouble + SPQR_small::Cdouble + SPQR_shrink::Cint + SPQR_nthreads::Cint + SPQR_flopcount::Cdouble + SPQR_analyze_time::Cdouble + SPQR_factorize_time::Cdouble + SPQR_solve_time::Cdouble + SPQR_flopcount_bound::Cdouble + SPQR_tol_used::Cdouble + SPQR_norm_E_fro::Cdouble + SPQR_istat::NTuple{10,SuiteSparse_long} + useGPU::Cint + maxGpuMemBytes::Csize_t + maxGpuMemFraction::Cdouble + gpuMemorySize::Csize_t + gpuKernelTime::Cdouble + gpuFlops::SuiteSparse_long + gpuNumKernelLaunches::Cint + cublasHandle::Ptr{Nothing} + gpuStream::NTuple{8,Ptr{Nothing}} + cublasEventPotrf::NTuple{3,Ptr{Nothing}} + updateCKernelsComplete::Ptr{Nothing} + updateCBuffersFree::NTuple{8,Ptr{Nothing}} + dev_mempool::Ptr{Nothing} + dev_mempool_size::Csize_t + host_pinned_mempool::Ptr{Nothing} + host_pinned_mempool_size::Csize_t + devBuffSize::Csize_t + ibuffer::Cint + syrkStart::Cdouble + cholmod_cpu_gemm_time::Cdouble + cholmod_cpu_syrk_time::Cdouble + cholmod_cpu_trsm_time::Cdouble + cholmod_cpu_potrf_time::Cdouble + cholmod_gpu_gemm_time::Cdouble + cholmod_gpu_syrk_time::Cdouble + cholmod_gpu_trsm_time::Cdouble + cholmod_gpu_potrf_time::Cdouble + cholmod_assemble_time::Cdouble + cholmod_assemble_time2::Cdouble + cholmod_cpu_gemm_calls::Csize_t + cholmod_cpu_syrk_calls::Csize_t + cholmod_cpu_trsm_calls::Csize_t + cholmod_cpu_potrf_calls::Csize_t + cholmod_gpu_gemm_calls::Csize_t + cholmod_gpu_syrk_calls::Csize_t + cholmod_gpu_trsm_calls::Csize_t + cholmod_gpu_potrf_calls::Csize_t + + function Common() + common = new() + @isok ccall((@cholmod_name("start"), :libcholmod), + Cint, (Ptr{Common},), common) + finalizer(common) do common + @isok ccall((@cholmod_name("finish"), :libcholmod), + Cint, (Ptr{Common},), common) + end + end end -function finish(a::Vector{UInt8}) - @isok ccall((@cholmod_name("finish"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a -end +Base.unsafe_convert(::Type{Ptr{Common}},c::Common) = + reinterpret(Ptr{Common}, pointer_from_objref(c)) + +const common = Vector{Common}() -function defaults(a::Vector{UInt8}) +function defaults!(common) @isok ccall((@cholmod_name("defaults"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a + Cint, (Ptr{Common},), common) + return common end const build_version_array = Vector{Cint}(undef, 3) @@ -111,7 +233,7 @@ function __init__() from www.julialang.org, which ship with the correct versions of all dependencies. """ - elseif build_version_array[1] != current_version_array[1] + elseif build_version != current_version @warn """ CHOLMOD version incompatibility @@ -148,30 +270,13 @@ function __init__() end ### Initiate CHOLMOD - ### common_struct controls the type of factorization and keeps pointers + ### common controls the type of factorization and keeps pointers ### to temporary memory. We need to manage a copy for each thread. nt = Threads.nthreads() - resize!(common_struct , nt) - resize!(common_supernodal, nt) - resize!(common_final_ll , nt) - resize!(common_print , nt) - resize!(common_itype , nt) - resize!(common_dtype , nt) - resize!(common_nmethods , nt) - resize!(common_postorder , nt) + resize!(common, nt) for i in 1:nt - common_struct[i] = fill(0xff, common_size) - - common_supernodal[i] = pointer(common_struct[i], cholmod_com_offsets[4] + 1) - common_final_ll[i] = pointer(common_struct[i], cholmod_com_offsets[7] + 1) - common_print[i] = pointer(common_struct[i], cholmod_com_offsets[13] + 1) - common_itype[i] = pointer(common_struct[i], cholmod_com_offsets[18] + 1) - common_dtype[i] = pointer(common_struct[i], cholmod_com_offsets[19] + 1) - common_nmethods[i] = pointer(common_struct[i], cholmod_com_offsets[15] + 1) - common_postorder[i] = pointer(common_struct[i], cholmod_com_offsets[17] + 1) - - start(common_struct[i]) # initializes CHOLMOD - set_print_level(common_struct[i], 0) # no printing from CHOLMOD by default + common[i] = Common() + common[i].print = 0 # no printing from CHOLMOD by default end # Register gc tracked allocator if CHOLMOD is new enough @@ -188,10 +293,6 @@ function __init__() end end -function set_print_level(cm::Vector{UInt8}, lev::Integer) - unsafe_store!(common_print[Threads.threadid()], lev) -end - #################### # Type definitions # #################### @@ -412,47 +513,47 @@ Factor(FC::FactorComponent) = Factor(FC.F) ### cholmod_core_h ### function allocate_dense(m::Integer, n::Integer, d::Integer, ::Type{Tv}) where {Tv<:VTypes} Dense(ccall((@cholmod_name("allocate_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{Cvoid}), - m, n, d, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, d, xtyp(Tv), common[Threads.threadid()])) end function free!(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes} @isok ccall((@cholmod_name("free_dense"), :libcholmod), Cint, - (Ref{Ptr{C_Dense{Tv}}}, Ptr{Cvoid}), - p, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}), + p, common[Threads.threadid()]) end function zeros(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("zeros"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end zeros(m::Integer, n::Integer) = zeros(m, n, Float64) function ones(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("ones"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end ones(m::Integer, n::Integer) = ones(m, n, Float64) function eye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("eye"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end eye(m::Integer, n::Integer) = eye(m, n, Float64) eye(n::Integer) = eye(n, n, Float64) function copy(A::Dense{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("copy_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Ptr{C_Dense{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Dense{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function sort!(S::Sparse{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("sort"), :libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - S, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, common[Threads.threadid()]) return S end @@ -467,15 +568,15 @@ function norm_dense(D::Dense{Tv}, p::Integer) where Tv<:VTypes throw(ArgumentError("second argument must be either 0 (Inf norm), 1, or 2")) end ccall((@cholmod_name("norm_dense"), :libcholmod), Cdouble, - (Ptr{C_Dense{Tv}}, Cint, Ptr{UInt8}), - D, p, common_struct[Threads.threadid()]) + (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), + D, p, common[Threads.threadid()]) end ### cholmod_check.h ### function check_dense(A::Dense{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_dense"), :libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Ptr{UInt8}), - pointer(A), common_struct[Threads.threadid()]) != 0 + (Ptr{C_Dense{Tv}}, Ptr{Common}), + pointer(A), common[Threads.threadid()]) != 0 end # Non-Dense wrappers @@ -485,42 +586,42 @@ function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer, Sparse(ccall((@cholmod_name("allocate_sparse"), :libcholmod), Ptr{C_Sparse{Tv}}, (Csize_t, Csize_t, Csize_t, Cint, - Cint, Cint, Cint, Ptr{Cvoid}), + Cint, Cint, Cint, Ptr{Common}), nrow, ncol, nzmax, sorted, - packed, stype, xtyp(Tv), common_struct[Threads.threadid()])) + packed, stype, xtyp(Tv), common[Threads.threadid()])) end function free!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes @isok ccall((@cholmod_name("free_sparse"), :libcholmod), Cint, - (Ref{Ptr{C_Sparse{Tv}}}, Ptr{UInt8}), - ptr, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) end function free!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes # Warning! Important that finalizer doesn't modify the global Common struct. @isok ccall((@cholmod_name("free_factor"), :libcholmod), Cint, - (Ref{Ptr{C_Factor{Tv}}}, Ptr{Cvoid}), - ptr, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) end function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("aat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{UInt8}), - A, fset, length(fset), mode, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{Common}), + A, fset, length(fset), mode, common[Threads.threadid()])) end function sparse_to_dense(A::Sparse{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("sparse_to_dense"),:libcholmod), Ptr{C_Dense{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function dense_to_sparse(D::Dense{Tv}, ::Type{SuiteSparse_long}) where Tv<:VTypes Sparse(ccall((@cholmod_name("dense_to_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Dense{Tv}}, Cint, Ptr{UInt8}), - D, true, common_struct[Threads.threadid()])) + (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), + D, true, common[Threads.threadid()])) end function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes @@ -528,89 +629,89 @@ function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes ss.xtype == PATTERN && throw(CHOLMODException("only numeric factors are supported")) Sparse(ccall((@cholmod_name("factor_to_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()])) + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()])) end function change_factor!(F::Factor{Tv}, to_ll::Bool, to_super::Bool, to_packed::Bool, to_monotonic::Bool) where Tv<:VTypes @isok ccall((@cholmod_name("change_factor"),:libcholmod), Cint, - (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{UInt8}), - xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common_struct[Threads.threadid()]) + (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}), + xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) end function check_sparse(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()]) != 0 + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()]) != 0 end function check_factor(F::Factor{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()]) != 0 + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()]) != 0 end function nnz(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("nnz"),:libcholmod), Int, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()]) end function speye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("speye"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end function spzeros(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("spzeros"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, nzmax, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, nzmax, xtyp(Tv), common[Threads.threadid()])) end function transpose_(A::Sparse{Tv}, values::Integer) where Tv<:VTypes Sparse(ccall((@cholmod_name("transpose"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, values, common[Threads.threadid()])) end function copy(F::Factor{Tv}) where Tv<:VTypes Factor(ccall((@cholmod_name("copy_factor"),:libcholmod), Ptr{C_Factor{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()])) + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()])) end function copy(A::Sparse{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("copy_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function copy(A::Sparse{Tv}, stype::Integer, mode::Integer) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("copy"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{UInt8}), - A, stype, mode, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{Common}), + A, stype, mode, common[Threads.threadid()])) end ### cholmod_check.h ### function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes isascii(name) || error("non-ASCII name: $name") - set_print_level(common_struct[Threads.threadid()], 3) + common[Threads.threadid()] = 3 @isok ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{UInt8}), - A, name, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), + A, name, common[Threads.threadid()]) nothing end function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes - set_print_level(common_struct[Threads.threadid()], 3) + common[Threads.threadid()] = 3 @isok ccall((@cholmod_name("print_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{UInt8}), - F, name, common_struct[Threads.threadid()]) + (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), + F, name, common[Threads.threadid()]) nothing end @@ -625,9 +726,9 @@ function ssmult(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, Sparse(ccall((@cholmod_name("ssmult"),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Cint, - Cint, Ptr{UInt8}), + Cint, Ptr{Common}), A, B, stype, values, - sorted, common_struct[Threads.threadid()])) + sorted, common[Threads.threadid()])) end function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes @@ -635,15 +736,15 @@ function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes throw(ArgumentError("norm argument must be either 0 or 1")) end ccall((@cholmod_name("norm_sparse"), :libcholmod), Cdouble, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, norm, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, norm, common[Threads.threadid()]) end function horzcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("horzcat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, B, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, B, values, common[Threads.threadid()])) end function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealTypes @@ -671,8 +772,8 @@ function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealType sA = unsafe_load(pointer(A)) @isok ccall((@cholmod_name("scale"),:libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - S, scale, A, common_struct[Threads.threadid()]) + (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, scale, A, common[Threads.threadid()]) A end @@ -687,16 +788,16 @@ function sdmult!(A::Sparse{Tv}, transpose::Bool, @isok ccall((@cholmod_name("sdmult"),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Cint, Ref{ComplexF64}, Ref{ComplexF64}, - Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{UInt8}), - A, transpose, α, β, X, Y, common_struct[Threads.threadid()]) + Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), + A, transpose, α, β, X, Y, common[Threads.threadid()]) Y end function vertcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("vertcat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, B, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, B, values, common[Threads.threadid()])) end function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes @@ -706,43 +807,42 @@ function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes nzdiag = Ref{SuiteSparse_long}() rv = ccall((@cholmod_name("symmetry"), :libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Cint, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{UInt8}), + Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{Common}), A, option, xmatched, pmatched, - nzoffdiag, nzdiag, common_struct[Threads.threadid()]) + nzoffdiag, nzdiag, common[Threads.threadid()]) rv, xmatched[], pmatched[], nzoffdiag[], nzdiag[] end # cholmod_cholesky.h # For analyze, analyze_p, and factorize_p!, the Common argument must be # supplied in order to control if the factorization is LLt or LDLt -function analyze(A::Sparse{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function analyze(A::Sparse{Tv}) where Tv<:VTypes Factor(ccall((@cholmod_name("analyze"),:libcholmod), Ptr{C_Factor{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, cmmn)) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end -function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}, - cmmn::Vector{UInt8}) where Tv<:VTypes +function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}) where Tv<:VTypes length(perm) != size(A,1) && throw(BoundsError()) Factor(ccall((@cholmod_name("analyze_p"),:libcholmod), Ptr{C_Factor{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Csize_t, Ptr{UInt8}), - A, perm, C_NULL, 0, cmmn)) + Csize_t, Ptr{Common}), + A, perm, C_NULL, 0, common[Threads.threadid()])) end -function factorize!(A::Sparse{Tv}, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function factorize!(A::Sparse{Tv}, F::Factor{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("factorize"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{UInt8}), - A, F, cmmn) + (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + A, F, common[Threads.threadid()]) F end -function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}) where Tv<:VTypes # note that β is passed as a complex number (double beta[2]), # but the CHOLMOD manual says that only beta[0] (real part) is used @isok ccall((@cholmod_name("factorize_p"),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t, - Ptr{C_Factor{Tv}}, Ptr{UInt8}), - A, β, C_NULL, 0, F, cmmn) + Ptr{C_Factor{Tv}}, Ptr{Common}), + A, β, C_NULL, 0, F, common[Threads.threadid()]) F end @@ -760,8 +860,8 @@ function solve(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) where Tv<:VTypes end end Dense(ccall((@cholmod_name("solve"),:libcholmod), Ptr{C_Dense{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Dense{Tv}}, Ptr{UInt8}), - sys, F, B, common_struct[Threads.threadid()])) + (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), + sys, F, B, common[Threads.threadid()])) end function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes @@ -771,16 +871,16 @@ function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes end Sparse(ccall((@cholmod_name("spsolve"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - sys, F, B, common_struct[Threads.threadid()])) + (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Sparse{Tv}}, Ptr{Common}), + sys, F, B, common[Threads.threadid()])) end # Autodetects the types function read_sparse(file::Libc.FILE, ::Type{SuiteSparse_long}) ptr = ccall((@cholmod_name("read_sparse"), :libcholmod), Ptr{C_Sparse{Cvoid}}, - (Ptr{Cvoid}, Ptr{UInt8}), - file.ptr, common_struct[Threads.threadid()]) + (Ptr{Cvoid}, Ptr{Common}), + file.ptr, common[Threads.threadid()]) if ptr == C_NULL throw(ArgumentError("sparse matrix construction failed. Check that input file is valid.")) end @@ -1274,24 +1374,22 @@ end ## Factorization methods ## Compute that symbolic factorization only -function fact_(A::Sparse{<:VTypes}, cm::Array{UInt8}; +function fact_(A::Sparse{<:VTypes}; perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing, postorder::Bool=true, userperm_only::Bool=true) sA = unsafe_load(pointer(A)) sA.stype == 0 && throw(ArgumentError("sparse matrix is not symmetric/Hermitian")) - if !postorder - unsafe_store!(common_postorder[Threads.threadid()], 0) - end + common[Threads.threadid()].postorder = postorder if perm === nothing || isempty(perm) # TODO: deprecate empty perm - F = analyze(A, cm) + F = analyze(A) else # user permutation provided if userperm_only # use perm even if it is worse than AMD - unsafe_store!(common_nmethods[Threads.threadid()], 1) + common[Threads.threadid()].nmethods = 1 end - F = analyze_p(A, SuiteSparse_long[p-1 for p in perm], cm) + F = analyze_p(A, SuiteSparse_long[p-1 for p in perm]) end return F @@ -1300,10 +1398,10 @@ end function cholesky!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv # Makes it an LLt - unsafe_store!(common_final_ll[Threads.threadid()], 1) + common[Threads.threadid()].final_ll = true # Compute the numerical factorization - factorize_p!(A, shift, F, common_struct[Threads.threadid()]) + factorize_p!(A, shift, F) check && (issuccess(F) || throw(LinearAlgebra.PosDefException(1))) return F @@ -1336,11 +1434,11 @@ cholesky!(F::Factor, A::Union{SparseMatrixCSC{T}, function cholesky(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Compute the symbolic factorization - F = fact_(A, cm; perm = perm) + F = fact_(A; perm = perm) # Compute the numerical factorization cholesky!(F, A; shift = shift, check = check) @@ -1460,14 +1558,14 @@ cholesky(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, function ldlt!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Makes it an LDLt change_factor!(F, false, false, true, false) # Compute the numerical factorization - factorize_p!(A, shift, F, cm) + factorize_p!(A, shift, F) check && (issuccess(F) || throw(LinearAlgebra.ZeroPivotException(1))) return F @@ -1500,16 +1598,16 @@ ldlt!(F::Factor, A::Union{SparseMatrixCSC{T}, function ldlt(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Makes it an LDLt - unsafe_store!(common_final_ll[Threads.threadid()], 0) + cm.final_ll = false # Really make sure it's an LDLt by avoiding supernodal factorization - unsafe_store!(common_supernodal[Threads.threadid()], 0) + cm.supernodal = 0 # Compute the symbolic factorization - F = fact_(A, cm; perm = perm) + F = fact_(A; perm = perm) # Compute the numerical factorization ldlt!(F, A; shift = shift, check = check) @@ -1580,8 +1678,8 @@ function lowrankupdowndate!(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) where Tv throw(DimensionMismatch("matrix dimensions do not fit")) end @isok ccall((@cholmod_name("updown"), :libcholmod), Cint, - (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Cvoid}), - update, C, F, common_struct[Threads.threadid()]) + (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + update, C, F, common[Threads.threadid()]) F end diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl index e94fa73994d03..0cb0d470fc897 100644 --- a/stdlib/SuiteSparse/src/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -52,7 +52,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Dense{Tv}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, - Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{Cvoid}), + Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{CHOLMOD.Common}), ordering, # all, except 3:given treated as 0:fixed tol, # columns with 2-norm <= tol treated as 0 econ, # e = max(min(m,econ),rank(A)) @@ -68,7 +68,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, H, # m-by-nh Householder vectors HPinv, # size m row permutation HTau, # 1-by-nh Householder coefficients - CHOLMOD.common_struct[Threads.threadid()]) # /* workspace and parameters */ + CHOLMOD.common[Threads.threadid()]) # /* workspace and parameters */ if rnk < 0 error("Sparse QR factorization failed") @@ -86,8 +86,8 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # correct deallocator function is called and that the memory count in # the common struct is updated ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{Cvoid}), - n, sizeof(CHOLMOD.SuiteSparse_long), e, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), + n, sizeof(CHOLMOD.SuiteSparse_long), e, CHOLMOD.common[Threads.threadid()]) end hpinv = HPinv[] if hpinv == C_NULL @@ -101,8 +101,8 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # correct deallocator function is called and that the memory count in # the common struct is updated ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{Cvoid}), - m, sizeof(CHOLMOD.SuiteSparse_long), hpinv, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), + m, sizeof(CHOLMOD.SuiteSparse_long), hpinv, CHOLMOD.common[Threads.threadid()]) end return rnk, _E, _HPinv diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index 020c7129cc56f..b0230f97eae2e 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -16,6 +16,21 @@ using SparseArrays: getcolptr # CHOLMOD tests Random.seed!(123) +@testset "Check that the Common and Method Julia structs are consistent with their C counterparts" begin + common_size = ccall((:jl_cholmod_common_size, :libsuitesparse_wrapper), Csize_t, ()) + @test common_size == sizeof(CHOLMOD.Common) + + method_offsets = Vector{Csize_t}(undef,15) + ccall((:jl_cholmod_method_offsets, :libsuitesparse_wrapper), + Nothing, (Ptr{Csize_t},), method_offsets) + @test method_offsets == fieldoffset.(CHOLMOD.Method,1:length(method_offsets)) + + common_offsets = Vector{Csize_t}(undef,107) + ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), + Nothing, (Ptr{Csize_t},), common_offsets) + @test common_offsets == fieldoffset.(CHOLMOD.Common,1:length(common_offsets)) +end + @testset "based on deps/SuiteSparse-4.0.2/CHOLMOD/Demo/" begin # chm_rdsp(joinpath(Sys.BINDIR, "../../deps/SuiteSparse-4.0.2/CHOLMOD/Demo/Matrix/bcsstk01.tri")) @@ -237,8 +252,8 @@ end ## The struct pointer must be constructed by the library constructor and then modified afterwards to checks that the method throws @testset "illegal dtype (for now but should be supported at some point)" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, CHOLMOD.SINGLE, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -246,8 +261,8 @@ end @testset "illegal dtype" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -255,8 +270,8 @@ end @testset "illegal xtype" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 3, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 3) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -264,8 +279,8 @@ end @testset "illegal itype I" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, CHOLMOD.INTLONG, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -273,8 +288,8 @@ end @testset "illegal itype II" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -324,8 +339,8 @@ end # Test Sparse and Factor @testset "test free!" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Float64}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) @test CHOLMOD.free!(p) end diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index 6b704c4bf1112..436f919a60976 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.8.1+0" +version = "5.8.1+2" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93" From 28a33122008fb33bf15c92be6b6b791fe1eb025a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 19 Apr 2021 05:27:08 -0400 Subject: [PATCH 200/439] [SparseArrays] similar on sparse matrix returned uninitialized space (#40444) Co-authored-by: Klaus Crusius --- stdlib/SparseArrays/src/sparsematrix.jl | 12 ++++++------ stdlib/SparseArrays/src/sparsevector.jl | 13 ++++++------- stdlib/SparseArrays/test/sparse.jl | 14 +++++++------- stdlib/SparseArrays/test/sparsevector.jl | 12 ++++++------ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 7bd988d881152..888db226ddd14 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -469,17 +469,17 @@ function _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew} newrowval = copyto!(similar(rowvals(S), TiNew), rowvals(S)) return SparseMatrixCSC(size(S, 1), size(S, 2), newcolptr, newrowval, similar(nonzeros(S), TvNew)) end -# parent methods for similar that preserves only storage space (for when new and old dims differ) +# parent methods for similar that preserves only storage space (for when new dims are 2-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(rowvals(S), TiNew), similar(nonzeros(S), TvNew)) -# parent method for similar that allocates an empty sparse vector (when new dims are single) + SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) +# parent method for similar that allocates an empty sparse vector (for when new dims are 1-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) -# + # The following methods hook into the AbstractArray similar hierarchy. The first method # covers similar(A[, Tv]) calls, which preserve stored-entry structure, and the latter -# methods cover similar(A[, Tv], shape...) calls, which preserve storage space when the shape -# calls for a two-dimensional result. +# methods cover similar(A[, Tv], shape...) calls, which partially preserve +# storage space when the shape calls for a two-dimensional result. similar(S::AbstractSparseMatrixCSC{<:Any,Ti}, ::Type{TvNew}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti) similar(S::AbstractSparseMatrixCSC{<:Any,Ti}, ::Type{TvNew}, dims::Union{Dims{1},Dims{2}}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti, dims) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 09696ab1e06c8..52142553e5019 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -89,25 +89,24 @@ indtype(x::SparseVectorView) = indtype(parent(x)) # parent method for similar that preserves stored-entry structure (for when new and old dims match) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}) where {TvNew,TiNew} = SparseVector(length(S), copyto!(similar(nonzeroinds(S), TiNew), nonzeroinds(S)), similar(nonzeros(S), TvNew)) -# parent method for similar that preserves nothing (for when old and new dims differ, and new is 1d) +# parent method for similar that preserves nothing (for when new dims are 1-d) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) -# parent method for similar that preserves storage space (for old and new dims differ, and new is 2d) +# parent method for similar that preserves storage space (for when new dims are 2-d) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew), similar(nonzeros(S), TvNew)) + SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) + # The following methods hook into the AbstractArray similar hierarchy. The first method # covers similar(A[, Tv]) calls, which preserve stored-entry structure, and the latter # methods cover similar(A[, Tv], shape...) calls, which preserve nothing if the dims -# specify a SparseVector result and storage space if the dims specify a SparseMatrixCSC result. +# specify a SparseVector or a SparseMatrixCSC result. similar(S::SparseVector{<:Any,Ti}, ::Type{TvNew}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti) similar(S::SparseVector{<:Any,Ti}, ::Type{TvNew}, dims::Union{Dims{1},Dims{2}}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti, dims) # The following methods cover similar(A, Tv, Ti[, shape...]) calls, which specify the # result's index type in addition to its entry type, and aren't covered by the hooks above. -# The calls without shape again preserve stored-entry structure, whereas those with -# one-dimensional shape preserve nothing, and those with two-dimensional shape -# preserve storage space. +# The calls without shape again preserve stored-entry structure but no storage space. similar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}) where{TvNew,TiNew} = _sparsesimilar(S, TvNew, TiNew) similar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Union{Dims{1},Dims{2}}) where {TvNew,TiNew} = diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ef5159d41031d..a622d2bc8bcc0 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2487,22 +2487,22 @@ end @test typeof(simA) == typeof(A) @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) - # test similar with entry type and Dims{2} specification (preserves storage space only) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 + # test similar with entry type and Dims{2} specification (empty storage space) simA = similar(A, Float32, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32,eltype(getcolptr(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type, index type, and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, Int8, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32, Int8} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with Dims{1} specification (preserves nothing) simA = similar(A, (6,)) @test typeof(simA) == SparseVector{eltype(nonzeros(A)),eltype(getcolptr(A))} diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index e141deea40517..6d29633bb04e0 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -1424,22 +1424,22 @@ end @test typeof(simA) == SparseMatrixCSC{eltype(nonzeros(A)),eltype(nonzeroinds(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32,eltype(nonzeroinds(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type, index type, and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, Int8, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32, Int8} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 end @testset "Fast operations on full column views" begin From 58bde1851c9df1904791fce3c5edb9ef8581ca06 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Mon, 19 Apr 2021 05:34:16 -0400 Subject: [PATCH 201/439] faster reductions of Transpose, Adjoint, PermutedDimsArray (#39513) --- base/Base.jl | 5 +++-- base/permuteddimsarray.jl | 10 ++++++++++ stdlib/LinearAlgebra/src/adjtrans.jl | 21 +++++++++++++++++++++ stdlib/LinearAlgebra/test/adjtrans.jl | 20 ++++++++++++++++++++ test/arrayops.jl | 4 ++++ 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 5a4826fe5df26..f92cd4e1c3c08 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -213,8 +213,6 @@ include("methodshow.jl") include("cartesian.jl") using .Cartesian include("multidimensional.jl") -include("permuteddimsarray.jl") -using .PermutedDimsArrays include("broadcast.jl") using .Broadcast @@ -293,6 +291,9 @@ end include("reducedim.jl") # macros in this file relies on string.jl include("accumulate.jl") +include("permuteddimsarray.jl") +using .PermutedDimsArrays + # basic data structures include("ordering.jl") using .Order diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 429fa67b2a3ab..3fc2a2340efdc 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -253,6 +253,16 @@ end P end +function Base._mapreduce_dim(f, op, init::Base._InitialValue, A::PermutedDimsArray, dims::Colon) + Base._mapreduce_dim(f, op, init, parent(A), dims) +end + +function Base.mapreducedim!(f, op, B::AbstractArray{T,N}, A::PermutedDimsArray{T,N,perm,iperm}) where {T,N,perm,iperm} + C = PermutedDimsArray{T,N,iperm,perm,typeof(B)}(B) # make the inverse permutation for the output + Base.mapreducedim!(f, op, C, parent(A)) + B +end + function Base.showarg(io::IO, A::PermutedDimsArray{T,N,perm}, toplevel) where {T,N,perm} print(io, "PermutedDimsArray(") Base.showarg(io, parent(A), false) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index f3d08abc54b0e..494429a4fca2d 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -185,7 +185,9 @@ end # some aliases for internal convenience use const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S} const AdjointAbsVec{T} = Adjoint{T,<:AbstractVector} +const AdjointAbsMat{T} = Adjoint{T,<:AbstractMatrix} const TransposeAbsVec{T} = Transpose{T,<:AbstractVector} +const TransposeAbsMat{T} = Transpose{T,<:AbstractMatrix} const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector} const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractMatrix} @@ -275,6 +277,25 @@ Broadcast.broadcast_preserving_zero_d(f, avs::Union{Number,AdjointAbsVec}...) = Broadcast.broadcast_preserving_zero_d(f, tvs::Union{Number,TransposeAbsVec}...) = transpose(broadcast((xs...) -> transpose(f(transpose.(xs)...)), quasiparentt.(tvs)...)) # TODO unify and allow mixed combinations with a broadcast style + +### reductions +# faster to sum the Array than to work through the wrapper +Base._mapreduce_dim(f, op, init::Base._InitialValue, A::Transpose, dims::Colon) = + transpose(Base._mapreduce_dim(_sandwich(transpose, f), _sandwich(transpose, op), init, parent(A), dims)) +Base._mapreduce_dim(f, op, init::Base._InitialValue, A::Adjoint, dims::Colon) = + adjoint(Base._mapreduce_dim(_sandwich(adjoint, f), _sandwich(adjoint, op), init, parent(A), dims)) +# sum(A'; dims) +Base.mapreducedim!(f, op, B::AbstractArray, A::TransposeAbsMat) = + transpose(Base.mapreducedim!(_sandwich(transpose, f), _sandwich(transpose, op), transpose(B), parent(A))) +Base.mapreducedim!(f, op, B::AbstractArray, A::AdjointAbsMat) = + adjoint(Base.mapreducedim!(_sandwich(adjoint, f), _sandwich(adjoint, op), adjoint(B), parent(A))) + +_sandwich(adj::Function, fun) = (xs...,) -> adj(fun(map(adj, xs)...)) +for fun in [:identity, :add_sum, :mul_prod] #, :max, :min] + @eval _sandwich(::Function, ::typeof(Base.$fun)) = Base.$fun +end + + ### linear algebra (-)(A::Adjoint) = Adjoint( -A.parent) diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index e6f271b2b4650..083c8dfa5cb29 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -576,4 +576,24 @@ end @test transpose(Int[]) * Int[] == 0 end +@testset "reductions: $adjtrans" for adjtrans in [transpose, adjoint] + mat = rand(ComplexF64, 3,5) + @test sum(adjtrans(mat)) ≈ sum(collect(adjtrans(mat))) + @test sum(adjtrans(mat), dims=1) ≈ sum(collect(adjtrans(mat)), dims=1) + @test sum(adjtrans(mat), dims=(1,2)) ≈ sum(collect(adjtrans(mat)), dims=(1,2)) + + @test sum(imag, adjtrans(mat)) ≈ sum(imag, collect(adjtrans(mat))) + @test sum(imag, adjtrans(mat), dims=1) ≈ sum(imag, collect(adjtrans(mat)), dims=1) + + mat = [rand(ComplexF64,2,2) for _ in 1:3, _ in 1:5] + @test sum(adjtrans(mat)) ≈ sum(collect(adjtrans(mat))) + @test sum(adjtrans(mat), dims=1) ≈ sum(collect(adjtrans(mat)), dims=1) + @test sum(adjtrans(mat), dims=(1,2)) ≈ sum(collect(adjtrans(mat)), dims=(1,2)) + + @test sum(imag, adjtrans(mat)) ≈ sum(imag, collect(adjtrans(mat))) + @test sum(x -> x[1,2], adjtrans(mat)) ≈ sum(x -> x[1,2], collect(adjtrans(mat))) + @test sum(imag, adjtrans(mat), dims=1) ≈ sum(imag, collect(adjtrans(mat)), dims=1) + @test sum(x -> x[1,2], adjtrans(mat), dims=1) ≈ sum(x -> x[1,2], collect(adjtrans(mat)), dims=1) +end + end # module TestAdjointTranspose diff --git a/test/arrayops.jl b/test/arrayops.jl index 80a37c9d2f26a..27e366f1ce3cc 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -701,6 +701,10 @@ end perm = randperm(4) @test isequal(A,permutedims(permutedims(A,perm),invperm(perm))) @test isequal(A,permutedims(permutedims(A,invperm(perm)),perm)) + + @test sum(permutedims(A,perm)) ≈ sum(PermutedDimsArray(A,perm)) + @test sum(permutedims(A,perm), dims=2) ≈ sum(PermutedDimsArray(A,perm), dims=2) + @test sum(permutedims(A,perm), dims=(2,4)) ≈ sum(PermutedDimsArray(A,perm), dims=(2,4)) end m = [1 2; 3 4] From 6a40cf88e852c3059754ab3a7587f1aca15553fd Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 19 Apr 2021 04:36:04 -0500 Subject: [PATCH 202/439] faster Float16 sinh (#39432) --- base/special/hyperbolic.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/base/special/hyperbolic.jl b/base/special/hyperbolic.jl index f6ff43d900b1b..d84cadcb2b6f2 100644 --- a/base/special/hyperbolic.jl +++ b/base/special/hyperbolic.jl @@ -14,6 +14,7 @@ # is preserved. # ==================================================== + # Hyperbolic functions # sinh methods H_SMALL_X(::Type{Float64}) = 2.0^-28 @@ -49,6 +50,11 @@ function sinh_kernel(x::Float32) return Float32(res*x) end +@inline function sinh16_kernel(x::Float32) + res = evalpoly(x*x, (1.0f0, 0.16666667f0, 0.008333337f0, 0.00019841001f0, + 2.7555539f-6, 2.514339f-8, 1.6260095f-10)) + return Float16(res*x) +end function sinh(x::T) where T<:Union{Float32,Float64} # Method @@ -74,6 +80,14 @@ function sinh(x::T) where T<:Union{Float32,Float64} return copysign(T(.5)*(E - 1/E),x) end +function Base.sinh(a::Float16) + x = Float32(a) + absx = abs(x) + absx <= SINH_SMALL_X(Float32) && return sinh16_kernel(x) + E = exp(absx) + return Float16(copysign(.5f0*(E - 1/E),x)) +end + COSH_SMALL_X(::Type{T}) where T= one(T) function cosh_kernel(x2::Float32) From 399ec046c4e84c3e5dcd91ba8203f9f3c8d3d054 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 19 Apr 2021 05:40:59 -0400 Subject: [PATCH 203/439] safepoints are required in any lock than may be used with allocations (#40487) (which is pretty much all locks) --- src/codegen.cpp | 5 ++++- src/dlload.c | 14 +------------- src/gc.c | 9 ++++----- src/gf.c | 8 ++++---- src/julia.h | 14 +++++++------- src/julia_internal.h | 7 +++---- src/module.c | 36 ++++++++++++++++++------------------ src/runtime_ccall.cpp | 38 ++++++++++++++++++-------------------- 8 files changed, 59 insertions(+), 72 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 4be8510adcbea..1a3460e44fbdd 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -608,7 +608,10 @@ static const auto jlegal_func = new JuliaFunction{ [](LLVMContext &C) { Type *T = PointerType::get(T_jlvalue, AddressSpace::CalleeRooted); return FunctionType::get(T_int32, {T, T}, false); }, - nullptr, + [](LLVMContext &C) { return AttributeList::get(C, + Attributes(C, {Attribute::ReadOnly, Attribute::NoUnwind, Attribute::ArgMemOnly}), + AttributeSet(), + None); }, }; static const auto jl_alloc_obj_func = new JuliaFunction{ "julia.gc_alloc_obj", diff --git a/src/dlload.c b/src/dlload.c index 62f28d583a85a..df03d9d8e900f 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -156,7 +156,7 @@ JL_DLLEXPORT int jl_dlclose(void *handle) JL_NOTSAFEPOINT #endif } -JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, int throw_err) JL_NOTSAFEPOINT // (or throw) +JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, int throw_err) { char path[PATHBUF], relocated[PATHBUF]; int i; @@ -178,20 +178,12 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)(uintptr_t)(&jl_load_dynamic_library), (HMODULE*)&handle)) { -#ifndef __clang_analyzer__ - // Hide the error throwing from the analyser since there isn't a way to express - // "safepoint only when throwing error" currently. jl_error("could not load base module"); -#endif } #else Dl_info info; if (!dladdr((void*)(uintptr_t)&jl_load_dynamic_library, &info) || !info.dli_fname) { -#ifndef __clang_analyzer__ - // Hide the error throwing from the analyser since there isn't a way to express - // "safepoint only when throwing error" currently. jl_error("could not load base module"); -#endif } handle = dlopen(info.dli_fname, RTLD_NOW); #endif @@ -274,11 +266,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, #else const char *reason = dlerror(); #endif -#ifndef __clang_analyzer__ - // Hide the error throwing from the analyser since there isn't a way to express - // "safepoint only when throwing error" currently. jl_errorf("could not load library \"%s\"\n%s", modname, reason); -#endif } handle = NULL; diff --git a/src/gc.c b/src/gc.c index 94f5a80fd0cbe..df06d7e5a6e7f 100644 --- a/src/gc.c +++ b/src/gc.c @@ -480,9 +480,9 @@ void jl_gc_run_all_finalizers(jl_ptls_t ptls) run_finalizers(ptls); } -static void gc_add_finalizer_(jl_ptls_t ptls, void *v, void *f) +static void gc_add_finalizer_(jl_ptls_t ptls, void *v, void *f) JL_NOTSAFEPOINT { - int8_t gc_state = jl_gc_unsafe_enter(ptls); + assert(ptls->gc_state == 0); arraylist_t *a = &ptls->finalizers; // This acquire load and the release store at the end are used to // synchronize with `finalize_object` on another thread. Apart from the GC, @@ -506,15 +506,14 @@ static void gc_add_finalizer_(jl_ptls_t ptls, void *v, void *f) items[oldlen] = v; items[oldlen + 1] = f; jl_atomic_store_release(&a->len, oldlen + 2); - jl_gc_unsafe_leave(ptls, gc_state); } -JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) +JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) JL_NOTSAFEPOINT { gc_add_finalizer_(ptls, (void*)(((uintptr_t)v) | 1), f); } -JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) +JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT { if (__unlikely(jl_typeis(f, jl_voidpointer_type))) { jl_gc_add_ptr_finalizer(ptls, v, jl_unbox_voidpointer(f)); diff --git a/src/gf.c b/src/gf.c index 71c9c9f05f9ad..5bdf7c8ec29b0 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1368,7 +1368,7 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma } if (!jl_is_method(replaced->def.method)) return; // shouldn't happen, but better to be safe - JL_LOCK_NOGC(&replaced->def.method->writelock); + JL_LOCK(&replaced->def.method->writelock); jl_code_instance_t *codeinst = replaced->cache; while (codeinst) { if (codeinst->max_world == ~(size_t)0) { @@ -1388,13 +1388,13 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma invalidate_method_instance(replaced, max_world, depth + 1); } } - JL_UNLOCK_NOGC(&replaced->def.method->writelock); + JL_UNLOCK(&replaced->def.method->writelock); } // invalidate cached methods that overlap this definition static void invalidate_backedges(jl_method_instance_t *replaced_mi, size_t max_world, const char *why) { - JL_LOCK_NOGC(&replaced_mi->def.method->writelock); + JL_LOCK(&replaced_mi->def.method->writelock); jl_array_t *backedges = replaced_mi->backedges; if (backedges) { // invalidate callers (if any) @@ -1405,7 +1405,7 @@ static void invalidate_backedges(jl_method_instance_t *replaced_mi, size_t max_w invalidate_method_instance(replaced[i], max_world, 1); } } - JL_UNLOCK_NOGC(&replaced_mi->def.method->writelock); + JL_UNLOCK(&replaced_mi->def.method->writelock); if (why && _jl_debug_method_invalidation) { jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced_mi); jl_value_t *loctag = jl_cstr_to_string(why); diff --git a/src/julia.h b/src/julia.h index 588b4397e3ab1..1e0d96af669c7 100644 --- a/src/julia.h +++ b/src/julia.h @@ -838,7 +838,8 @@ typedef enum { JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t); -JL_DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f); +JL_DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_finalize(jl_value_t *o); JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value); JL_DLLEXPORT jl_value_t *jl_gc_alloc_0w(void); @@ -1531,11 +1532,10 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var); // get binding for assignment JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, int error); -JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m JL_PROPAGATES_ROOT, - jl_sym_t *var); +JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var); -JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; -JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var); +JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT); @@ -1549,7 +1549,7 @@ JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t JL_DLLEXPORT void jl_module_import_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname); JL_DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s); JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s); -JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m); STATIC_INLINE jl_function_t *jl_get_function(jl_module_t *m, const char *name) { @@ -1703,7 +1703,7 @@ enum JL_RTLD_CONSTANT { #define JL_RTLD_DEFAULT (JL_RTLD_LAZY | JL_RTLD_DEEPBIND) typedef void *jl_uv_libhandle; // compatible with dlopen (void*) / LoadLibrary (HMODULE) -JL_DLLEXPORT jl_uv_libhandle jl_load_dynamic_library(const char *fname, unsigned flags, int throw_err) JL_NOTSAFEPOINT; +JL_DLLEXPORT jl_uv_libhandle jl_load_dynamic_library(const char *fname, unsigned flags, int throw_err); JL_DLLEXPORT jl_uv_libhandle jl_dlopen(const char *filename, unsigned flags) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_dlclose(jl_uv_libhandle handle) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_dlsym(jl_uv_libhandle handle, const char *symbol, void ** value, int throw_err) JL_NOTSAFEPOINT; diff --git a/src/julia_internal.h b/src/julia_internal.h index f3f69bf8f9e7b..dc7236c6b6f40 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -563,7 +563,7 @@ void jl_compute_field_offsets(jl_datatype_t *st); jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims, int isunboxed, int hasptr, int isunion, int elsz); void jl_module_run_initializer(jl_module_t *m); -jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT; +jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); void jl_binding_deprecation_warning(jl_module_t *m, jl_binding_t *b); extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED; extern htable_t jl_current_modules JL_GLOBALLY_ROOTED; @@ -1043,10 +1043,9 @@ extern void *jl_crtdll_handle; extern void *jl_winsock_handle; #endif -void *jl_get_library_(const char *f_lib, int throw_err) JL_NOTSAFEPOINT; +void *jl_get_library_(const char *f_lib, int throw_err); #define jl_get_library(f_lib) jl_get_library_(f_lib, 1) -JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, - void **hnd) JL_NOTSAFEPOINT; +JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, void **hnd); JL_DLLEXPORT void *jl_lazy_load_and_lookup(jl_value_t *lib_val, const char *f_name); JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline( jl_value_t *fobj, jl_datatype_t *result, htable_t *cache, jl_svec_t *fill, diff --git a/src/module.c b/src/module.c index 20c119bedc27c..231efbb357653 100644 --- a/src/module.c +++ b/src/module.c @@ -150,7 +150,7 @@ static jl_binding_t *new_binding(jl_sym_t *name) // get binding for assignment JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, int error) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; @@ -160,7 +160,7 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, b->owner = m; } else if (error) { - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); jl_errorf("cannot assign a value to variable %s.%s from module %s", jl_symbol_name(b->owner->name), jl_symbol_name(var), jl_symbol_name(m->name)); } @@ -170,10 +170,11 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, b = new_binding(var); b->owner = m; *bp = b; + JL_GC_PROMISE_ROOTED(b); jl_gc_wb_buf(m, b, sizeof(jl_binding_t)); } - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b; } @@ -208,7 +209,7 @@ JL_DLLEXPORT jl_module_t *jl_get_module_of_binding(jl_module_t *m, jl_sym_t *var // like jl_get_binding_wr, but has different error paths JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t **bp = _jl_get_module_binding_bp(m, var); jl_binding_t *b = *bp; @@ -218,7 +219,7 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_ b->owner = m; } else { - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); jl_binding_t *b2 = jl_get_binding(b->owner, b->name); if (b2 == NULL || b2->value == NULL) jl_errorf("invalid method definition: imported function %s.%s does not exist", @@ -239,7 +240,7 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_ jl_gc_wb_buf(m, b, sizeof(jl_binding_t)); } - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b; } @@ -583,33 +584,33 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var) JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b != HT_NOTFOUND && (b->exportp || b->owner==m); } -JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t *b = _jl_get_module_binding(m, var); - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b != HT_NOTFOUND && b->exportp; } -JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t *b = _jl_get_module_binding(m, var); - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b != HT_NOTFOUND && b->owner != NULL; } -JL_DLLEXPORT jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT +JL_DLLEXPORT jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) { - JL_LOCK_NOGC(&m->lock); + JL_LOCK(&m->lock); jl_binding_t *b = _jl_get_module_binding(m, var); - JL_UNLOCK_NOGC(&m->lock); + JL_UNLOCK(&m->lock); return b == HT_NOTFOUND ? NULL : b; } @@ -626,7 +627,6 @@ JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *va JL_TYPECHK(jl_set_global, module, (jl_value_t*)m); JL_TYPECHK(jl_set_global, symbol, (jl_value_t*)var); jl_binding_t *bp = jl_get_binding_wr(m, var, 1); - JL_GC_PROMISE_ROOTED(bp); jl_checked_assignment(bp, val); } diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 307acc9c28cd1..050347513aa45 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -27,9 +27,8 @@ using namespace llvm; static std::map libMap; static jl_mutex_t libmap_lock; extern "C" -void *jl_get_library_(const char *f_lib, int throw_err) JL_NOTSAFEPOINT +void *jl_get_library_(const char *f_lib, int throw_err) { - void *hnd; if (f_lib == NULL) return jl_RTLD_DEFAULT_handle; #ifdef _OS_WINDOWS_ @@ -40,23 +39,22 @@ void *jl_get_library_(const char *f_lib, int throw_err) JL_NOTSAFEPOINT if (strcmp(f_lib, JL_LIBJULIA_DL_LIBNAME) == 0) return jl_libjulia_handle; #endif - JL_LOCK_NOGC(&libmap_lock); + JL_LOCK(&libmap_lock); // This is the only operation we do on the map, which doesn't invalidate // any references or iterators. void **map_slot = &libMap[f_lib]; - JL_UNLOCK_NOGC(&libmap_lock); - hnd = jl_atomic_load_acquire(map_slot); - if (hnd != NULL) - return hnd; - // We might run this concurrently on two threads but it doesn't matter. - hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, throw_err); - if (hnd != NULL) - jl_atomic_store_release(map_slot, hnd); + void *hnd = *map_slot; + if (hnd == NULL) { + hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, throw_err); + if (hnd != NULL) + *map_slot = hnd; + } + JL_UNLOCK(&libmap_lock); return hnd; } extern "C" JL_DLLEXPORT -void *jl_load_and_lookup(const char *f_lib, const char *f_name, void **hnd) JL_NOTSAFEPOINT +void *jl_load_and_lookup(const char *f_lib, const char *f_name, void **hnd) { void *handle = jl_atomic_load_acquire(hnd); if (!handle) @@ -210,11 +208,11 @@ extern "C" JL_DLLEXPORT char *jl_format_filename(const char *output_pattern) } -static jl_mutex_t trampoline_lock; // for accesses to the cache and freelist +static jl_mutex_t trampoline_lock; // for accesses to the cache and freelist static void *trampoline_freelist; -static void *trampoline_alloc() // lock taken by caller +static void *trampoline_alloc() JL_NOTSAFEPOINT // lock taken by caller { const int sz = 64; // oversized for most platforms. todo: use precise value? if (!trampoline_freelist) { @@ -235,6 +233,7 @@ static void *trampoline_alloc() // lock taken by caller #endif errno = last_errno; void *next = NULL; + assert(sz < jl_page_size); for (size_t i = 0; i + sz <= jl_page_size; i += sz) { void **curr = (void**)((char*)mem + i); *curr = next; @@ -272,6 +271,8 @@ static void trampoline_deleter(void **f) JL_UNLOCK_NOGC(&trampoline_lock); } +typedef void *(*init_trampoline_t)(void *tramp, void **nval) JL_NOTSAFEPOINT; + // Use of `cache` is not clobbered in JL_TRY JL_GCC_IGNORE_START("-Wclobbered") extern "C" JL_DLLEXPORT @@ -282,7 +283,7 @@ jl_value_t *jl_get_cfunction_trampoline( // call-site constants: htable_t *cache, // weakref htable indexed by (fobj, vals) jl_svec_t *fill, - void *(*init_trampoline)(void *tramp, void **nval), + init_trampoline_t init_trampoline, jl_unionall_t *env, jl_value_t **vals) { @@ -339,11 +340,8 @@ jl_value_t *jl_get_cfunction_trampoline( ((void**)result)[1] = (void*)fobj; } if (!permanent) { - void *ptr_finalizer[2] = { - (void*)jl_voidpointer_type, - (void*)&trampoline_deleter - }; - jl_gc_add_finalizer(result, (jl_value_t*)&ptr_finalizer[1]); + jl_ptls_t ptls = jl_get_ptls_states(); + jl_gc_add_ptr_finalizer(ptls, result, (void*)(uintptr_t)&trampoline_deleter); ((void**)result)[2] = (void*)cache; ((void**)result)[3] = (void*)nval; } From d67f986973445579e0488d3c4cffedc26c07137d Mon Sep 17 00:00:00 2001 From: quildtide <42811940+quildtide@users.noreply.github.com> Date: Mon, 19 Apr 2021 05:46:35 -0400 Subject: [PATCH 204/439] Set DelimitedFiles.readdlm use_mmap default to false for all OSes (#40415) Increased resilience to edge cases where OS is reported Unix-like but Filesystem is abnormal Fixes #8891 Fixes #40352 --- NEWS.md | 3 +++ stdlib/DelimitedFiles/src/DelimitedFiles.jl | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index eed4172c5a31e..24be1feb2108d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -132,6 +132,9 @@ Standard library changes * `mmap` is now exported ([#39816]). +#### DelimitedFiles + +* `readdlm` now defaults to `use_mmap=false` on all OSes for consistent reliability in abnormal filesystem situations ([#40415]). Deprecated or removed --------------------- diff --git a/stdlib/DelimitedFiles/src/DelimitedFiles.jl b/stdlib/DelimitedFiles/src/DelimitedFiles.jl index bf88c12ea9cf2..3091fed79fee8 100644 --- a/stdlib/DelimitedFiles/src/DelimitedFiles.jl +++ b/stdlib/DelimitedFiles/src/DelimitedFiles.jl @@ -190,8 +190,9 @@ Specifying `skipstart` will ignore the corresponding number of initial lines fro If `skipblanks` is `true`, blank lines in the input will be ignored. If `use_mmap` is `true`, the file specified by `source` is memory mapped for potential -speedups. Default is `true` except on Windows. On Windows, you may want to specify `true` if -the file is large, and is only read once and not written to. +speedups if the file is large. Default is `false'. On a Windows filesystem, `use_mmap` should not be set +to `true` unless the file is only read once and is also not written to. +Some edge cases exist where an OS is Unix-like but the filesystem is Windows-like. If `quotes` is `true`, columns enclosed within double-quote (\") characters are allowed to contain new lines and column delimiters. Double-quote characters within a quoted field must @@ -232,7 +233,7 @@ readdlm_auto(input::IO, dlm::AbstractChar, T::Type, eol::AbstractChar, auto::Boo function readdlm_auto(input::AbstractString, dlm::AbstractChar, T::Type, eol::AbstractChar, auto::Bool; opts...) isfile(input) || throw(ArgumentError("Cannot open \'$input\': not a file")) optsd = val_opts(opts) - use_mmap = get(optsd, :use_mmap, Sys.iswindows() ? false : true) + use_mmap = get(optsd, :use_mmap, false) fsz = filesize(input) if use_mmap && fsz > 0 && fsz < typemax(Int) a = open(input, "r") do f From cfc45b402908a0acb3f56a2a3196d65e4b64d602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20S=C3=B6derlind?= Date: Mon, 19 Apr 2021 11:47:44 +0200 Subject: [PATCH 205/439] add `selectdim(A, 2, 3:4)` example (#40456) This adds a `selectdim(A, 2, 3:4)` example to illustrate that several indices can be used (as this is not entirely clear in the text). Based on a suggestion in https://discourse.julialang.org/t/pick-rows-from-array-ndims-not-known-in-advance/59033/6 --- base/abstractarraymath.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 7e88baaa0d840..b14c4816c8178 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -117,6 +117,11 @@ julia> selectdim(A, 2, 3) 2-element view(::Matrix{Int64}, :, 3) with eltype Int64: 3 7 + +julia> selectdim(A, 2, 3:4) +2×2 view(::Matrix{Int64}, :, 3:4) with eltype Int64: + 3 4 + 7 8 ``` """ @inline selectdim(A::AbstractArray, d::Integer, i) = _selectdim(A, d, i, _setindex(i, d, map(Slice, axes(A))...)) From 0598d13c9d4063f4ad8bbc6eda5a85b9396485e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Argel=20Ram=C3=ADrez=20Reyes?= Date: Mon, 19 Apr 2021 02:49:02 -0700 Subject: [PATCH 206/439] Added docstring for -> (#40470) Co-authored-by: Fredrik Ekre --- base/docs/basedocs.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 99a08b03f4d0b..6c29a25aae3d9 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -602,6 +602,32 @@ the last expression in the function body. """ kw"function" +""" + x -> y + +Create an anonymous function mapping argument(s) `x` to the function body `y`. + +```jldoctest +julia> f = x -> x^2 + 2x - 1 +#1 (generic function with 1 method) + +julia> f(2) +7 +``` + +Anonymous functions can also be defined for multiple argumets. +```jldoctest +julia> g = (x,y) -> x^2 + y^2 +#2 (generic function with 1 method) + +julia> g(2,3) +13 +``` + +See the manual section on [anonymous functions](@ref man-anonymous-functions) for more details. +""" +kw"->" + """ return From 83f5786ed5279874847b5a24b25390d658206af4 Mon Sep 17 00:00:00 2001 From: regier21 Date: Mon, 19 Apr 2021 02:52:07 -0700 Subject: [PATCH 207/439] Add docs for RegexMatch and keys(::RegexMatch) (#40486) --- base/regex.jl | 65 ++++++++++++++++++++++++++++++++++++++- doc/src/base/strings.md | 2 ++ doc/src/manual/strings.md | 6 ++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/base/regex.jl b/base/regex.jl index 7fae9326c231b..82e2042552ee4 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -145,6 +145,47 @@ in a string using an `AbstractPattern`. """ abstract type AbstractMatch end +""" + RegexMatch + +A type representing a single match to a `Regex` found in a string. +Typically created from the [`match`](@ref) function. + +The `match` field stores the substring of the entire matched string. +The `captures` field stores the substrings for each capture group, indexed by number. +To index by capture group name, the entire match object should be indexed instead, +as shown in the examples. +The location of the start of the match is stored in the `offset` field. +The `offsets` field stores the locations of the start of each capture group, +with 0 denoting a group that was not captured. + +This type can be used as an iterator over the capture groups of the `Regex`, +yielding the substrings captured in each group. +Because of this, the captures of a match can be destructured. +If a group was not captured, `nothing` will be yielded instead of a substring. + +Methods that accept a `RegexMatch` object are defined for [`iterate`](@ref), +[`length`](@ref), [`eltype`](@ref), [`keys`](@ref keys(::RegexMatch)), [`haskey`](@ref), and +[`getindex`](@ref), where keys are the the names or numbers of a capture group. +See [`keys`](@ref keys(::RegexMatch)) for more information. + +# Examples +```jldoctest +julia> m = match(r"(?\\d+):(?\\d+)(am|pm)?", "11:30 in the morning") +RegexMatch("11:30", hour="11", minute="30", 3=nothing) + +julia> hr, min, ampm = m; + +julia> hr +"11" + +julia> m["minute"] +"30" + +julia> m.match +"11:30" +``` +""" struct RegexMatch <: AbstractMatch match::SubString{String} captures::Vector{Union{Nothing,SubString{String}}} @@ -153,6 +194,28 @@ struct RegexMatch <: AbstractMatch regex::Regex end +""" + keys(m::RegexMatch) -> Vector + +Return a vector of keys for all capture groups of the underlying regex. +A key is included even if the capture group fails to match. +That is, `idx` will be in the return value even if `m[idx] == nothing`. + +Unnamed capture groups will have integer keys corresponding to their index. +Named capture groups will have string keys. + +!!! compat "Julia 1.6" + This method was added in Julia 1.6 + +# Examples +```jldoctest +julia> keys(match(r"(?\\d+):(?\\d+)(am|pm)?", "11:30")) +3-element Vector{Any}: + "hour" + "minute" + 3 +``` +""" function keys(m::RegexMatch) idx_to_capture_name = PCRE.capture_names(m.regex.regex) return map(eachindex(m.captures)) do i @@ -275,7 +338,7 @@ end """ match(r::Regex, s::AbstractString[, idx::Integer[, addopts]]) -Search for the first match of the regular expression `r` in `s` and return a `RegexMatch` +Search for the first match of the regular expression `r` in `s` and return a [`RegexMatch`](@ref) object containing the match, or nothing if the match failed. The matching substring can be retrieved by accessing `m.match` and the captured sequences can be retrieved by accessing `m.captures` The optional `idx` argument specifies an index at which to start the search. diff --git a/doc/src/base/strings.md b/doc/src/base/strings.md index 185a915705f2c..a7e9a8ee4eeee 100644 --- a/doc/src/base/strings.md +++ b/doc/src/base/strings.md @@ -33,6 +33,8 @@ Base.isvalid(::Any, ::Any) Base.isvalid(::AbstractString, ::Integer) Base.match Base.eachmatch +Base.RegexMatch +Base.keys(::RegexMatch) Base.isless(::AbstractString, ::AbstractString) Base.:(==)(::AbstractString, ::AbstractString) Base.cmp(::AbstractString, ::AbstractString) diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 743ce3caa3c0d..4b3c35d5b45f6 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -801,7 +801,7 @@ else end ``` -If a regular expression does match, the value returned by [`match`](@ref) is a `RegexMatch` +If a regular expression does match, the value returned by [`match`](@ref) is a [`RegexMatch`](@ref) object. These objects record how the expression matches, including the substring that the pattern matches and any captured substrings, if there are any. This example only captures the portion of the substring that matches, but perhaps we want to capture any non-blank text after the comment @@ -882,10 +882,10 @@ julia> m.offsets ``` It is convenient to have captures returned as an array so that one can use destructuring syntax -to bind them to local variables: +to bind them to local variables. As a convinience, the `RegexMatch` object implements iterator methods that pass through to the `captures` field, so you can destructure the match object directly: ```jldoctest acdmatch -julia> first, second, third = m.captures; first +julia> first, second, third = m; first "a" ``` From 3d08f826b12659282cc3b8a47d3bb41cd329b026 Mon Sep 17 00:00:00 2001 From: Murari Soundararajan <73845678+murari0@users.noreply.github.com> Date: Mon, 19 Apr 2021 05:53:05 -0400 Subject: [PATCH 208/439] Add `get(::Function, ::ImmutableDict, key)` to resolve #40413 (#40471) --- base/dict.jl | 8 ++++++++ test/dict.jl | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/base/dict.jl b/base/dict.jl index 1c176a2eab864..0ad77959f8225 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -792,6 +792,14 @@ function get(dict::ImmutableDict, key, default) return default end +function get(default::Callable, dict::ImmutableDict, key) + while isdefined(dict, :parent) + isequal(dict.key, key) && return dict.value + dict = dict.parent + end + return default() +end + # this actually defines reverse iteration (e.g. it should not be used for merge/copy/filter type operations) function iterate(d::ImmutableDict{K,V}, t=d) where {K, V} !isdefined(t, :parent) && return nothing diff --git a/test/dict.jl b/test/dict.jl index 534e88ada036c..7cbaf699fc3cc 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -684,6 +684,7 @@ import Base.ImmutableDict d4 = ImmutableDict(d3, k2 => v1) dnan = ImmutableDict{String, Float64}(k2, NaN) dnum = ImmutableDict(dnan, k2 => 1) + f(x) = x^2 @test isempty(collect(d)) @test !isempty(collect(d1)) @@ -729,6 +730,18 @@ import Base.ImmutableDict @test get(d4, "key1", :default) === v2 @test get(d4, "foo", :default) === :default @test get(d, k1, :default) === :default + @test get(d1, "key1") do + f(2) + end === v1 + @test get(d4, "key1") do + f(4) + end === v2 + @test get(d4, "foo") do + f(6) + end === 36 + @test get(d, k1) do + f(8) + end === 64 @test d1["key1"] === v1 @test d4["key1"] === v2 @test empty(d3) === d From a4fc56a57cf04b5aa460e271761d12294598a2fe Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 19 Apr 2021 12:21:10 -0400 Subject: [PATCH 209/439] LibGit2: branch missing test in last_error (#39033) --- stdlib/LibGit2/test/libgit2.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 892fb8bb6f3fe..c987438aace86 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -171,6 +171,12 @@ end @test findfirst(isequal(LibGit2.Consts.FEATURE_HTTPS), f) !== nothing end +@testset "No error at first" begin + class, msg = LibGit2.Error.last_error() + @test msg == "No errors" + @test class == LibGit2.Error.Class(0) +end + @testset "OID" begin z = LibGit2.GitHash() @test LibGit2.iszero(z) From f6b47ff8734e383d237c3ca48979d4a5a2e88bc5 Mon Sep 17 00:00:00 2001 From: Daniel Bruegmann Date: Mon, 19 Apr 2021 19:06:56 +0200 Subject: [PATCH 210/439] Add scal!(a,X) (#40446) --- stdlib/LinearAlgebra/src/blas.jl | 9 +++++++++ stdlib/LinearAlgebra/test/blas.jl | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 0ef4f14d092b5..57fd5c03342d7 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -218,15 +218,21 @@ end """ scal!(n, a, X, incx) + scal!(a, X) Overwrite `X` with `a*X` for the first `n` elements of array `X` with stride `incx`. Returns `X`. + +If `n` and `incx` are not provided, `length(X)` and `stride(X,1)` are used. """ function scal! end """ scal(n, a, X, incx) + scal(a, X) Return `X` scaled by `a` for the first `n` elements of array `X` with stride `incx`. + +If `n` and `incx` are not provided, `length(X)` and `stride(X,1)` are used. """ function scal end @@ -242,9 +248,12 @@ for (fname, elty) in ((:dscal_,:Float64), n, DA, DX, incx) DX end + + scal!(DA::$elty, DX::AbstractArray{$elty}) = scal!(length(DX),DA,DX,stride(DX,1)) end end scal(n, DA, DX, incx) = scal!(n, DA, copy(DX), incx) +scal(DA, DX) = scal!(DA, copy(DX)) ## dot diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index be325617acb53..911b684b1793b 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -514,6 +514,11 @@ end BLAS.axpby!(elty(2), x, elty(3), y) @test y == WrappedArray(elty[19, 50, 30, 56]) @test BLAS.iamax(x) == 2 + + M = fill(elty(1.0), 3, 3) + BLAS.scal!(elty(2), view(M,:,2)) + BLAS.scal!(elty(3), view(M,3,:)) + @test M == elty[1. 2. 1.; 1. 2. 1.; 3. 6. 3.] # Level 2 A = WrappedArray(elty[1 2; 3 4]) x = WrappedArray(elty[1, 2]) From b67d706f6553cf572fa1aa547ba8586c4eee4b04 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 19 Apr 2021 15:05:35 -0400 Subject: [PATCH 211/439] Revert "LibGit2: branch missing test in last_error (#39033)" (#40530) This reverts commit a4fc56a57cf04b5aa460e271761d12294598a2fe. --- stdlib/LibGit2/test/libgit2.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index c987438aace86..892fb8bb6f3fe 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -171,12 +171,6 @@ end @test findfirst(isequal(LibGit2.Consts.FEATURE_HTTPS), f) !== nothing end -@testset "No error at first" begin - class, msg = LibGit2.Error.last_error() - @test msg == "No errors" - @test class == LibGit2.Error.Class(0) -end - @testset "OID" begin z = LibGit2.GitHash() @test LibGit2.iszero(z) From 2435f96f92ebe8635fd3c43efc93c94cc0ed291a Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Mon, 19 Apr 2021 17:04:42 -0400 Subject: [PATCH 212/439] Add many "see also" links to docstrings (#38606) --- base/abstractarray.jl | 82 ++++++++++++++--- base/abstractarraymath.jl | 16 ++-- base/abstractset.jl | 14 ++- base/accumulate.jl | 2 + base/array.jl | 52 ++++++++++- base/bool.jl | 2 + base/combinatorics.jl | 7 ++ base/complex.jl | 17 ++++ base/div.jl | 16 +++- base/docs/basedocs.jl | 90 ++++++++++++++++--- base/essentials.jl | 13 ++- base/file.jl | 10 +++ base/float.jl | 56 +++++++++++- base/hashing.jl | 6 +- base/iddict.jl | 2 +- base/int.jl | 39 +++++++- base/irrationals.jl | 4 +- base/iterators.jl | 32 +++++++ base/math.jl | 48 +++++++++- base/mathconstants.jl | 28 ++++++ base/missing.jl | 4 +- base/multidimensional.jl | 2 + base/number.jl | 38 +++++++- base/operators.jl | 24 ++++- base/permuteddimsarray.jl | 20 +++-- base/promotion.jl | 19 +++- base/reduce.jl | 19 +++- base/reducedim.jl | 4 + base/reflection.jl | 27 +++++- base/set.jl | 11 ++- base/show.jl | 17 +++- base/some.jl | 4 +- base/sort.jl | 6 +- base/special/exp.jl | 18 +++- base/special/trig.jl | 8 ++ base/strings/io.jl | 6 +- base/strings/util.jl | 10 ++- base/threadingconstructs.jl | 8 ++ base/tuple.jl | 4 + doc/src/base/arrays.md | 2 + doc/src/base/base.md | 5 ++ doc/src/base/math.md | 2 + stdlib/Distributed/docs/src/index.md | 2 +- stdlib/InteractiveUtils/docs/src/index.md | 2 +- .../InteractiveUtils/src/InteractiveUtils.jl | 6 ++ stdlib/InteractiveUtils/src/macros.jl | 8 +- stdlib/LinearAlgebra/docs/src/index.md | 1 + stdlib/LinearAlgebra/src/dense.jl | 7 +- stdlib/LinearAlgebra/src/generic.jl | 4 + stdlib/Printf/docs/src/index.md | 2 +- 50 files changed, 747 insertions(+), 79 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 6552e7128ef8b..45a6118412712 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -8,6 +8,8 @@ Supertype for `N`-dimensional arrays (or array-like types) with elements of type `T`. [`Array`](@ref) and other types are subtypes of this. See the manual section on the [`AbstractArray` interface](@ref man-interface-array). + +See also: [`AbstractVector`](@ref), [`AbstractMatrix`](@ref), [`eltype`](@ref), [`ndims`](@ref). """ AbstractArray @@ -24,6 +26,8 @@ dimension to just get the length of that dimension. Note that `size` may not be defined for arrays with non-standard indices, in which case [`axes`](@ref) may be useful. See the manual chapter on [arrays with custom indices](@ref man-custom-indices). +See also: [`length`](@ref), [`ndims`](@ref), [`eachindex`](@ref), [`sizeof`](@ref). + # Examples ```jldoctest julia> A = fill(1, (2,3,4)); @@ -75,6 +79,8 @@ end Return the tuple of valid indices for array `A`. +See also: [`size`](@ref), [`keys`](@ref), [`eachindex`](@ref). + # Examples ```jldoctest @@ -174,6 +180,8 @@ For dictionary types, this will be a `Pair{KeyType,ValType}`. The definition instead of types. However the form that accepts a type argument should be defined for new types. +See also: [`keytype`](@ref), [`typeof`](@ref). + # Examples ```jldoctest julia> eltype(fill(1f0, (2,2))) @@ -202,6 +210,8 @@ elsize(A::AbstractArray) = elsize(typeof(A)) Return the number of dimensions of `A`. +See also: [`size`](@ref), [`axes`](@ref). + # Examples ```jldoctest julia> A = fill(1, (3,4,5)); @@ -220,6 +230,8 @@ Return the number of elements in the collection. Use [`lastindex`](@ref) to get the last valid index of an indexable collection. +See also: [`size`](@ref), [`ndims`](@ref), [`eachindex`](@ref). + # Examples ```jldoctest julia> length(1:5) @@ -336,6 +348,8 @@ Return the last index of `collection`. If `d` is given, return the last index of The syntaxes `A[end]` and `A[end, end]` lower to `A[lastindex(A)]` and `A[lastindex(A, 1), lastindex(A, 2)]`, respectively. +See also: [`axes`](@ref), [`firstindex`](@ref), [`eachindex`](@ref), [`prevind`](@ref). + # Examples ```jldoctest julia> lastindex([1,2,4]) @@ -354,6 +368,11 @@ lastindex(a, d) = (@_inline_meta; last(axes(a, d))) Return the first index of `collection`. If `d` is given, return the first index of `collection` along dimension `d`. +The syntaxes `A[begin]` and `A[1, begin]` lower to `A[firstindex(A)]` and +`A[1, firstindex(A, 2)]`, respectively. + +See also: [`first`](@ref), [`axes`](@ref), [`lastindex`](@ref), [`nextind`](@ref). + # Examples ```jldoctest julia> firstindex([1,2,4]) @@ -374,6 +393,8 @@ first(a::AbstractArray) = a[first(eachindex(a))] Get the first element of an iterable collection. Return the start point of an [`AbstractRange`](@ref) even if it is empty. +See also: [`only`](@ref), [`firstindex`](@ref), [`last`](@ref). + # Examples ```jldoctest julia> first(2:2:10) @@ -395,6 +416,8 @@ end Get the first `n` elements of the iterable collection `itr`, or fewer elements if `itr` is not long enough. +See also: [`startswith`](@ref), [`Iterators.take`](@ref). + !!! compat "Julia 1.6" This method requires at least Julia 1.6. @@ -426,6 +449,8 @@ Get the last element of an ordered collection, if it can be computed in O(1) tim accomplished by calling [`lastindex`](@ref) to get the last index. Return the end point of an [`AbstractRange`](@ref) even if it is empty. +See also [`first`](@ref), [`endswith`](@ref). + # Examples ```jldoctest julia> last(1:2:10) @@ -472,6 +497,8 @@ end Return a tuple of the memory strides in each dimension. +See also: [`stride`](@ref). + # Examples ```jldoctest julia> A = fill(1, (3,4,5)); @@ -487,6 +514,8 @@ function strides end Return the distance in memory (in number of elements) between adjacent elements in dimension `k`. +See also: [`strides`](@ref). + # Examples ```jldoctest julia> A = fill(1, (3,4,5)); @@ -660,6 +689,8 @@ Return `true` if the given `index` is within the bounds of arrays can extend this method in order to provide a specialized bounds checking implementation. +See also [`checkbounds`](@ref). + # Examples ```jldoctest julia> checkindex(Bool, 1:20, 8) @@ -735,6 +766,7 @@ julia> similar(falses(10), Float64, 2, 4) 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314 ``` +See also: [`undef`](@ref), [`isassigned`](@ref). """ similar(a::AbstractArray{T}) where {T} = similar(a, T) similar(a::AbstractArray, ::Type{T}) where {T} = similar(a, T, to_shape(axes(a))) @@ -791,6 +823,8 @@ similar(::Type{T}, dims::Dims) where {T<:AbstractArray} = T(undef, dims) Create an empty vector similar to `v`, optionally changing the `eltype`. +See also: [`empty!`](@ref), [`isempty`](@ref), [`isassigned`](@ref). + # Examples ```jldoctest @@ -815,6 +849,7 @@ elements in `dst`. If `dst` and `src` are of the same type, `dst == src` should hold after the call. If `dst` and `src` are multidimensional arrays, they must have equal [`axes`](@ref). + See also [`copyto!`](@ref). !!! compat "Julia 1.1" @@ -922,11 +957,12 @@ end """ copyto!(dest::AbstractArray, src) -> dest - Copy all elements from collection `src` to array `dest`, whose length must be greater than or equal to the length `n` of `src`. The first `n` elements of `dest` are overwritten, the other elements are left untouched. +See also [`copy!`](@ref Base.copy!), [`copy`](@ref). + # Examples ```jldoctest julia> x = [1., 0., 3., 0., 5.]; @@ -2130,18 +2166,28 @@ end foreach(f, c...) -> Nothing Call function `f` on each element of iterable `c`. -For multiple iterable arguments, `f` is called elementwise. -`foreach` should be used instead of `map` when the results of `f` are not +For multiple iterable arguments, `f` is called elementwise, and iteration stops when +any iterator is finished. + +`foreach` should be used instead of [`map`](@ref) when the results of `f` are not needed, for example in `foreach(println, array)`. # Examples ```jldoctest -julia> a = 1:3:7; +julia> tri = 1:3:7; res = Int[]; -julia> foreach(x -> println(x^2), a) -1 -16 -49 +julia> foreach(x -> push!(res, x^2), tri) + +julia> res +3-element Vector{$(Int)}: + 1 + 16 + 49 + +julia> foreach((x, y) -> println(x, " with ", y), tri, 'a':'z') +1 with a +4 with b +7 with c ``` """ foreach(f) = (f(); nothing) @@ -2162,6 +2208,8 @@ colons go in this expression. The results are concatenated along the remaining d For example, if `dims` is `[1,2]` and `A` is 4-dimensional, `f` is called on `A[:,:,i,j]` for all `i` and `j`. +See also [`eachcol`](@ref), [`eachslice`](@ref). + # Examples ```jldoctest julia> a = reshape(Vector(1:16),(2,2,2,2)) @@ -2308,9 +2356,9 @@ mapany(f, itr) = Any[f(x) for x in itr] map(f, c...) -> collection Transform collection `c` by applying `f` to each element. For multiple collection arguments, -apply `f` elementwise. +apply `f` elementwise, and stop when when any of them is exhausted. -See also: [`mapslices`](@ref) +See also: [`map!`](@ref), [`foreach`](@ref), [`mapreduce`](@ref), [`mapslices`](@ref), [`zip`](@ref), [`Iterators.map`](@ref). # Examples ```jldoctest @@ -2320,7 +2368,7 @@ julia> map(x -> x * 2, [1, 2, 3]) 4 6 -julia> map(+, [1, 2, 3], [10, 20, 30]) +julia> map(+, [1, 2, 3], [10, 20, 30, 400, 5000]) 3-element Vector{Int64}: 11 22 @@ -2365,7 +2413,9 @@ end map!(function, destination, collection...) Like [`map`](@ref), but stores the result in `destination` rather than a new -collection. `destination` must be at least as large as the first collection. +collection. `destination` must be at least as large as the smallest collection. + +See also: [`map`](@ref), [`foreach`](@ref), [`zip`](@ref), [`copyto!`](@ref). # Examples ```jldoctest @@ -2378,6 +2428,14 @@ julia> a 2.0 4.0 6.0 + +julia> map!(+, zeros(Int, 5), 100:999, 1:3) +5-element Vector{$(Int)}: + 101 + 103 + 105 + 0 + 0 ``` """ function map!(f::F, dest::AbstractArray, As::AbstractArray...) where {F} diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index b14c4816c8178..3545d33ec5cf5 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -36,7 +36,7 @@ julia> vec(1:3) 1:3 ``` -See also [`reshape`](@ref). +See also [`reshape`](@ref), [`dropdims`](@ref). """ vec(a::AbstractArray) = reshape(a,length(a)) vec(a::AbstractVector) = a @@ -52,6 +52,8 @@ Remove the dimensions specified by `dims` from array `A`. Elements of `dims` must be unique and within the range `1:ndims(A)`. `size(A,i)` must equal 1 for all `i` in `dims`. +See also: [`reshape`](@ref), [`vec`](@ref). + # Examples ```jldoctest julia> a = reshape(Vector(1:4),(2,2,1,1)) @@ -106,6 +108,8 @@ Return a view of all the data of `A` where the index for dimension `d` equals `i Equivalent to `view(A,:,:,...,i,:,:,...)` where `i` is in position `d`. +See also: [`eachslice`](@ref). + # Examples ```jldoctest julia> A = [1 2 3 4; 5 6 7 8] @@ -143,6 +147,8 @@ Circularly shift, i.e. rotate, the data in an array. The second argument is a tu vector giving the amount to shift in each dimension, or an integer to shift only in the first dimension. +See also: [`circshift!`](@ref), [`circcopy!`](@ref), [`bitrotate`](@ref), [`<<`](@ref). + # Examples ```jldoctest julia> b = reshape(Vector(1:16), (4,4)) @@ -190,8 +196,6 @@ julia> circshift(a, -1) 1 1 ``` - -See also [`circshift!`](@ref). """ function circshift(a::AbstractArray, shiftamt) circshift!(similar(a), a, map(Integer, (shiftamt...,))) @@ -204,6 +208,8 @@ end Construct an array by repeating array `A` a given number of times in each dimension, specified by `counts`. +See also: [`fill`](@ref), [`Iterators.repeated`](@ref), [`Iterators.cycle`](@ref). + # Examples ```jldoctest julia> repeat([1, 2, 3], 2) @@ -397,7 +403,7 @@ end#module Create a generator that iterates over the first dimension of vector or matrix `A`, returning the rows as `AbstractVector` views. -See also [`eachcol`](@ref) and [`eachslice`](@ref). +See also [`eachcol`](@ref), [`eachslice`](@ref), [`mapslices`](@ref). !!! compat "Julia 1.1" This function requires at least Julia 1.1. @@ -465,7 +471,7 @@ the data from the other dimensions in `A`. Only a single dimension in `dims` is currently supported. Equivalent to `(view(A,:,:,...,i,:,: ...)) for i in axes(A, dims))`, where `i` is in position `dims`. -See also [`eachrow`](@ref), [`eachcol`](@ref), and [`selectdim`](@ref). +See also [`eachrow`](@ref), [`eachcol`](@ref), [`mapslices`](@ref), and [`selectdim`](@ref). !!! compat "Julia 1.1" This function requires at least Julia 1.1. diff --git a/base/abstractset.jl b/base/abstractset.jl index 659417b7bfd4e..697a1ca275aae 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -13,6 +13,8 @@ copy!(dst::AbstractSet, src::AbstractSet) = union!(empty!(dst), src) Construct the union of sets. Maintain order with arrays. +See also: [`intersect`](@ref), [`isdisjoint`](@ref), [`vcat`](@ref), [`Iterators.flatten`](@ref). + # Examples ```jldoctest julia> union([1, 2], [3, 4]) @@ -101,6 +103,8 @@ end Construct the intersection of sets. Maintain order with arrays. +See also: [`setdiff`](@ref), [`isdisjoint`](@ref), [`issubset`](@ref Base.issubset), [`issetequal`](@ref). + # Examples ```jldoctest julia> intersect([1, 2, 3], [3, 4, 5]) @@ -145,6 +149,8 @@ intersect!(s::AbstractSet, itr) = Construct the set of elements in `s` but not in any of the iterables in `itrs`. Maintain order with arrays. +See also [`setdiff!`](@ref), [`union`](@ref) and [`intersect`](@ref). + # Examples ```jldoctest julia> setdiff([1,2,3], [3,4,5]) @@ -194,6 +200,8 @@ Construct the symmetric difference of elements in the passed in sets. When `s` is not an `AbstractSet`, the order is maintained. Note that in this case the multiplicity of elements matters. +See also [`symdiff!`](@ref), [`setdiff`](@ref), [`union`](@ref) and [`intersect`](@ref). + # Examples ```jldoctest julia> symdiff([1,2,3], [3,4,5], [4,5,6]) @@ -246,7 +254,7 @@ function ⊇ end Determine whether every element of `a` is also in `b`, using [`in`](@ref). -See also [`⊊`](@ref), [`⊈`](@ref). +See also [`⊊`](@ref), [`⊈`](@ref), [`∩`](@ref intersect), [`∪`](@ref union), [`contains`](@ref). # Examples ```jldoctest @@ -357,6 +365,8 @@ false Determine whether `a` and `b` have the same elements. Equivalent to `a ⊆ b && b ⊆ a` but more efficient when possible. +See also: [`isdisjoint`](@ref), [`union`](@ref). + # Examples ```jldoctest julia> issetequal([1, 2], [1, 2, 3]) @@ -390,6 +400,8 @@ end Return whether the collections `v1` and `v2` are disjoint, i.e. whether their intersection is empty. +See also: [`issetequal`](@ref), [`intersect`](@ref). + !!! compat "Julia 1.5" This function requires at least Julia 1.5. """ diff --git a/base/accumulate.jl b/base/accumulate.jl index f90f85b315d7c..c1ec372de9033 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -204,6 +204,8 @@ Cumulative product of an iterator. See also [`cumprod!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). +See also [`cumprod!`](@ref), [`accumulate`](@ref), [`cumsum`](@ref). + !!! compat "Julia 1.5" `cumprod` on a non-array iterator requires at least Julia 1.5. diff --git a/base/array.jl b/base/array.jl index 7fd3ea8fb0bc2..c17d832d391f1 100644 --- a/base/array.jl +++ b/base/array.jl @@ -54,6 +54,8 @@ Array One-dimensional dense array with elements of type `T`, often used to represent a mathematical vector. Alias for [`Array{T,1}`](@ref). + +See also [`empty`](@ref), [`similar`](@ref) and [`zero`](@ref) for creating vectors. """ const Vector{T} = Array{T,1} @@ -62,6 +64,9 @@ const Vector{T} = Array{T,1} Two-dimensional dense array with elements of type `T`, often used to represent a mathematical matrix. Alias for [`Array{T,2}`](@ref). + +See also [`fill`](@ref), [`zeros`](@ref), [`undef`](@ref) and [`similar`](@ref) +for creating matrices. """ const Matrix{T} = Array{T,2} @@ -356,6 +361,8 @@ end Create a shallow copy of `x`: the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original. + +See also [`copy!`](@ref Base.copy!), [`copyto!`](@ref). """ copy @@ -433,6 +440,8 @@ array of floats, with each element initialized to `1.0`. `dims` may be specified as either a tuple or a sequence of arguments. For example, the common idiom `fill(x)` creates a zero-dimensional array containing the single value `x`. +See also: [`fill!`](@ref), [`zeros`](@ref), [`ones`](@ref), [`similar`](@ref). + # Examples ```jldoctest julia> fill(1.0, (2,3)) @@ -469,7 +478,7 @@ fill(v, dims::Tuple{}) = (a=Array{typeof(v),0}(undef, dims); fill!(a, v); a) zeros([T=Float64,] dims...) Create an `Array`, with element type `T`, of all zeros with size specified by `dims`. -See also [`fill`](@ref), [`ones`](@ref). +See also [`fill`](@ref), [`ones`](@ref), [`zero`](@ref). # Examples ```jldoctest @@ -600,6 +609,8 @@ Return an `Array` of all items in a collection or iterator. For dictionaries, re [`HasShape`](@ref IteratorSize) trait, the result will have the same shape and number of dimensions as the argument. +Used by comprehensions to turn a generator into an `Array`. + # Examples ```jldoctest julia> collect(1:2:13) @@ -611,6 +622,13 @@ julia> collect(1:2:13) 9 11 13 + +julia> [x^2 for x in 1:8 if isodd(x)] +4-element Vector{Int64}: + 1 + 9 + 25 + 49 ``` """ collect(itr) = _collect(1:1 #= Array =#, itr, IteratorEltype(itr), IteratorSize(itr)) @@ -934,6 +952,8 @@ collection to it. The result of the preceding example is equivalent to `append!( 5, 6])`. For `AbstractSet` objects, [`union!`](@ref) can be used instead. See [`sizehint!`](@ref) for notes about the performance model. + +See also [`pushfirst!`](@ref). """ function push! end @@ -983,6 +1003,9 @@ themselves in another collection. The result of the preceding example is equival `push!([1, 2, 3], 4, 5, 6)`. See [`sizehint!`](@ref) for notes about the performance model. + +See also [`vcat`](@ref) for vectors, [`union!`](@ref) for sets, +and [`prepend!`](@ref) and [`pushfirst!`](@ref) for the opposite order. """ function append!(a::Vector, items::AbstractVector) itemindices = eachindex(items) @@ -1157,6 +1180,8 @@ Remove an item in `collection` and return it. If `collection` is an ordered container, the last item is returned; for unordered containers, an arbitrary element is returned. +See also: [`popfirst!`](@ref), [`popat!`](@ref), [`delete!`](@ref), [`deleteat!`](@ref), [`splice!`](@ref), and [`push!`](@ref). + # Examples ```jldoctest julia> A=[1, 2, 3] @@ -1205,7 +1230,8 @@ Remove the item at the given `i` and return it. Subsequent items are shifted to fill the resulting gap. When `i` is not a valid index for `a`, return `default`, or throw an error if `default` is not specified. -See also [`deleteat!`](@ref) and [`splice!`](@ref). + +See also: [`pop!`](@ref), [`popfirst!`](@ref), [`deleteat!`](@ref), [`splice!`](@ref). !!! compat "Julia 1.5" This function is available as of Julia 1.5. @@ -1278,6 +1304,8 @@ Remove the first `item` from `collection`. This function is called `shift` in many other programming languages. +See also: [`pop!`](@ref), [`popat!`](@ref), [`delete!`](@ref). + # Examples ```jldoctest julia> A = [1, 2, 3, 4, 5, 6] @@ -1316,6 +1344,8 @@ end Insert an `item` into `a` at the given `index`. `index` is the index of `item` in the resulting `a`. +See also: [`push!`](@ref), [`replace`](@ref), [`popat!`](@ref), [`splice!`](@ref). + # Examples ```jldoctest julia> insert!([6, 5, 4, 2, 1], 4, 3) @@ -1343,6 +1373,8 @@ end Remove the item at the given `i` and return the modified `a`. Subsequent items are shifted to fill the resulting gap. +See also: [`delete!`](@ref), [`popat!`](@ref), [`splice!`](@ref). + # Examples ```jldoctest julia> deleteat!([6, 5, 4, 3, 2, 1], 2) @@ -1454,6 +1486,8 @@ Subsequent items are shifted left to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item. +See also: [`replace`](@ref), [`delete!`](@ref), [`deleteat!`](@ref), [`pop!`](@ref), [`popat!`](@ref). + # Examples ```jldoctest julia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5) @@ -1603,7 +1637,7 @@ end reverse(v [, start=1 [, stop=length(v) ]] ) Return a copy of `v` reversed from start to stop. See also [`Iterators.reverse`](@ref) -for reverse-order iteration without making a copy. +for reverse-order iteration without making a copy, and in-place [`reverse!`](@ref). # Examples ```jldoctest @@ -1806,6 +1840,8 @@ To search for other kinds of values, pass a predicate as the first argument. Indices or keys are of the same type as those returned by [`keys(A)`](@ref) and [`pairs(A)`](@ref). +See also: [`findall`](@ref), [`findnext`](@ref), [`findlast`](@ref), [`searchsortedfirst`](@ref). + # Examples ```jldoctest julia> A = [false, false, true, false] @@ -1947,6 +1983,8 @@ or `nothing` if not found. Indices are of the same type as those returned by [`keys(A)`](@ref) and [`pairs(A)`](@ref). +See also: [`findnext`](@ref), [`findfirst`](@ref), [`findall`](@ref). + # Examples ```jldoctest julia> A = [false, false, true, true] @@ -1992,6 +2030,8 @@ Return `nothing` if there is no `true` value in `A`. Indices or keys are of the same type as those returned by [`keys(A)`](@ref) and [`pairs(A)`](@ref). +See also: [`findfirst`](@ref), [`findprev`](@ref), [`findall`](@ref). + # Examples ```jldoctest julia> A = [true, false, true, false] @@ -2184,6 +2224,8 @@ To search for other kinds of values, pass a predicate as the first argument. Indices or keys are of the same type as those returned by [`keys(A)`](@ref) and [`pairs(A)`](@ref). +See also: [`findfirst`](@ref), [`searchsorted`](@ref). + # Examples ```jldoctest julia> A = [true, false, false, true] @@ -2241,6 +2283,8 @@ Return an array containing the first index in `b` for each value in `a` that is a member of `b`. The output array contains `nothing` wherever `a` is not a member of `b`. +See also: [`sortperm`](@ref), [`findfirst`](@ref). + # Examples ```jldoctest julia> a = ['a', 'b', 'c', 'b', 'd', 'a']; @@ -2374,6 +2418,8 @@ The function `f` is passed one argument. !!! compat "Julia 1.4" Support for `a` as a tuple requires at least Julia 1.4. +See also: [`filter!`](@ref), [`Iterators.filter`](@ref). + # Examples ```jldoctest julia> a = 1:10 diff --git a/base/bool.jl b/base/bool.jl index 297aa1863a64e..d42cfb0603279 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -14,6 +14,8 @@ typemax(::Type{Bool}) = true Boolean not. Implements [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic), returning [`missing`](@ref) if `x` is `missing`. +See also [`~`](@ref) for bitwise not. + # Examples ```jldoctest julia> !true diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 7411de5b40043..daa534e068af6 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -228,8 +228,15 @@ invpermute!(a, p::AbstractVector) = invpermute!!(a, copymutable(p)) Return the inverse permutation of `v`. If `B = A[v]`, then `A == B[invperm(v)]`. +See also [`sortperm`](@ref), [`invpermute!`](@ref), [`isperm`](@ref), [`permutedims`](@ref). + # Examples ```jldoctest +julia> p = (2, 3, 1); + +julia> invperm(p) +(3, 1, 2) + julia> v = [2; 4; 3; 1]; julia> invperm(v) diff --git a/base/complex.jl b/base/complex.jl index 7cf266f2bc4de..4fe736a7c0465 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -7,6 +7,8 @@ Complex number type with real and imaginary part of type `T`. `ComplexF16`, `ComplexF32` and `ComplexF64` are aliases for `Complex{Float16}`, `Complex{Float32}` and `Complex{Float64}` respectively. + +See also: [`Real`](@ref), [`complex`](@ref), [`real`](@ref). """ struct Complex{T<:Real} <: Number re::T @@ -20,10 +22,15 @@ Complex(x::Real) = Complex(x, zero(x)) The imaginary unit. +See also: [`imag`](@ref), [`angle`](@ref), [`complex`](@ref). + # Examples ```jldoctest julia> im * im -1 + 0im + +julia> (2.0 + 3im)^2 +-5.0 + 12.0im ``` """ const im = Complex(false, true) @@ -54,6 +61,8 @@ float(::Type{Complex{T}}) where {T} = Complex{float(T)} Return the real part of the complex number `z`. +See also: [`imag`](@ref), [`reim`](@ref), [`complex`](@ref), [`isreal`](@ref), [`Real`](@ref). + # Examples ```jldoctest julia> real(1 + 3im) @@ -67,6 +76,8 @@ real(z::Complex) = z.re Return the imaginary part of the complex number `z`. +See also: [`conj`](@ref), [`reim`](@ref), [`adjoint`](@ref), [`angle`](@ref). + # Examples ```jldoctest julia> imag(1 + 3im) @@ -254,6 +265,8 @@ end Compute the complex conjugate of a complex number `z`. +See also: [`angle`](@ref), [`adjoint`](@ref). + # Examples ```jldoctest julia> conj(1 + 3im) @@ -533,6 +546,8 @@ end Return ``\\exp(iz)``. +See also [`cispi`](@ref), [`angle`](@ref). + # Examples ```jldoctest julia> cis(π) ≈ -1 @@ -574,6 +589,8 @@ end Compute the phase angle in radians of a complex number `z`. +See also: [`atan`](@ref), [`cis`](@ref). + # Examples ```jldoctest julia> rad2deg(angle(1 + im)) diff --git a/base/div.jl b/base/div.jl index d78220c530608..8b8361c4150ed 100644 --- a/base/div.jl +++ b/base/div.jl @@ -88,12 +88,16 @@ rem(x::Integer, y::Integer, r::RoundingMode{:Nearest}) = divrem(x, y, r)[2] Largest integer less than or equal to `x/y`. Equivalent to `div(x, y, RoundDown)`. -See also: [`div`](@ref) +See also: [`div`](@ref), [`cld`](@ref), [`fld1`](@ref). # Examples ```jldoctest julia> fld(7.3,5.5) 1.0 + +julia> fld.(-5:5, 3)' +1×11 adjoint(::Vector{Int64}) with eltype Int64: + -2 -2 -1 -1 -1 0 0 0 1 1 1 ``` Because `fld(x, y)` implements strictly correct floored rounding based on the true value of floating-point numbers, unintuitive situations can arise. For example: @@ -118,12 +122,16 @@ fld(a, b) = div(a, b, RoundDown) Smallest integer larger than or equal to `x/y`. Equivalent to `div(x, y, RoundUp)`. -See also: [`div`](@ref) +See also: [`div`](@ref), [`fld`](@ref). # Examples ```jldoctest julia> cld(5.5,2.2) 3.0 + +julia> cld.(-5:5, 3)' +1×11 adjoint(::Vector{Int64}) with eltype Int64: + -1 -1 -1 0 0 0 1 1 1 2 2 ``` """ cld(a, b) = div(a, b, RoundUp) @@ -136,6 +144,8 @@ The quotient and remainder from Euclidean division. Equivalent to `(div(x,y,r), rem(x,y,r))`. Equivalently, with the default value of `r`, this call is equivalent to `(x÷y, x%y)`. +See also: [`fldmod`](@ref), [`cld`](@ref). + # Examples ```jldoctest julia> divrem(3,7) @@ -211,6 +221,8 @@ end The floored quotient and modulus after division. A convenience wrapper for `divrem(x, y, RoundDown)`. Equivalent to `(fld(x,y), mod(x,y))`. + +See also: [`fld`](@ref), [`cld`](@ref), [`fldmod1`](@ref). """ fldmod(x,y) = divrem(x, y, RoundDown) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 6c29a25aae3d9..d7c944ffed78c 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -718,7 +718,7 @@ See the manual section on [control flow](@ref man-conditional-evaluation) for mo ``` julia> x = 1; y = 2; -julia> println(x > y ? "x is larger" : "y is larger") +julia> x > y ? println("x is larger") : println("y is larger") y is larger ``` """ @@ -976,6 +976,19 @@ kw";" x && y Short-circuiting boolean AND. + +See also [`&`](@ref), the ternary operator `? :`, and the manual section on [control flow](@ref man-conditional-evaluation). + +# Examples +```jldoctest +julia> x = 3; + +julia> x > 1 && x < 10 && x isa Int +true + +julia> x < 0 && error("expected positive x") +false +``` """ kw"&&" @@ -983,6 +996,17 @@ kw"&&" x || y Short-circuiting boolean OR. + +See also: [`|`](@ref), [`xor`](@ref), [`&&`](@ref). + +# Examples +```jldoctest +julia> pi < 3 || ℯ < 3 +true + +julia> false || true || println("neither is true!") +true +``` """ kw"||" @@ -1206,6 +1230,8 @@ devnull Nothing A type with no fields that is the type of [`nothing`](@ref). + +See also: [`isnothing`](@ref), [`Some`](@ref), [`Missing`](@ref). """ Nothing @@ -1214,6 +1240,8 @@ Nothing The singleton instance of type [`Nothing`](@ref), used by convention when there is no value to return (as in a C `void` function) or when a variable or field holds no value. + +See also: [`isnothing`](@ref), [`something`](@ref), [`missing`](@ref). """ nothing @@ -1756,6 +1784,8 @@ NaN julia> false * NaN 0.0 ``` + +See also: [`digits`](@ref), [`iszero`](@ref), [`NaN`](@ref). """ Bool @@ -1842,10 +1872,18 @@ Symbol(x...) Construct a tuple of the given objects. +See also [`Tuple`](@ref), [`NamedTuple`](@ref). + # Examples ```jldoctest -julia> tuple(1, 'a', pi) -(1, 'a', π) +julia> tuple(1, 'b', pi) +(1, 'b', π) + +julia> ans === (1, 'b', π) +true + +julia> Tuple(Real[1, 2, pi]) # takes a collection +(1, 2, π) ``` """ tuple @@ -1908,6 +1946,8 @@ setfield! Get the concrete type of `x`. +See also [`eltype`](@ref). + # Examples ```jldoctest julia> a = 1//2; @@ -1964,7 +2004,7 @@ isdefined """ Vector{T}(undef, n) -Construct an uninitialized [`Vector{T}`](@ref) of length `n`. See [`undef`](@ref). +Construct an uninitialized [`Vector{T}`](@ref) of length `n`. # Examples ```julia-repl @@ -2014,14 +2054,19 @@ Vector{T}(::Missing, n) """ Matrix{T}(undef, m, n) -Construct an uninitialized [`Matrix{T}`](@ref) of size `m`×`n`. See [`undef`](@ref). +Construct an uninitialized [`Matrix{T}`](@ref) of size `m`×`n`. # Examples ```julia-repl julia> Matrix{Float64}(undef, 2, 3) 2×3 Array{Float64, 2}: - 6.93517e-310 6.93517e-310 6.93517e-310 - 6.93517e-310 6.93517e-310 1.29396e-320 + 2.36365e-314 2.28473e-314 5.0e-324 + 2.26704e-314 2.26711e-314 NaN + +julia> similar(ans, Int32, 2, 2) +2×2 Matrix{Int32}: + 490537216 1277177453 + 1 1936748399 ``` """ Matrix{T}(::UndefInitializer, m, n) @@ -2069,19 +2114,28 @@ containing elements of type `T`. `N` can either be supplied explicitly, as in `Array{T,N}(undef, dims)`, or be determined by the length or number of `dims`. `dims` may be a tuple or a series of integer arguments corresponding to the lengths in each dimension. If the rank `N` is supplied explicitly, then it must -match the length or number of `dims`. See [`undef`](@ref). +match the length or number of `dims`. Here [`undef`](@ref) is +the [`UndefInitializer`](@ref). # Examples ```julia-repl julia> A = Array{Float64, 2}(undef, 2, 3) # N given explicitly -2×3 Array{Float64, 2}: +2×3 Matrix{Float64}: 6.90198e-310 6.90198e-310 6.90198e-310 6.90198e-310 6.90198e-310 0.0 -julia> B = Array{Float64}(undef, 2) # N determined by the input -2-element Array{Float64, 1}: - 1.87103e-320 - 0.0 +julia> B = Array{Float64}(undef, 4) # N determined by the input +4-element Vector{Float64}: + 2.360075077e-314 + NaN + 2.2671131793e-314 + 2.299821756e-314 + +julia> similar(B, 2, 4, 1) # use typeof(B), and the given size +2×4×1 Array{Float64, 3}: +[:, :, 1] = + 2.26703e-314 2.26708e-314 0.0 2.80997e-314 + 0.0 2.26703e-314 2.26708e-314 0.0 ``` """ Array{T,N}(::UndefInitializer, dims) @@ -2158,10 +2212,12 @@ Alias for `UndefInitializer()`, which constructs an instance of the singleton ty [`UndefInitializer`](@ref), used in array initialization to indicate the array-constructor-caller would like an uninitialized array. +See also: [`missing`](@ref), [`similar`](@ref). + # Examples ```julia-repl julia> Array{Float64, 1}(undef, 3) -3-element Array{Float64, 1}: +3-element Vector{Float64}: 2.2752528595e-314 2.202942107e-314 2.275252907e-314 @@ -2197,6 +2253,8 @@ julia> +(1, 20, 4) Unary minus operator. +See also: [`abs`](@ref), [`flipsign`](@ref). + # Examples ```jldoctest julia> -1 @@ -2408,6 +2466,8 @@ number of trailing elements. `Vararg{T,N}` corresponds to exactly `N` elements o `Vararg{T}` corresponds to zero or more elements of type `T`. `Vararg` tuple types are used to represent the arguments accepted by varargs methods (see the section on [Varargs Functions](@ref) in the manual.) +See also [`NTuple`](@ref). + # Examples ```jldoctest julia> mytupletype = Tuple{AbstractString, Vararg{Int}} @@ -2440,6 +2500,8 @@ is considered an abstract type, and tuple types are only concrete if their param field names; fields are only accessed by index. See the manual section on [Tuple Types](@ref). + +See also [`Vararg`](@ref), [`NTuple`](@ref), [`tuple`](@ref), [`NamedTuple`](@ref). """ Tuple diff --git a/base/essentials.jl b/base/essentials.jl index c92167c553cb7..d9a9ab4b0d721 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -131,7 +131,8 @@ end Tests whether variable `s` is defined in the current scope. -See also [`isdefined`](@ref). +See also [`isdefined`](@ref) for field properties and [`isassigned`](@ref) for +array indexes or [`haskey`](@ref) for other mappings. # Examples ```jldoctest @@ -217,6 +218,8 @@ julia> y = convert(Vector{Int}, x); julia> y === x true ``` + +See also: [`round`](@ref), [`trunc`](@ref), [`oftype`](@ref), [`reinterpret`](@ref). """ function convert end @@ -249,6 +252,8 @@ argtail(x, rest...) = rest Return a `Tuple` consisting of all but the first component of `x`. +See also: [`front`](@ref Base.front), [`rest`](@ref Base.rest), [`first`](@ref), [`Iterators.peel`](@ref). + # Examples ```jldoctest julia> Base.tail((1,2,3)) @@ -809,6 +814,8 @@ values(itr) = itr A type with no fields whose singleton instance [`missing`](@ref) is used to represent missing values. + +See also: [`skipmissing`](@ref), [`nonmissingtype`](@ref), [`Nothing`](@ref). """ struct Missing end @@ -816,6 +823,8 @@ struct Missing end missing The singleton instance of type [`Missing`](@ref) representing a missing value. + +See also: [`NaN`](@ref), [`skipmissing`](@ref), [`nonmissingtype`](@ref). """ const missing = Missing() @@ -823,6 +832,8 @@ const missing = Missing() ismissing(x) Indicate whether `x` is [`missing`](@ref). + +See also: [`skipmissing`](@ref), [`isnothing`](@ref), [`isnan`](@ref). """ ismissing(x) = x === missing diff --git a/base/file.jl b/base/file.jl index e1e323700344f..3a038863107bc 100644 --- a/base/file.jl +++ b/base/file.jl @@ -34,6 +34,8 @@ export Get the current working directory. +See also: [`cd`](@ref), [`tempdir`](@ref). + # Examples ```julia-repl julia> pwd() @@ -67,6 +69,8 @@ end Set the current working directory. +See also: [`pwd`](@ref), [`mkdir`](@ref), [`mkpath`](@ref), [`mktempdir`](@ref). + # Examples ```julia-repl julia> cd("/home/JuliaUser/Projects/julia") @@ -673,6 +677,8 @@ the temporary directory is automatically deleted when the process exits. The `cleanup` keyword argument was added in Julia 1.3. Relatedly, starting from 1.3, Julia will remove the temporary paths created by `mktempdir` when the Julia process exits, unless `cleanup` is explicitly set to `false`. + +See also: [`mktemp`](@ref), [`mkdir`](@ref). """ function mktempdir(parent::AbstractString=tempdir(); prefix::AbstractString=temp_prefix, cleanup::Bool=true) @@ -707,6 +713,8 @@ end Apply the function `f` to the result of [`mktemp(parent)`](@ref) and remove the temporary file upon completion. + +See also: [`mktempdir`](@ref). """ function mktemp(fn::Function, parent::AbstractString=tempdir()) (tmp_path, tmp_io) = mktemp(parent, cleanup=false) @@ -730,6 +738,8 @@ end Apply the function `f` to the result of [`mktempdir(parent; prefix)`](@ref) and remove the temporary directory all of its contents upon completion. +See also: [`mktemp`](@ref), [`mkdir`](@ref). + !!! compat "Julia 1.2" The `prefix` keyword argument was added in Julia 1.2. """ diff --git a/base/float.jl b/base/float.jl index cb4000b51fac2..7344be40660d5 100644 --- a/base/float.jl +++ b/base/float.jl @@ -36,6 +36,20 @@ const Inf = Inf64 Inf, Inf64 Positive infinity of type [`Float64`](@ref). + +See also: [`isfinite`](@ref), [`typemax`](@ref), [`NaN`](@ref), [`Inf32`](@ref). + +# Examples +```jldoctest +julia> π/0 +Inf + +julia> +1.0 / -0.0 +-Inf + +julia> ℯ^-Inf +0.0 +``` """ Inf, Inf64 @@ -44,6 +58,20 @@ const NaN = NaN64 NaN, NaN64 A not-a-number value of type [`Float64`](@ref). + +See also: [`isnan`](@ref), [`missing`](@ref), [`NaN32`](@ref), [`Inf`](@ref). + +# Examples +```jldoctest +julia> 0/0 +NaN + +julia> Inf - Inf +NaN + +julia> NaN == NaN, isequal(NaN, NaN), NaN === NaN +(false, true, true) +``` """ NaN, NaN64 @@ -226,6 +254,17 @@ Bool(x::Float16) = x==0 ? false : x==1 ? true : throw(InexactError(:Bool, Bool, float(x) Convert a number or array to a floating point data type. + +See also: [`complex`](@ref), [`oftype`](@ref), [`convert`](@ref). + +# Examples +```jldoctest +julia> float(1:1000) +1.0:1.0:1000.0 + +julia> float(typemax(Int32)) +2.147483647e9 +``` """ float(x) = AbstractFloat(x) @@ -469,6 +508,8 @@ abs(x::Float64) = abs_float(x) Test whether a number value is a NaN, an indeterminate value which is neither an infinity nor a finite number ("not a number"). + +See also: [`iszero`](@ref), [`isone`](@ref), [`isinf`](@ref), [`ismissing`](@ref). """ isnan(x::AbstractFloat) = (x != x)::Bool isnan(x::Number) = false @@ -481,6 +522,8 @@ isfinite(x::Integer) = true isinf(f) -> Bool Test whether a number is infinite. + +See also: [`Inf`](@ref), [`iszero`](@ref), [`isfinite`](@ref), [`isnan`](@ref). """ isinf(x::Real) = !isnan(x) & !isfinite(x) @@ -641,7 +684,7 @@ uabs(x::BitSigned) = unsigned(abs(x)) nextfloat(x::AbstractFloat, n::Integer) The result of `n` iterative applications of `nextfloat` to `x` if `n >= 0`, or `-n` -applications of `prevfloat` if `n < 0`. +applications of [`prevfloat`](@ref) if `n < 0`. """ function nextfloat(f::IEEEFloat, d::Integer) F = typeof(f) @@ -686,6 +729,8 @@ end Return the smallest floating point number `y` of the same type as `x` such `x < y`. If no such `y` exists (e.g. if `x` is `Inf` or `NaN`), then return `x`. + +See also: [`prevfloat`](@ref), [`eps`](@ref), [`issubnormal`](@ref). """ nextfloat(x::AbstractFloat) = nextfloat(x,1) @@ -693,7 +738,7 @@ nextfloat(x::AbstractFloat) = nextfloat(x,1) prevfloat(x::AbstractFloat, n::Integer) The result of `n` iterative applications of `prevfloat` to `x` if `n >= 0`, or `-n` -applications of `nextfloat` if `n < 0`. +applications of [`nextfloat`](@ref) if `n < 0`. """ prevfloat(x::AbstractFloat, d::Integer) = nextfloat(x, -d) @@ -815,6 +860,8 @@ floatmin(x::T) where {T<:AbstractFloat} = floatmin(T) Return the largest finite number representable by the floating-point type `T`. +See also: [`typemax`](@ref), [`floatmin`](@ref), [`eps`](@ref). + # Examples ```jldoctest julia> floatmax(Float16) @@ -825,6 +872,9 @@ julia> floatmax(Float32) julia> floatmax() 1.7976931348623157e308 + +julia> typemax(Float64) +Inf ``` """ floatmax(x::T) where {T<:AbstractFloat} = floatmax(T) @@ -879,6 +929,8 @@ is the nearest floating point number to ``y``, then |y-x| \\leq \\operatorname{eps}(x)/2. ``` +See also: [`nextfloat`](@ref), [`issubnormal`](@ref), [`floatmax`](@ref). + # Examples ```jldoctest julia> eps(1.0) diff --git a/base/hashing.jl b/base/hashing.jl index 26b18f11c2fe2..580b27ab86ee0 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -10,10 +10,12 @@ optional second argument `h` is a hash code to be mixed with the result. New types should implement the 2-argument form, typically by calling the 2-argument `hash` method recursively in order to mix hashes of the contents with each other (and with `h`). -Typically, any type that implements `hash` should also implement its own `==` (hence -`isequal`) to guarantee the property mentioned above. Types supporting subtraction +Typically, any type that implements `hash` should also implement its own [`==`](@ref) (hence +[`isequal`](@ref)) to guarantee the property mentioned above. Types supporting subtraction (operator `-`) should also implement [`widen`](@ref), which is required to hash values inside heterogeneous arrays. + +See also: [`objectid`](@ref), [`Dict`](@ref), [`Set`](@ref). """ hash(x::Any) = hash(x, zero(UInt)) hash(w::WeakRef, h::UInt) = hash(w.value, h) diff --git a/base/iddict.jl b/base/iddict.jl index a03edbb60723b..7247a85c9afc8 100644 --- a/base/iddict.jl +++ b/base/iddict.jl @@ -3,7 +3,7 @@ """ IdDict([itr]) -`IdDict{K,V}()` constructs a hash table using object-id as hash and +`IdDict{K,V}()` constructs a hash table using [`objectid`](@ref) as hash and `===` as equality with keys of type `K` and values of type `V`. See [`Dict`](@ref) for further help. In the example below, The `Dict` diff --git a/base/int.jl b/base/int.jl index 02a9ace0fe3f1..85482f12a5c07 100644 --- a/base/int.jl +++ b/base/int.jl @@ -154,6 +154,8 @@ when `abs` is applied to the minimum representable value of a signed integer. That is, when `x == typemin(typeof(x))`, `abs(x) == x < 0`, not `-x` as might be expected. +See also: [`abs2`](@ref), [`unsigned`](@ref), [`sign`](@ref). + # Examples ```jldoctest julia> abs(-3) @@ -178,12 +180,17 @@ abs(x::Signed) = flipsign(x,x) Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as unsigned without checking for negative values. + +See also: [`signed`](@ref), [`sign`](@ref), [`signbit`](@ref). + # Examples ```jldoctest julia> unsigned(-2) 0xfffffffffffffffe + julia> unsigned(2) 0x0000000000000002 + julia> signed(unsigned(-2)) -2 ``` @@ -196,6 +203,8 @@ unsigned(x::BitSigned) = reinterpret(typeof(convert(Unsigned, zero(x))), x) Convert a number to a signed integer. If the argument is unsigned, it is reinterpreted as signed without checking for overflow. + +See also: [`unsigned`](@ref), [`sign`](@ref), [`signbit`](@ref). """ signed(x) = x % typeof(convert(Signed, zero(x))) signed(x::BitUnsigned) = reinterpret(typeof(convert(Signed, zero(x))), x) @@ -233,6 +242,8 @@ exceptions, see note below). type, and so rounding error may occur. In particular, if the exact result is very close to `y`, then it may be rounded to `y`. +See also: [`rem`](@ref), [`div`](@ref), [`fld`](@ref), [`mod1`](@ref), [`invmod`](@ref). + ```jldoctest julia> mod(8, 3) 2 @@ -248,6 +259,10 @@ julia> mod(eps(), 3) julia> mod(-eps(), 3) 3.0 + +julia> mod.(-5:5, 3)' +1×11 adjoint(::Vector{Int64}) with eltype Int64: + 1 2 0 1 2 0 1 2 0 1 2 ``` """ function mod(x::T, y::T) where T<:Integer @@ -272,6 +287,8 @@ rem(x::T, y::T) where {T<:BitUnsigned64} = checked_urem_int(x, y) Bitwise not. +See also: [`!`](@ref), [`&`](@ref), [`|`](@ref). + # Examples ```jldoctest julia> ~4 @@ -293,6 +310,8 @@ Bitwise and. Implements [three-valued logic](https://en.wikipedia.org/wiki/Three returning [`missing`](@ref) if one operand is `missing` and the other is `true`. Add parentheses for function application form: `(&)(x, y)`. +See also: [`|`](@ref), [`xor`](@ref), [`&&`](@ref). + # Examples ```jldoctest julia> 4 & 10 @@ -316,6 +335,8 @@ false Bitwise or. Implements [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic), returning [`missing`](@ref) if one operand is `missing` and the other is `false`. +See also: [`&`](@ref), [`xor`](@ref), [`||`](@ref). + # Examples ```jldoctest julia> 4 | 10 @@ -498,6 +519,8 @@ A negative value of `k` will rotate to the right instead. !!! compat "Julia 1.5" This function requires Julia 1.5 or later. +See also: [`<<`](@ref), [`circshift`](@ref), [`BitArray`](@ref). + ```jldoctest julia> bitrotate(UInt8(114), 2) 0xc9 @@ -559,7 +582,9 @@ is less than or equal to `x`. `trunc(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits`, `sigdigits` and `base` work as for [`round`](@ref). +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). + +See also: [`%`](@ref rem), [`floor`](@ref), [`unsigned`](@ref). """ function trunc end @@ -574,7 +599,7 @@ equal to `x`. `floor(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits`, `sigdigits` and `base` work as for [`round`](@ref). +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). """ function floor end @@ -589,7 +614,7 @@ equal to `x`. `ceil(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not representable. -`digits`, `sigdigits` and `base` work as for [`round`](@ref). +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). """ function ceil end @@ -702,6 +727,8 @@ function typemin end The highest value representable by the given (real) numeric `DataType`. +See also: [`floatmax`](@ref), [`typemin`](@ref), [`eps`](@ref). + # Examples ```jldoctest julia> typemax(Int8) @@ -709,6 +736,12 @@ julia> typemax(Int8) julia> typemax(UInt32) 0xffffffff + +julia> typemax(Float64) +Inf + +julia> floatmax(Float32) # largest finite floating point number +3.4028235f38 ``` """ function typemax end diff --git a/base/irrationals.jl b/base/irrationals.jl index 545d9091ee840..b1ecaf8557090 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -22,7 +22,9 @@ abstract type AbstractIrrational <: Real end Irrational{sym} <: AbstractIrrational Number type representing an exact irrational value denoted by the -symbol `sym`. +symbol `sym`, such as [`π`](@ref pi), [`ℯ`](@ref) and [`γ`](@ref Base.MathConstants.eulergamma). + +See also [`@irrational`], [`AbstractIrrational`](@ref). """ struct Irrational{sym} <: AbstractIrrational end diff --git a/base/iterators.jl b/base/iterators.jl index 618c3e04547cf..b9f2aaf882360 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -276,6 +276,8 @@ the `zip` iterator is a tuple of values of its subiterators. `zip` orders the calls to its subiterators in such a way that stateful iterators will not advance when another iterator finishes in the current iteration. +See also: [`enumerate`](@ref), [`splat`](@ref Base.splat). + # Examples ```jldoctest julia> a = 1:5 @@ -429,6 +431,12 @@ julia> foreach(println, f) 1 3 5 + +julia> [x for x in [1, 2, 3, 4, 5] if isodd(x)] # collects a generator over Iterators.filter +3-element Vector{Int64}: + 1 + 3 + 5 ``` """ filter(flt, itr) = Filter(flt, itr) @@ -526,6 +534,8 @@ end An iterator that yields the same elements as `iter`, but starting at the given `state`. +See also: [`Iterators.drop`](@ref), [`Iterators.peel`](@ref), [`Base.rest`](@ref). + # Examples ```jldoctest julia> collect(Iterators.rest([1,2,3,4], 2)) @@ -544,6 +554,8 @@ rest(itr) = itr Returns the first element and an iterator over the remaining elements. +See also: [`Iterators.drop`](@ref), [`Iterators.take`](@ref). + # Examples ```jldoctest julia> (a, rest) = Iterators.peel("abc"); @@ -622,6 +634,8 @@ end An iterator that generates at most the first `n` elements of `iter`. +See also: [`drop`](@ref Iterators.drop), [`peel`](@ref Iterators.peel), [`first`](@ref), [`take!`](@ref). + # Examples ```jldoctest julia> a = 1:2:11 @@ -833,6 +847,8 @@ end An iterator that cycles through `iter` forever. If `iter` is empty, so is `cycle(iter)`. +See also: [`Iterators.repeated`](@ref), [`repeat`](@ref). + # Examples ```jldoctest julia> for (i, v) in enumerate(Iterators.cycle("hello")) @@ -872,6 +888,8 @@ repeated(x) = Repeated(x) An iterator that generates the value `x` forever. If `n` is specified, generates `x` that many times (equivalent to `take(repeated(x), n)`). +See also: [`Iterators.cycle`](@ref), [`repeat`](@ref). + # Examples ```jldoctest julia> a = Iterators.repeated([1 2], 4); @@ -907,12 +925,17 @@ Return an iterator over the product of several iterators. Each generated element a tuple whose `i`th element comes from the `i`th argument iterator. The first iterator changes the fastest. +See also: [`zip`](@ref), [`Iterators.flatten`](@ref). + # Examples ```jldoctest julia> collect(Iterators.product(1:2, 3:5)) 2×3 Matrix{Tuple{Int64, Int64}}: (1, 3) (1, 4) (1, 5) (2, 3) (2, 4) (2, 5) + +julia> ans == [(x,y) for x in 1:2, y in 3:5] # collects a generator involving Iterators.product +true ``` """ product(iters...) = ProductIterator(iters) @@ -1042,6 +1065,15 @@ julia> collect(Iterators.flatten((1:2, 8:9))) 2 8 9 + +julia> [(x,y) for x in 0:1 for y in 'a':'c'] # collects generators involving Iterators.flatten +6-element Vector{Tuple{Int64, Char}}: + (0, 'a') + (0, 'b') + (0, 'c') + (1, 'a') + (1, 'b') + (1, 'c') ``` """ flatten(itr) = Flatten(itr) diff --git a/base/math.jl b/base/math.jl index b66a058e5ae9e..44da5e04ea5a5 100644 --- a/base/math.jl +++ b/base/math.jl @@ -47,15 +47,17 @@ end Return `x` if `lo <= x <= hi`. If `x > hi`, return `hi`. If `x < lo`, return `lo`. Arguments are promoted to a common type. +See also [`clamp!`](@ref), [`min`](@ref), [`max`](@ref). + # Examples ```jldoctest -julia> clamp.([pi, 1.0, big(10.)], 2., 9.) +julia> clamp.([pi, 1.0, big(10)], 2.0, 9.0) 3-element Vector{BigFloat}: 3.141592653589793238462643383279502884197169399375105820974944592307816406286198 2.0 9.0 -julia> clamp.([11,8,5],10,6) # an example where lo > hi +julia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi 3-element Vector{Int64}: 6 6 @@ -73,12 +75,18 @@ clamp(x::X, lo::L, hi::H) where {X,L,H} = Clamp `x` between `typemin(T)` and `typemax(T)` and convert the result to type `T`. +See also [`trunc`](@ref). + # Examples ```jldoctest julia> clamp(200, Int8) 127 + julia> clamp(-200, Int8) -128 + +julia> trunc(Int, 4pi^2) +39 ``` """ clamp(x, ::Type{T}) where {T<:Integer} = clamp(x, typemin(T), typemax(T)) % T @@ -89,6 +97,19 @@ clamp(x, ::Type{T}) where {T<:Integer} = clamp(x, typemin(T), typemax(T)) % T Restrict values in `array` to the specified range, in-place. See also [`clamp`](@ref). + +# Examples +```jldoctest +julia> row = collect(-4:4)'; + +julia> clamp!(row, 0, Inf) +1×9 adjoint(::Vector{Int64}) with eltype Int64: + 0 0 0 0 0 1 2 3 4 + +julia> clamp.((-4:4)', 0, Inf) +1×9 Matrix{Float64}: + 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0 +``` """ function clamp!(x::AbstractArray, lo, hi) @inbounds for i in eachindex(x) @@ -205,6 +226,8 @@ end @horner(x, p...) Evaluate `p[1] + x * (p[2] + x * (....))`, i.e. a polynomial via Horner's rule. + +See also [`@evalpoly`](@ref), [`evalpoly`](@ref). """ macro horner(x, p...) xesc, pesc = esc(x), esc.(p) @@ -224,6 +247,8 @@ that is, the coefficients are given in ascending order by power of `z`. This ma to efficient inline code that uses either Horner's method or, for complex `z`, a more efficient Goertzel-like algorithm. +See also [`evalpoly`](@ref). + # Examples ```jldoctest julia> @evalpoly(3, 1, 0, 1) @@ -273,6 +298,8 @@ rad2deg(z::AbstractFloat) = z * (180 / oftype(z, pi)) Convert `x` from degrees to radians. +See also: [`rad2deg`](@ref), [`sind`](@ref). + # Examples ```jldoctest julia> deg2rad(90) @@ -390,6 +417,8 @@ asinh(x::Number) sin(x) Compute sine of `x`, where `x` is in radians. + +See also [`sind`], [`sinpi`], [`sincos`], [`cis`]. """ sin(x::Number) @@ -397,6 +426,8 @@ sin(x::Number) cos(x) Compute cosine of `x`, where `x` is in radians. + +See also [`cosd`], [`cospi`], [`sincos`], [`cis`]. """ cos(x::Number) @@ -441,6 +472,8 @@ atanh(x::Number) Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. Use complex negative arguments to obtain complex results. +See also [`log1p`], [`log2`], [`log10`]. + # Examples ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" julia> log(2) @@ -462,6 +495,8 @@ log(x::Number) Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. +See also: [`exp2`](@ref), [`ldexp`](@ref). + # Examples ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" julia> log2(4) @@ -539,6 +574,8 @@ end Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. Use complex negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. +See also: [`hypot`](@ref). + # Examples ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" julia> sqrt(big(81)) @@ -553,6 +590,13 @@ Stacktrace: julia> sqrt(big(complex(-81))) 0.0 + 9.0im + +julia> .√(1:4) +4-element Vector{Float64}: + 1.0 + 1.4142135623730951 + 1.7320508075688772 + 2.0 ``` """ sqrt(x) diff --git a/base/mathconstants.jl b/base/mathconstants.jl index a3d1be99becbb..156dc9e1ce39a 100644 --- a/base/mathconstants.jl +++ b/base/mathconstants.jl @@ -23,10 +23,17 @@ Base.@irrational catalan 0.91596559417721901505 catalan The constant pi. +Unicode `π` can be typed by writing `\\pi` then pressing tab in the Julia REPL, and in many editors. + +See also: [`sinpi`](@ref), [`sincospi`](@ref), [`deg2rad`](@ref). + # Examples ```jldoctest julia> pi π = 3.1415926535897... + +julia> 1/2pi +0.15915494309189535 ``` """ π, const pi = π @@ -37,10 +44,20 @@ julia> pi The constant ℯ. +Unicode `ℯ` can be typed by writing `\\euler` and pressing tab in the Julia REPL, and in many editors. + +See also: [`exp`](@ref), [`cis`](@ref), [`cispi`](@ref). + # Examples ```jldoctest julia> ℯ ℯ = 2.7182818284590... + +julia> log(ℯ) +1 + +julia> ℯ^(im)π ≈ -1 +true ``` """ ℯ, const e = ℯ @@ -55,6 +72,11 @@ Euler's constant. ```jldoctest julia> Base.MathConstants.eulergamma γ = 0.5772156649015... + +julia> dx = 10^-6; + +julia> sum(-exp(-x) * log(x) for x in dx:dx:100) * dx +0.5772078382499134 ``` """ γ, const eulergamma = γ @@ -69,6 +91,9 @@ The golden ratio. ```jldoctest julia> Base.MathConstants.golden φ = 1.6180339887498... + +julia> (2ans - 1)^2 ≈ 5 +true ``` """ φ, const golden = φ @@ -82,6 +107,9 @@ Catalan's constant. ```jldoctest julia> Base.MathConstants.catalan catalan = 0.9159655941772... + +julia> sum(log(x)/(1+x^2) for x in 1:0.01:10^6) * 0.01 +0.9159466120554123 ``` """ catalan diff --git a/base/missing.jl b/base/missing.jl index b89c394bea046..80b02015266ce 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -201,6 +201,8 @@ Use [`collect`](@ref) to obtain an `Array` containing the non-`missing` values i be a `Vector` since it is not possible to remove missings while preserving dimensions of the input. +See also [`coalesce`](@ref), [`ismissing`](@ref), [`something`](@ref). + # Examples ```jldoctest julia> x = skipmissing([1, missing, 2]) @@ -404,7 +406,7 @@ end Return the first value in the arguments which is not equal to [`missing`](@ref), if any. Otherwise return `missing`. -See also [`something`](@ref). +See also [`skipmissing`](@ref), [`something`](@ref). # Examples diff --git a/base/multidimensional.jl b/base/multidimensional.jl index d9251cdebe096..5ef46bb1da468 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1160,6 +1160,8 @@ their indices; any offset results in a (circular) wraparound. If the arrays have overlapping indices, then on the domain of the overlap `dest` agrees with `src`. +See also: [`circshift`](@ref). + # Examples ```julia-repl julia> src = reshape(Vector(1:16), (4,4)) diff --git a/base/number.jl b/base/number.jl index 142796d3903ac..8dfa56aa0f61a 100644 --- a/base/number.jl +++ b/base/number.jl @@ -25,6 +25,8 @@ isinteger(x::Integer) = true Return `true` if `x == zero(x)`; if `x` is an array, this checks whether all of the elements of `x` are zero. +See also: [`isone`](@ref), [`isinteger`](@ref), [`isfinite`](@ref), [`isnan`](@ref). + # Examples ```jldoctest julia> iszero(0.0) @@ -110,6 +112,8 @@ copy(x::Number) = x # some code treats numbers as collection-like Returns `true` if the value of the sign of `x` is negative, otherwise `false`. +See also [`sign`](@ref) and [`copysign`](@ref). + # Examples ```jldoctest julia> signbit(-4) @@ -131,6 +135,23 @@ signbit(x::Real) = x < 0 sign(x) Return zero if `x==0` and ``x/|x|`` otherwise (i.e., ±1 for real `x`). + +See also [`signbit`](@ref), [`zero`](@ref), [`copysign`](@ref), [`flipsign`](@ref). + +# Examples +```jldoctest +julia> sign(-4.0) +-1.0 + +julia> sign(99) +1 + +julia> sign(-0.0) +-0.0 + +julia> sign(0 + im) +0.0 + 1.0im +``` """ sign(x::Number) = iszero(x) ? x/abs(oneunit(x)) : x/abs(x) sign(x::Real) = ifelse(x < zero(x), oftype(one(x),-1), ifelse(x > zero(x), one(x), typeof(one(x))(x))) @@ -222,10 +243,18 @@ inv(x::Number) = one(x)/x Multiply `x` and `y`, giving the result as a larger type. +See also [`promote`](@ref), [`Base.add_sum`](@ref). + # Examples ```jldoctest -julia> widemul(Float32(3.), 4.) -12.0 +julia> widemul(Float32(3.0), 4.0) isa BigFloat +true + +julia> typemax(Int8) * typemax(Int8) +1 + +julia> widemul(typemax(Int8), typemax(Int8)) # == 127^2 +16129 ``` """ widemul(x::Number, y::Number) = widen(x)*widen(y) @@ -243,6 +272,8 @@ map(f, x::Number, ys::Number...) = f(x, ys...) Get the additive identity element for the type of `x` (`x` can also specify the type itself). +See also [`iszero`](@ref), [`one`](@ref), [`oneunit`](@ref), [`oftype`](@ref). + # Examples ```jldoctest julia> zero(1) @@ -280,6 +311,9 @@ should return an identity value of the same precision If you want a quantity that is of the same type as `x`, or of type `T`, even if `x` is dimensionful, use [`oneunit`](@ref) instead. +See also the [`identity`](@ref) function, +and `I` in [`LinearAlgebra`](@ref man-linalg) for the identity matrix. + # Examples ```jldoctest julia> one(3.7) diff --git a/base/operators.jl b/base/operators.jl index fcd32cb0206ec..7269a15718a58 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -563,6 +563,8 @@ extrema(f, x::Real) = (y = f(x); (y, y)) The identity function. Returns its argument. +See also: [`one`](@ref), [`oneunit`](@ref), and [`LinearAlgebra`](@ref man-linalg)'s `I`. + # Examples ```jldoctest julia> identity("Well, what did you expect?") @@ -696,7 +698,7 @@ julia> bitstring(Int8(3)) julia> bitstring(Int8(12)) "00001100" ``` -See also [`>>`](@ref), [`>>>`](@ref). +See also [`>>`](@ref), [`>>>`](@ref), [`exp2`](@ref), [`ldexp`](@ref). """ function <<(x::Integer, c::Integer) @_inline_meta @@ -803,6 +805,8 @@ end Remainder from Euclidean division, returning a value of the same sign as `x`, and smaller in magnitude than `y`. This value is always exact. +See also: [`div`](@ref), [`mod`](@ref), [`mod1`](@ref), [`divrem`](@ref). + # Examples ```jldoctest julia> x = 15; y = 4; @@ -812,6 +816,10 @@ julia> x % y julia> x == div(x, y) * y + rem(x, y) true + +julia> rem.(-5:5, 3)' +1×11 adjoint(::Vector{Int64}) with eltype Int64: + -2 -1 0 -2 -1 0 1 2 0 1 2 ``` """ rem @@ -824,6 +832,8 @@ const % = rem The quotient from Euclidean (integer) division. Generally equivalent to a mathematical operation x/y without a fractional part. +See also: [`cld`](@ref), [`fld`](@ref), [`rem`](@ref), [`divrem`](@ref). + # Examples ```jldoctest julia> 9 ÷ 4 @@ -834,6 +844,10 @@ julia> -5 ÷ 3 julia> 5.0 ÷ 2 2.0 + +julia> div.(-5:5, 3)' +1×11 adjoint(::Vector{Int64}) with eltype Int64: + -1 -1 -1 0 0 0 0 0 1 1 1 ``` """ div @@ -1010,7 +1024,7 @@ julia> fs = [ julia> ∘(fs...)(3) 3.0 ``` -See also [`ComposedFunction`](@ref). +See also [`ComposedFunction`](@ref), [`!f::Function`](@ref). """ function ∘ end @@ -1070,6 +1084,8 @@ end Predicate function negation: when the argument of `!` is a function, it returns a function which computes the boolean negation of `f`. +See also [`∘`](@ref). + # Examples ```jldoctest julia> str = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" @@ -1090,6 +1106,8 @@ julia> filter(!isletter, str) A type representing a partially-applied version of the two-argument function `f`, with the first argument fixed to the value "x". In other words, `Fix1(f, x)` behaves similarly to `y->f(x, y)`. + +See also [`Fix2`](@ref Base.Fix2). """ struct Fix1{F,T} <: Function f::F @@ -1350,6 +1368,8 @@ julia> [1, 2] .∈ ([2, 3],) 0 1 ``` + +See also: [`insorted`](@ref), [`contains`](@ref), [`occursin`](@ref), [`issubset`](@ref). """ in diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 3fc2a2340efdc..9c12616e5f265 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -24,7 +24,7 @@ Given an AbstractArray `A`, create a view `B` such that the dimensions appear to be permuted. Similar to `permutedims`, except that no copying occurs (`B` shares storage with `A`). -See also: [`permutedims`](@ref). +See also: [`permutedims`](@ref), [`invperm`](@ref). # Examples ```jldoctest @@ -83,10 +83,10 @@ end """ permutedims(A::AbstractArray, perm) -Permute the dimensions of array `A`. `perm` is a vector specifying a permutation of length -`ndims(A)`. +Permute the dimensions of array `A`. `perm` is a vector or a tuple of length `ndims(A)` +specifying the permutation. -See also: [`PermutedDimsArray`](@ref). +See also: [`permutedims!`](@ref), [`PermutedDimsArray`](@ref), [`transpose`](@ref), [`invperm`](@ref). # Examples ```jldoctest @@ -100,7 +100,7 @@ julia> A = reshape(Vector(1:8), (2,2,2)) 5 7 6 8 -julia> permutedims(A, [3, 2, 1]) +julia> permutedims(A, (3, 2, 1)) 2×2×2 Array{Int64, 3}: [:, :, 1] = 1 3 @@ -109,6 +109,16 @@ julia> permutedims(A, [3, 2, 1]) [:, :, 2] = 2 4 6 8 + +julia> B = randn(5, 7, 11, 13); + +julia> perm = [4,1,3,2]; + +julia> size(permutedims(B, perm)) +(13, 5, 11, 7) + +julia> size(B)[perm] == ans +true ``` """ function permutedims(A::AbstractArray, perm) diff --git a/base/promotion.jl b/base/promotion.jl index a6e6d8fdcac4e..43add6cbf5f62 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -5,7 +5,6 @@ """ typejoin(T, S) - Return the closest common ancestor of `T` and `S`, i.e. the narrowest type from which they both inherit. """ @@ -144,6 +143,17 @@ end Compute a type that contains both `T` and `S`, which could be either a parent of both types, or a `Union` if appropriate. Falls back to [`typejoin`](@ref). + +See instead [`promote`](@ref), [`promote_type`](@ref). + +# Examples +```jldoctest +julia> Base.promote_typejoin(Int, Float64) +Real + +julia> Base.promote_type(Int, Float64) +Float64 +``` """ function promote_typejoin(@nospecialize(a), @nospecialize(b)) c = typejoin(_promote_typesubtract(a), _promote_typesubtract(b)) @@ -191,6 +201,9 @@ tolerated; for example, `promote_type(Int64, Float64)` returns [`Float64`](@ref) even though strictly, not all [`Int64`](@ref) values can be represented exactly as `Float64` values. +See also: [`promote`](@ref), [`promote_typejoin`](@ref), [`promote_rule`](@ref). + +# Examples ```jldoctest julia> promote_type(Int64, Float64) Float64 @@ -254,6 +267,8 @@ promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = Convert all arguments to a common type, and return them all (as a tuple). If no arguments can be converted, an error is raised. +See also: [`promote_type`], [`promote_rule`]. + # Examples ```jldoctest julia> promote(Int8(1), Float16(4.5), Float32(4.1)) @@ -335,7 +350,7 @@ where usually `^ == Base.^` unless `^` has been defined in the calling namespace.) If `y` is a negative integer literal, then `Base.literal_pow` transforms the operation to `inv(x)^-y` by default, where `-y` is positive. - +# Examples ```jldoctest julia> 3^5 243 diff --git a/base/reduce.jl b/base/reduce.jl index 66fb9bd45de87..ca252a08922c3 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -518,6 +518,8 @@ for non-empty collections. !!! compat "Julia 1.6" Keyword argument `init` requires Julia 1.6 or later. +See also: [`reduce`](@ref), [`mapreduce`](@ref), [`count`](@ref), [`union`](@ref). + # Examples ```jldoctest julia> sum(1:20) @@ -572,6 +574,8 @@ for non-empty collections. !!! compat "Julia 1.6" Keyword argument `init` requires Julia 1.6 or later. +See also: [`reduce`](@ref), [`cumprod`](@ref), [`any`](@ref). + # Examples ```jldoctest julia> prod(1:5) @@ -806,6 +810,8 @@ Return the maximal element of the collection `itr` and its index or key. If there are multiple maximal elements, then the first one will be returned. Values are compared with `isless`. +See also: [`findmin`](@ref), [`argmax`](@ref), [`maximum`](@ref). + # Examples ```jldoctest @@ -863,6 +869,8 @@ Return the minimal element of the collection `itr` and its index or key. If there are multiple minimal elements, then the first one will be returned. `NaN` is treated as less than all other values except `missing`. +See also: [`findmax`](@ref), [`argmin`](@ref), [`minimum`](@ref). + # Examples ```jldoctest @@ -913,6 +921,8 @@ The collection must not be empty. Values are compared with `isless`. +See also: [`argmin`](@ref), [`findmax`](@ref). + # Examples ```jldoctest julia> argmax([8, 0.1, -9, pi]) @@ -950,7 +960,6 @@ julia> argmin(x -> -x^3 + x^2 - 10, -5:5) julia> argmin(acos, 0:0.1:1) 1.0 - ``` """ argmin(f, domain) = findmin(f, domain)[2] @@ -965,6 +974,8 @@ The collection must not be empty. `NaN` is treated as less than all other values except `missing`. +See also: [`argmax`](@ref), [`findmin`](@ref). + # Examples ```jldoctest julia> argmin([8, 0.1, -9, pi]) @@ -992,6 +1003,8 @@ If the input contains [`missing`](@ref) values, return `missing` if all non-miss values are `false` (or equivalently, if the input contains no `true` value), following [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic). +See also: [`all`](@ref), [`count`](@ref), [`sum`](@ref), [`|`](@ref), , [`||`](@ref). + # Examples ```jldoctest julia> a = [true,false,false,true] @@ -1028,6 +1041,8 @@ If the input contains [`missing`](@ref) values, return `missing` if all non-miss values are `true` (or equivalently, if the input contains no `false` value), following [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic). +See also: [`all!`](@ref), [`any`](@ref), [`count`](@ref), [`&`](@ref), , [`&&`](@ref), [`allunique`](@ref). + # Examples ```jldoctest julia> a = [true,false,false,true] @@ -1167,6 +1182,8 @@ to start counting from and therefore also determines the output type. !!! compat "Julia 1.6" `init` keyword was added in Julia 1.6. +See also: [`any`](@ref), [`sum`](@ref). + # Examples ```jldoctest julia> count(i->(4<=i<=6), [2,3,4,5,6]) diff --git a/base/reducedim.jl b/base/reducedim.jl index e21854ef31c18..c473049dd5fa0 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -590,6 +590,8 @@ Compute the maximum value of an array over the given dimensions. See also the [`max(a,b)`](@ref) function to take the maximum of two or more arguments, which can be applied elementwise to arrays via `max.(a,b)`. +See also: [`maximum!`](@ref), [`extrema`](@ref), [`findmax`](@ref), [`argmax`](@ref). + # Examples ```jldoctest julia> A = [1 2; 3 4] @@ -665,6 +667,8 @@ Compute the minimum value of an array over the given dimensions. See also the [`min(a,b)`](@ref) function to take the minimum of two or more arguments, which can be applied elementwise to arrays via `min.(a,b)`. +See also: [`minimum!`](@ref), [`extrema`](@ref), [`findmin`](@ref), [`argmin`](@ref). + # Examples ```jldoctest julia> A = [1 2; 3 4] diff --git a/base/reflection.jl b/base/reflection.jl index d9cd893474364..a8bfb04903816 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -20,6 +20,8 @@ nameof(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m) Get a module's enclosing `Module`. `Main` is its own parent. +See also: [`names`](@ref), [`nameof`](@ref), [`fullname`](@ref), [`@__MODULE__`](@ref). + # Examples ```jldoctest julia> parentmodule(Main) @@ -94,6 +96,8 @@ are also included. As a special case, all names defined in `Main` are considered \"exported\", since it is not idiomatic to explicitly export names from `Main`. + +See also: [`@locals`](@ref Base.@locals), [`@__MODULE__`](@ref). """ names(m::Module; all::Bool = false, imported::Bool = false) = sort!(ccall(:jl_module_names, Array{Symbol,1}, (Any, Cint, Cint), m, all, imported)) @@ -167,10 +171,15 @@ fieldname(t::Type{<:Tuple}, i::Integer) = Get a tuple with the names of the fields of a `DataType`. +See also [`propertynames`](@ref), [`hasfield`](@ref). + # Examples ```jldoctest julia> fieldnames(Rational) (:num, :den) + +julia> fieldnames(typeof(1+im)) +(:re, :im) ``` """ fieldnames(t::DataType) = (fieldcount(t); # error check to make sure type is specific enough @@ -287,6 +296,8 @@ end objectid(x) Get a hash value for `x` based on object identity. `objectid(x)==objectid(y)` if `x === y`. + +See also [`hash`](@ref), [`IdDict`](@ref). """ objectid(@nospecialize(x)) = ccall(:jl_object_id, UInt, (Any,), x) @@ -446,6 +457,8 @@ Return `true` iff value `v` is mutable. See [Mutable Composite Types](@ref) for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of `DataType` is mutable. +See also [`isbits`](@ref), [`isstructtype`](@ref). + # Examples ```jldoctest julia> ismutable(1) @@ -519,6 +532,8 @@ This category of types is significant since they are valid as type parameters, may not track [`isdefined`](@ref) / [`isassigned`](@ref) status, and have a defined layout that is compatible with C. +See also [`isbits`](@ref), [`isprimitivetype`](@ref), [`ismutable`](@ref). + # Examples ```jldoctest julia> isbitstype(Complex{Float64}) @@ -533,7 +548,7 @@ isbitstype(@nospecialize(t::Type)) = (@_pure_meta; isa(t, DataType) && t.isbitst """ isbits(x) -Return `true` if `x` is an instance of an `isbitstype` type. +Return `true` if `x` is an instance of an [`isbitstype`](@ref) type. """ isbits(@nospecialize x) = (@_pure_meta; typeof(x).isbitstype) @@ -564,6 +579,8 @@ end Determine whether type `T` is a concrete type, meaning it could have direct instances (values `x` such that `typeof(x) === T`). +See also: [`isbits`](@ref), [`isabstracttype`](@ref), [`issingletontype`](@ref). + # Examples ```jldoctest julia> isconcretetype(Complex) @@ -927,6 +944,8 @@ A list of modules can also be specified as an array. !!! compat "Julia 1.4" At least Julia 1.4 is required for specifying a module. + +See also: [`which`](@ref) and `@which`. """ function methods(@nospecialize(f), @nospecialize(t), mod::Union{Tuple{Module},AbstractArray{Module},Nothing}=nothing) @@ -1291,6 +1310,8 @@ end Returns the method of `f` (a `Method` object) that would be called for arguments of the given `types`. If `types` is an abstract type, then the method that would be called by `invoke` is returned. + +See also: [`parentmodule`](@ref), and `@which` and `@edit` in [`InteractiveUtils`](@ref man-interactive-utils). """ function which(@nospecialize(f), @nospecialize(t)) if isa(f, Core.Builtin) @@ -1635,6 +1656,8 @@ as well to get the properties of an instance of the type. of the documented interface of `x`. If you want it to also return "private" fieldnames intended for internal use, pass `true` for the optional second argument. REPL tab completion on `x.` shows only the `private=false` properties. + +See also: [`hasproperty`](@ref), [`hasfield`](@ref). """ propertynames(x) = fieldnames(typeof(x)) propertynames(m::Module) = names(m) @@ -1647,5 +1670,7 @@ Return a boolean indicating whether the object `x` has `s` as one of its own pro !!! compat "Julia 1.2" This function requires at least Julia 1.2. + +See also: [`propertynames`](@ref), [`hasfield`](@ref). """ hasproperty(x, s::Symbol) = s in propertynames(x) diff --git a/base/set.jl b/base/set.jl index fb837fbf86166..0c8a8b95b10ce 100644 --- a/base/set.jl +++ b/base/set.jl @@ -17,6 +17,8 @@ Set() = Set{Any}() Construct a [`Set`](@ref) of the values generated by the given iterable object, or an empty set. Should be used instead of [`BitSet`](@ref) for sparse integer sets, or for sets of arbitrary objects. + +See also: [`push!`](@ref), [`empty!`](@ref), [`union!`](@ref), [`in`](@ref). """ Set(itr) = _Set(itr, IteratorEltype(itr)) @@ -105,6 +107,8 @@ as determined by [`isequal`](@ref), in the order that the first of each set of equivalent elements originally appears. The element type of the input is preserved. +See also: [`unique!`](@ref), [`allunique`](@ref). + # Examples ```jldoctest julia> unique([1, 2, 6, 2]) @@ -371,6 +375,8 @@ end Return `true` if all values from `itr` are distinct when compared with [`isequal`](@ref). +See also: [`unique`](@ref), [`issorted`](@ref). + # Examples ```jldoctest julia> a = [1; 2; 3] @@ -379,6 +385,9 @@ julia> a = [1; 2; 3] 2 3 +julia> allunique(a) +true + julia> allunique([a, a]) false ``` @@ -537,7 +546,7 @@ of the result will not include singleton types which are replaced with values of a different type: for example, `Union{T,Missing}` will become `T` if `missing` is replaced. -See also [`replace!`](@ref). +See also [`replace!`](@ref), [`splice!`](@ref), [`delete!`](@ref), [`insert!`](@ref). # Examples ```jldoctest diff --git a/base/show.jl b/base/show.jl index a601007eeedef..dca5f97f99830 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1016,9 +1016,22 @@ end show_supertypes(typ::DataType) = show_supertypes(stdout, typ) """ - @show + @show exs... -Show an expression and result, returning the result. See also [`show`](@ref). +Prints one or more expressions, and their results, to `stdout`, and returns the last result. + +See also: [`show`](@ref), [`@info`](@ref Logging), [`println`](@ref). + +# Examples +```jldoctest +julia> x = @show 1+2 +1 + 2 = 3 +3 + +julia> @show x^2 x/2; +x ^ 2 = 9 +x / 2 = 1.5 +``` """ macro show(exs...) blk = Expr(:block) diff --git a/base/some.jl b/base/some.jl index 272ed0e00ce31..30fc36d32e13f 100644 --- a/base/some.jl +++ b/base/some.jl @@ -64,6 +64,8 @@ Return `true` if `x === nothing`, and return `false` if not. !!! compat "Julia 1.1" This function requires at least Julia 1.1. + +See also [`something`](@ref), [`notnothing`](@ref), [`ismissing`](@ref). """ isnothing(x) = x === nothing @@ -75,7 +77,7 @@ Return the first value in the arguments which is not equal to [`nothing`](@ref), if any. Otherwise throw an error. Arguments of type [`Some`](@ref) are unwrapped. -See also [`coalesce`](@ref). +See also [`coalesce`](@ref), [`skipmissing`](@ref). # Examples ```jldoctest diff --git a/base/sort.jl b/base/sort.jl index 1a994398bea04..d16de5904c8dd 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -307,6 +307,8 @@ according to the order specified by the `by`, `lt` and `rev` keywords, assuming is already sorted in that order. Return an empty range located at the insertion point if `a` does not contain values equal to `x`. +See also: [`insorted`](@ref), [`searchsortedfirst`](@ref), [`sort`](@ref), [`findall`](@ref). + # Examples ```jldoctest julia> searchsorted([1, 2, 4, 5, 5, 7], 4) # single match @@ -333,6 +335,8 @@ Return the index of the first value in `a` greater than or equal to `x`, accordi specified order. Return `length(a) + 1` if `x` is greater than all values in `a`. `a` is assumed to be sorted. +See also: [`searchsortedlast`](@ref), [`searchsorted`](@ref), [`findfirst`](@ref). + # Examples ```jldoctest julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 4) # single match @@ -877,7 +881,7 @@ using the same keywords as [`sort!`](@ref). The permutation is guaranteed to be if the sorting algorithm is unstable, meaning that indices of equal elements appear in ascending order. -See also [`sortperm!`](@ref). +See also [`sortperm!`](@ref), [`partialsortperm`](@ref), [`invperm`](@ref), [`indexin`](@ref). # Examples ```jldoctest diff --git a/base/special/exp.jl b/base/special/exp.jl index 5591f3603eee2..c9d53ed8aa695 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -297,12 +297,17 @@ end @doc """ exp(x) -Compute the natural base exponential of `x`, in other words ``e^x``. +Compute the natural base exponential of `x`, in other words ``ℯ^x``. + +See also [`exp2`](@ref), [`exp10`](@ref) and [`cis`](@ref). # Examples ```jldoctest julia> exp(1.0) 2.718281828459045 + +julia> exp(im * pi) == cis(pi) +true ``` """ exp(x::Real) @@ -311,10 +316,18 @@ julia> exp(1.0) Compute the base 2 exponential of `x`, in other words ``2^x``. +See also [`ldexp`](@ref), [`<<`](@ref). + # Examples ```jldoctest julia> exp2(5) 32.0 + +julia> 2^5 +32 + +julia> exp2(63) > typemax(Int) +true ``` """ exp2(x) @@ -328,6 +341,9 @@ Compute the base 10 exponential of `x`, in other words ``10^x``. ```jldoctest julia> exp10(2) 100.0 + +julia> 10^2 +100 ``` """ exp10(x) diff --git a/base/special/trig.jl b/base/special/trig.jl index 6ebfd2f2932aa..e7b9e2085bb98 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -168,6 +168,8 @@ end Simultaneously compute the sine and cosine of `x`, where `x` is in radians, returning a tuple `(sine, cosine)`. + +See also [`cis`](@ref), [`sincospi`](@ref), [`sincosd`](@ref). """ function sincos(x::T) where T<:Union{Float32, Float64} if abs(x) < T(pi)/4 @@ -742,6 +744,8 @@ mulpi_ext(x::Real) = pi*x # Fallback sinpi(x) Compute ``\\sin(\\pi x)`` more accurately than `sin(pi*x)`, especially for large `x`. + +See also [`sind`](@ref), [`cospi`](@ref), [`sincospi`](@ref). """ function sinpi(x::T) where T<:AbstractFloat if !isfinite(x) @@ -863,6 +867,8 @@ where `x` is in radians), returning a tuple `(sine, cosine)`. !!! compat "Julia 1.6" This function requires Julia 1.6 or later. + +See also: [`cispi`](@ref), [`sincosd`](@ref), [`sinpi`](@ref). """ function sincospi(x::T) where T<:AbstractFloat if !isfinite(x) @@ -1069,6 +1075,8 @@ isinf_real(x::Number) = false sinc(x) Compute ``\\sin(\\pi x) / (\\pi x)`` if ``x \\neq 0``, and ``1`` if ``x = 0``. + +See also [`cosc`](@ref), its derivative. """ sinc(x::Number) = _sinc(float(x)) sinc(x::Integer) = iszero(x) ? one(x) : zero(x) diff --git a/base/strings/io.jl b/base/strings/io.jl index f80479dd79f90..3977f137510e3 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -64,10 +64,10 @@ Hello, world julia> io = IOBuffer(); -julia> println(io, "Hello, world") +julia> println(io, "Hello", ',', " world.") julia> String(take!(io)) -"Hello, world\\n" +"Hello, world.\\n" ``` """ println(io::IO, xs...) = print(io, xs..., "\n") @@ -172,6 +172,8 @@ highly efficient, then it may make sense to add a method to `string` and define `print(io::IO, x::MyType) = print(io, string(x))` to ensure the functions are consistent. +See also: [`String`](@ref), [`repr`](@ref), [`sprint`](@ref), [`show`](@ref @show). + # Examples ```jldoctest julia> string("a", 1, true) diff --git a/base/strings/util.jl b/base/strings/util.jl index 2d043b5a360a9..11161ce49af09 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -10,7 +10,7 @@ const Chars = Union{AbstractChar,Tuple{Vararg{AbstractChar}},AbstractVector{<:Ab Return `true` if `s` starts with `prefix`. If `prefix` is a vector or set of characters, test whether the first character of `s` belongs to that set. -See also [`endswith`](@ref). +See also [`endswith`](@ref), [`contains`](@ref). # Examples ```jldoctest @@ -30,7 +30,7 @@ startswith(str::AbstractString, chars::Chars) = !isempty(str) && first(str)::Abs Return `true` if `s` ends with `suffix`. If `suffix` is a vector or set of characters, test whether the last character of `s` belongs to that set. -See also [`startswith`](@ref). +See also [`startswith`](@ref), [`contains`](@ref). # Examples ```jldoctest @@ -77,6 +77,8 @@ Return `true` if `haystack` contains `needle`. This is the same as `occursin(needle, haystack)`, but is provided for consistency with `startswith(haystack, needle)` and `endswith(haystack, needle)`. +See also [`occursin`](@ref), [`in`](@ref), [`issubset`](@ref). + # Examples ```jldoctest julia> contains("JuliaLang is pretty cool!", "Julia") @@ -166,6 +168,8 @@ The call `chop(s)` removes the last character from `s`. If it is requested to remove more characters than `length(s)` then an empty string is returned. +See also [`chomp`](@ref), [`startswith`](@ref), [`first`](@ref). + # Examples ```jldoctest julia> a = "March" @@ -196,6 +200,8 @@ end Remove a single trailing newline from a string. +See also [`chop`](@ref). + # Examples ```jldoctest julia> chomp("Hello\\n") diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index f35cb37da990b..179bc3170fa52 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -15,6 +15,10 @@ threadid() = Int(ccall(:jl_threadid, Int16, ())+1) Get the number of threads available to the Julia process. This is the inclusive upper bound on [`threadid()`](@ref). + +See also: `BLAS.get_num_threads` and `BLAS.set_num_threads` in the +[`LinearAlgebra`](@ref man-linalg) standard library, and `nprocs()` in the +[`Distributed`](@ref man-distributed) standard library. """ nthreads() = Int(unsafe_load(cglobal(:jl_n_threads, Cint))) @@ -114,6 +118,10 @@ The default schedule (used when no `schedule` argument is present) is subject to !!! compat "Julia 1.5" The `schedule` argument is available as of Julia 1.5. + +See also: [`@spawn`](@ref Threads.@spawn), [`nthreads()`](@ref Threads.nthreads), +[`threadid()`](@ref Threads.threadid), `pmap` in [`Distributed`](@ref man-distributed), +`BLAS.set_num_threads` in [`LinearAlgebra`](@ref man-linalg). """ macro threads(args...) na = length(args) diff --git a/base/tuple.jl b/base/tuple.jl index 3894ec83139fc..55c00084c3c63 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -110,6 +110,8 @@ in assignments, like `a, b... = collection`. !!! compat "Julia 1.6" `Base.rest` requires at least Julia 1.6. +See also: [`first`](@ref first), [`Iterators.rest`](@ref). + # Examples ```jldoctest julia> a = [1 2; 3 4] @@ -186,6 +188,8 @@ safe_tail(t::Tuple{}) = () Return a `Tuple` consisting of all but the last component of `x`. +See also: [`first`](@ref), [`tail`](@ref Base.tail). + # Examples ```jldoctest julia> Base.front((1,2,3)) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index ec8678361da60..f8c014677f6c9 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -40,6 +40,7 @@ Base.trues Base.falses Base.fill Base.fill! +Base.empty Base.similar ``` @@ -91,6 +92,7 @@ Base.Broadcast.result_style Base.getindex(::AbstractArray, ::Any...) Base.setindex!(::AbstractArray, ::Any, ::Any...) Base.copyto!(::AbstractArray, ::CartesianIndices, ::AbstractArray, ::CartesianIndices) +Base.copy! Base.isassigned Base.Colon Base.CartesianIndex diff --git a/doc/src/base/base.md b/doc/src/base/base.md index fe3e7e4ff498a..e747c9137bc09 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -158,6 +158,7 @@ Base.typejoin Base.typeintersect Base.promote_type Base.promote_rule +Base.promote_typejoin Base.isdispatchtuple ``` @@ -213,12 +214,14 @@ Core.Union Union{} Core.UnionAll Core.Tuple +Core.NTuple Core.NamedTuple Base.@NamedTuple Base.Val Core.Vararg Core.Nothing Base.isnothing +Base.notnothing Base.Some Base.something Base.Enums.Enum @@ -243,6 +246,7 @@ new Base.:(|>) Base.:(∘) Base.ComposedFunction +Base.splat ``` ## Syntax @@ -406,6 +410,7 @@ Base.isconst Base.nameof(::Function) Base.functionloc(::Any, ::Any) Base.functionloc(::Method) +Base.@locals ``` ## Internals diff --git a/doc/src/base/math.md b/doc/src/base/math.md index 8f8a038df83c0..177324abccfaa 100644 --- a/doc/src/base/math.md +++ b/doc/src/base/math.md @@ -67,6 +67,7 @@ Base.tan(::Number) Base.Math.sind Base.Math.cosd Base.Math.tand +Base.Math.sincosd Base.Math.sinpi Base.Math.cospi Base.Math.sincospi @@ -177,6 +178,7 @@ Base.nextprod Base.invmod Base.powermod Base.ndigits +Base.add_sum Base.widemul Base.Math.evalpoly Base.Math.@evalpoly diff --git a/stdlib/Distributed/docs/src/index.md b/stdlib/Distributed/docs/src/index.md index 1b1675eccc1a2..dc8cef5e22d92 100644 --- a/stdlib/Distributed/docs/src/index.md +++ b/stdlib/Distributed/docs/src/index.md @@ -1,4 +1,4 @@ -# Distributed Computing +# [Distributed Computing](@id man-distributed) ```@docs Distributed.addprocs diff --git a/stdlib/InteractiveUtils/docs/src/index.md b/stdlib/InteractiveUtils/docs/src/index.md index 6b996fb333fc5..71499744ecb1d 100644 --- a/stdlib/InteractiveUtils/docs/src/index.md +++ b/stdlib/InteractiveUtils/docs/src/index.md @@ -1,4 +1,4 @@ -# Interactive Utilities +# [Interactive Utilities](@id man-interactive-utils) This module is intended for interactive work. It is loaded automaticaly in [interactive mode](@ref command-line-options). diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index c0c6f2df05215..db87e9e5cba04 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -81,6 +81,8 @@ Print information about the version of Julia in use. The output is controlled with boolean keyword arguments: - `verbose`: print all additional information + +See also: [`VERSION`](@ref). """ function versioninfo(io::IO=stdout; verbose::Bool=false) println(io, "Julia Version $VERSION") @@ -261,6 +263,8 @@ subtypes(m::Module, x::Type) = _subtypes_in([m], x) Return a list of immediate subtypes of DataType `T`. Note that all currently loaded subtypes are included, including those not visible in the current module. +See also [`supertype`](@ref), [`supertypes`](@ref), [`methodswith`](@ref). + # Examples ```jldoctest julia> subtypes(Integer) @@ -279,6 +283,8 @@ Return a tuple `(T, ..., Any)` of `T` and all its supertypes, as determined by successive calls to the [`supertype`](@ref) function, listed in order of `<:` and terminated by `Any`. +See also [`subtypes`](@ref). + # Examples ```jldoctest julia> supertypes(Int) diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 011a0034378b2..79473f6d5bb36 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -247,7 +247,9 @@ It calls out to the `functionloc` function. Applied to a function or macro call, it evaluates the arguments to the specified call, and returns the `Method` object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the -`which` function. +[`which`](@ref) function. + +See also: [`@less`](@ref), [`@edit`](@ref). """ :@which @@ -256,6 +258,8 @@ to a variable, it returns the module in which the variable was bound. It calls o Evaluates the arguments to the function or macro call, determines their types, and calls the `less` function on the resulting expression. + +See also: [`@edit`](@ref), [`@which`](@ref), [`@code_lowered`](@ref). """ :@less @@ -264,6 +268,8 @@ function on the resulting expression. Evaluates the arguments to the function or macro call, determines their types, and calls the `edit` function on the resulting expression. + +See also: [`@less`](@ref), [`@which`](@ref). """ :@edit diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 48d44d98f7ca0..baafe762cea3f 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -577,6 +577,7 @@ LinearAlgebra.BLAS.trmv LinearAlgebra.BLAS.trsv! LinearAlgebra.BLAS.trsv LinearAlgebra.BLAS.set_num_threads +LinearAlgebra.BLAS.get_num_threads ``` ## LAPACK functions diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index e21c4200f9394..e1294d7166d1d 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -75,7 +75,8 @@ isposdef!(A::AbstractMatrix) = Test whether a matrix is positive definite (and Hermitian) by trying to perform a Cholesky factorization of `A`. -See also [`isposdef!`](@ref) + +See also [`isposdef!`](@ref), [`cholesky`](@ref). # Examples ```jldoctest @@ -205,6 +206,8 @@ diagind(m::Integer, n::Integer, k::Integer=0) = An `AbstractRange` giving the indices of the `k`th diagonal of the matrix `M`. +See also: [`diag`](@ref), [`diagm`](@ref), [`Diagonal`](@ref). + # Examples ```jldoctest julia> A = [1 2 3; 4 5 6; 7 8 9] @@ -227,7 +230,7 @@ end The `k`th diagonal of a matrix, as a vector. -See also: [`diagm`](@ref) +See also: [`diagm`](@ref), [`diagind`](@ref), [`Diagonal`](@ref), [`isdiag`](@ref). # Examples ```jldoctest diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 17a565ee76cb2..b74ac6cced810 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1109,6 +1109,8 @@ When `A` is sparse, a similar polyalgorithm is used. For indefinite matrices, th factorization does not use pivoting during the numerical factorization and therefore the procedure can fail even for invertible matrices. +See also: [`factorize`](@ref), [`pinv`](@ref). + # Examples ```jldoctest julia> A = [1 0; 1 -2]; B = [32; -4]; @@ -1529,6 +1531,8 @@ end Matrix determinant. +See also: [`logdet`](@ref) and [`logabsdet`](@ref). + # Examples ```jldoctest julia> M = [1 0; 2 2] diff --git a/stdlib/Printf/docs/src/index.md b/stdlib/Printf/docs/src/index.md index 828e527ed0cad..48e38e2b2ce5b 100644 --- a/stdlib/Printf/docs/src/index.md +++ b/stdlib/Printf/docs/src/index.md @@ -1,4 +1,4 @@ -# Printf +# [Printf](@id man-printf) ```@docs Printf.@printf From 5784cd3451efb22ad60017ac425c6e0ccecab386 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 20 Apr 2021 00:17:49 -0400 Subject: [PATCH 213/439] enable new Float16 methods for sinh and cbrt (#40534) From #39432 and #39441, these were still using their old definition due to method overwriting. --- base/math.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/base/math.jl b/base/math.jl index 44da5e04ea5a5..c08c25d05f112 100644 --- a/base/math.jl +++ b/base/math.jl @@ -1195,7 +1195,7 @@ include("special/log.jl") # Float16 definitions -for func in (:sin,:cos,:tan,:asin,:acos,:atan,:sinh,:cosh,:tanh,:asinh,:acosh, +for func in (:sin,:cos,:tan,:asin,:acos,:atan,:cosh,:tanh,:asinh,:acosh, :atanh,:log,:log2,:log10,:sqrt,:lgamma,:log1p) @eval begin $func(a::Float16) = Float16($func(Float32(a))) @@ -1203,13 +1203,12 @@ for func in (:sin,:cos,:tan,:asin,:acos,:atan,:sinh,:cosh,:tanh,:asinh,:acosh, end end -for func in (:exp,:exp2,:exp10) +for func in (:exp,:exp2,:exp10,:sinh) @eval $func(a::ComplexF16) = ComplexF16($func(ComplexF32(a))) end atan(a::Float16,b::Float16) = Float16(atan(Float32(a),Float32(b))) -cbrt(a::Float16) = Float16(cbrt(Float32(a))) sincos(a::Float16) = Float16.(sincos(Float32(a))) for f in (:sin, :cos, :tan, :asin, :atan, :acos, From 3428e8833eb66b873d436200959e7848f25a45a0 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Tue, 20 Apr 2021 09:38:26 +0200 Subject: [PATCH 214/439] Fix eigvecs(:::SymTridiagonal) with longer off-diagonal vector (#40526) Co-authored-by: Marcelo Forets --- stdlib/LinearAlgebra/src/lapack.jl | 13 +++++++++---- stdlib/LinearAlgebra/test/lapack.jl | 2 +- stdlib/LinearAlgebra/test/tridiag.jl | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 0dd1f86db5459..2019943b4e388 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -3835,7 +3835,7 @@ for (stev, stebz, stegr, stein, elty) in eev = copy(ev) eev[n] = zero($elty) else - throw(DimensionMismatch("ev has length $(length(ev)) but should be either $(length(dv) - 1) or $(length(dv))")) + throw(DimensionMismatch("ev has length $ne but needs one less than or equal to dv's length, $n)")) end abstol = Vector{$elty}(undef, 1) @@ -3878,10 +3878,15 @@ for (stev, stebz, stegr, stein, elty) in require_one_based_indexing(dv, ev_in, w_in, iblock_in, isplit_in) chkstride1(dv, ev_in, w_in, iblock_in, isplit_in) n = length(dv) - if length(ev_in) != n - 1 - throw(DimensionMismatch("ev_in has length $(length(ev_in)) but needs one less than dv's length, $n)")) + ne = length(ev_in) + if ne == n - 1 + ev = [ev_in; zero($elty)] + elseif ne == n + ev = copy(ev_in) + ev[n] = zero($elty) + else + throw(DimensionMismatch("ev_in has length $ne but needs one less than or equal to dv's length, $n)")) end - ev = [ev_in; zeros($elty,1)] ldz = n #Leading dimension #Number of eigenvalues to find if !(1 <= length(w_in) <= n) diff --git a/stdlib/LinearAlgebra/test/lapack.jl b/stdlib/LinearAlgebra/test/lapack.jl index c8e2c82e97150..6453f0f521092 100644 --- a/stdlib/LinearAlgebra/test/lapack.jl +++ b/stdlib/LinearAlgebra/test/lapack.jl @@ -410,7 +410,7 @@ end @test_throws DimensionMismatch LAPACK.stev!('U',d,rand(elty,11)) @test_throws DimensionMismatch LAPACK.stebz!('A','B',zero(elty),zero(elty),0,0,-1.,d,rand(elty,10)) @test_throws DimensionMismatch LAPACK.stegr!('N','A',d,rand(elty,11),zero(elty),zero(elty),0,0) - @test_throws DimensionMismatch LAPACK.stein!(d,zeros(elty,10),zeros(elty,10),zeros(BlasInt,10),zeros(BlasInt,10)) + @test_throws DimensionMismatch LAPACK.stein!(d,zeros(elty,11),zeros(elty,10),zeros(BlasInt,10),zeros(BlasInt,10)) @test_throws DimensionMismatch LAPACK.stein!(d,e,zeros(elty,11),zeros(BlasInt,10),zeros(BlasInt,10)) end end diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index e310766b2a66c..8cfde8fb5067c 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -590,6 +590,8 @@ end F2 = eigen(A2) test_approx_eq_modphase(F.vectors, F2.vectors) @test F.values ≈ F2.values ≈ eigvals(A) ≈ eigvals(A2) + @test eigvecs(A) ≈ eigvecs(A2) + @test eigvecs(A, eigvals(A)[1:1]) ≈ eigvecs(A2, eigvals(A2)[1:1]) end @testset "non-commutative algebra (#39701)" begin From b315648d93cfbea0d0a170dcd28cb1b7d535a502 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:39:20 +0200 Subject: [PATCH 215/439] Promote eltype when dividing UniformScaling by matrix (#40528) --- stdlib/LinearAlgebra/src/uniformscaling.jl | 6 ++++-- stdlib/LinearAlgebra/test/uniformscaling.jl | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 71dd11a2f9e87..1b2e3010ff27d 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -265,7 +265,8 @@ end *(J::UniformScaling, x::Number) = UniformScaling(J.λ*x) /(J1::UniformScaling, J2::UniformScaling) = J2.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ/J2.λ) -/(J::UniformScaling, A::AbstractMatrix) = lmul!(J.λ, inv(A)) +/(J::UniformScaling, A::AbstractMatrix) = + (invA = inv(A); lmul!(J.λ, convert(AbstractMatrix{promote_type(eltype(J),eltype(invA))}, invA))) /(A::AbstractMatrix, J::UniformScaling) = J.λ == 0 ? throw(SingularException(1)) : A/J.λ /(v::AbstractVector, J::UniformScaling) = reshape(v, length(v), 1) / J @@ -273,7 +274,8 @@ end \(J1::UniformScaling, J2::UniformScaling) = J1.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ\J2.λ) \(J::UniformScaling, A::AbstractVecOrMat) = J.λ == 0 ? throw(SingularException(1)) : J.λ\A -\(A::AbstractMatrix, J::UniformScaling) = rmul!(inv(A), J.λ) +\(A::AbstractMatrix, J::UniformScaling) = + (invA = inv(A); rmul!(convert(AbstractMatrix{promote_type(eltype(invA),eltype(J))}, invA), J.λ)) \(F::Factorization, J::UniformScaling) = F \ J(size(F,1)) \(x::Number, J::UniformScaling) = UniformScaling(x\J.λ) diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 4eea74b12ff15..33b2ba7032734 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -528,4 +528,12 @@ end @test sum(A - I) ≈ -3.0 end +@testset "type promotion when dividing UniformScaling by matrix" begin + A = randn(5,5) + cA = complex(A) + J = (5+2im)*I + @test J/A ≈ J/cA + @test A\J ≈ cA\J +end + end # module TestUniformscaling From 7bbb75d5551c5edfeba9033105cc7e3eb7ed2374 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 20 Apr 2021 05:36:30 -0400 Subject: [PATCH 216/439] docs: mention privacy of type fields in style-guide (#40533) close #12064 close #7561 Co-authored-by: Spencer Russell --- doc/src/manual/style-guide.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 8e863e866b366..3a94f263e9e65 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -134,6 +134,32 @@ a = Vector{Union{Int,AbstractString,Tuple,Array}}(undef, n) In this case `Vector{Any}(undef, n)` is better. It is also more helpful to the compiler to annotate specific uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. +## Prefer exported methods over direct field access + +Idiomatic Julia code should generally treat a module's exported methods as the +interface to its types. An object's fields are generally considered +implementation details and user code should only access them directly if this +is stated to be the API. This has several benefits: + +- Package developers are freer to change the implementation without breaking + user code. +- Methods can be passed to higher-order constructs like [`map`](@ref) (e.g. + `map(imag, zs))` rather than `[z.im for z in zs]`). +- Methods can be defined on abstract types. +- Methods can describe a conceptual operation that can be shared across + disparate types (e.g. `real(z)` works on Complex numbers or Quaternions). + +Julia's dispatch system encourages this style because `play(x::MyType)` only +defines the `play` method on that particular type, leaving other types to +have their own implementation. + +Similarly, non-exported functions are typically internal and subject to change, +unless the documentations states otherwise. Names sometimes are given a `_` prefix +(or suffix) to further suggest that something is "internal" or an +implementation-detail, but it is not a rule. + +Counter-examples to this rule include [`NamedTuple`](@ref), [`RegexMatch`](@ref match), [`StatStruct`](@ref stat). + ## Use naming conventions consistent with Julia `base/` * modules and type names use capitalization and camel case: `module SparseArrays`, `struct UnitRange`. From d998c7e74c84bb6f78916e71bf4efab936347170 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 20 Apr 2021 11:37:13 +0200 Subject: [PATCH 217/439] SparseArrays: add Printf to test deps. (#40520) --- stdlib/SparseArrays/Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/Project.toml b/stdlib/SparseArrays/Project.toml index 53d4a9f064ad3..bc8a968cfb4ff 100644 --- a/stdlib/SparseArrays/Project.toml +++ b/stdlib/SparseArrays/Project.toml @@ -8,7 +8,8 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [extras] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Dates", "Test", "InteractiveUtils"] +test = ["Dates", "Test", "Printf", "InteractiveUtils"] From ba71161a041fefbf3ed592de9a892f0e7ae2a725 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Tue, 20 Apr 2021 13:13:10 +0200 Subject: [PATCH 218/439] remove `===` for singleton equality tip (#40517) With #38905 merged, this shouldn't apply in general anymore. I am sure with `==` being a generic function, there will still be cases where using `===` will lead to more precise inference, but I don't think this is worth specifically mentioning in the performance tips. --- doc/src/manual/performance-tips.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 8535028c0fa3c..86005171e8f74 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1600,11 +1600,3 @@ will not require this degree of programmer annotation to attain performance. In the mean time, some user-contributed packages like [FastClosures](https://github.com/c42f/FastClosures.jl) automate the insertion of `let` statements as in `abmult3`. - -## Checking for equality with a singleton - -When checking if a value is equal to some singleton it can be -better for performance to check for identicality (`===`) instead of -equality (`==`). The same advice applies to using `!==` over `!=`. -These type of checks frequently occur e.g. when implementing the iteration -protocol and checking if `nothing` is returned from [`iterate`](@ref). From 002fc5f145849007b473453561aad5f8862526c2 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Tue, 20 Apr 2021 09:41:25 -0400 Subject: [PATCH 219/439] doc: `take!(::IOBuffer)` may make copies (#27442) Simple doc change to reflect the implementation. --- base/iobuffer.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 8df6af0087137..e204eca906cbf 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -353,8 +353,7 @@ isopen(io::GenericIOBuffer) = io.readable || io.writable || io.seekable || bytes """ take!(b::IOBuffer) -Obtain the contents of an `IOBuffer` as an array, without copying. Afterwards, the -`IOBuffer` is reset to its initial state. +Obtain the contents of an `IOBuffer` as an array. Afterwards, the `IOBuffer` is reset to its initial state. # Examples ```jldoctest From 81052523a2fb19ee78fe066132715a3e421ccc7e Mon Sep 17 00:00:00 2001 From: jch8ri Date: Tue, 20 Apr 2021 10:12:23 -0400 Subject: [PATCH 220/439] add some docs for Dates formatters Co-authored-by: Jameson Nash --- stdlib/Dates/docs/src/index.md | 9 +++++ stdlib/Dates/src/io.jl | 60 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index c423b85ef4aba..3c52eaf1d9dee 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -858,6 +858,15 @@ Months of the Year: | `November` | `Nov` | 11 | | `December` | `Dec` | 12 | +#### Common Date Formatters + +```@docs +ISODateTimeFormat +ISODateFormat +ISOTimeFormat +RFC1123Format +``` + ```@meta DocTestSetup = nothing ``` diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 721e36deef7a8..3de39f05e0e33 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -367,8 +367,9 @@ When parsing a time with a `p` specifier, any hour (either `H` or `I`) is interp as a 12-hour clock, so the `I` code is mainly useful for output. Creating a DateFormat object is expensive. Whenever possible, create it once and use it many times -or try the `dateformat""` string macro. Using this macro creates the DateFormat object once at -macro expansion time and reuses it later. see [`@dateformat_str`](@ref). +or try the [`dateformat""`](@ref @dateformat_str) string macro. Using this macro creates the DateFormat +object once at macro expansion time and reuses it later. There are also several [pre-defined formatters](@ref +Common-Date-Formatters), listed later. See [`DateTime`](@ref) and [`format`](@ref) for how to use a DateFormat object to parse and write Date strings respectively. @@ -443,14 +444,63 @@ macro dateformat_str(str) end # Standard formats + +""" + Dates.ISODateTimeFormat + +Describes the ISO8601 formatting for a date and time. This is the default value for `Dates.format` +of a `DateTime`. + +# Example +```jldoctest +julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), ISODateTimeFormat) +"2018-08-08T12:00:43.001" +``` +""" const ISODateTimeFormat = DateFormat("yyyy-mm-dd\\THH:MM:SS.s") +default_format(::Type{DateTime}) = ISODateTimeFormat + +""" + Dates.ISODateFormat + +Describes the ISO8601 formatting for a date. This is the default value for `Dates.format` of a `Date`. + +# Example +```jldoctest +julia> Dates.format(Date(2018, 8, 8), ISODateFormat) +"2018-08-08" +``` +""" const ISODateFormat = DateFormat("yyyy-mm-dd") +default_format(::Type{Date}) = ISODateFormat + +""" + Dates.ISOTimeFormat + +Describes the ISO8601 formatting for a time. This is the default value for `Dates.format` of a `Time`. + +# Example +```jldoctest +julia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat) +"12:00:43.001" +``` +""" const ISOTimeFormat = DateFormat("HH:MM:SS.s") +default_format(::Type{Time}) = ISOTimeFormat + +""" + Dates.RFC1123Format + +Describes the RFC1123 formatting for a date and time. + +# Example +```jldoctest +julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format) +"Wed, 08 Aug 2018 12:00:43" +``` +""" const RFC1123Format = DateFormat("e, dd u yyyy HH:MM:SS") -default_format(::Type{DateTime}) = ISODateTimeFormat -default_format(::Type{Date}) = ISODateFormat -default_format(::Type{Time}) = ISOTimeFormat ### API From 1131876c28e4f10b7f9fb83299c5e5d32e9a9af3 Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Wed, 21 Apr 2021 04:36:37 +1000 Subject: [PATCH 221/439] Document the guarantees that should be provided by `isequal` (#34798) --- base/operators.jl | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index 7269a15718a58..bf4a8a98bddf6 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -93,6 +93,10 @@ and of missing values. `isequal` treats all floating-point `NaN` values as equal to each other, treats `-0.0` as unequal to `0.0`, and [`missing`](@ref) as equal to `missing`. Always returns a `Bool` value. +`isequal` is an equivalence relation - it is reflexive (`===` implies `isequal`), symmetric +(`isequal(a, b)` implies `isequal(b, a)`) and transitive (`isequal(a, b)` and +`isequal(b, c)` implies `isequal(a, c)`). + # Implementation The default implementation of `isequal` calls `==`, so a type that does not involve floating-point values generally only needs to define `==`. @@ -101,8 +105,12 @@ floating-point values generally only needs to define `==`. that `hash(x) == hash(y)`. This typically means that types for which a custom `==` or `isequal` method exists must -implement a corresponding `hash` method (and vice versa). Collections typically implement -`isequal` by calling `isequal` recursively on all contents. +implement a corresponding [`hash`](@ref) method (and vice versa). Collections typically +implement `isequal` by calling `isequal` recursively on all contents. + +Furthermore, `isequal` is linked with [`isless`](@ref), and they work together to +define a fixed total ordering, where exactly one of `isequal(x, y)`, `isless(x, y)`, or +`isless(y, x)` must be `true` (and the other two `false`). Scalar types generally do not need to implement `isequal` separate from `==`, unless they represent floating-point numbers amenable to a more efficient implementation than that @@ -121,6 +129,12 @@ true julia> isequal(0.0, -0.0) false + +julia> missing == missing +missing + +julia> isequal(missing, missing) +true ``` """ isequal(x, y) = x == y @@ -135,8 +149,8 @@ isequal(x::AbstractFloat, y::Real ) = (isnan(x) & isnan(y)) | signequal( """ isless(x, y) -Test whether `x` is less than `y`, according to a fixed total order. -`isless` is not defined on all pairs of values `(x, y)`. However, if it +Test whether `x` is less than `y`, according to a fixed total order (defined together with +[`isequal`](@ref)). `isless` is not defined on all pairs of values `(x, y)`. However, if it is defined, it is expected to satisfy the following: - If `isless(x, y)` is defined, then so is `isless(y, x)` and `isequal(x, y)`, and exactly one of those three yields `true`. From bb5b98e72a151c41471d8cc14cacb495d647fb7f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 20 Apr 2021 11:46:14 -0700 Subject: [PATCH 222/439] Document what public API means (#35715) Provides some guidelines, in addition to those added recently by #40533 to the style-guide, per #7561. --- doc/src/base/base.md | 5 +++++ doc/src/manual/faq.md | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index e747c9137bc09..0eac8913542da 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -15,6 +15,11 @@ Some general notes: * By convention, function names ending with an exclamation point (`!`) modify their arguments. Some functions have both modifying (e.g., `sort!`) and non-modifying (`sort`) versions. +The behaviors of `Base` and standard libraries are stable as defined in +[SemVer](https://semver.org/) only if they are documented; i.e., included in the +[Julia documentation](https://docs.julialang.org/) and not marked as unstable. +See [API FAQ](@ref man-api) for more information. + ## Getting Around ```@docs diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index c6bcd69424c7a..7d72d0a0208d9 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -18,6 +18,33 @@ For similar reasons, automated translation to Julia would also typically generat On the other hand, language *interoperability* is extremely useful: we want to exploit existing high-quality code in other languages from Julia (and vice versa)! The best way to enable this is not a transpiler, but rather via easy inter-language calling facilities. We have worked hard on this, from the built-in `ccall` intrinsic (to call C and Fortran libraries) to [JuliaInterop](https://github.com/JuliaInterop) packages that connect Julia to Python, Matlab, C++, and more. +## [Public API](@id man-api) + +### How does Julia define its public API? + +The only interfaces that are stable with respect to [SemVer](https://semver.org/) of `julia` +version are the Julia `Base` and standard libraries interfaces described in +[the documentation](https://docs.julialang.org/) and not marked as unstable (e.g., +experimental and internal). Functions, types, and constants are not part of the public +API if they are not included in the documentation, _even if they have docstrings_. + +### There is a useful undocumented function/type/constant. Can I use it? + +Updating Julia may break your code if you use non-public API. If the code is +self-contained, it may be a good idea to copy it into your project. If you want to rely on +a complex non-public API, especially when using it from a stable package, it is a good idea +to open an [issue](https://github.com/JuliaLang/julia/issues) or +[pull request](https://github.com/JuliaLang/julia/pulls) to start a discussion for turning it +into a public API. However, we do not discourage the attempt to create packages that expose +stable public interfaces while relying on non-public implementation details of `julia` and +buffering the differences across different `julia` versions. + +### The documentation is not accurate enough. Can I rely on the existing behavior? + +Please open an [issue](https://github.com/JuliaLang/julia/issues) or +[pull request](https://github.com/JuliaLang/julia/pulls) to start a discussion for turning the +existing behavior into a public API. + ## Sessions and the REPL ### How do I delete an object in memory? From 6985788019ff7bfb108f706fe68d6475b2020d7a Mon Sep 17 00:00:00 2001 From: jaideep-seth <36701121+jaideep-seth@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:34:34 +0530 Subject: [PATCH 223/439] doc: add `@` to help (#33824) Co-authored-by: jaideep-seth Co-authored-by: Jameson Nash --- base/docs/basedocs.jl | 12 ++++++++++++ doc/src/base/punctuation.md | 18 +++++++++--------- doc/src/manual/metaprogramming.md | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index d7c944ffed78c..bb98043994ba6 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -452,6 +452,18 @@ For other purposes, `:( ... )` and `quote .. end` blocks are treated identically """ kw"quote" +""" + @ + +The at sign followed by a macro name marks a macro call. Macros provide the +ability to include generated code in the final body of a program. A macro maps +a tuple of arguments, expressed as space-separated expressions or a +function-call-like argument list, to a returned *expression*. The resulting +expression is compiled directly into the surrounding code. See +[Metaprogramming](@ref man-macros) for more details and examples. +""" +kw"@" + """ {} diff --git a/doc/src/base/punctuation.md b/doc/src/base/punctuation.md index 3a92d021f2f10..6b2f6501f17ae 100644 --- a/doc/src/base/punctuation.md +++ b/doc/src/base/punctuation.md @@ -2,17 +2,17 @@ Extended documentation for mathematical symbols & functions is [here](@ref math-ops). -| symbol | meaning | -|:----------- |:----------------------------------------------------------------------------------------------------------------------------------------------- | -| `@m` | the at-symbol invokes [macro](@ref man-macros) `m`; followed by space-separated expressions or a function-call-like argument list | +| symbol | meaning | +|:----------- |:--------------------------------------------------------------------------------------------| +| `@` | the at-sign marks a [macro](@ref man-macros) invocation; optionally followed by an argument list | | [`!`](@ref) | an exclamation mark is a prefix operator for logical negation ("not") | | `a!` | function names that end with an exclamation mark modify one or more of their arguments by convention | | `#` | the number sign (or hash or pound) character begins single line comments | -| `#=` | when followed by an equals sign, it begins a multi-line comment (these are nestable) | +| `#=` | when followed by an equals sign, it begins a multi-line comment (these are nestable) | | `=#` | end a multi-line comment by immediately preceding the number sign with an equals sign | | `$` | the dollar sign is used for [string](@ref string-interpolation) and [expression](@ref man-expression-interpolation) interpolation | | [`%`](@ref rem) | the percent symbol is the remainder operator | -| [`^`](@ref) | the caret is the exponentiation operator | +| [`^`](@ref) | the caret is the exponentiation operator | | [`&`](@ref) | single ampersand is bitwise and | | [`&&`](@ref)| double ampersands is short-circuiting boolean and | | [`\|`](@ref)| single pipe character is bitwise or | @@ -31,7 +31,7 @@ Extended documentation for mathematical symbols & functions is [here](@ref math- | `[,]` | [vector literal constructor](@ref man-array-literals) (calling [`vect`](@ref Base.vect)) | | `[;]` | [vertical concatenation](@ref man-array-concatenation) (calling [`vcat`](@ref) or [`hvcat`](@ref)) | | `[   ]` | with space-separated expressions, [horizontal concatenation](@ref man-concatenation) (calling [`hcat`](@ref) or [`hvcat`](@ref)) | -| `T{ }` | curly braces following a type list that type's [parameters](@ref Parametric-Types) | +| `T{ }` | curly braces following a type list that type's [parameters](@ref Parametric-Types) | | `{}` | curly braces can also be used to group multiple [`where`](@ref) expressions in function declarations | | `;` | semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation | | `,` | commas separate function arguments or tuple or array components | @@ -55,6 +55,6 @@ Extended documentation for mathematical symbols & functions is [here](@ref math- | [`==`](@ref)| double equals sign is value equality comparison | | [`===`](@ref) | triple equals sign is programmatically identical equality comparison | | [`=>`](@ref Pair) | right arrow using an equals sign defines a [`Pair`](@ref) typically used to populate [dictionaries](@ref Dictionaries) | -| `->` | right arrow using a hyphen defines an [anonymous function](@ref man-anonymous-functions) on a single line | -| `|>` | pipe operator passes output from the left argument to input of the right argument, usually a [function](@ref Function-composition-and-piping) | -| `∘` | function composition operator (typed with \circ{tab}) combines two functions as though they are a single larger [function](@ref Function-composition-and-piping) | +| `->` | right arrow using a hyphen defines an [anonymous function](@ref man-anonymous-functions) on a single line | +| `|>` | pipe operator passes output from the left argument to input of the right argument, usually a [function](@ref Function-composition-and-piping) | +| `∘` | function composition operator (typed with \circ{tab}) combines two functions as though they are a single larger [function](@ref Function-composition-and-piping) | diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index fe9604183bcaf..a374b9c879e6a 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -466,7 +466,7 @@ julia> eval(ex) ## [Macros](@id man-macros) -Macros provide a method to include generated code in the final body of a program. A macro maps +Macros provide a mechanism to include generated code in the final body of a program. A macro maps a tuple of arguments to a returned *expression*, and the resulting expression is compiled directly rather than requiring a runtime [`eval`](@ref) call. Macro arguments may include expressions, literal values, and symbols. From ca6df85aa3881243bb13c0b63f78c22773cadbf9 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 21 Apr 2021 21:40:04 +0800 Subject: [PATCH 224/439] unexport cat_shape (#40549) --- base/deprecated.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index f64bd38779994..f1d097678f3a2 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -237,7 +237,7 @@ function parameter_upper_bound(t::UnionAll, idx) end # these were internal functions, but some packages seem to be relying on them -@deprecate cat_shape(dims, shape::Tuple{}, shapes::Tuple...) cat_shape(dims, shapes) +@deprecate cat_shape(dims, shape::Tuple{}, shapes::Tuple...) cat_shape(dims, shapes) false cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not recursively calls itself # END 1.6 deprecations From e37e98a91466f7f5e8d06e64d5357e2839fff433 Mon Sep 17 00:00:00 2001 From: Debaditya Pal Date: Wed, 21 Apr 2021 19:45:31 +0530 Subject: [PATCH 225/439] Transpose and Adjoint support for exp, log and sqrt functions (#39373) --- stdlib/LinearAlgebra/src/dense.jl | 8 ++++++++ stdlib/LinearAlgebra/test/dense.jl | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index e1294d7166d1d..27fa515e70a02 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -559,6 +559,8 @@ julia> exp(A) """ exp(A::StridedMatrix{<:BlasFloat}) = exp!(copy(A)) exp(A::StridedMatrix{<:Union{Integer,Complex{<:Integer}}}) = exp!(float.(A)) +exp(A::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(exp(parent(A))) +exp(A::Transpose{<:Any,<:AbstractMatrix}) = transpose(exp(parent(A))) """ cis(A::AbstractMatrix) @@ -762,6 +764,9 @@ function log(A::StridedMatrix) end end +log(A::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(log(parent(A))) +log(A::Transpose{<:Any,<:AbstractMatrix}) = transpose(log(parent(A))) + """ sqrt(A::AbstractMatrix) @@ -837,6 +842,9 @@ function sqrt(A::StridedMatrix{T}) where {T<:Union{Real,Complex}} end end +sqrt(A::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(sqrt(parent(A))) +sqrt(A::Transpose{<:Any,<:AbstractMatrix}) = transpose(sqrt(parent(A))) + function inv(A::StridedMatrix{T}) where T checksquare(A) S = typeof((one(T)*zero(T) + one(T)*zero(T))/one(T)) diff --git a/stdlib/LinearAlgebra/test/dense.jl b/stdlib/LinearAlgebra/test/dense.jl index 1cd9c8e6898b2..de5b25a868fcb 100644 --- a/stdlib/LinearAlgebra/test/dense.jl +++ b/stdlib/LinearAlgebra/test/dense.jl @@ -145,9 +145,13 @@ end @testset "Matrix square root" begin asq = sqrt(a) @test asq*asq ≈ a + @test sqrt(transpose(a))*sqrt(transpose(a)) ≈ transpose(a) + @test sqrt(adjoint(a))*sqrt(adjoint(a)) ≈ adjoint(a) asym = a + a' # symmetric indefinite asymsq = sqrt(asym) @test asymsq*asymsq ≈ asym + @test sqrt(transpose(asym))*sqrt(transpose(asym)) ≈ transpose(asym) + @test sqrt(adjoint(asym))*sqrt(adjoint(asym)) ≈ adjoint(asym) if eltype(a) <: Real # real square root apos = a * a @test sqrt(apos)^2 ≈ apos @@ -447,6 +451,11 @@ end 183.765138646367 183.765138646366 163.679601723179; 71.797032399996 91.8825693231832 111.968106246371]') @test exp(A1) ≈ eA1 + @test exp(adjoint(A1)) ≈ adjoint(eA1) + @test exp(transpose(A1)) ≈ transpose(eA1) + for f in (sin, cos, sinh, cosh, tanh, tan) + @test f(adjoint(A1)) ≈ f(copy(adjoint(A1))) + end A2 = convert(Matrix{elty}, [29.87942128909879 0.7815750847907159 -2.289519314033932; @@ -457,20 +466,28 @@ end -18231880972009252.0 60605228702221920.0 101291842930249760.0; -30475770808580480.0 101291842930249728.0 169294411240851968.0]) @test exp(A2) ≈ eA2 + @test exp(adjoint(A2)) ≈ adjoint(eA2) + @test exp(transpose(A2)) ≈ transpose(eA2) A3 = convert(Matrix{elty}, [-131 19 18;-390 56 54;-387 57 52]) eA3 = convert(Matrix{elty}, [-1.50964415879218 -5.6325707998812 -4.934938326092; 0.367879439109187 1.47151775849686 1.10363831732856; 0.135335281175235 0.406005843524598 0.541341126763207]') @test exp(A3) ≈ eA3 + @test exp(adjoint(A3)) ≈ adjoint(eA3) + @test exp(transpose(A3)) ≈ transpose(eA3) A4 = convert(Matrix{elty}, [0.25 0.25; 0 0]) eA4 = convert(Matrix{elty}, [1.2840254166877416 0.2840254166877415; 0 1]) @test exp(A4) ≈ eA4 + @test exp(adjoint(A4)) ≈ adjoint(eA4) + @test exp(transpose(A4)) ≈ transpose(eA4) A5 = convert(Matrix{elty}, [0 0.02; 0 0]) eA5 = convert(Matrix{elty}, [1 0.02; 0 1]) @test exp(A5) ≈ eA5 + @test exp(adjoint(A5)) ≈ adjoint(eA5) + @test exp(transpose(A5)) ≈ transpose(eA5) # Hessenberg @test hessenberg(A1).H ≈ convert(Matrix{elty}, @@ -496,15 +513,23 @@ end 1/4 1/5 1/6 1/7; 1/5 1/6 1/7 1/8]) @test exp(log(A4)) ≈ A4 + @test exp(log(transpose(A4))) ≈ transpose(A4) + @test exp(log(adjoint(A4))) ≈ adjoint(A4) A5 = convert(Matrix{elty}, [1 1 0 1; 0 1 1 0; 0 0 1 1; 1 0 0 1]) @test exp(log(A5)) ≈ A5 + @test exp(log(transpose(A5))) ≈ transpose(A5) + @test exp(log(adjoint(A5))) ≈ adjoint(A5) A6 = convert(Matrix{elty}, [-5 2 0 0 ; 1/2 -7 3 0; 0 1/3 -9 4; 0 0 1/4 -11]) @test exp(log(A6)) ≈ A6 + @test exp(log(transpose(A6))) ≈ transpose(A6) + @test exp(log(adjoint(A6))) ≈ adjoint(A6) A7 = convert(Matrix{elty}, [1 0 0 1e-8; 0 1 0 0; 0 0 1 0; 0 0 0 1]) @test exp(log(A7)) ≈ A7 + @test exp(log(transpose(A7))) ≈ transpose(A7) + @test exp(log(adjoint(A7))) ≈ adjoint(A7) end @testset "Integer promotion tests" begin From 9520c6950181ad72206f758d49a2ce1237df6aec Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 21 Apr 2021 18:27:15 +0200 Subject: [PATCH 226/439] at_test_nowarn does not suppress the content of stderr anymore (#39028) Co-authored-by: Jameson Nash --- stdlib/Test/src/Test.jl | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 43d4ae689b5b5..596aedb2d9aa7 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -770,7 +770,26 @@ with this macro. Use [`@test_logs`](@ref) instead. """ macro test_nowarn(expr) quote - @test_warn r"^(?!.)"s $(esc(expr)) + # Duplicate some code from `@test_warn` to allow printing the content of + # `stderr` again to `stderr` here while suppressing it for `@test_warn`. + # If that shouldn't be used, it would be possible to just use + # @test_warn isempty $(esc(expr)) + # here. + let fname = tempname() + try + ret = open(fname, "w") do f + redirect_stderr(f) do + $(esc(expr)) + end + end + stderr_content = read(fname, String) + print(stderr, stderr_content) # this is helpful for debugging + @test isempty(stderr_content) + ret + finally + rm(fname, force=true) + end + end end end From d47565ea90424110ac91b835dcb2a1e7037fe53f Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 29 Mar 2021 16:45:46 -0400 Subject: [PATCH 227/439] [LLVM] patch list for LLVM 12 --- deps/llvm.mk | 16 +- .../llvm-12-D75072-SCEV-add-type.patch | 425 ++++++++++++++++++ .../llvm-12-D97435-AArch64-movaddrreg.patch | 164 +++++++ 3 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 deps/patches/llvm-12-D75072-SCEV-add-type.patch create mode 100644 deps/patches/llvm-12-D97435-AArch64-movaddrreg.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 476375354da22..7ec9eaca02afb 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -561,7 +561,7 @@ $(eval $(call LLVM_PATCH,llvm-11-ppc-half-ctr)) # remove for LLVM 12 $(eval $(call LLVM_PATCH,llvm-11-ppc-sp-from-bp)) # remove for LLVM 12 $(eval $(call LLVM_PATCH,llvm-rGb498303066a6-gcc11-header-fix)) # remove for LLVM 12 $(eval $(call LLVM_PATCH,llvm-11-D94813-mergeicmps)) -$(eval $(call LLVM_PATCH,llvm-11-D94980-CTR-half)) +$(eval $(call LLVM_PATCH,llvm-11-D94980-CTR-half)) # remove for LLVM 12 $(eval $(call LLVM_PATCH,llvm-11-D94058-sext-atomic-ops)) # remove for LLVM 12 $(eval $(call LLVM_PATCH,llvm-11-D96283-dagcombine-half)) # remove for LLVM 12 $(eval $(call LLVM_PROJ_PATCH,llvm-11-AArch64-FastIsel-bug)) @@ -570,6 +570,20 @@ $(eval $(call LLVM_PROJ_PATCH,llvm-11-D97571-AArch64-loh)) # remove for LLVM 13 $(eval $(call LLVM_PROJ_PATCH,llvm-11-aarch64-addrspace)) # remove for LLVM 13 endif # LLVM_VER 11.0 +ifeq ($(LLVM_VER_SHORT),12.0) +$(eval $(call LLVM_PATCH,llvm7-revert-D44485)) # Needs upstreaming +$(eval $(call LLVM_PATCH,llvm-12-D75072-SCEV-add-type)) +$(eval $(call LLVM_PATCH,llvm-julia-tsan-custom-as)) +ifeq ($(BUILD_LLVM_CLANG),1) +$(eval $(call LLVM_PATCH,llvm-D88630-clang-cmake)) +endif +$(eval $(call LLVM_PATCH,llvm-11-D93154-globalisel-as)) +$(eval $(call LLVM_PATCH,llvm-11-D94813-mergeicmps)) +$(eval $(call LLVM_PROJ_PATCH,llvm-11-AArch64-FastIsel-bug)) +$(eval $(call LLVM_PATCH,llvm-12-D97435-AArch64-movaddrreg)) +$(eval $(call LLVM_PROJ_PATCH,llvm-11-D97571-AArch64-loh)) # remove for LLVM 13 +$(eval $(call LLVM_PROJ_PATCH,llvm-11-aarch64-addrspace)) # remove for LLVM 13 +endif # LLVM_VER 12.0 # Add a JL prefix to the version map. DO NOT REMOVE ifneq ($(LLVM_VER), svn) diff --git a/deps/patches/llvm-12-D75072-SCEV-add-type.patch b/deps/patches/llvm-12-D75072-SCEV-add-type.patch new file mode 100644 index 0000000000000..c74cd70b20e65 --- /dev/null +++ b/deps/patches/llvm-12-D75072-SCEV-add-type.patch @@ -0,0 +1,425 @@ +From 4827d22b3e297b82c7689f0fb06b38e67d92b578 Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Wed, 21 Apr 2021 12:25:07 -0400 +Subject: [PATCH] [SCEV] Record NI types in add exprs + +This fixes a case where loop-reduce introduces ptrtoint/inttoptr for +non-integral address space pointers. Over the past several years, we +have gradually improved the SCEVExpander to actually do something +sensible for non-integral pointer types. However, that obviously +relies on the expander knowing what the type of the SCEV expression is. +That is usually the case, but there is one important case where it's +not: The type of an add expression is just the type of the last operand, +so if the non-integral pointer is not the last operand, later uses of +that SCEV may not realize that the given add expression contains +non-integral pointers and may try to expand it as integers. + +One interesting observation is that we do get away with this scheme in +shockingly many cases. The reason for this is that SCEV expressions +often have an `scUnknown` pointer base, which our sort order on the +operands of add expressions sort behind basically everything else, +so it usually ends up as the last operand. + +One situation where this fails is included as a test case. This test +case was bugpoint-reduced from the issue reported at +https://github.com/JuliaLang/julia/issues/31156. What happens here +is that the pointer base is an scAddRec from an outer loop, plus an +scUnknown integer offset. By our sort order, the scUnknown gets sorted +after the scAddRec pointer base, thus making an add expression of these +two operands have integer type. This then confuses the expander, into +attempting to expand the whole thing as integers, which will obviously +fail when reaching the non-integral pointer. + +I considered a few options to solve this, but here's what I ended up +settling on: The AddExpr class gains a new subclass that explicitly +stores the type of the expression. This subclass is used whenever one +of the operands is a non-integral pointer. To reduce the impact for the +regular case (where the SCEV expression contains no non-integral +pointers), a bit flag is kept in each flag expression to indicate +whether it is of non-integral pointer type (this should give the same +answer as asking if getType() is non-integral, but performing that +query may involve a pointer chase and requires the DataLayout). For +add expressions that flag is also used to indicate whether we're using +the subclass or not. This is slightly inefficient, because it uses +the subclass even in the (not uncommon) case where the last operand +does actually accurately reflect the non-integral pointer type. However, +it didn't seem worth the extra flag bit and complexity to do this +micro-optimization. + +I had hoped that we could additionally restrict mul exprs from +containing any non-integral pointers, and also require add exprs to +only have one operand containg such pointers (but not more), but this +turned out not to work. The reason for this is that SCEV wants to +form differences between pointers, which it represents as `A + B*-1`, +so we need to allow both multiplication by `-1` and addition with +multiple non-integral pointer arguments. I'm not super happy with +that situation, but I think it exposes a more general problem with +non-integral pointers in LLVM. We don't actually have a way to express +the difference between two non-integral pointers at the IR level. +In theory this is a problem for SCEV, because it means that we can't +materialize such SCEV expression. However, in practice, these +expressions generally have the same base pointer, so SCEV will +appropriately simplify them to just the integer components. +Nevertheless it is a bit unsatisfying. Perhaps we could have an +intrinsic that takes the byte difference between two pointers to the +same allocated object (in the same sense as is used in getelementptr), +which should be a sensible operation even for non-integral pointers. +However, given the practical considerations above, that's a project +for another time. For now, simply allowing the existing pointer-diff +pattern for non-integral pointers seems to work ok. + +Differential Revision: https://reviews.llvm.org/D75072 +--- + llvm/include/llvm/Analysis/ScalarEvolution.h | 21 ++++- + .../Analysis/ScalarEvolutionExpressions.h | 81 ++++++++++++++++--- + llvm/lib/Analysis/ScalarEvolution.cpp | 41 +++++++--- + .../LoopStrengthReduce/nonintegral.ll | 35 +++++++- + 4 files changed, 155 insertions(+), 23 deletions(-) + +diff --git llvm/include/llvm/Analysis/ScalarEvolution.h llvm/include/llvm/Analysis/ScalarEvolution.h +index b3f199de2cfa..d98fbeb5dcf7 100644 +--- llvm/include/llvm/Analysis/ScalarEvolution.h ++++ llvm/include/llvm/Analysis/ScalarEvolution.h +@@ -120,6 +120,19 @@ public: + NoWrapMask = (1 << 3) - 1 + }; + ++ /// HasNonIntegralPointerFlag are bitfield indices into SubclassData. ++ /// ++ /// When constructing SCEV expressions for LLVM expressions with non-integral ++ /// pointer types, some additional processing is required to ensure that we ++ /// don't introduce any illegal transformations. However, non-integral pointer ++ /// types are a very rarely used feature, so we want to make sure to only do ++ /// such processing if they are actually used. To ensure minimal performance ++ /// impact, we memoize that fact in using these flags. ++ enum HasNonIntegralPointerFlag { ++ FlagNoNIPointers = 0, ++ FlagHasNIPointers = (1 << 3) ++ }; ++ + explicit SCEV(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, + unsigned short ExpressionSize) + : FastID(ID), SCEVType(SCEVTy), ExpressionSize(ExpressionSize) {} +@@ -156,6 +169,10 @@ public: + return ExpressionSize; + } + ++ bool hasNonIntegralPointers() const { ++ return SubclassData & FlagHasNIPointers; ++ } ++ + /// Print out the internal representation of this scalar to the specified + /// stream. This should really only be used for debugging purposes. + void print(raw_ostream &OS) const; +@@ -745,7 +762,7 @@ public: + const BasicBlock *ExitingBlock); + + /// The terms "backedge taken count" and "exit count" are used +- /// interchangeably to refer to the number of times the backedge of a loop ++ /// interchangeably to refer to the number of times the backedge of a loop + /// has executed before the loop is exited. + enum ExitCountKind { + /// An expression exactly describing the number of times the backedge has +@@ -758,7 +775,7 @@ public: + }; + + /// Return the number of times the backedge executes before the given exit +- /// would be taken; if not exactly computable, return SCEVCouldNotCompute. ++ /// would be taken; if not exactly computable, return SCEVCouldNotCompute. + /// For a single exit loop, this value is equivelent to the result of + /// getBackedgeTakenCount. The loop is guaranteed to exit (via *some* exit) + /// before the backedge is executed (ExitCount + 1) times. Note that there +diff --git llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +index 37e675f08afc..6e532b22f5b3 100644 +--- llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h ++++ llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +@@ -228,6 +228,13 @@ class Type; + return getNoWrapFlags(FlagNW) != FlagAnyWrap; + } + ++ void setHasNIPtr(bool HasNIPtr) { ++ if (HasNIPtr) ++ SubclassData |= FlagHasNIPointers; ++ else ++ SubclassData &= ~FlagHasNIPointers; ++ } ++ + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || +@@ -264,19 +271,16 @@ class Type; + + Type *Ty; + ++ protected: + SCEVAddExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scAddExpr, O, N) { +- auto *FirstPointerTypedOp = find_if(operands(), [](const SCEV *Op) { +- return Op->getType()->isPointerTy(); +- }); +- if (FirstPointerTypedOp != operands().end()) +- Ty = (*FirstPointerTypedOp)->getType(); +- else +- Ty = getOperand(0)->getType(); ++ + } + + public: +- Type *getType() const { return Ty; } ++ // Returns the type of the add expression, by looking either at the last operand ++ // or deferring to the SCEVAddNIExpr subclass. ++ Type *getType() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { +@@ -284,6 +288,46 @@ class Type; + } + }; + ++ /// This node represents an addition of some number of SCEVs, one which ++ /// is a non-integral pointer type, requiring us to know the type exactly for ++ /// correctness. ++ class SCEVAddNIExpr : public SCEVAddExpr { ++ friend class ScalarEvolution; ++ PointerType *NIType; ++ ++ SCEVAddNIExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N, ++ PointerType *NIType) ++ : SCEVAddExpr(ID, O, N), NIType(NIType) { ++ SubclassData |= FlagHasNIPointers; ++ } ++ ++ public: ++ Type *getType() const { return NIType; } ++ ++ /// Methods for support type inquiry through isa, cast, and dyn_cast: ++ static bool classof(const SCEV *S) { ++ return S->getSCEVType() == scAddExpr && S->hasNonIntegralPointers(); ++ } ++ }; ++ ++ inline Type *SCEVAddExpr::getType() const { ++ // In general, use the type of the last operand, which is likely to be a ++ // pointer type, if there is one. This doesn't usually matter, but it can ++ // help reduce casts when the expressions are expanded. In the (unusual) ++ // case that we're working with non-integral pointers, we have a subclass ++ // that stores that type explicitly. ++ if (hasNonIntegralPointers()) ++ return cast(this)->getType(); ++ ++ auto *FirstPointerTypedOp = find_if(operands(), [](const SCEV *Op) { ++ return Op->getType()->isPointerTy(); ++ }); ++ if (FirstPointerTypedOp != operands().end()) ++ return (*FirstPointerTypedOp)->getType(); ++ else ++ return getOperand(0)->getType(); ++ } ++ + /// This node represents multiplication of some number of SCEVs. + class SCEVMulExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; +@@ -293,6 +337,18 @@ class Type; + : SCEVCommutativeExpr(ID, scMulExpr, O, N) {} + + public: ++ Type *getType() const { ++ // In general, we can't form SCEVMulExprs with non-integral pointer types, ++ // but for the moment we need to allow a special case: Multiplying by ++ // -1 to be able express the difference between two pointers. In order ++ // to maintain the invariant that SCEVs with the NI flag set should have ++ // a type corresponding to the contained NI ptr, we need to return the ++ // type of the pointer here. ++ if (hasNonIntegralPointers()) ++ return getOperand(getNumOperands() - 1)->getType(); ++ return SCEVCommutativeExpr::getType(); ++ } ++ + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scMulExpr; +@@ -531,9 +587,12 @@ class Type; + /// instances owned by a ScalarEvolution. + SCEVUnknown *Next; + +- SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, +- ScalarEvolution *se, SCEVUnknown *next) : +- SCEV(ID, scUnknown, 1), CallbackVH(V), SE(se), Next(next) {} ++ SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, ScalarEvolution *se, ++ SCEVUnknown *next, bool ValueIsNIPtr) ++ : SCEV(ID, scUnknown, 1), CallbackVH(V), SE(se), Next(next) { ++ if (ValueIsNIPtr) ++ SubclassData |= FlagHasNIPointers; ++ } + + // Implement CallbackVH. + void deleted() override; +diff --git llvm/lib/Analysis/ScalarEvolution.cpp llvm/lib/Analysis/ScalarEvolution.cpp +index fe9d8297d679..1fa7b8ce1451 100644 +--- llvm/lib/Analysis/ScalarEvolution.cpp ++++ llvm/lib/Analysis/ScalarEvolution.cpp +@@ -389,12 +389,13 @@ Type *SCEV::getType() const { + case scSignExtend: + return cast(this)->getType(); + case scAddRecExpr: +- case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: + case scUMinExpr: + case scSMinExpr: + return cast(this)->getType(); ++ case scMulExpr: ++ return cast(this)->getType(); + case scAddExpr: + return cast(this)->getType(); + case scUDivExpr: +@@ -2679,16 +2680,27 @@ ScalarEvolution::getOrCreateAddExpr(ArrayRef Ops, + SCEV::NoWrapFlags Flags) { + FoldingSetNodeID ID; + ID.AddInteger(scAddExpr); +- for (const SCEV *Op : Ops) +- ID.AddPointer(Op); ++ bool HasNIPtr = false; ++ PointerType *NIPtrType = nullptr; ++ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { ++ ID.AddPointer(Ops[i]); ++ if (Ops[i]->hasNonIntegralPointers()) { ++ HasNIPtr = true; ++ NIPtrType = cast(Ops[i]->getType()); ++ } ++ } + void *IP = nullptr; + SCEVAddExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); +- S = new (SCEVAllocator) +- SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size()); ++ if (HasNIPtr) ++ S = new (SCEVAllocator) ++ SCEVAddNIExpr(ID.Intern(SCEVAllocator), O, Ops.size(), NIPtrType); ++ else ++ S = new (SCEVAllocator) ++ SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + addToLoopUseLists(S); + } +@@ -2701,8 +2713,10 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef Ops, + const Loop *L, SCEV::NoWrapFlags Flags) { + FoldingSetNodeID ID; + ID.AddInteger(scAddRecExpr); +- for (unsigned i = 0, e = Ops.size(); i != e; ++i) ++ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { ++ assert(i == 0 || !Ops[i]->hasNonIntegralPointers()); + ID.AddPointer(Ops[i]); ++ } + ID.AddPointer(L); + void *IP = nullptr; + SCEVAddRecExpr *S = +@@ -2716,6 +2730,7 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef Ops, + addToLoopUseLists(S); + } + setNoWrapFlags(S, Flags); ++ S->setHasNIPtr(Ops[0]->hasNonIntegralPointers()); + return S; + } + +@@ -2724,8 +2739,11 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef Ops, + SCEV::NoWrapFlags Flags) { + FoldingSetNodeID ID; + ID.AddInteger(scMulExpr); +- for (unsigned i = 0, e = Ops.size(); i != e; ++i) ++ bool HasNIPtr = false; ++ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { ++ HasNIPtr |= Ops[i]->hasNonIntegralPointers(); + ID.AddPointer(Ops[i]); ++ } + void *IP = nullptr; + SCEVMulExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); +@@ -2738,6 +2756,7 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef Ops, + addToLoopUseLists(S); + } + S->setNoWrapFlags(Flags); ++ S->setHasNIPtr(HasNIPtr); + return S; + } + +@@ -3615,8 +3634,11 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind, + return ExistingSCEV; + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); +- SCEV *S = new (SCEVAllocator) ++ SCEVMinMaxExpr *S = new (SCEVAllocator) + SCEVMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size()); ++ // For MinMaxExprs it's sufficient to see if the first Op has NI data, as the ++ // operands all need to be of the same type. ++ S->setHasNIPtr(Ops[0]->hasNonIntegralPointers()); + + UniqueSCEVs.InsertNode(S, IP); + addToLoopUseLists(S); +@@ -3716,8 +3738,9 @@ const SCEV *ScalarEvolution::getUnknown(Value *V) { + "Stale SCEVUnknown in uniquing map!"); + return S; + } ++ bool ValueIsNIPtr = getDataLayout().isNonIntegralPointerType(V->getType()); + SCEV *S = new (SCEVAllocator) SCEVUnknown(ID.Intern(SCEVAllocator), V, this, +- FirstUnknown); ++ FirstUnknown, ValueIsNIPtr); + FirstUnknown = cast(S); + UniqueSCEVs.InsertNode(S, IP); + return S; +diff --git llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll +index 5648e3aa74af..6936521f3a64 100644 +--- llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll ++++ llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll +@@ -2,7 +2,7 @@ + + ; Address Space 10 is non-integral. The optimizer is not allowed to use + ; ptrtoint/inttoptr instructions. Make sure that this doesn't happen +-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12" ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13" + target triple = "x86_64-unknown-linux-gnu" + + define void @japi1__unsafe_getindex_65028(i64 addrspace(10)* %arg) { +@@ -43,3 +43,36 @@ if38: ; preds = %L119 + done: ; preds = %if38 + ret void + } ++ ++; This is a bugpoint-reduced regression test - It doesn't make too much sense by itself, ++; but creates the correct SCEV expressions to reproduce the issue. See ++; https://github.com/JuliaLang/julia/issues/31156 for the original bug report. ++define void @"japi1_permutedims!_4259"(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i1 %g, i8 addrspace(13)* %base) #0 { ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++; CHECK: getelementptr i8, i8 addrspace(13)* {{.*}}, i64 {{.*}} ++top: ++ br label %L42.L46_crit_edge.us ++ ++L42.L46_crit_edge.us: ; preds = %L82.us.us.loopexit, %top ++ %value_phi11.us = phi i64 [ %a, %top ], [ %2, %L82.us.us.loopexit ] ++ %0 = sub i64 %value_phi11.us, %b ++ %1 = add i64 %0, %c ++ %spec.select = select i1 %g, i64 %d, i64 0 ++ br label %L62.us.us ++ ++L82.us.us.loopexit: ; preds = %L62.us.us ++ %2 = add i64 %e, %value_phi11.us ++ br label %L42.L46_crit_edge.us ++ ++L62.us.us: ; preds = %L62.us.us, %L42.L46_crit_edge.us ++ %value_phi21.us.us = phi i64 [ %6, %L62.us.us ], [ %spec.select, %L42.L46_crit_edge.us ] ++ %3 = add i64 %1, %value_phi21.us.us ++ %4 = getelementptr inbounds i8, i8 addrspace(13)* %base, i64 %3 ++ %5 = load i8, i8 addrspace(13)* %4, align 1 ++ %6 = add i64 %f, %value_phi21.us.us ++ br i1 %g, label %L82.us.us.loopexit, label %L62.us.us, !llvm.loop !1 ++} ++ ++!1 = distinct !{!1, !2} ++!2 = !{!"llvm.loop.isvectorized", i32 1} +-- +2.31.1 + diff --git a/deps/patches/llvm-12-D97435-AArch64-movaddrreg.patch b/deps/patches/llvm-12-D97435-AArch64-movaddrreg.patch new file mode 100644 index 0000000000000..01d49a85f1007 --- /dev/null +++ b/deps/patches/llvm-12-D97435-AArch64-movaddrreg.patch @@ -0,0 +1,164 @@ +From 3adadbab531e0d7dc17499a6570b129e87f00c77 Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Wed, 21 Apr 2021 12:38:40 -0400 +Subject: [PATCH] [Aarch64] Correct register class for pseudo instructions + +This constrains the Mov* and similar pseudo instruction to take +GPR64common register classes rather than GPR64. GPR64 includs XZR +which is invalid here, because this pseudo instructions expands +into an adrp/add pair sharing a destination register. XZR is invalid +on add and attempting to encode it will instead increment the stack +pointer causing crashes (downstream report at [1]). The test case +there reproduces on LLVM11, but I do not have a test case that +reaches this code path on main, since it is being masked by +improved dead code elimination introduced in D91513. Nevertheless, +this seems like a good thing to fix in case there are other cases +that dead code elimination doesn't clean up (e.g. if `optnone` is +used and the optimization is skipped). + +I think it would be worth auditing uses of GPR64 in pseudo +instructions to see if there are any similar issues, but I do not +have a high enough view of the backend or knowledge of the +Aarch64 architecture to do this quickly. + +[1] https://github.com/JuliaLang/julia/issues/39818 + +Reviewed By: t.p.northover + +Differential Revision: https://reviews.llvm.org/D97435 +--- + .../AArch64/AArch64ExpandPseudoInsts.cpp | 1 + + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 32 +++++++++---------- + .../GlobalISel/select-blockaddress.mir | 5 +-- + .../select-jump-table-brjt-constrain.mir | 2 +- + .../GlobalISel/select-jump-table-brjt.mir | 2 +- + 5 files changed, 22 insertions(+), 20 deletions(-) + +diff --git llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +index e57650ae60b1..612fbeb5f531 100644 +--- llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp ++++ llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +@@ -886,6 +886,7 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, + case AArch64::MOVaddrEXT: { + // Expand into ADRP + ADD. + Register DstReg = MI.getOperand(0).getReg(); ++ assert(DstReg != AArch64::XZR); + MachineInstrBuilder MIB1 = + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg) + .add(MI.getOperand(1)); +diff --git llvm/lib/Target/AArch64/AArch64InstrInfo.td llvm/lib/Target/AArch64/AArch64InstrInfo.td +index 171d3dbaa814..6fe0bd1ef168 100644 +--- llvm/lib/Target/AArch64/AArch64InstrInfo.td ++++ llvm/lib/Target/AArch64/AArch64InstrInfo.td +@@ -656,40 +656,40 @@ let isReMaterializable = 1, isCodeGenOnly = 1 in { + // removed, along with the AArch64Wrapper node. + + let AddedComplexity = 10 in +-def LOADgot : Pseudo<(outs GPR64:$dst), (ins i64imm:$addr), +- [(set GPR64:$dst, (AArch64LOADgot tglobaladdr:$addr))]>, ++def LOADgot : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), ++ [(set GPR64common:$dst, (AArch64LOADgot tglobaladdr:$addr))]>, + Sched<[WriteLDAdr]>; + + // The MOVaddr instruction should match only when the add is not folded + // into a load or store address. + def MOVaddr +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaladdr:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp tglobaladdr:$hi), + tglobaladdr:$low))]>, + Sched<[WriteAdrAdr]>; + def MOVaddrJT +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp tjumptable:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp tjumptable:$hi), + tjumptable:$low))]>, + Sched<[WriteAdrAdr]>; + def MOVaddrCP +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp tconstpool:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp tconstpool:$hi), + tconstpool:$low))]>, + Sched<[WriteAdrAdr]>; + def MOVaddrBA +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp tblockaddress:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp tblockaddress:$hi), + tblockaddress:$low))]>, + Sched<[WriteAdrAdr]>; + def MOVaddrTLS +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp tglobaltlsaddr:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp tglobaltlsaddr:$hi), + tglobaltlsaddr:$low))]>, + Sched<[WriteAdrAdr]>; + def MOVaddrEXT +- : Pseudo<(outs GPR64:$dst), (ins i64imm:$hi, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow (AArch64adrp texternalsym:$hi), ++ : Pseudo<(outs GPR64common:$dst), (ins i64imm:$hi, i64imm:$low), ++ [(set GPR64common:$dst, (AArch64addlow (AArch64adrp texternalsym:$hi), + texternalsym:$low))]>, + Sched<[WriteAdrAdr]>; + // Normally AArch64addlow either gets folded into a following ldr/str, +@@ -697,8 +697,8 @@ def MOVaddrEXT + // might appear without either of them, so allow lowering it into a plain + // add. + def ADDlowTLS +- : Pseudo<(outs GPR64:$dst), (ins GPR64:$src, i64imm:$low), +- [(set GPR64:$dst, (AArch64addlow GPR64:$src, ++ : Pseudo<(outs GPR64sp:$dst), (ins GPR64sp:$src, i64imm:$low), ++ [(set GPR64sp:$dst, (AArch64addlow GPR64sp:$src, + tglobaltlsaddr:$low))]>, + Sched<[WriteAdr]>; + +diff --git llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir +index 45012f23de62..70cb802ed3a3 100644 +--- llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir ++++ llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir +@@ -30,9 +30,10 @@ registers: + body: | + ; CHECK-LABEL: name: test_blockaddress + ; CHECK: bb.0 (%ir-block.0): +- ; CHECK: [[MOVaddrBA:%[0-9]+]]:gpr64 = MOVaddrBA target-flags(aarch64-page) blockaddress(@test_blockaddress, %ir-block.block), target-flags(aarch64-pageoff, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block) ++ ; CHECK: [[MOVaddrBA:%[0-9]+]]:gpr64common = MOVaddrBA target-flags(aarch64-page) blockaddress(@test_blockaddress, %ir-block.block), target-flags(aarch64-pageoff, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block) + ; CHECK: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @addr, target-flags(aarch64-pageoff, aarch64-nc) @addr +- ; CHECK: STRXui [[MOVaddrBA]], [[MOVaddr]], 0 :: (store 8 into @addr) ++ ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY [[MOVaddrBA]] ++ ; CHECK: STRXui [[COPY]], [[MOVaddr]], 0 :: (store 8 into @addr) + ; CHECK: BR [[MOVaddrBA]] + ; CHECK: bb.1.block (address-taken): + ; CHECK: RET_ReallyLR +diff --git llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt-constrain.mir llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt-constrain.mir +index 440a03173c83..59b8dea2d0ce 100644 +--- llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt-constrain.mir ++++ llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt-constrain.mir +@@ -30,7 +30,7 @@ body: | + ; CHECK: Bcc 8, %bb.3, implicit $nzcv + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x40000000), %bb.3(0x40000000) +- ; CHECK: [[MOVaddrJT:%[0-9]+]]:gpr64 = MOVaddrJT target-flags(aarch64-page) %jump-table.0, target-flags(aarch64-pageoff, aarch64-nc) %jump-table.0 ++ ; CHECK: [[MOVaddrJT:%[0-9]+]]:gpr64common = MOVaddrJT target-flags(aarch64-page) %jump-table.0, target-flags(aarch64-pageoff, aarch64-nc) %jump-table.0 + ; CHECK: early-clobber %6:gpr64, early-clobber %7:gpr64sp = JumpTableDest32 [[MOVaddrJT]], [[SUBREG_TO_REG]], %jump-table.0 + ; CHECK: BR %6 + ; CHECK: bb.2: +diff --git llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir +index 6b84c6d10843..b8c9a6c881da 100644 +--- llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir ++++ llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir +@@ -65,7 +65,7 @@ body: | + ; CHECK: bb.1.entry: + ; CHECK: successors: %bb.3(0x2aaaaaab), %bb.4(0x2aaaaaab), %bb.2(0x2aaaaaab) + ; CHECK: [[COPY2:%[0-9]+]]:gpr32 = COPY $wzr +- ; CHECK: [[MOVaddrJT:%[0-9]+]]:gpr64 = MOVaddrJT target-flags(aarch64-page) %jump-table.0, target-flags(aarch64-pageoff, aarch64-nc) %jump-table.0 ++ ; CHECK: [[MOVaddrJT:%[0-9]+]]:gpr64common = MOVaddrJT target-flags(aarch64-page) %jump-table.0, target-flags(aarch64-pageoff, aarch64-nc) %jump-table.0 + ; CHECK: early-clobber %18:gpr64, early-clobber %19:gpr64sp = JumpTableDest32 [[MOVaddrJT]], [[SUBREG_TO_REG]], %jump-table.0 + ; CHECK: BR %18 + ; CHECK: bb.2.sw.bb: +-- +2.31.1 + From 7f7efb101288b05d12617e789bebe1ae63ccd5ad Mon Sep 17 00:00:00 2001 From: Arun sanganal <74652697+ArunSanganal@users.noreply.github.com> Date: Wed, 21 Apr 2021 23:21:06 +0530 Subject: [PATCH 228/439] added docstring for single-quotes pair in basedocs.jl (#39609) One of the operators in #33666 that wasn't previously searchable --- base/docs/basedocs.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index bb98043994ba6..5efe97ed9debc 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -276,6 +276,19 @@ julia> z """ kw"global" +""" + ' ' + +A pair of single-quote characters delimit a [`Char`](@ref) (that is, character) literal. + +# Examples +```jldoctest +julia> 'j' +'j': ASCII/Unicode U+006A (category Ll: Letter, lowercase) +``` +""" +kw"''" + """ = From 2307f8086bb1d2780da0490be2de0b129575e74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 21 Apr 2021 20:29:42 +0200 Subject: [PATCH 229/439] Fix rational division by zero (#40551) * Fix rational division by zero * Replace `BigFloat` by `BigInt` Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- base/gmp.jl | 2 +- test/gmp.jl | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index b957ab22a4bea..90874b01977c2 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -931,7 +931,7 @@ function Base.://(x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.num) throw(DivideError()) end - return (isneg(x.num) ? -one(BigFloat) : one(BigFloat)) // y.num + return (isneg(x.num) ? -one(BigInt) : one(BigInt)) // y.num end zq = _MPQ() ccall((:__gmpq_div, :libgmp), Cvoid, diff --git a/test/gmp.jl b/test/gmp.jl index 3d7317b37bacc..1f34f67ecf1f5 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -69,6 +69,18 @@ ee = typemax(Int64) @test big(typeof(complex(x, x))) == typeof(big(complex(x, x))) end end + @testset "division" begin + oz = big(1 // 0) + zo = big(0 // 1) + + @test_throws DivideError() oz / oz + @test oz == oz / one(oz) + @test -oz == oz / (-one(oz)) + @test zero(oz) == one(oz) / oz + @test_throws DivideError() zo / zo + @test one(zo) / zo == big(1//0) + @test -one(zo) / zo == big(-1//0) + end end @testset "div, fld, mod, rem" begin for i = -10:10, j = [-10:-1; 1:10] From f103bb4543a0c1fb606d96469324bc33f064889c Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 21 Apr 2021 14:32:52 -0400 Subject: [PATCH 230/439] logging: redirect closed streams to stderr/stdout (#40423) This has the additional benefit of making the initial logger respect changes to redirect_stderr/stdout, until the user explicitly sets another stream as the logging destination. Fix #26798 Fix #38482 Replaces #26920, which provided the idea and most of the implementation Co-authored-by: Joe Petviashvili --- base/logging.jl | 20 ++++++++++++------ stdlib/Logging/src/ConsoleLogger.jl | 23 +++++++++++++++------ stdlib/Logging/src/Logging.jl | 5 ++++- test/corelogging.jl | 32 +++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/base/logging.jl b/base/logging.jl index 066523771f5fb..2404c1107e58c 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -611,21 +611,25 @@ attached to the task. """ current_logger() = current_logstate().logger +const closed_stream = IOBuffer(UInt8[]) +close(closed_stream) #------------------------------------------------------------------------------- # SimpleLogger """ - SimpleLogger(stream=stderr, min_level=Info) + SimpleLogger([stream,] min_level=Info) Simplistic logger for logging all messages with level greater than or equal to -`min_level` to `stream`. +`min_level` to `stream`. If stream is closed then messages with log level +greater or equal to `Warn` will be logged to `stderr` and below to `stdout`. """ struct SimpleLogger <: AbstractLogger stream::IO min_level::LogLevel message_limits::Dict{Any,Int} end -SimpleLogger(stream::IO=stderr, level=Info) = SimpleLogger(stream, level, Dict{Any,Int}()) +SimpleLogger(stream::IO, level=Info) = SimpleLogger(stream, level, Dict{Any,Int}()) +SimpleLogger(level=Info) = SimpleLogger(closed_stream, level) shouldlog(logger::SimpleLogger, level, _module, group, id) = get(logger.message_limits, id, 1) > 0 @@ -644,7 +648,11 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module, remaining > 0 || return end buf = IOBuffer() - iob = IOContext(buf, logger.stream) + stream = logger.stream + if !isopen(stream) + stream = level < Warn ? stdout : stderr + end + iob = IOContext(buf, stream) levelstr = level == Warn ? "Warning" : string(level) msglines = split(chomp(string(message)::String), '\n') println(iob, "┌ ", levelstr, ": ", msglines[1]) @@ -656,10 +664,10 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module, println(iob, "│ ", key, " = ", val) end println(iob, "└ @ ", _module, " ", filepath, ":", line) - write(logger.stream, take!(buf)) + write(stream, take!(buf)) nothing end -_global_logstate = LogState(SimpleLogger(Core.stderr, CoreLogging.Info)) +_global_logstate = LogState(SimpleLogger()) end # CoreLogging diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 2a96b08eb5ed2..04c56c6dbfaae 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license """ - ConsoleLogger(stream=stderr, min_level=Info; meta_formatter=default_metafmt, + ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt, show_limited=true, right_justify=0) Logger with formatting optimized for readability in a text console, for example @@ -30,12 +30,19 @@ struct ConsoleLogger <: AbstractLogger right_justify::Int message_limits::Dict{Any,Int} end -function ConsoleLogger(stream::IO=stderr, min_level=Info; +function ConsoleLogger(stream::IO, min_level=Info; meta_formatter=default_metafmt, show_limited=true, right_justify=0) ConsoleLogger(stream, min_level, meta_formatter, show_limited, right_justify, Dict{Any,Int}()) end +function ConsoleLogger(min_level=Info; + meta_formatter=default_metafmt, show_limited=true, + right_justify=0) + ConsoleLogger(closed_stream, min_level, meta_formatter, + show_limited, right_justify, Dict{Any,Int}()) +end + shouldlog(logger::ConsoleLogger, level, _module, group, id) = get(logger.message_limits, id, 1) > 0 @@ -110,12 +117,16 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Generate a text representation of the message and all key value pairs, # split into lines. msglines = [(indent=0, msg=l) for l in split(chomp(string(message)::String), '\n')] - dsize = displaysize(logger.stream)::Tuple{Int,Int} + stream = logger.stream + if !isopen(stream) + stream = level < Warn ? stdout : stderr + end + dsize = displaysize(stream)::Tuple{Int,Int} nkwargs = length(kwargs)::Int if nkwargs > hasmaxlog valbuf = IOBuffer() rows_per_value = max(1, dsize[1] ÷ (nkwargs + 1 - hasmaxlog)) - valio = IOContext(IOContext(valbuf, logger.stream), + valio = IOContext(IOContext(valbuf, stream), :displaysize => (rows_per_value, dsize[2] - 5), :limit => logger.show_limited) for (key, val) in kwargs @@ -136,7 +147,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String} minsuffixpad = 2 buf = IOBuffer() - iob = IOContext(buf, logger.stream) + iob = IOContext(buf, stream) nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) + msglines[end].indent + termlength(msglines[end].msg) + (isempty(suffix) ? 0 : length(suffix)+minsuffixpad) @@ -164,6 +175,6 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module println(iob) end - write(logger.stream, take!(buf)) + write(stream, take!(buf)) nothing end diff --git a/stdlib/Logging/src/Logging.jl b/stdlib/Logging/src/Logging.jl index b44b8ae67473c..a9d86d9bd4418 100644 --- a/stdlib/Logging/src/Logging.jl +++ b/stdlib/Logging/src/Logging.jl @@ -29,6 +29,9 @@ for sym in [ @eval const $sym = Base.CoreLogging.$sym end +using Base.CoreLogging: + closed_stream + export AbstractLogger, LogLevel, @@ -56,7 +59,7 @@ include("ConsoleLogger.jl") # handle_message, shouldlog, min_enabled_level, catch_exceptions, function __init__() - global_logger(ConsoleLogger(stderr)) + global_logger(ConsoleLogger()) end end diff --git a/test/corelogging.jl b/test/corelogging.jl index 89f69be438810..698209661456b 100644 --- a/test/corelogging.jl +++ b/test/corelogging.jl @@ -341,15 +341,43 @@ end String(take!(io)) end + function genmsg_out(level, message, _module, filepath, line; kws...) + fname = tempname() + f = open(fname, "w") + logger = SimpleLogger() + redirect_stdout(f) do + handle_message(logger, level, message, _module, :group, :id, + filepath, line; kws...) + end + close(f) + buf = read(fname) + rm(fname) + String(buf) + end + + function genmsg_err(level, message, _module, filepath, line; kws...) + fname = tempname() + f = open(fname, "w") + logger = SimpleLogger() + redirect_stderr(f) do + handle_message(logger, level, message, _module, :group, :id, + filepath, line; kws...) + end + close(f) + buf = read(fname) + rm(fname) + String(buf) + end + # Simple - @test genmsg(Info, "msg", Main, "some/path.jl", 101) == + @test genmsg_out(Info, "msg", Main, "some/path.jl", 101) == """ ┌ Info: msg └ @ Main some/path.jl:101 """ # Multiline message - @test genmsg(Warn, "line1\nline2", Main, "some/path.jl", 101) == + @test genmsg_err(Warn, "line1\nline2", Main, "some/path.jl", 101) == """ ┌ Warning: line1 │ line2 From e490918ee08531e974a7637f156d02deb1823691 Mon Sep 17 00:00:00 2001 From: "John M. Kuhn" Date: Wed, 21 Apr 2021 14:34:20 -0400 Subject: [PATCH 231/439] Document splitext() with multiple extensions (#40554) --- base/path.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/base/path.jl b/base/path.jl index 88d050e750118..c56230784f01d 100644 --- a/base/path.jl +++ b/base/path.jl @@ -188,8 +188,8 @@ basename(path::AbstractString) = splitdir(path)[2] """ splitext(path::AbstractString) -> (AbstractString, AbstractString) -If the last component of a path contains a dot, split the path into everything before the -dot and everything including and after the dot. Otherwise, return a tuple of the argument +If the last component of a path contains one or more dots, split the path into everything before the +last dot and everything including and after the dot. Otherwise, return a tuple of the argument unmodified and the empty string. "splitext" is short for "split extension". # Examples @@ -197,8 +197,11 @@ unmodified and the empty string. "splitext" is short for "split extension". julia> splitext("/home/myuser/example.jl") ("/home/myuser/example", ".jl") -julia> splitext("/home/myuser/example") -("/home/myuser/example", "") +julia> splitext("/home/myuser/example.tar.gz") +("/home/myuser/example.tar", ".gz") + +julia> splitext("/home/my.user/example") +("/home/my.user/example", "") ``` """ function splitext(path::String) From d294b25d7022d995f369e2623c6329c03674c8d4 Mon Sep 17 00:00:00 2001 From: jamesonquinn Date: Wed, 21 Apr 2021 14:35:29 -0400 Subject: [PATCH 232/439] docs: add FAQ on parametric invariance (#21261) --- doc/src/manual/faq.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 7d72d0a0208d9..6b065bb58db7e 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -741,6 +741,32 @@ julia> remotecall_fetch(anon_bar, 2) 1 ``` +## Troubleshooting "method not matched": parametric type invariance and `MethodError`s + +### Why doesn't it work to declare `foo(bar::Vector{Real}) = 42` and then call `foo([1])`? + +As you'll see if you try this, the result is a `MethodError`: + +```jldoctest +julia> foo(x::Vector{Real}) = 42 +foo (generic function with 1 method) + +julia> foo([1]) +ERROR: MethodError: no method matching foo(::Vector{Int64}) +Closest candidates are: + foo(!Matched::Vector{Real}) at none:1 +``` + +This is because `Vector{Real}` is not a supertype of `Vector{Int}`! You can solve this problem with something +like `foo(bar::Vector{T}) where {T<:Real}` (or the short form `foo(bar::Vector{<:Real})` if the static parameter `T` +is not needed in the body of the function). The `T` is a wild card: you first specify that it must be a +subtype of Real, then specify the function takes a Vector of with elements of that type. + +This same issue goes for any composite type `Comp`, not just `Vector`. If `Comp` has a parameter declared of +type `Y`, then another type `Comp2` with a parameter of type `X<:Y` is not a subtype of `Comp`. This is +type-invariance (by contrast, Tuple is type-covariant in its parameters). See [Parametric Composite +Types](@ref man-parametric-composite-types) for more explanation of these. + ### Why does Julia use `*` for string concatenation? Why not `+` or something else? The [main argument](@ref man-concatenation) against `+` is that string concatenation is not From 33e9d3728826e00e4cb23365c9d7e4dad7869222 Mon Sep 17 00:00:00 2001 From: Bob Cassels Date: Wed, 21 Apr 2021 14:37:18 -0400 Subject: [PATCH 233/439] docs: provide more detail on some noteworthy differences with Common Lisp (#36685) --- doc/src/manual/noteworthy-differences.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index d19c774f044b0..270489ed7a9ee 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -353,7 +353,13 @@ For users coming to Julia from R, these are some noteworthy differences: - The typical Julia workflow for prototyping also uses continuous manipulation of the image, implemented with the [Revise.jl](https://github.com/timholy/Revise.jl) package. -- Bignums are supported, but conversion is not automatic; ordinary integers [overflow](@ref faq-integer-arithmetic). +- For performance, Julia prefers that operations have [type stability](@ref man-type-stability). Where Common Lisp abstracts away from the underlying machine operations, Julia cleaves closer to them. For example: + - Integer division using `/` always returns a floating-point result, even if the computation is exact. + - `//` always returns a rational result + - `÷` always returns a (truncated) integer result + - Bignums are supported, but conversion is not automatic; ordinary integers [overflow](@ref faq-integer-arithmetic). + - Complex numbers are supported, but to get complex results, [you need complex inputs](@ref faq-domain-errors). + - There are multiple Complex and Rational types, with different component types. - Modules (namespaces) can be hierarchical. [`import`](@ref) and [`using`](@ref) have a dual role: they load the code and make it available in the namespace. `import` for only the module name is possible (roughly equivalent to `ASDF:LOAD-OP`). Slot names don't need to be exported separately. Global variables can't be assigned to from outside the module (except with `eval(mod, :(var = val))` as an escape hatch). From 64927510e614457ff8d5150edd06432d73c87a48 Mon Sep 17 00:00:00 2001 From: Rogerluo Date: Wed, 21 Apr 2021 14:45:10 -0400 Subject: [PATCH 234/439] allow creating an undef Diagonal (#38282) --- stdlib/LinearAlgebra/src/diagonal.jl | 7 +++++++ stdlib/LinearAlgebra/test/diagonal.jl | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index e4a1899e16770..06bda6495dd0f 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -63,6 +63,13 @@ AbstractMatrix{T}(D::Diagonal) where {T} = Diagonal{T}(D) Matrix(D::Diagonal) = diagm(0 => D.diag) Array(D::Diagonal) = Matrix(D) +""" + Diagonal{T}(undef, n) + +Construct an uninitialized `Diagonal{T}` of length `n`. See `undef`. +""" +Diagonal{T}(::UndefInitializer, n::Integer) where T = Diagonal(Vector{T}(undef, n)) + # For D<:Diagonal, similar(D[, neweltype]) should yield a Diagonal matrix. # On the other hand, similar(D, [neweltype,] shape...) should yield a sparse matrix. # The first method below effects the former, and the second the latter. diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 0ae2920fc0e86..ad2b9e8682077 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -744,6 +744,10 @@ end @test dot(zeros(Int32, 0), Diagonal(zeros(Int, 0)), zeros(Int16, 0)) === 0 end +@testset "Diagonal(undef)" begin + d = Diagonal{Float32}(undef, 2) + @test length(d.diag) == 2 +end @testset "permutedims (#39447)" begin for D in (Diagonal(zeros(5)), Diagonal(zeros(5) .+ 1im), Diagonal([[1,2],[3,4]])) From 9418acc1e10f1fe389e26c4676f566578e78fa4c Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Wed, 21 Apr 2021 20:47:46 +0200 Subject: [PATCH 235/439] Add docstring for keys(::AbstractArray) (#36073) This is helpful for users, and it matters because some Base functions may rely on these guarantees for their correct behavior (e.g. `hash`). Co-authored-by: Matt Bauman --- base/abstractarray.jl | 13 +++++++++++++ doc/src/base/arrays.md | 1 + 2 files changed, 14 insertions(+) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 45a6118412712..a5782b99e581c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -119,6 +119,19 @@ axes1(iter) = oneto(length(iter)) unsafe_indices(A) = axes(A) unsafe_indices(r::AbstractRange) = (oneto(unsafe_length(r)),) # Ranges use checked_sub for size +""" + keys(a::AbstractArray) + +Return an efficient array describing all valid indices for `a` arranged in the shape of `a` itself. + +They keys of 1-dimensional arrays (vectors) are integers, whereas all other N-dimensional +arrays use [`CartesianIndex`](@ref) to describe their locations. Often the special array +types [`LinearIndices`](@ref) and [`CartesianIndices`](@ref) are used to efficiently +represent these arrays of integers and `CartesianIndex`es, respectively. + +Note that the `keys` of an array might not be the most efficient index type; for maximum +performance use [`eachindex`](@ref) instead. +""" keys(a::AbstractArray) = CartesianIndices(axes(a)) keys(a::AbstractVector) = LinearIndices(a) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index f8c014677f6c9..0493ae1e35e72 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -52,6 +52,7 @@ Base.size Base.axes(::Any) Base.axes(::AbstractArray, ::Any) Base.length(::AbstractArray) +Base.keys(::AbstractArray) Base.eachindex Base.IndexStyle Base.IndexLinear From 770faac96c678fe03979d8c132ac7474beae5b00 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 21 Apr 2021 20:48:24 +0200 Subject: [PATCH 236/439] fetch is a noop when on the same worker (#19044) I was quite confused by this example, since I didn't realize that there is a `getindex(f::Future, args...) = getindex(fetch(f), args...)`. Because of this I misinterpreted the example (my first conclusion: `remote_call` must magically unpack the `Future`). Also, it didn't really make clear, that fetch turns into a noop if applied to a `Future` from the same worker. I tried to add this information in a concise way. --- doc/src/manual/distributed-computing.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index 6e3231a76ed1a..16f57314e945b 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -80,10 +80,18 @@ you read from a remote object to obtain data needed by the next local operation. but is more efficient. ```julia-repl -julia> remotecall_fetch(getindex, 2, r, 1, 1) +julia> remotecall_fetch(r-> fetch(r)[1, 1], 2, r) 0.18526337335308085 ``` +This fetches the array on worker 2 and returns the first value. Note, that `fetch` doesn't move any data in +this case, since it's executed on the worker that owns the array. One can also write: + +```julia-repl +julia> remotecall_fetch(getindex, 2, r, 1, 1) +0.10824216411304866 +``` + Remember that [`getindex(r,1,1)`](@ref) is [equivalent](@ref man-array-indexing) to `r[1,1]`, so this call fetches the first element of the future `r`. From ae1aa16bc0ee608568d799e25620ba9580110f9b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 21 Apr 2021 14:50:58 -0400 Subject: [PATCH 237/439] process: make SIGPIPE an always failure (#39574) This error code does not exist on Windows, so any code that relied on this was broken (would fail this test) on that platform already. In most cases, it was actually a serious error too, such as `cp -v` or `tar -v`, which will indeed fail midway and give corrupt results if you do not read their output to completion! Reverts #1469, in essence --- base/process.jl | 2 +- test/spawn.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/process.jl b/base/process.jl index 0c7db8a405d20..e7a460b0e8ead 100644 --- a/base/process.jl +++ b/base/process.jl @@ -476,7 +476,7 @@ function test_success(proc::Process) #TODO: this codepath is not currently tested throw(_UVError("could not start process " * repr(proc.cmd), proc.exitcode)) end - return proc.exitcode == 0 && (proc.termsignal == 0 || proc.termsignal == SIGPIPE) + return proc.exitcode == 0 && proc.termsignal == 0 end function success(x::Process) diff --git a/test/spawn.jl b/test/spawn.jl index b2111fed07378..75c7252ab673e 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -55,8 +55,8 @@ out = read(`$echocmd hello` & `$echocmd world`, String) @test (run(`$printfcmd " \033[34m[stdio passthrough ok]\033[0m\n"`); true) -# Test for SIGPIPE being treated as normal termination (throws an error if broken) -Sys.isunix() && run(pipeline(yescmd, `head`, devnull)) +# Test for SIGPIPE being a failure condition +@test_throws ProcessFailedException run(pipeline(yescmd, `head`, devnull)) let p = run(pipeline(yescmd, devnull), wait=false) t = @async kill(p) From 7fe05db29340aa42c280290ffc922d8dc0e20c72 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 21 Apr 2021 15:06:18 -0400 Subject: [PATCH 238/439] remove some exports from Broadcast (#40543) It seems like these were unintentional (and undocumented). Refs #26919. --- base/Base.jl | 3 ++- base/broadcast.jl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index f92cd4e1c3c08..df304f6b87a67 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -216,7 +216,8 @@ include("multidimensional.jl") include("broadcast.jl") using .Broadcast -using .Broadcast: broadcasted, broadcasted_kwsyntax, materialize, materialize! +using .Broadcast: broadcasted, broadcasted_kwsyntax, materialize, materialize!, + broadcast_preserving_zero_d, andand, oror # missing values include("missing.jl") diff --git a/base/broadcast.jl b/base/broadcast.jl index fd3fcba74fb57..4c3f91c50638f 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -11,7 +11,7 @@ using .Base.Cartesian using .Base: Indices, OneTo, tail, to_shape, isoperator, promote_typejoin, @pure, _msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, unalias import .Base: copy, copyto!, axes -export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, broadcast_preserving_zero_d, BroadcastFunction, andand, oror +export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, BroadcastFunction ## Computing the result's axes: deprecated name const broadcast_axes = axes From 50400fbb869c9280c1241447c8417efe6a34d29b Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Thu, 22 Apr 2021 08:42:38 +0200 Subject: [PATCH 239/439] Doc: Mention that dropdims'ed array shares memory (#40544) Co-authored-by: Jameson Nash Co-authored-by: Michael Abbott <32575566+mcabbott@users.noreply.github.com> --- base/abstractarraymath.jl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 3545d33ec5cf5..fc1adf90d7d6e 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -48,9 +48,13 @@ _sub(t::Tuple, s::Tuple) = _sub(tail(t), tail(s)) """ dropdims(A; dims) -Remove the dimensions specified by `dims` from array `A`. -Elements of `dims` must be unique and within the range `1:ndims(A)`. -`size(A,i)` must equal 1 for all `i` in `dims`. +Return an array with the same data as `A`, but with the dimensions specified by +`dims` removed. `size(A,d)` must equal 1 for every `d` in `dims`, +and repeated dimensions or numbers outside `1:ndims(A)` are forbidden. + +The result shares the same underlying data as `A`, such that the +result is mutable if and only if `A` is mutable, and setting elements of one +alters the values of the other. See also: [`reshape`](@ref), [`vec`](@ref). @@ -62,11 +66,17 @@ julia> a = reshape(Vector(1:4),(2,2,1,1)) 1 3 2 4 -julia> dropdims(a; dims=3) +julia> b = dropdims(a; dims=3) 2×2×1 Array{Int64, 3}: [:, :, 1] = 1 3 2 4 + +julia> b[1,1,1] = 5; a +2×2×1×1 Array{Int64, 4}: +[:, :, 1, 1] = + 5 3 + 2 4 ``` """ dropdims(A; dims) = _dropdims(A, dims) From 1fbb5367575592ee179b6d165c732a9319536c92 Mon Sep 17 00:00:00 2001 From: Rik Huijzer Date: Thu, 22 Apr 2021 19:33:28 +0200 Subject: [PATCH 240/439] Improve type stability for tryparse VersionNumber (#40557) Co-authored-by: Simeon Schaub --- base/version.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/version.jl b/base/version.jl index f3dda52c4ea10..77676f80e3676 100644 --- a/base/version.jl +++ b/base/version.jl @@ -107,7 +107,7 @@ end function tryparse(::Type{VersionNumber}, v::AbstractString) v == "∞" && return typemax(VersionNumber) - m = match(VERSION_REGEX, v) + m = match(VERSION_REGEX, String(v)::String) m === nothing && return nothing major, minor, patch, minus, prerl, plus, build = m.captures major = parse(VInt, major::AbstractString) From 4f271b17b92b9614318d72ef79c519157d578474 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 22 Apr 2021 14:36:58 -0400 Subject: [PATCH 241/439] change some `::AbstractString` fields to `::String` (#40569) --- base/array.jl | 2 +- base/channels.jl | 2 +- base/compiler/validation.jl | 2 +- base/errorshow.jl | 2 +- base/io.jl | 2 +- base/iostream.jl | 2 +- base/libuv.jl | 2 +- base/meta.jl | 2 +- base/missing.jl | 2 +- base/simdloop.jl | 2 +- base/version_git.sh | 8 ++++---- stdlib/Mmap/src/Mmap.jl | 2 +- stdlib/SuiteSparse/src/cholmod_h.jl | 2 +- stdlib/SuiteSparse/src/umfpack.jl | 2 +- stdlib/Test/test/runtests.jl | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/base/array.jl b/base/array.jl index c17d832d391f1..febbf4fb351cf 100644 --- a/base/array.jl +++ b/base/array.jl @@ -9,7 +9,7 @@ The objects called do not have matching dimensionality. Optional argument `msg` descriptive error string. """ struct DimensionMismatch <: Exception - msg::AbstractString + msg::String end DimensionMismatch() = DimensionMismatch("") diff --git a/base/channels.jl b/base/channels.jl index 3b171ede0699e..1557504bbe21e 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -295,7 +295,7 @@ function close_chnl_on_taskdone(t::Task, c::Channel) end struct InvalidStateException <: Exception - msg::AbstractString + msg::String state::Symbol end diff --git a/base/compiler/validation.jl b/base/compiler/validation.jl index 751b594130ad2..f6b89f8f5cd04 100644 --- a/base/compiler/validation.jl +++ b/base/compiler/validation.jl @@ -51,7 +51,7 @@ const SIGNATURE_NARGS_MISMATCH = "method signature does not match number of meth const SLOTNAMES_NARGS_MISMATCH = "CodeInfo for method contains fewer slotnames than the number of method arguments" struct InvalidCodeError <: Exception - kind::AbstractString + kind::String meta::Any end InvalidCodeError(kind::AbstractString) = InvalidCodeError(kind, nothing) diff --git a/base/errorshow.jl b/base/errorshow.jl index e52fde76ab96e..ceca8b268e42b 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -9,7 +9,7 @@ This method is used to display the exception after a call to [`throw`](@ref). # Examples ```jldoctest julia> struct MyException <: Exception - msg::AbstractString + msg::String end julia> function Base.showerror(io::IO, err::MyException) diff --git a/base/io.jl b/base/io.jl index dc588a8efd0e9..44fe54ff1df37 100644 --- a/base/io.jl +++ b/base/io.jl @@ -15,7 +15,7 @@ struct EOFError <: Exception end A system call failed with an error code (in the `errno` global variable). """ struct SystemError <: Exception - prefix::AbstractString + prefix::String errnum::Int32 extrainfo SystemError(p::AbstractString, e::Integer, extrainfo) = new(p, e, extrainfo) diff --git a/base/iostream.jl b/base/iostream.jl index 35255752bd1b5..98f15fd8a7db7 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -13,7 +13,7 @@ Mostly used to represent files returned by [`open`](@ref). mutable struct IOStream <: IO handle::Ptr{Cvoid} ios::Array{UInt8,1} - name::AbstractString + name::String mark::Int64 lock::ReentrantLock _dolock::Bool diff --git a/base/libuv.jl b/base/libuv.jl index 82298516f4a1b..c63045f4b1b68 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -74,7 +74,7 @@ end ## Libuv error handling ## struct IOError <: Exception - msg::AbstractString + msg::String code::Int32 IOError(msg::AbstractString, code::Integer) = new(msg, code) end diff --git a/base/meta.jl b/base/meta.jl index 98bbcc8cdd358..af170707874af 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -188,7 +188,7 @@ The expression passed to the [`parse`](@ref) function could not be interpreted a expression. """ struct ParseError <: Exception - msg::AbstractString + msg::String end function _parse_string(text::AbstractString, filename::AbstractString, diff --git a/base/missing.jl b/base/missing.jl index 80b02015266ce..f061bd08d52e0 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -12,7 +12,7 @@ where it is not supported. The error message, in the `msg` field may provide more specific details. """ struct MissingException <: Exception - msg::AbstractString + msg::String end showerror(io::IO, ex::MissingException) = diff --git a/base/simdloop.jl b/base/simdloop.jl index e0b6d89d97277..29e2382cf39aa 100644 --- a/base/simdloop.jl +++ b/base/simdloop.jl @@ -8,7 +8,7 @@ export @simd, simd_outer_range, simd_inner_length, simd_index # Error thrown from ill-formed uses of @simd struct SimdError <: Exception - msg::AbstractString + msg::String end # Parse iteration space expression diff --git a/base/version_git.sh b/base/version_git.sh index d2ac9cb6058a7..c46021097995e 100644 --- a/base/version_git.sh +++ b/base/version_git.sh @@ -5,11 +5,11 @@ echo "# This file was autogenerated in base/version_git.sh" echo "struct GitVersionInfo" -echo " commit::AbstractString" -echo " commit_short::AbstractString" -echo " branch::AbstractString" +echo " commit::String" +echo " commit_short::String" +echo " branch::String" echo " build_number::Int" -echo " date_string::AbstractString" +echo " date_string::String" echo " tagged_commit::Bool" echo " fork_master_distance::Int" echo " fork_master_timestamp::Float64" diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index 9a9d795a5aa17..6919421b92277 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -13,7 +13,7 @@ const PAGESIZE = Int(Sys.isunix() ? ccall(:jl_getpagesize, Clong, ()) : ccall(:j # for mmaps not backed by files mutable struct Anonymous <: IO - name::AbstractString + name::String readonly::Bool create::Bool end diff --git a/stdlib/SuiteSparse/src/cholmod_h.jl b/stdlib/SuiteSparse/src/cholmod_h.jl index 26bb046b45dfc..08b8464238a59 100644 --- a/stdlib/SuiteSparse/src/cholmod_h.jl +++ b/stdlib/SuiteSparse/src/cholmod_h.jl @@ -71,7 +71,7 @@ const VTypes = Union{ComplexF64, Float64} const VRealTypes = Union{Float64} struct CHOLMODException <: Exception - msg::AbstractString + msg::String end macro isok(A) diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl index a6e0cf54d4b23..4d6593a34aad9 100644 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -18,7 +18,7 @@ import ..increment, ..increment!, ..decrement, ..decrement! include("umfpack_h.jl") struct MatrixIllConditionedException <: Exception - msg::AbstractString + msg::String end function umferror(status::Integer) diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 88179ebbfb554..1b99fcf4a66e2 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -503,7 +503,7 @@ import Test: record, finish using Test: get_testset_depth, get_testset using Test: AbstractTestSet, Result, Pass, Fail, Error struct CustomTestSet <: Test.AbstractTestSet - description::AbstractString + description::String foo::Int results::Vector # constructor takes a description string and options keyword arguments From 2c88fb7d1f308896b68c97e118088c10ea077086 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 22 Apr 2021 11:52:06 -0700 Subject: [PATCH 242/439] Document assignment destructuring (#30579) * Document assignment destructuring * Add reference to slurping assignment (#37410) * mention swapping variables and other kinds of LHS Co-authored-by: Jameson Nash Co-authored-by: Simeon Schaub --- base/tuple.jl | 5 +- doc/src/manual/functions.md | 103 +++++++++++++++++++++++++++++++----- doc/src/manual/variables.md | 2 +- 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index 55c00084c3c63..6d0ab5157f4c7 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -104,8 +104,9 @@ state `itr_state`. Return a `Tuple`, if `collection` itself is a `Tuple`, a subt `AbstractVector`, if `collection` is an `AbstractArray`, a subtype of `AbstractString` if `collection` is an `AbstractString`, and an arbitrary iterator, falling back to `Iterators.rest(collection[, itr_state])`, otherwise. -Can be overloaded for user-defined collection types to customize the behavior of slurping -in assignments, like `a, b... = collection`. + +Can be overloaded for user-defined collection types to customize the behavior of [slurping +in assignments](@ref destructuring-assignment), like `a, b... = collection`. !!! compat "Julia 1.6" `Base.rest` requires at least Julia 1.6. diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 5d1d649b75062..bfc02cbf5cba4 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -352,12 +352,26 @@ Named tuples are very similar to tuples, except that fields can additionally be using dot syntax (`x.a`) in addition to the regular indexing syntax (`x[1]`). -## Multiple Return Values +## [Destructuring Assignment and Multiple Return Values](@id destructuring-assignment) -In Julia, one returns a tuple of values to simulate returning multiple values. However, tuples -can be created and destructured without needing parentheses, thereby providing an illusion that -multiple values are being returned, rather than a single tuple value. For example, the following -function returns a pair of values: +A comma-separated list of variables (optionally wrapped in parentheses) can appear on the +left side of an assignment: the value on the right side is _destructured_ by iterating +over and assigning to each variable in turn: + +```jldoctest +julia> (a,b,c) = 1:3 +1:3 + +julia> b +2 +``` + +The value on the right should be an iterator (see [Iteration interface](@ref man-interface-iteration)) +at least as long as the number of variables on the left (any excess elements of the +iterator are ignored). + +This can be used to return multiple values from functions by returning a tuple or +other iterable value. For example, the following function returns two values: ```jldoctest foofunc julia> function foo(a,b) @@ -374,8 +388,7 @@ julia> foo(2,3) (5, 6) ``` -A typical usage of such a pair of return values, however, extracts each value into a variable. -Julia supports simple tuple "destructuring" that facilitates this: +Destructuring assignment extracts each value into a variable: ```jldoctest foofunc julia> x, y = foo(2,3) @@ -388,15 +401,79 @@ julia> y 6 ``` -You can also return multiple values using the `return` keyword: +Another common use is for swapping variables: +```jldoctest foofunc +julia> y, x = x, y +(5, 6) -```julia -function foo(a,b) - return a+b, a*b -end +julia> x +6 + +julia> y +5 +``` + +If only a subset of the elements of the iterator are required, a common convention is to assign ignored elements to a variable +consisting of only underscores `_` (which is an otherwise invalid variable name, see +[Allowed Variable Names](@ref man-allowed-variable-names)): + +```jldoctest +julia> _, _, _, d = 1:10 +1:10 + +julia> d +4 +``` + +Other valid left-hand side expressions can be used as elements of the assignment list, which will call [`setindex!`](@ref) or [`setproperty!`](@ref), or recursively destructure individual elements of the iterator: + +```jldoctest +julia> X = zeros(3); + +julia> X[1], (a,b) = (1, (2, 3)) +(1, (2, 3)) + +julia> X +3-element Vector{Float64}: + 1.0 + 0.0 + 0.0 + +julia> a +2 + +julia> b +3 +``` + +!!! compat "Julia 1.6" + `...` with assignment requires Julia 1.6 + +If the last symbol in the assignment list is suffixed by `...` (known as _slurping_), then +it will be assigned a collection or lazy iterator of the remaining elements of the +right-hand side iterator: + +```jldoctest +julia> a, b... = "hello" +"hello" + +julia> a +'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase) + +julia> b +"ello" + +julia> a, b... = Iterators.map(abs2, 1:4) +Base.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4) + +julia> a +1 + +julia> b +Base.Iterators.Rest{Base.Generator{UnitRange{Int64}, typeof(abs2)}, Int64}(Base.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4), 1) ``` -This has the exact same effect as the previous definition of `foo`. +See [`Base.rest`](@ref) for details on the precise handling and customization for specific iterators. ## Argument destructuring diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 3711264d84382..e8e60a15d54c1 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -90,7 +90,7 @@ julia> sqrt = 4 ERROR: cannot assign a value to variable Base.sqrt from module Main ``` -## Allowed Variable Names +## [Allowed Variable Names](@id man-allowed-variable-names) Variable names must begin with a letter (A-Z or a-z), underscore, or a subset of Unicode code points greater than 00A0; in particular, [Unicode character categories](http://www.fileformat.info/info/unicode/category/index.htm) From 15a44e9c4cb9bdf6800ccb2850a92b3874ba2a9d Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 22 Apr 2021 13:45:28 -0700 Subject: [PATCH 243/439] Fix `llvm-tools` when installing with `LLVM_ASSERTS=1` (#40447) When installing with `LLVM_ASSERTS=1`, we need our `llvm-tools` to be an assert build as well. --- contrib/refresh_checksums.mk | 4 +- deps/Versions.make | 1 + deps/checksums/llvm | 290 +++++++++++++++++++++-------------- deps/llvm.mk | 2 + 4 files changed, 180 insertions(+), 117 deletions(-) diff --git a/contrib/refresh_checksums.mk b/contrib/refresh_checksums.mk index 12e3d4825ae42..c6c358daa699e 100644 --- a/contrib/refresh_checksums.mk +++ b/contrib/refresh_checksums.mk @@ -73,9 +73,11 @@ $(foreach project,$(BB_GCC_EXPANDED_PROJECTS),$(foreach triplet,$(TRIPLETS),$(fo $(foreach project,$(BB_CXX_EXPANDED_PROJECTS),$(foreach triplet,$(NON_CLANG_TRIPLETS),$(foreach cxxstring_abi,cxx11 cxx03,$(eval $(call checksum_dep,$(project),$(triplet)-$(cxxstring_abi)))))) $(foreach project,$(BB_CXX_EXPANDED_PROJECTS),$(foreach triplet,$(CLANG_TRIPLETS),$(eval $(call checksum_dep,$(project),$(triplet))))) -# Special libLLVM_asserts_jll targets +# Special libLLVM_asserts_jll/LLVM_assert_jll targets $(foreach triplet,$(NON_CLANG_TRIPLETS),$(foreach cxxstring_abi,cxx11 cxx03,$(eval $(call checksum_dep,llvm,$(triplet)-$(cxxstring_abi),assert)))) +$(foreach triplet,$(NON_CLANG_TRIPLETS),$(foreach cxxstring_abi,cxx11 cxx03,$(eval $(call checksum_dep,llvm-tools,$(triplet)-$(cxxstring_abi),assert)))) $(foreach triplet,$(CLANG_TRIPLETS),$(eval $(call checksum_dep,llvm,$(triplet),assert))) +$(foreach triplet,$(CLANG_TRIPLETS),$(eval $(call checksum_dep,llvm-tools,$(triplet),assert))) # External stdlibs checksum-stdlibs: diff --git a/deps/Versions.make b/deps/Versions.make index 8501acd31f4f7..93d7be4a932ec 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -51,6 +51,7 @@ LLVM_JLL_NAME := libLLVM # LLVM_tools (downloads LLVM_jll to get things like `lit` and `opt`) LLVM_TOOLS_JLL_NAME := LLVM LLVM_TOOLS_JLL_VER := 11.0.1+3 +LLVM_TOOLS_ASSERT_JLL_VER := 11.0.1+3 # LLVM libunwind LLVMUNWIND_VER := 11.0.1 diff --git a/deps/checksums/llvm b/deps/checksums/llvm index 69bacfdf5a928..296796224f288 100644 --- a/deps/checksums/llvm +++ b/deps/checksums/llvm @@ -1,61 +1,119 @@ -libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/1468270825363bffb3d99d3ca9216d7d -libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/b94c1273553204440b5f51a3b1fa8c96ad8eae2090e50c3cf10fed44f960e5d0a6c95d967b7e006f842d550cc59b06ed8585962399772e1c2d6d1e6cf7686567 -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/5ea96996524ebc1c69794d7e9ba2b252 -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/8fd7d5debae5277a5d099c24c195ed1c110f95169bc05ebe42fbb697683f2012a95507b682dd978a25918582dcfd548233d26a3e74a3098e85758dd63b5ba98e -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/49e5dedbdcad40a5966aca51c8913d3b -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/107a57a298416760c2f806901080963c2b1b3d09f16bef698db6e28b084c36f86796956deff096b4e014a61b29319e1fe1ed95f6a807ab3f1a6350288f85160a -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/7d594f4af283181513816fe50d299861 -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/f074bca4a57c827c16558783b7efe8d31f12d4a0500a374ed9303a4beba2e848343d9d66da4bd0643c8df10004a6b7a9074a0f99bdba6e2b7eae939a892c7a0f -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/1328f6c829ddc5361e5217aa9d2ba1f0 -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/238fc6e8eeed72f6fc23b9ea5e9083b8812447799fbb73ba13b2613c6ae0d35cdd8835276e8c9e34450d8c682121cf28601dbc6ce6c160ccabe7c36043441d78 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/f863e9b6afea27c93b04575194bd83b7 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/deb3d89d5cdfdeee2a8665d79e2cf77dca693c66bdfd5e10fdba9cb54cefce27a85aed76804ade511a65aff5e1a99f66748b827253ffdaca6c5c55c5947e4d5d -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/0fc8a804ddcb6bebc2ca285697427a60 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/8cc0f98bc20bcaa47a6c6e28a559018b572b27c2c3507554abd2d5a09ecc36219881ab391625f47a581cf7a569534b693760abbe3b31a31b111c3a751051bc55 -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/eaf1aa0154ba5906a48848b1fd4770da -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/e4531b5eb09be3ac6440e32dcface0360cc75595da00fa1bd178306e9780bd26eb7413a705d4b49d3d7eafd8f403a448bad9aae40bad56fb40bbea8db75e5f06 -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/57307cc154a85a84297f94f71593829d -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/c8c8d35982a7df99ec468b688dee8ccf627512c6f009aea27cbd7fc8d350bcb915136753c18fc1a0ebcf621d9540d1995fae3f7532c31dfe70f1b3ea07275695 -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/701b49c22b69b6e4a91cc1559b3b2622 -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/1173b249d04df31a3d17e120666953654ce3274b749e137a24e137faa28b424a3a60bff9bf3c23f8299cdcb6b77fcf883b60654abced4b854e6080788a4093ea -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/e781f504156bdf748cbebbae86173fcf -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/572d0eadc5f3c495aef529d03fe3a3f890cac655fb7b8fc7dba92943023355a4494f72a2de5bb302756d5bbc36658b32babe4efdeca2f85f0b9f244f3c5e650e -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/b460698fc6f652366a0b869bfb2b1646 -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/00f3caefa2885be6550f20a86048057b6beb17044ea822ffa9fb9df65c848eb7ffafbac4f6546ca16a1dfc344cfb851b7d42cc3a7f3f8a2b19a5044748a6f64e -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/b4f0efa367651e7e37976cb7052eda02 -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/5af81df4c76dad4ab5387e3006f350f9387dbda5b131adb2b75669dde284a281af34f041dd00a0e8b6e0e8e92e7e4138fec5f83a6e2fc82fca8c3c6a637900a1 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/ee47fdaec1107506ace19f70d090622f -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/32c7702bc599f06be6c5403574b1cece6d07b2c9787bd3b08e73a3746a187956609f2b7cdf0c673fbdd3105030138cf0c622a08e59f4180cea5109cc486fc570 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/d6a47e2c969aed82c377f42248b54b75 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/c95f7e895832deed7d99155ada1df46e1dd1e43dd24fb8aaf94e4109f301b8163b8c8f83f3a2fd65d7b445e4d194f456e2cdd93ba36ed70ac4131c805a0c89e0 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/158ce4bcdb7cdf26faad269a6133e2eb -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/f19f556f25e602da754e666476686411d484297cbe1d51f8d21e167feb241c44e1b94d502b4984649340c515dcf38a53be9d949805c29ca0e959101900f68fc7 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/fe72914bc292072e1f474ffb41e01a99 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/87a300e6928b69a4ddc59a375a9c172cbef82dd14ee101ac97ea1a652e1e4cb69d8c1ba61f4e4c2889884c58a571a257cd3390a504ceb88b0cb4a514143541b8 -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/309fdd429e740941e0deab08f1043c5b -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/b01bcb83a6ef208692bd26899e7e75177f6bd619afeae0dc46217ece0f79bd81d2f07fedf70084478fe1f8abcc2d031a0ea06b55ac55a34f3facabb38a2a993f -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/a9ee212809e891f147916cb6568f8b0e -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/927a010c326dac7faa4ce822b7ed01048b825a8050ae03d11963a864bf8f70b810e58985d37ec04cb69e7ca5c8a4956438f8c5f50dc8af90dc00bb10c0b6dd28 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/6a2f2cd6cad70e27029f4a7c78196589 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/77bee805988a0df69cda34c5196f29234d5e4c7cf55da2154fd5a4f431123cfa3ef870a7ee10dd773eeb446647f500edca844cc89d1fc39d04caea6be58ce6a1 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/f780073977fddf46200103b476ba4176 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/40107288f36fe50e8f60fcd7b18a9058f36a6794cf8e8f06328437fb77f0890e1b890aba7f931329d98219faaf922dc14474f66340e6a70b8309f171e2bbc901 -libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/db4d528b06836c46d46755fc93cceaea -libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/cb62a0db35f0f1cc4723c2313eed265c4e11dc6b225d5b30afd7e2aae0c79b0dc23558640a409862a31ccbe337e4c6e4c1a35f3c93251a1c714dedf5f4637716 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/b00cef3645e589cb217d8df10173124c -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/4de8fd6f90a5f85278c1045731e71855969b615e228a6b63bf53c84b145c3d8db4a7fc236301249e6ac195ee13fe62b0c23dee1c50c968ba74a1f9857e5ae3d8 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/d326d3cd8918ef4abf4aa26a93f77310 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/ae49a764b848d179d8799793a79ba3cf03ece82d84e4d26b1f48256ce159984b1c54439db1f7b928f0526a85fb3b11021e9620104ae0404b7b85824aeb59d42f -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/10f34bf03747a92e6cdb6ed206b21724 -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ed06c31ae0024e60f7ac3a77dcde37e8aa545b280e0aef669edd6cf3f060b6acb90072c488f91a44bab6e573a3e50576a4b0a11f12596a63729a46547a7276af -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/55ad55e3e093d1a3c32775036c68f629 -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/d1a30dd14b64c49397c45b2e53aa6099585ef22014fd9091dda39a7ccf03c78b85b018f3844c90c56aff47c6725bc5dfd73b5e6402ea13f73109aea6debaa276 -libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/7d88bc9491b83793e39f494f45b7e636 -libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/c6065593e89f861661ec9c1fb35e416496e79e9e0f56e5ed4b7ba9fbf8b236716ff7733bb60b5de8942b6f9aca5705e0236e7fcbedb24109767fc12c29542d01 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/a012e6c9829ec51f260bbdedb20a2863 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/24dc81297cab5d7eafa47de5d0ab5ca0b3da3ffd032de94488c81556d5ebaec850884dd561e14de98fa7dc0104d45acdd0298e0b0339dbb7351a9dbaa32320f5 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bc0f8437c9f2aba1a7e696cafd3b4618 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/ac640918e72b169fffd4a43f1453965ea0ba734c582c3f6b04cd6f020b032b4745ed79208a43ba1c1f700f0122596466da4ed881a89a67f6df3a62141dab9f04 +LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/181e555215a01db6017bef6b75b857f6 +LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/7940b4494e5806319d013feb42771884c320b964fc674abfd8979169fe32bfbfa03558195e520a108fd645a4c7a06ef918d59cd411dbd086b6a46f80e5ff2c9c +LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/b02bb670ea84bcca20f318ffb26a79fd +LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/f05004c2fd6fbfdfe502e4f83babb7c29f9863e900e711c86023e878808eb1a31ff0285c3288a616a2dbecd7dfe3036fdf4465a64633af723f10c2fce68aa84d +LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/9aae2250dca2c2e8aa305d0175596fbd +LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/0ca30244061b3bd6f0b0a6bbbf61fc40b02db00b3e9bca4aa79013ac12137aa7e872ba7113c6bad3ca08225431a9d9a4d2267852606e8360b866e5752f027965 +LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/f3c3b9667ec2ab3dd9f3663859a0a736 +LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/5b1abc1967009154a71fc43813a80d37e1c8531575938b2682212478b51591def16a7141292844568ce65f76bc686a7e9f7a4d77b9311a57226ccd43d8494d48 +LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/98505793b877160dfc7466284fea9e71 +LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/90a0b9d8da40eaf29d9d7448a3611ee264eb90cd947fa68a6e5e2757d580e82bfbe8ffe3d31c2c2f1eade66d2d4b69a7dd79830b813b62ac7bba289281325559 +LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/fdc1abc12cf08fae3d4e110976e5967e +LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/6157dec83258fff29d54fe2f3783a7975a4487a5bc1b98f8355054970ad958eb26ee11f7a2f60c5ab8ae5c8e799275fc712051b00039a14febd0db66520d29b8 +LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/2c492cfd7cac00863fe373f8d91ce84c +LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/654e9842373cb52114407340f8cf4c5954966ba677cae9aa085e22a3ed167bb1670286f3f3dcb6798913fee45937da0327817a97f48db021d997c22862b039ef +LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/81b6c3bcb6b5e595f5fc12aee8596bfb +LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/8360352c772c69f9cd9469b41ee7494534248ae0480f7661f9303747cb3a87e26d5659fbf32d7dd11ba70b4f24812cf94dacd7565b92b42c9d63da388b8e93e0 +LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/c9559f735a8419e77a874dd75451d726 +LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/64cb59c966a1f42d1f31e32cf584602cd1a6a3bb5c3d805197c8e3cd96ebfc1ad3959bf52be2767d88110fe0025307f1e1982e9029630dd5438e94886da21366 +LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/bacdfbffc987ab1e4e0a023c4f1cb636 +LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/d9f772a958ff3621f10bc562833a7121a4b3c3aec8d8d03694554714dd54537aa89af0e080f16ffdcf965ae33bd1bb05d9659beeaa86ffb7e553a4202b924a0f +LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/018802fd42e68b24459c4040df0019cc +LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/ddcf9f104f47485cea67d0e5862393c2161e6aaf2e1cced1b0600b5b2dfb3c35895d00e47349de298cc9164665cc8cc8af3249997b716872fe23bb58bb1ea370 +LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/dc1ccc83441df682b09624bf7047aaf9 +LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/b717137c831f698cd9b3339e5beb0a2e9d6fd8c59961f91d70b8e76d8b1ef7bd9ef610a49d02d45bd6e7130262f37601a780e33509b78e2b1caafd40eeead7d1 +LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/74749fde3378518041fcae2e447370ea +LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/b60715831b4583679455ceffe82acc19ef6c7fe3798b02f3df8a08a129a4f80fbfd7ab59c663db4f4418285dc3551e536c3edda2e24310d10cecdd89596588fd +LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/0d403181fae7d966c536ee0cd6e39c12 +LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/71728fdc4b559df058d9ddc6dcd1dfae4d2dc854e2038ba14baef62e1cba7f3e2c7565fd2942b069690497989e846d0b5a572e0bbea8de7873752e43bc6827c5 +LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/791e288d0acc976ddf18776540b21ca2 +LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/49dc3c9a2952f928d51c0af64c9f87b441c05a3f7c497be7564052936bb44c4e5dbc05dca3b69d9123d784647f6ca1c528ece5bc11ad39059fb8d465582ff394 +LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/da303f41ec8ad7329e826a5e94af8889 +LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/39deaf22f9e5c2422eefaea6d64c8d78d3235385edb43ce050f8f34c5c9d128c7b155adb2af5c1f0653f92932324f9a8a564df6dc97009402842e98b4b9a17de +LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/3c5c77b8534eb0756c112193e4028838 +LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/9b00f22b169f17f1766e40da5a7aee602cf0b1f34ae97cdd02f59f3f7613f192dfa6a0235764a175efe4cf1ddcc1850d37052ea45e16947f0d1ad79deb6812d9 +LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/757aab5c47122ed033f987847a95ec0c +LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/de54c3f21959ebcb081601deb01bbbafe415b05cc7240fce230483b2901d77f89575a74384fb55c919bfe25a8ca8cde2f2e0c6f4f6a809fc73499f4752f2043a +LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/c7f3d289428d68802eaea4cae65e043c +LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/54fcb15fd2019dc0f5c3db10c24c9d21d8159e923b215dd000d6107a136b69ff240bc447b2a280a023f25e98880a86ea89cd42e1e3caacabeb59a4ba18b96d32 +LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/a3032d9310fdfcea2c0e6aa2cc27fe49 +LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/a8f8c4739b17f902f08307dc2f154ebe90a229299d476d8723cffe504cdfa91a8c36aadab4c12c1db4ea8cc056de17b66e68e1f086ad5d30d5f2edcc53da2337 +LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/ba581dd66006b02e1e7643b93af14499 +LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/8037109625c8cab5e310ff95aa852bd792b35f04b6830870962add89caaf0efbe001d08d6f870044e998a7b14216700a806eb132daadc5c4accd77baeebfb15e +LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/9d9c737b6e98a41086a1802283730757 +LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/b24025364052233f977c17bb5f9675b4404fb4b197f35752a8a2591ac9786eb8aa5b4053ca4269e6c4de9daf401f88b0361880c3b3201be2db91626f9cad9030 +LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/ef4535f1aaa5867e9dc4401e894086eb +LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/a1d7e4bdc72f33ec669023c89d4dcba8bd4b644e7c38e27784ab0f052e8efc08cb0cb89c38d5ee471961c8c8bfd6eaecc89898e70093a494f6cc53b9a36652eb +LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/bcae5538b46ba7241b429dd568faa1b7 +LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/f336e5d7d007298027efe39a9b50afb32376d1361622097fac6a0530ce8a834f0cfb6d8abf05cf964bb5159b0864bedac978fb95031cb84672e0bc0b037d03aa +LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/353ba4a877af02d2a986cb4917fc6cbc +LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ea038f9a12a84df32e62d877320eb041d2363b1714ded05508b1fdfb2a874a6964114833a7435feaad1040fd31a533acd29e48731f49e8df3b60fcea04f565fc +LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/81d43dea36a9e2ba628263b1af36461b +LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/a99b2dbdaf55cd36e8ead346fc7fae4ecd430cb98895343d6a409d0ea95406836048638dd5ab73129a2b2a637abd1e997515d8de1e9e5e8449e0f9d747773d4c +LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/0f83ccf57dcb7814976a57c42c91c454 +LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/06c3a97b6ec4f9095e8e978ccab0e65e03d26f99d90485c7893b6a41a53a4e5a8e8e531592e20f9d73a1100fe87f7fad793dc6cd19b09ae0bdaec5c362b7b4ac +LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/8db6882c343f0ff1ed3137c1a17a1676 +LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/a3fbc239389eaae152f4a21e5b50b6afd09adeb75d8e32754dfba5da3815991dd05ef5c403ef9539bdd47cad3f9b2c7066a61e3f40243f7bd237a7480172be86 +LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bee41a179343b54359aba1b159110a39 +LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/3db19d091bd52cfc2018a25f28bf7714f6337bd93b24349ad90d2954f60317189e5e65241ff114c9f7cd15933b685f0a4a193d45daf21af593fe2890ab98843e +LLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/574a70c914cfd54913a1d530f26a3961 +LLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/d7774e12566563905079699b28e056f403dde49078fe49b5e0cf4dc56ef1db457ffcc45bb0fba380e0768c9a5e5eddfe88fb1021205f6ad6565b3c6dd2e07dfc +LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/6a6866d3f5dd438410465ca3c75b0af0 +LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/ebf55880264d68876df2a82e3e105d13834fe379942270c5b054c50f7eb3c8f4b821ac171a7081bb378b178ca386c608c1340db6d693885bd79d53f958c9e601 +LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/a5623a828b84769cac493494c9c6d3d0 +LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/410ed00c107a6e05f322d4ea6eca9f16f7e4e986c335201e4a7092cfb20d7638fd9166176414dee782d0e656ee4b2252eea7055dcc526cecf6136ff47033dcf8 +LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/bf3323c7d6480fcfd75834e3240e7582 +LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/6fcdafe8de348020c4ecd75fe3ab0a7fca833b97545a4711c74a0f7646a64f302577c5d4bb55a77fb65b4d78dcabee670ea6c01f88c8730a7b9cc4fdae824557 +LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/fdc19a6e662037860b0a17d9b6c3a57e +LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/c30e08f6f2b926716e4e8594cabe66ef555eaa1f0cfa2ff578bc7fc550facd7a4c72eb3315dc68b11a4a76c62032bd7d6ca42ef472bafec76e1354d51276ac94 +LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/a570eb7a0a54a2175e8d65ba4d575bcc +LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/4944957b89ae0b61cded44f2fae879449a3d0bded0f4f515f0d1cdf6cac8bf834f5665b8d734e56e4818b07c639cd2617e033042fd358888a4bf808be1984f43 +LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/f5adea7936399d7ab1eaa8b71735e1c6 +LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/40daec8c3dc618e54032d645ab7d5914d1be4d02e16e5368b68826bb0c34461c767240535f757cf83afedb36b117cc809a371d7ef1e7d369d3d9ab19ba293f52 +LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/7b4759412d408ffc5d65295f2f6c31b0 +LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/f074208696be67c8107c8a9d188923642dcb839db82a871c5ee9778295ec5b18f7a7135fc65e4a0ac51cf20254bf1902f83b347fd10fa4e9c618acc9b52cb1fa +LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/d0aae4b55b3940727c4f88f7003e83bc +LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/ed62c5f919dbe72991f8466ba35ccf4be70e9deb4fcde47674acff75a7db7e5c4c4864dc3bb8869185e607d6e7be318b6f164465cb36b24f09426348701f51d6 +LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/f213dd3241c44763703a140528a05005 +LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/b2b56174fe9c5d6b8be0b111e0326c5916b6c7b97b8fa1c488ac5135a27d522d2422ed833436f49a76effdf575b8709025cab73a9487e895e3833d98f0d7c164 +LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/84f215e794678522449f8a8de56d9372 +LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/9d2ce1d97c9323481b6a6a13c8b3866772d3e9047b4969e3715867de903308887ebcf7fbe9c417f5a8f21e9fa3e5d6b0bc72dde94b441074d0e05aebc5962d5e +LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/9b65ba3b076d4d1d4ba9ee6eb332350d +LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/cf952eaf6bfc00e346985ff17165349309e9602edf2f44991897cdba4f1ed59429792bf7fe1d32e27674f7ec65926cd6ba070d62f35c812876ab685b517e0b49 +LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/95986e68c2d10a6231520d727cae100c +LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/065c99fcb52ed9e0f750715412f7ed80ba994dab3d6618da768b65ece144b6a17d4032604b47436f02f69c0f98b628245324af37c06a85166baa673bce2732f5 +LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/9388137e938f1e87ec0f7004989e29c4 +LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/5391a1e53c24456d9062a87c1cc7213a3042e56d9e97a2b775e77af8596c1acc4b1fa0ae860db834ed8b2033257222b7993b2edede59ceac2dc468a3bb590b20 +LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/ec4c8597ab5a356e53d405e2d2b2af00 +LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/0b088ea2a639d17945c7bbc52505c108d12d9ce3c22b4083c98ba47ce4450d90dba025491a3fbebc6a1ce7a8098b3655f9cbaa828e9159996a8f735359fa5efd +LLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/51270032209dbca8cab5e083fc1bdd74 +LLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/7eac24bb3aabfbe3bb64c4a28f4f8939bbc6677eeb27ed377d69ecdcff8e7e8cafd792181db41873b09ede991b0b5e02d3bbab5d21da120d2cb573fdd4849bff +LLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/323faee592864ff277b73ba03227d5bc +LLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/a45f96554b234ea03560338ac4d94af292af9731bf9022a30dacaf6ffbab293d599787f8aaaadb95de2364379037953ae13864b6fd4baf4281cb565589aefb8d +LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/6fa5b4a5c945d91edd07ac663a7c9b32 +LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/0e1782adbfc5d27c3bac951580a8bcc0683963fda9f9ea5b98d50bef11e5b4d61d59216a24006e23c467ed46b7f0e7bd4223bd9732642e729615dcb23910126b +LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/7d17ae9f78a02936d4c5f4d764940444 +LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/bed864a3b8fbc6a178be479bb4ffb5c2fe8d24059e08a626dfc6b8bd75f8b7e7bb7758e38aa5da98e4dd1ab6e3179b3a968fcaf309a06b4d663d0d0819053241 +LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/4e774c9ecedb46eb3ef189bff2bfed8c +LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/de1220a01bda6065cc125bb968de7d7b1c4f54ede47e3b411dad02eab38d620ef2016ae4a71034ce7c4d9996b615e190c6ad373b31d045d3e3e78f6d19d9dc52 +LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/2559547bb81c94199e3f165983be91cb +LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/deba81e6bd36e0bea4a5627570807d9942adb578f79a7a0bb32f5e489219d1d0483ccd6e5ffec5315b1582fdb50f67a985af6f738199118fe6aa7da6d4838f63 +LLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/8618c79f170124dd5e585995fe028d45 +LLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/68fd57412805f12c81525fb4ff5d9a3223b3fd435f7828d47f914dd5af7d6ed546d0b37b94bcdeb57fd0aad7ab672353f547a62af0b2da5f941b5ad03b65a00f +LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/825d637c6c1010431f567505b1639766 +LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/42bb554cc858b8af03f7f3b8d99ba017a5948951e1b653478e52477eba8a93e9d7a2dd9e50cdbc3ed6563483b01b12b5142a7aaae3534f4e5bc88b5e9298b3f2 +LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/dbf66bbc19a9c4331820e570e70456dc +LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/914e4831cb6873555739a300454cc6123634232a4bcee2bfad6e405e4af8e55f36b05ea4d164803b1b46ab6efaf2e38e6f1322962d044a21a070b53b4fc749e1 +LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/9ac711e2feba8e641601dfa934499478 +LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/f6cd0b432e4b19b2e5d6ac48aa2173d606a1126067cdf8d35b32dcf0cf8cb032a9ad537256fc7e16fab3173147240589969799c70822b7bd126c60b66566c519 +LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/e0262bcc1991c3d2818e0ab2cb06cd5f +LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/cbe609b686ae5a09fa54878a8557e294331e3c384a7d4a6385c9feb66f0087208399a0f7b55adb267a38704c4fa3850e7254dd8454f78933a1bf24fd15dd1f40 +LLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/5b63bc9dbb26c2c707391a0a245e9f7f +LLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/6dec55c91ae2c2384eb1915ed1377bd987baa82dbe6dd2382ea866f2c02a8415a0b0d511c1ef21dc034b199801523d4cc9c0e4b58c6c590489f375b8be845794 +LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/1d14014582c5fc00067a9c7383c9cf63 +LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/c304544b642a715f99d0b5f50e8ad55b8acf79af64169b7f1a6e3ae75d61317991afa352b5d078845cef20a800eee36fc0b21340c6616c21b9706f704b8ad7cd +LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/1e7dd492c73e042da4ab0b15f885add1 +LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/94cce6053b3d8cbafb98d7f737e51f04c044376c3203c236d228ed61d0a65cb136d0dd355609fbc5d4746794610d18ac3aad8168a61809e4ae4316dd51147587 libLLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/7b2400d9ae3ed7a9091011b7951c8ce7 libLLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/9078fc8c24d1749b303f5c7843bbb6b5322080e4adfca0b96d7757454783617253dfcee07f24d1adaf3768563d298029a69bb75d39dc0701d024c27c66e50fd3 libLLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/712ea06bba40025d5ad86229585e1eb9 @@ -114,63 +172,63 @@ libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/97e8cfab218937f77421285f0d libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/cd514c19006f4f997b8530109a8b2f0099df1e0af7c0e5fe85dea65b01056cfd2b959190e17a3da8a3a223c59859aadd7486d1b6a71ab3207242e9bea891d546 libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/f4ab87e307e014acf4600dc0a1d8120f libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/a44840a51cad8a7d0db296a3f3613372562c3c5464bb2f1a8e0352d9e521bcaa83053a70d0e369d75718cdd142584f24bd727b6717401174a270835ab40205a1 +libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/1468270825363bffb3d99d3ca9216d7d +libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/b94c1273553204440b5f51a3b1fa8c96ad8eae2090e50c3cf10fed44f960e5d0a6c95d967b7e006f842d550cc59b06ed8585962399772e1c2d6d1e6cf7686567 +libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/5ea96996524ebc1c69794d7e9ba2b252 +libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/8fd7d5debae5277a5d099c24c195ed1c110f95169bc05ebe42fbb697683f2012a95507b682dd978a25918582dcfd548233d26a3e74a3098e85758dd63b5ba98e +libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/49e5dedbdcad40a5966aca51c8913d3b +libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/107a57a298416760c2f806901080963c2b1b3d09f16bef698db6e28b084c36f86796956deff096b4e014a61b29319e1fe1ed95f6a807ab3f1a6350288f85160a +libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/7d594f4af283181513816fe50d299861 +libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/f074bca4a57c827c16558783b7efe8d31f12d4a0500a374ed9303a4beba2e848343d9d66da4bd0643c8df10004a6b7a9074a0f99bdba6e2b7eae939a892c7a0f +libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/1328f6c829ddc5361e5217aa9d2ba1f0 +libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/238fc6e8eeed72f6fc23b9ea5e9083b8812447799fbb73ba13b2613c6ae0d35cdd8835276e8c9e34450d8c682121cf28601dbc6ce6c160ccabe7c36043441d78 +libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/f863e9b6afea27c93b04575194bd83b7 +libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/deb3d89d5cdfdeee2a8665d79e2cf77dca693c66bdfd5e10fdba9cb54cefce27a85aed76804ade511a65aff5e1a99f66748b827253ffdaca6c5c55c5947e4d5d +libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/0fc8a804ddcb6bebc2ca285697427a60 +libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/8cc0f98bc20bcaa47a6c6e28a559018b572b27c2c3507554abd2d5a09ecc36219881ab391625f47a581cf7a569534b693760abbe3b31a31b111c3a751051bc55 +libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/eaf1aa0154ba5906a48848b1fd4770da +libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/e4531b5eb09be3ac6440e32dcface0360cc75595da00fa1bd178306e9780bd26eb7413a705d4b49d3d7eafd8f403a448bad9aae40bad56fb40bbea8db75e5f06 +libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/57307cc154a85a84297f94f71593829d +libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/c8c8d35982a7df99ec468b688dee8ccf627512c6f009aea27cbd7fc8d350bcb915136753c18fc1a0ebcf621d9540d1995fae3f7532c31dfe70f1b3ea07275695 +libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/701b49c22b69b6e4a91cc1559b3b2622 +libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/1173b249d04df31a3d17e120666953654ce3274b749e137a24e137faa28b424a3a60bff9bf3c23f8299cdcb6b77fcf883b60654abced4b854e6080788a4093ea +libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/e781f504156bdf748cbebbae86173fcf +libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/572d0eadc5f3c495aef529d03fe3a3f890cac655fb7b8fc7dba92943023355a4494f72a2de5bb302756d5bbc36658b32babe4efdeca2f85f0b9f244f3c5e650e +libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/b460698fc6f652366a0b869bfb2b1646 +libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/00f3caefa2885be6550f20a86048057b6beb17044ea822ffa9fb9df65c848eb7ffafbac4f6546ca16a1dfc344cfb851b7d42cc3a7f3f8a2b19a5044748a6f64e +libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/b4f0efa367651e7e37976cb7052eda02 +libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/5af81df4c76dad4ab5387e3006f350f9387dbda5b131adb2b75669dde284a281af34f041dd00a0e8b6e0e8e92e7e4138fec5f83a6e2fc82fca8c3c6a637900a1 +libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/ee47fdaec1107506ace19f70d090622f +libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/32c7702bc599f06be6c5403574b1cece6d07b2c9787bd3b08e73a3746a187956609f2b7cdf0c673fbdd3105030138cf0c622a08e59f4180cea5109cc486fc570 +libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/d6a47e2c969aed82c377f42248b54b75 +libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/c95f7e895832deed7d99155ada1df46e1dd1e43dd24fb8aaf94e4109f301b8163b8c8f83f3a2fd65d7b445e4d194f456e2cdd93ba36ed70ac4131c805a0c89e0 +libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/158ce4bcdb7cdf26faad269a6133e2eb +libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/f19f556f25e602da754e666476686411d484297cbe1d51f8d21e167feb241c44e1b94d502b4984649340c515dcf38a53be9d949805c29ca0e959101900f68fc7 +libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/fe72914bc292072e1f474ffb41e01a99 +libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/87a300e6928b69a4ddc59a375a9c172cbef82dd14ee101ac97ea1a652e1e4cb69d8c1ba61f4e4c2889884c58a571a257cd3390a504ceb88b0cb4a514143541b8 +libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/309fdd429e740941e0deab08f1043c5b +libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/b01bcb83a6ef208692bd26899e7e75177f6bd619afeae0dc46217ece0f79bd81d2f07fedf70084478fe1f8abcc2d031a0ea06b55ac55a34f3facabb38a2a993f +libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/a9ee212809e891f147916cb6568f8b0e +libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/927a010c326dac7faa4ce822b7ed01048b825a8050ae03d11963a864bf8f70b810e58985d37ec04cb69e7ca5c8a4956438f8c5f50dc8af90dc00bb10c0b6dd28 +libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/6a2f2cd6cad70e27029f4a7c78196589 +libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/77bee805988a0df69cda34c5196f29234d5e4c7cf55da2154fd5a4f431123cfa3ef870a7ee10dd773eeb446647f500edca844cc89d1fc39d04caea6be58ce6a1 +libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/f780073977fddf46200103b476ba4176 +libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/40107288f36fe50e8f60fcd7b18a9058f36a6794cf8e8f06328437fb77f0890e1b890aba7f931329d98219faaf922dc14474f66340e6a70b8309f171e2bbc901 +libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/db4d528b06836c46d46755fc93cceaea +libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/cb62a0db35f0f1cc4723c2313eed265c4e11dc6b225d5b30afd7e2aae0c79b0dc23558640a409862a31ccbe337e4c6e4c1a35f3c93251a1c714dedf5f4637716 +libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/b00cef3645e589cb217d8df10173124c +libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/4de8fd6f90a5f85278c1045731e71855969b615e228a6b63bf53c84b145c3d8db4a7fc236301249e6ac195ee13fe62b0c23dee1c50c968ba74a1f9857e5ae3d8 +libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/d326d3cd8918ef4abf4aa26a93f77310 +libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/ae49a764b848d179d8799793a79ba3cf03ece82d84e4d26b1f48256ce159984b1c54439db1f7b928f0526a85fb3b11021e9620104ae0404b7b85824aeb59d42f +libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/10f34bf03747a92e6cdb6ed206b21724 +libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ed06c31ae0024e60f7ac3a77dcde37e8aa545b280e0aef669edd6cf3f060b6acb90072c488f91a44bab6e573a3e50576a4b0a11f12596a63729a46547a7276af +libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/55ad55e3e093d1a3c32775036c68f629 +libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/d1a30dd14b64c49397c45b2e53aa6099585ef22014fd9091dda39a7ccf03c78b85b018f3844c90c56aff47c6725bc5dfd73b5e6402ea13f73109aea6debaa276 +libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/7d88bc9491b83793e39f494f45b7e636 +libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/c6065593e89f861661ec9c1fb35e416496e79e9e0f56e5ed4b7ba9fbf8b236716ff7733bb60b5de8942b6f9aca5705e0236e7fcbedb24109767fc12c29542d01 +libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/a012e6c9829ec51f260bbdedb20a2863 +libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/24dc81297cab5d7eafa47de5d0ab5ca0b3da3ffd032de94488c81556d5ebaec850884dd561e14de98fa7dc0104d45acdd0298e0b0339dbb7351a9dbaa32320f5 +libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bc0f8437c9f2aba1a7e696cafd3b4618 +libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/ac640918e72b169fffd4a43f1453965ea0ba734c582c3f6b04cd6f020b032b4745ed79208a43ba1c1f700f0122596466da4ed881a89a67f6df3a62141dab9f04 llvm-11.0.1.src.tar.xz/md5/6ec7ae9fd43da9b87cda15b3ab9cc7af llvm-11.0.1.src.tar.xz/sha512/b42c67ef88e09dd94171f85cdf49a421a15cfc82ff715c7ce6de22f98cefbe6c7cdf6bf4af7ca017d56ecf6aa3e36df3d823a78cf2dd5312de4301b54b43dbe8 -LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/181e555215a01db6017bef6b75b857f6 -LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/7940b4494e5806319d013feb42771884c320b964fc674abfd8979169fe32bfbfa03558195e520a108fd645a4c7a06ef918d59cd411dbd086b6a46f80e5ff2c9c -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/b02bb670ea84bcca20f318ffb26a79fd -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/f05004c2fd6fbfdfe502e4f83babb7c29f9863e900e711c86023e878808eb1a31ff0285c3288a616a2dbecd7dfe3036fdf4465a64633af723f10c2fce68aa84d -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/9aae2250dca2c2e8aa305d0175596fbd -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/0ca30244061b3bd6f0b0a6bbbf61fc40b02db00b3e9bca4aa79013ac12137aa7e872ba7113c6bad3ca08225431a9d9a4d2267852606e8360b866e5752f027965 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/f3c3b9667ec2ab3dd9f3663859a0a736 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/5b1abc1967009154a71fc43813a80d37e1c8531575938b2682212478b51591def16a7141292844568ce65f76bc686a7e9f7a4d77b9311a57226ccd43d8494d48 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/98505793b877160dfc7466284fea9e71 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/90a0b9d8da40eaf29d9d7448a3611ee264eb90cd947fa68a6e5e2757d580e82bfbe8ffe3d31c2c2f1eade66d2d4b69a7dd79830b813b62ac7bba289281325559 -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/fdc1abc12cf08fae3d4e110976e5967e -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/6157dec83258fff29d54fe2f3783a7975a4487a5bc1b98f8355054970ad958eb26ee11f7a2f60c5ab8ae5c8e799275fc712051b00039a14febd0db66520d29b8 -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/2c492cfd7cac00863fe373f8d91ce84c -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/654e9842373cb52114407340f8cf4c5954966ba677cae9aa085e22a3ed167bb1670286f3f3dcb6798913fee45937da0327817a97f48db021d997c22862b039ef -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/81b6c3bcb6b5e595f5fc12aee8596bfb -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/8360352c772c69f9cd9469b41ee7494534248ae0480f7661f9303747cb3a87e26d5659fbf32d7dd11ba70b4f24812cf94dacd7565b92b42c9d63da388b8e93e0 -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/c9559f735a8419e77a874dd75451d726 -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/64cb59c966a1f42d1f31e32cf584602cd1a6a3bb5c3d805197c8e3cd96ebfc1ad3959bf52be2767d88110fe0025307f1e1982e9029630dd5438e94886da21366 -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/bacdfbffc987ab1e4e0a023c4f1cb636 -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/d9f772a958ff3621f10bc562833a7121a4b3c3aec8d8d03694554714dd54537aa89af0e080f16ffdcf965ae33bd1bb05d9659beeaa86ffb7e553a4202b924a0f -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/018802fd42e68b24459c4040df0019cc -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/ddcf9f104f47485cea67d0e5862393c2161e6aaf2e1cced1b0600b5b2dfb3c35895d00e47349de298cc9164665cc8cc8af3249997b716872fe23bb58bb1ea370 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/dc1ccc83441df682b09624bf7047aaf9 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/b717137c831f698cd9b3339e5beb0a2e9d6fd8c59961f91d70b8e76d8b1ef7bd9ef610a49d02d45bd6e7130262f37601a780e33509b78e2b1caafd40eeead7d1 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/74749fde3378518041fcae2e447370ea -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/b60715831b4583679455ceffe82acc19ef6c7fe3798b02f3df8a08a129a4f80fbfd7ab59c663db4f4418285dc3551e536c3edda2e24310d10cecdd89596588fd -LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/0d403181fae7d966c536ee0cd6e39c12 -LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/71728fdc4b559df058d9ddc6dcd1dfae4d2dc854e2038ba14baef62e1cba7f3e2c7565fd2942b069690497989e846d0b5a572e0bbea8de7873752e43bc6827c5 -LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/791e288d0acc976ddf18776540b21ca2 -LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/49dc3c9a2952f928d51c0af64c9f87b441c05a3f7c497be7564052936bb44c4e5dbc05dca3b69d9123d784647f6ca1c528ece5bc11ad39059fb8d465582ff394 -LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/da303f41ec8ad7329e826a5e94af8889 -LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/39deaf22f9e5c2422eefaea6d64c8d78d3235385edb43ce050f8f34c5c9d128c7b155adb2af5c1f0653f92932324f9a8a564df6dc97009402842e98b4b9a17de -LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/3c5c77b8534eb0756c112193e4028838 -LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/9b00f22b169f17f1766e40da5a7aee602cf0b1f34ae97cdd02f59f3f7613f192dfa6a0235764a175efe4cf1ddcc1850d37052ea45e16947f0d1ad79deb6812d9 -LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/757aab5c47122ed033f987847a95ec0c -LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/de54c3f21959ebcb081601deb01bbbafe415b05cc7240fce230483b2901d77f89575a74384fb55c919bfe25a8ca8cde2f2e0c6f4f6a809fc73499f4752f2043a -LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/c7f3d289428d68802eaea4cae65e043c -LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/54fcb15fd2019dc0f5c3db10c24c9d21d8159e923b215dd000d6107a136b69ff240bc447b2a280a023f25e98880a86ea89cd42e1e3caacabeb59a4ba18b96d32 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/a3032d9310fdfcea2c0e6aa2cc27fe49 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/a8f8c4739b17f902f08307dc2f154ebe90a229299d476d8723cffe504cdfa91a8c36aadab4c12c1db4ea8cc056de17b66e68e1f086ad5d30d5f2edcc53da2337 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/ba581dd66006b02e1e7643b93af14499 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/8037109625c8cab5e310ff95aa852bd792b35f04b6830870962add89caaf0efbe001d08d6f870044e998a7b14216700a806eb132daadc5c4accd77baeebfb15e -LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/9d9c737b6e98a41086a1802283730757 -LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/b24025364052233f977c17bb5f9675b4404fb4b197f35752a8a2591ac9786eb8aa5b4053ca4269e6c4de9daf401f88b0361880c3b3201be2db91626f9cad9030 -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/ef4535f1aaa5867e9dc4401e894086eb -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/a1d7e4bdc72f33ec669023c89d4dcba8bd4b644e7c38e27784ab0f052e8efc08cb0cb89c38d5ee471961c8c8bfd6eaecc89898e70093a494f6cc53b9a36652eb -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/bcae5538b46ba7241b429dd568faa1b7 -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/f336e5d7d007298027efe39a9b50afb32376d1361622097fac6a0530ce8a834f0cfb6d8abf05cf964bb5159b0864bedac978fb95031cb84672e0bc0b037d03aa -LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/353ba4a877af02d2a986cb4917fc6cbc -LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ea038f9a12a84df32e62d877320eb041d2363b1714ded05508b1fdfb2a874a6964114833a7435feaad1040fd31a533acd29e48731f49e8df3b60fcea04f565fc -LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/81d43dea36a9e2ba628263b1af36461b -LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/a99b2dbdaf55cd36e8ead346fc7fae4ecd430cb98895343d6a409d0ea95406836048638dd5ab73129a2b2a637abd1e997515d8de1e9e5e8449e0f9d747773d4c -LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/0f83ccf57dcb7814976a57c42c91c454 -LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/06c3a97b6ec4f9095e8e978ccab0e65e03d26f99d90485c7893b6a41a53a4e5a8e8e531592e20f9d73a1100fe87f7fad793dc6cd19b09ae0bdaec5c362b7b4ac -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/8db6882c343f0ff1ed3137c1a17a1676 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/a3fbc239389eaae152f4a21e5b50b6afd09adeb75d8e32754dfba5da3815991dd05ef5c403ef9539bdd47cad3f9b2c7066a61e3f40243f7bd237a7480172be86 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bee41a179343b54359aba1b159110a39 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/3db19d091bd52cfc2018a25f28bf7714f6337bd93b24349ad90d2954f60317189e5e65241ff114c9f7cd15933b685f0a4a193d45daf21af593fe2890ab98843e diff --git a/deps/llvm.mk b/deps/llvm.mk index 476375354da22..aafaaa2c3220e 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -657,6 +657,8 @@ else # USE_BINARYBUILDER_LLVM ifeq ($(LLVM_ASSERTIONS), 1) LLVM_JLL_DOWNLOAD_NAME := libLLVM_assert LLVM_JLL_VER := $(LLVM_ASSERT_JLL_VER) +LLVM_TOOLS_JLL_DOWNLOAD_NAME := LLVM_assert +LLVM_TOOLS_JLL_VER := $(LLVM_TOOLS_ASSERT_JLL_VER) endif $(eval $(call bb-install,llvm,LLVM,false,true)) From fc02458492c60f6527245c6991f729c2a986f666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bia=C5=82as?= Date: Thu, 22 Apr 2021 23:23:36 +0200 Subject: [PATCH 244/439] Fix #31368: joinpath works on collections of paths (#38263) * Fix #31368: joinpath works on collections of paths * Update base/path.jl Co-authored-by: Jameson Nash * Apply suggestions from code review * Fixup Co-authored-by: Mustafa M Co-authored-by: Jameson Nash --- base/path.jl | 37 ++++++++++++++++++++++++++++--------- test/path.jl | 10 ++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/base/path.jl b/base/path.jl index c56230784f01d..2278bb4731948 100644 --- a/base/path.jl +++ b/base/path.jl @@ -254,16 +254,19 @@ function splitpath(p::String) return out end -joinpath(path::AbstractString)::String = path - if Sys.iswindows() -function joinpath(path::AbstractString, paths::AbstractString...)::String - result_drive, result_path = splitdrive(path) +function joinpath(paths::Union{Tuple, AbstractVector})::String + assertstring(x) = x isa AbstractString || throw(ArgumentError("path component is not a string: $(repr(x))")) + + isempty(paths) && throw(ArgumentError("collection of path components must be non-empty")) + assertstring(paths[1]) + result_drive, result_path = splitdrive(paths[1]) - local p_drive, p_path - for p in paths - p_drive, p_path = splitdrive(p) + p_path = "" + for i in firstindex(paths)+1:lastindex(paths) + assertstring(paths[i]) + p_drive, p_path = splitdrive(paths[i]) if startswith(p_path, ('\\', '/')) # second path is absolute @@ -299,8 +302,15 @@ end else -function joinpath(path::AbstractString, paths::AbstractString...)::String - for p in paths +function joinpath(paths::Union{Tuple, AbstractVector})::String + assertstring(x) = x isa AbstractString || throw(ArgumentError("path component is not a string: $(repr(x))")) + + isempty(paths) && throw(ArgumentError("collection of path components must be non-empty")) + assertstring(paths[1]) + path = paths[1] + for i in firstindex(paths)+1:lastindex(paths) + p = paths[i] + assertstring(p) if isabspath(p) path = p elseif isempty(path) || path[end] == '/' @@ -314,8 +324,12 @@ end end # os-test +joinpath(paths::AbstractString...)::String = joinpath(paths) + """ joinpath(parts::AbstractString...) -> String + joinpath(parts::Vector{AbstractString}) -> String + joinpath(parts::Tuple{AbstractString}) -> String Join path components into a full path. If some argument is an absolute path or (on Windows) has a drive specification that doesn't match the drive computed for @@ -331,6 +345,11 @@ letter casing, hence `joinpath("C:\\A","c:b") = "C:\\A\\b"`. julia> joinpath("/home/myuser", "example.jl") "/home/myuser/example.jl" ``` + +```jldoctest +julia> joinpath(["/home/myuser", "example.jl"]) +"/home/myuser/example.jl" +``` """ joinpath diff --git a/test/path.jl b/test/path.jl index e263b7c7db917..31de4baffd1a0 100644 --- a/test/path.jl +++ b/test/path.jl @@ -59,6 +59,11 @@ @test joinpath(S("foo"), S(homedir())) == homedir() @test joinpath(S(abspath("foo")), S(homedir())) == homedir() + for str in map(S, [sep, "a$(sep)b", "a$(sep)b$(sep)c", "a$(sep)b$(sep)c$(sep)d"]) + @test str == joinpath(splitpath(str)) + @test joinpath(splitpath(str)) == joinpath(splitpath(str)...) + end + if Sys.iswindows() @test joinpath(S("foo"),S("bar:baz")) == "bar:baz" @test joinpath(S("C:"),S("foo"),S("D:"),S("bar")) == "D:bar" @@ -75,6 +80,11 @@ @test joinpath(S("\\\\server\\share"),S("a")) == "\\\\server\\share\\a" @test joinpath(S("\\\\server\\share\\"), S("a")) == "\\\\server\\share\\a" + for str in map(S, ["c:\\", "c:\\a", "c:\\a\\b", "c:\\a\\b\\c", "c:\\a\\b\\c\\d"]) + @test str == joinpath(splitpath(str)) + @test joinpath(splitpath(str)) == joinpath(splitpath(str)...) + end + elseif Sys.isunix() @test joinpath(S("foo"),S("bar:baz")) == "foo$(sep)bar:baz" @test joinpath(S("C:"),S("foo"),S("D:"),S("bar")) == "C:$(sep)foo$(sep)D:$(sep)bar" From d7d2b0c692eb6ad409d7193ba8d9d42972cbf182 Mon Sep 17 00:00:00 2001 From: Iagoba Apellaniz Date: Fri, 23 Apr 2021 14:17:38 +0200 Subject: [PATCH 245/439] make \cdot, \interpunct, and \cdotp equivalent (#25157) Co-authored-by: Steven G. Johnson Co-authored-by: Steven G. Johnson --- NEWS.md | 2 ++ doc/src/manual/variables.md | 10 +++++++--- src/flisp/julia_charmap.h | 2 ++ src/flisp/julia_extensions.c | 10 ++++++++++ src/julia-parser.scm | 6 +++--- test/syntax.jl | 5 ++++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 24be1feb2108d..8321cb599411a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,7 +14,9 @@ New language features Language changes ---------------- + * `macroexpand`, `@macroexpand`, and `@macroexpand1` no longer wrap errors in a `LoadError`. To reduce breakage, `@test_throws` has been modified so that many affected tests will still pass ([#38379]]. +* The middle dot `·` (`\cdotp` U+00b7) and the Greek interpunct `·` (U+0387) are now treated as equivalent to the dot operator `⋅` (`\cdot` U+22c5) (#25157). Compiler/Runtime improvements ----------------------------- diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index e8e60a15d54c1..4461ee5c32afe 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -136,9 +136,13 @@ ERROR: syntax: unexpected "=" Some Unicode characters are considered to be equivalent in identifiers. Different ways of entering Unicode combining characters (e.g., accents) are treated as equivalent (specifically, Julia identifiers are [NFC](http://www.macchiato.com/unicode/nfc-faq)-normalized). -The Unicode characters `ɛ` (U+025B: Latin small letter open e) -and `µ` (U+00B5: micro sign) are treated as equivalent to the corresponding -Greek letters, because the former are easily accessible via some input methods. +Julia also includes a few non-standard equivalences for characters that are +visually similar and are easily entered by some input methods. The Unicode +characters `ɛ` (U+025B: Latin small letter open e) and `µ` (U+00B5: micro sign) +are treated as equivalent to the corresponding Greek letters. The middle dot +`·` (U+00B7) and the Greek +[interpunct](https://en.wikipedia.org/wiki/Interpunct) `·` (U+0387) are both +treated as the mathematical dot operator `⋅` (U+22C5). ## Stylistic Conventions diff --git a/src/flisp/julia_charmap.h b/src/flisp/julia_charmap.h index bed88a9ace4cd..7384df0c7f506 100644 --- a/src/flisp/julia_charmap.h +++ b/src/flisp/julia_charmap.h @@ -4,4 +4,6 @@ static const uint32_t charmap[][2] = { { 0x025B, 0x03B5 }, // latin small letter open e -> greek small letter epsilon { 0x00B5, 0x03BC }, // micro sign -> greek small letter mu + { 0x00B7, 0x22C5 }, // middot char -> dot operator (#25098) + { 0x0387, 0x22C5 }, // Greek interpunct -> dot operator (#25098) }; diff --git a/src/flisp/julia_extensions.c b/src/flisp/julia_extensions.c index e6ffcfcde131c..dbe94e1388069 100644 --- a/src/flisp/julia_extensions.c +++ b/src/flisp/julia_extensions.c @@ -351,6 +351,15 @@ value_t fl_accum_julia_symbol(fl_context_t *fl_ctx, value_t *args, uint32_t narg return symbol(fl_ctx, allascii ? str.buf : normalize(fl_ctx, str.buf)); } +/* convert a string to a symbol, first applying normalization */ +value_t fl_string2normsymbol(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) +{ + argcount(fl_ctx, "string->normsymbol", nargs, 1); + if (!fl_isstring(fl_ctx, args[0])) + type_error(fl_ctx, "string->normsymbol", "string", args[0]); + return symbol(fl_ctx, normalize(fl_ctx, (char*)cvalue_data(args[0]))); +} + static const builtinspec_t julia_flisp_func_info[] = { { "skip-ws", fl_skipws }, { "accum-julia-symbol", fl_accum_julia_symbol }, @@ -360,6 +369,7 @@ static const builtinspec_t julia_flisp_func_info[] = { { "op-suffix-char?", fl_julia_op_suffix_char }, { "strip-op-suffix", fl_julia_strip_op_suffix }, { "underscore-symbol?", fl_julia_underscore_symbolp }, + { "string->normsymbol", fl_string2normsymbol }, { NULL, NULL } }; diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 60cd047d12c76..c6510dcbd9536 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -21,7 +21,7 @@ (define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) (define prec-plus (append! '($) (add-dots '(+ - ¦ |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) -(define prec-times (add-dots '(* / ⌿ ÷ % & ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ ⨟))) +(define prec-times (add-dots '(* / ⌿ ÷ % & · · ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ ⨟))) (define prec-rational (add-dots '(//))) (define prec-bitshift (add-dots '(<< >> >>>))) ;; `where` @@ -234,7 +234,7 @@ (if (and (eqv? c0 #\*) (eqv? (peek-char port) #\*)) (error "use \"x^y\" instead of \"x**y\" for exponentiation, and \"x...\" instead of \"**x\" for splatting.")) (if (or (eof-object? (peek-char port)) (not (op-or-sufchar? (peek-char port)))) - (symbol (string c0)) ; 1-char operator + (string->normsymbol (string c0)) ; 1-char operator (let ((str (let loop ((str (string c0)) (c (peek-char port)) (in-suffix? #f)) @@ -267,7 +267,7 @@ (loop newop (peek-char port) sufchar?)) str)) str)))))) - (string->symbol str)))) + (string->normsymbol str)))) (define (accum-digits c pred port _-digit-sep) (let loop ((str '()) diff --git a/test/syntax.jl b/test/syntax.jl index ba71d750254e7..fc79d355e9c11 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -819,7 +819,7 @@ let f = function (x; kw...) end # normalization of Unicode symbols (#19464) -let ε=1, μ=2, x=3, î=4 +let ε=1, μ=2, x=3, î=4, ⋅=5 # issue #5434 (mu vs micro): @test Meta.parse("\u00b5") === Meta.parse("\u03bc") @test µ == μ == 2 @@ -829,6 +829,9 @@ let ε=1, μ=2, x=3, î=4 # latin vs greek ε (#14751) @test Meta.parse("\u025B") === Meta.parse("\u03B5") @test ɛ == ε == 1 + # middot char · or · vs math dot operator ⋅ (#25098) + @test Meta.parse("\u00b7") === Meta.parse("\u0387") === Meta.parse("\u22c5") + @test (·) == (·) == (⋅) == 5 end # issue #8925 From ac7974acef22b357e790be418b750987e86cb386 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Fri, 23 Apr 2021 13:59:06 -0700 Subject: [PATCH 246/439] [cli] Provide `.type` and `.size` annotations for symbols (#40575) On ELF platforms, `ld` can print out warnings that certain symbols do not have a type or size annotation. This adds the annotations to the `DEBUGINFO` and `EXPORT` helper macros, which are where this information was put for the windows assembler. With this patch, we should eliminate `ld` warnings such as: ``` warning: type and size of dynamic symbol `jl_symbol' are not defined ``` --- cli/trampolines/common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/trampolines/common.h b/cli/trampolines/common.h index 743d697d2467b..06d7b9e236971 100644 --- a/cli/trampolines/common.h +++ b/cli/trampolines/common.h @@ -23,6 +23,9 @@ .ascii STR(-export:##I(name)); \ .ascii " "; \ .section .text +#elif defined(__ELF__) +#define DEBUGINFO(name) .type CNAME(name),@function +#define EXPORT(name) .size CNAME(name), . - CNAME(name) #else #define DEBUGINFO(name) #define EXPORT(name) From 1474566ffc1dfe16f643b446f667178b78b56aa6 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sat, 24 Apr 2021 00:31:56 -0500 Subject: [PATCH 247/439] faster Float32 and Float16 pow (#40236) Approximately .5 ULP, relatively fast. Update float^integer as well --- base/math.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/base/math.jl b/base/math.jl index c08c25d05f112..b8d8a1866c575 100644 --- a/base/math.jl +++ b/base/math.jl @@ -911,13 +911,19 @@ end z end @inline function ^(x::Float32, y::Float32) - z = ccall("llvm.pow.f32", llvmcall, Float32, (Float32, Float32), x, y) + z = Float32(exp2_fast(log2(Float64(x))*y)) + if isnan(z) & !isnan(x+y) + throw_exp_domainerror(x) + end + z +end +@inline function ^(x::Float16, y::Float16) + z = Float16(exp2_fast(log2(Float32(x))*y)) if isnan(z) & !isnan(x+y) throw_exp_domainerror(x) end z end -@inline ^(x::Float16, y::Float16) = Float16(Float32(x)^Float32(y)) # TODO: optimize @inline function ^(x::Float64, y::Integer) y == -1 && return inv(x) @@ -925,7 +931,7 @@ end y == 1 && return x y == 2 && return x*x y == 3 && return x*x*x - ccall("llvm.pow.f64", llvmcall, Float64, (Float64, Float64), x, Float64(y)) + return x^Float64(y) end @inline function ^(x::Float32, y::Integer) y == -1 && return inv(x) @@ -933,7 +939,7 @@ end y == 1 && return x y == 2 && return x*x y == 3 && return x*x*x - ccall("llvm.pow.f32", llvmcall, Float32, (Float32, Float32), x, Float32(y)) + x^Float32(y) end @inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ y) @inline literal_pow(::typeof(^), x::Float16, ::Val{p}) where {p} = Float16(literal_pow(^,Float32(x),Val(p))) From e7a68057095db377e3eecc7e9b4b1357e5eb644b Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sat, 24 Apr 2021 16:53:07 +0900 Subject: [PATCH 248/439] avoid excessive inlining of Ryu (#40593) --- base/ryu/exp.jl | 2 +- base/ryu/fixed.jl | 2 +- base/ryu/shortest.jl | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/base/ryu/exp.jl b/base/ryu/exp.jl index 6356206971f8b..ff20118d68011 100644 --- a/base/ryu/exp.jl +++ b/base/ryu/exp.jl @@ -1,4 +1,4 @@ -@inline function writeexp(buf, pos, v::T, +function writeexp(buf, pos, v::T, precision=-1, plus=false, space=false, hash=false, expchar=UInt8('e'), decchar=UInt8('.'), trimtrailingzeros=false) where {T <: Base.IEEEFloat} @assert 0 < pos <= length(buf) diff --git a/base/ryu/fixed.jl b/base/ryu/fixed.jl index 14713111a95a1..360b2ae5ac407 100644 --- a/base/ryu/fixed.jl +++ b/base/ryu/fixed.jl @@ -1,4 +1,4 @@ -@inline function writefixed(buf, pos, v::T, +function writefixed(buf, pos, v::T, precision=-1, plus=false, space=false, hash=false, decchar=UInt8('.'), trimtrailingzeros=false) where {T <: Base.IEEEFloat} @assert 0 < pos <= length(buf) diff --git a/base/ryu/shortest.jl b/base/ryu/shortest.jl index 52502fecf9610..1259ee5c69794 100644 --- a/base/ryu/shortest.jl +++ b/base/ryu/shortest.jl @@ -224,11 +224,10 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. return b, e10 end - -@inline function writeshortest(buf::Vector{UInt8}, pos, x::T, - plus=false, space=false, hash=true, - precision=-1, expchar=UInt8('e'), padexp=false, decchar=UInt8('.'), - typed=false, compact=false) where {T} +function writeshortest(buf::Vector{UInt8}, pos, x::T, + plus=false, space=false, hash=true, + precision=-1, expchar=UInt8('e'), padexp=false, decchar=UInt8('.'), + typed=false, compact=false) where {T} @assert 0 < pos <= length(buf) neg = signbit(x) # special cases From e5da821de41a39cb3019b4e0a8c00890af06b39f Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Sat, 24 Apr 2021 13:47:46 +0200 Subject: [PATCH 249/439] Add CHOLMOD error handler (#40589) * Add CHOLMOD error handler * Remove some now-obsolete at-isok * Remove at-isok macro --- stdlib/SuiteSparse/src/cholmod.jl | 104 ++++++++++++++-------------- stdlib/SuiteSparse/src/cholmod_h.jl | 5 +- stdlib/SuiteSparse/test/cholmod.jl | 3 +- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index ef14709eb076c..af0dff10ed473 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -182,11 +182,11 @@ mutable struct Common function Common() common = new() - @isok ccall((@cholmod_name("start"), :libcholmod), + ccall((@cholmod_name("start"), :libcholmod), Cint, (Ptr{Common},), common) finalizer(common) do common - @isok ccall((@cholmod_name("finish"), :libcholmod), - Cint, (Ptr{Common},), common) + ccall((@cholmod_name("finish"), :libcholmod), + Cint, (Ptr{Common},), common) == TRUE end end end @@ -197,7 +197,7 @@ Base.unsafe_convert(::Type{Ptr{Common}},c::Common) = const common = Vector{Common}() function defaults!(common) - @isok ccall((@cholmod_name("defaults"), :libcholmod), + ccall((@cholmod_name("defaults"), :libcholmod), Cint, (Ptr{Common},), common) return common end @@ -274,9 +274,11 @@ function __init__() ### to temporary memory. We need to manage a copy for each thread. nt = Threads.nthreads() resize!(common, nt) + errorhandler = @cfunction(error_handler, Cvoid, (Cint, Cstring, Cint, Cstring)) for i in 1:nt common[i] = Common() common[i].print = 0 # no printing from CHOLMOD by default + common[i].error_handler = errorhandler end # Register gc tracked allocator if CHOLMOD is new enough @@ -518,9 +520,9 @@ function allocate_dense(m::Integer, n::Integer, d::Integer, ::Type{Tv}) where {T end function free!(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes} - @isok ccall((@cholmod_name("free_dense"), :libcholmod), Cint, - (Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}), - p, common[Threads.threadid()]) + ccall((@cholmod_name("free_dense"), :libcholmod), Cint, + (Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}), + p, common[Threads.threadid()]) == TRUE end function zeros(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("zeros"), :libcholmod), Ptr{C_Dense{Tv}}, @@ -551,9 +553,9 @@ function copy(A::Dense{Tv}) where Tv<:VTypes end function sort!(S::Sparse{Tv}) where Tv<:VTypes - @isok ccall((@cholmod_name("sort"), :libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - S, common[Threads.threadid()]) + ccall((@cholmod_name("sort"), :libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, common[Threads.threadid()]) return S end @@ -592,16 +594,16 @@ function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer, end function free!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes - @isok ccall((@cholmod_name("free_sparse"), :libcholmod), Cint, - (Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}), - ptr, common[Threads.threadid()]) + ccall((@cholmod_name("free_sparse"), :libcholmod), Cint, + (Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) == TRUE end function free!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes # Warning! Important that finalizer doesn't modify the global Common struct. - @isok ccall((@cholmod_name("free_factor"), :libcholmod), Cint, - (Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}), - ptr, common[Threads.threadid()]) + ccall((@cholmod_name("free_factor"), :libcholmod), Cint, + (Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) == TRUE end function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes @@ -635,9 +637,9 @@ end function change_factor!(F::Factor{Tv}, to_ll::Bool, to_super::Bool, to_packed::Bool, to_monotonic::Bool) where Tv<:VTypes - @isok ccall((@cholmod_name("change_factor"),:libcholmod), Cint, - (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}), - xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) + ccall((@cholmod_name("change_factor"),:libcholmod), Cint, + (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}), + xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) == TRUE end function check_sparse(A::Sparse{Tv}) where Tv<:VTypes @@ -702,16 +704,16 @@ end function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes isascii(name) || error("non-ASCII name: $name") common[Threads.threadid()] = 3 - @isok ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), - A, name, common[Threads.threadid()]) + ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), + A, name, common[Threads.threadid()]) nothing end function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes common[Threads.threadid()] = 3 - @isok ccall((@cholmod_name("print_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), - F, name, common[Threads.threadid()]) + ccall((@cholmod_name("print_factor"),:libcholmod), Cint, + (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), + F, name, common[Threads.threadid()]) nothing end @@ -771,9 +773,9 @@ function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealType end sA = unsafe_load(pointer(A)) - @isok ccall((@cholmod_name("scale"),:libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}), - S, scale, A, common[Threads.threadid()]) + ccall((@cholmod_name("scale"),:libcholmod), Cint, + (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, scale, A, common[Threads.threadid()]) A end @@ -785,11 +787,11 @@ function sdmult!(A::Sparse{Tv}, transpose::Bool, if nc != size(X, 1) throw(DimensionMismatch("incompatible dimensions, $nc and $(size(X,1))")) end - @isok ccall((@cholmod_name("sdmult"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Cint, - Ref{ComplexF64}, Ref{ComplexF64}, - Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), - A, transpose, α, β, X, Y, common[Threads.threadid()]) + ccall((@cholmod_name("sdmult"),:libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Cint, + Ref{ComplexF64}, Ref{ComplexF64}, + Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), + A, transpose, α, β, X, Y, common[Threads.threadid()]) Y end @@ -831,18 +833,18 @@ function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}) where Tv<:VTyp A, perm, C_NULL, 0, common[Threads.threadid()])) end function factorize!(A::Sparse{Tv}, F::Factor{Tv}) where Tv<:VTypes - @isok ccall((@cholmod_name("factorize"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), - A, F, common[Threads.threadid()]) + ccall((@cholmod_name("factorize"),:libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + A, F, common[Threads.threadid()]) F end function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}) where Tv<:VTypes # note that β is passed as a complex number (double beta[2]), # but the CHOLMOD manual says that only beta[0] (real part) is used - @isok ccall((@cholmod_name("factorize_p"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t, - Ptr{C_Factor{Tv}}, Ptr{Common}), - A, β, C_NULL, 0, F, common[Threads.threadid()]) + ccall((@cholmod_name("factorize_p"),:libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t, + Ptr{C_Factor{Tv}}, Ptr{Common}), + A, β, C_NULL, 0, F, common[Threads.threadid()]) F end @@ -877,14 +879,10 @@ end # Autodetects the types function read_sparse(file::Libc.FILE, ::Type{SuiteSparse_long}) - ptr = ccall((@cholmod_name("read_sparse"), :libcholmod), - Ptr{C_Sparse{Cvoid}}, - (Ptr{Cvoid}, Ptr{Common}), - file.ptr, common[Threads.threadid()]) - if ptr == C_NULL - throw(ArgumentError("sparse matrix construction failed. Check that input file is valid.")) - end - Sparse(ptr) + Sparse(ccall((@cholmod_name("read_sparse"), :libcholmod), + Ptr{C_Sparse{Cvoid}}, + (Ptr{Cvoid}, Ptr{Common}), + file.ptr, common[Threads.threadid()])) end function read_sparse(file::IO, T) @@ -963,7 +961,7 @@ function Sparse(m::Integer, n::Integer, unsafe_copyto!(s.i, pointer(rowval0), colptr0[n + 1]) unsafe_copyto!(s.x, pointer(nzval) , colptr0[n + 1]) - @isok check_sparse(o) + check_sparse(o) return o end @@ -1022,7 +1020,7 @@ function Sparse{Tv}(A::SparseMatrixCSC, stype::Integer) where Tv<:VTypes end end - @isok check_sparse(o) + check_sparse(o) return o end @@ -1677,9 +1675,9 @@ function lowrankupdowndate!(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) where Tv if lF.n != lC.nrow throw(DimensionMismatch("matrix dimensions do not fit")) end - @isok ccall((@cholmod_name("updown"), :libcholmod), Cint, - (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), - update, C, F, common[Threads.threadid()]) + ccall((@cholmod_name("updown"), :libcholmod), Cint, + (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + update, C, F, common[Threads.threadid()]) F end diff --git a/stdlib/SuiteSparse/src/cholmod_h.jl b/stdlib/SuiteSparse/src/cholmod_h.jl index 08b8464238a59..0528b736ba9e7 100644 --- a/stdlib/SuiteSparse/src/cholmod_h.jl +++ b/stdlib/SuiteSparse/src/cholmod_h.jl @@ -74,6 +74,7 @@ struct CHOLMODException <: Exception msg::String end -macro isok(A) - :($(esc(A)) == TRUE || throw(CHOLMODException(""))) +function error_handler(status::Cint, file::Cstring, line::Cint, message::Cstring)::Cvoid + status < 0 && throw(CHOLMODException(unsafe_string(message))) + nothing end diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index b0230f97eae2e..501be8860436e 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -238,8 +238,9 @@ end @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5-0.5im;0 0.5+0.5im 1] rm(testfile) + # this also tests that the error message is correctly retrieved from the library writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","%3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) - @test_throws ArgumentError sparse(CHOLMOD.Sparse(testfile)) + @test_throws CHOLMOD.CHOLMODException("indices out of range") sparse(CHOLMOD.Sparse(testfile)) rm(testfile) end end From c1b2fe24652bcfb5ea851ccbd5d287ab64c9acfd Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 24 Apr 2021 11:11:43 -0400 Subject: [PATCH 250/439] Random: cut randstring allocation size in half (#40584) --- stdlib/Random/src/misc.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stdlib/Random/src/misc.jl b/stdlib/Random/src/misc.jl index 3c09f5b30d257..7c26d36f0a0d4 100644 --- a/stdlib/Random/src/misc.jl +++ b/stdlib/Random/src/misc.jl @@ -71,7 +71,12 @@ function randstring end let b = UInt8['0':'9';'A':'Z';'a':'z'] global randstring - randstring(r::AbstractRNG, chars=b, n::Integer=8) = String(rand(r, chars, n)) + function randstring(r::AbstractRNG, chars=b, n::Integer=8) + T = eltype(chars) + v = T === UInt8 ? Base.StringVector(n) : Vector{T}(undef, n) + rand!(r, v, chars) + return String(v) + end randstring(r::AbstractRNG, n::Integer) = randstring(r, b, n) randstring(chars=b, n::Integer=8) = randstring(default_rng(), chars, n) randstring(n::Integer) = randstring(default_rng(), b, n) From 659bc121e98878ef6626cbc50f7041a2138c7e24 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Sat, 24 Apr 2021 11:16:54 -0400 Subject: [PATCH 251/439] add `inttype`, `floattype` like `uinttype` (#36526) --- base/float.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/base/float.jl b/base/float.jl index 7344be40660d5..fd5283fc82ab4 100644 --- a/base/float.jl +++ b/base/float.jl @@ -962,6 +962,17 @@ bswap(x::IEEEFloat) = bswap_int(x) uinttype(::Type{Float64}) = UInt64 uinttype(::Type{Float32}) = UInt32 uinttype(::Type{Float16}) = UInt16 +inttype(::Type{Float64}) = Int64 +inttype(::Type{Float32}) = Int32 +inttype(::Type{Float16}) = Int16 +# float size of integer +floattype(::Type{UInt64}) = Float64 +floattype(::Type{UInt32}) = Float32 +floattype(::Type{UInt16}) = Float16 +floattype(::Type{Int64}) = Float64 +floattype(::Type{Int32}) = Float32 +floattype(::Type{Int16}) = Float16 + ## Array operations on floating point numbers ## From 248c02f531948a1b66bdd887906d3746fd1ccc2b Mon Sep 17 00:00:00 2001 From: Alfredo Braunstein Date: Sat, 24 Apr 2021 19:37:49 +0200 Subject: [PATCH 252/439] stricter buffer sizes in SparseMatrixCSC (#40523) Make length(A.nzval)==nnz(A) and add strict buffer checking (#30662) * Add sizehint!(::SparseMatrixCSC, args...), * Fix illegal SparseMatrixCSC construction in cholmod and linalg. * Remove tests targetting now illegal buffers * Fix invalid buffer creation in kron and more * use widelength in sizehint! to cope with large matrices in 32 bit systems --- NEWS.md | 1 + stdlib/SparseArrays/src/higherorderfns.jl | 64 ++++---- stdlib/SparseArrays/src/linalg.jl | 49 +++--- stdlib/SparseArrays/src/sparsematrix.jl | 172 ++++++++-------------- stdlib/SparseArrays/src/sparsevector.jl | 16 +- stdlib/SparseArrays/test/sparse.jl | 49 +----- stdlib/SparseArrays/test/sparsevector.jl | 4 +- stdlib/SuiteSparse/src/cholmod.jl | 124 ++++++++++------ stdlib/SuiteSparse/test/cholmod.jl | 13 +- 9 files changed, 215 insertions(+), 277 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8321cb599411a..d048c6f2cccd2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -113,6 +113,7 @@ Standard library changes #### SparseArrays +* new `sizehint!(::SparseMatrixCSC, ::Integer)` method ([#30676]). #### Dates diff --git a/stdlib/SparseArrays/src/higherorderfns.jl b/stdlib/SparseArrays/src/higherorderfns.jl index 383211267ee3b..a5941da764883 100644 --- a/stdlib/SparseArrays/src/higherorderfns.jl +++ b/stdlib/SparseArrays/src/higherorderfns.jl @@ -8,7 +8,7 @@ import Base: map, map!, broadcast, copy, copyto!, _extrema_dims, _extrema_itr using Base: front, tail, to_shape using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseVector, AbstractSparseMatrixCSC, - AbstractSparseMatrix, AbstractSparseArray, indtype, nnz, nzrange, + AbstractSparseMatrix, AbstractSparseArray, indtype, nnz, nzrange, spzeros, SparseVectorUnion, AdjOrTransSparseVectorUnion, nonzeroinds, nonzeros, rowvals, getcolptr, widelength using Base.Broadcast: BroadcastStyle, Broadcasted, flatten using LinearAlgebra @@ -132,12 +132,17 @@ function trimstorage!(A::SparseVecOrMat, maxstored) resize!(storedvals(A), maxstored) return maxstored end + function expandstorage!(A::SparseVecOrMat, maxstored) - length(storedinds(A)) < maxstored && resize!(storedinds(A), maxstored) - length(storedvals(A)) < maxstored && resize!(storedvals(A), maxstored) + if length(storedinds(A)) < maxstored + resize!(storedinds(A), maxstored) + resize!(storedvals(A), maxstored) + end return maxstored end +_checkbuffers(S::SparseMatrixCSC) = (@assert length(getcolptr(S)) == size(S, 2) + 1 && getcolptr(S)[end] - 1 == length(rowvals(S)) == length(nonzeros(S)); S) +_checkbuffers(S::SparseVector) = (@assert length(storedvals(S)) == length(storedinds(S)); S) # (2) map[!] entry points map(f::Tf, A::SparseVector) where {Tf} = _noshapecheck_map(f, A) @@ -181,7 +186,7 @@ copy(bc::SpBroadcasted1) = _noshapecheck_map(bc.f, bc.args[1]) storedvals(C)[1] = fofnoargs broadcast!(f, view(storedvals(C), 2:length(storedvals(C)))) end - return C + return _checkbuffers(C) end function _diffshape_broadcast(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} @@ -224,22 +229,17 @@ _maxnnzfrom(shape::NTuple{2}, A::AbstractSparseMatrixCSC) = nnz(A) * div(shape[1 @inline _unchecked_maxnnzbcres(shape, As...) = _unchecked_maxnnzbcres(shape, As) @inline _checked_maxnnzbcres(shape::NTuple{1}, As...) = shape[1] != 0 ? _unchecked_maxnnzbcres(shape, As) : 0 @inline _checked_maxnnzbcres(shape::NTuple{2}, As...) = shape[1] != 0 && shape[2] != 0 ? _unchecked_maxnnzbcres(shape, As) : 0 -@inline function _allocres(shape::NTuple{1}, indextype, entrytype, maxnnz) - storedinds = Vector{indextype}(undef, maxnnz) - storedvals = Vector{entrytype}(undef, maxnnz) - return SparseVector(shape..., storedinds, storedvals) -end -@inline function _allocres(shape::NTuple{2}, indextype, entrytype, maxnnz) - pointers = ones(indextype, shape[2] + 1) - storedinds = Vector{indextype}(undef, maxnnz) - storedvals = Vector{entrytype}(undef, maxnnz) - return SparseMatrixCSC(shape..., pointers, storedinds, storedvals) +@inline function _allocres(shape::Union{NTuple{1},NTuple{2}}, indextype, entrytype, maxnnz) + X = spzeros(entrytype, indextype, shape) + resize!(storedinds(X), maxnnz) + resize!(storedvals(X), maxnnz) + return X end # (4) _map_zeropres!/_map_notzeropres! specialized for a single sparse vector/matrix "Stores only the nonzero entries of `map(f, Array(A))` in `C`." function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where Tf - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) Ck = 1 @inbounds for j in columns(C) setcolptr!(C, j, Ck) @@ -255,7 +255,7 @@ function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where Tf end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end """ Densifies `C`, storing `fillvalue` in place of each unstored entry in `A` and @@ -274,7 +274,7 @@ function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMa end # NOTE: Combining the fill! above into the loop above to avoid multiple sweeps over / # nonsequential access of storedvals(C) does not appear to improve performance. - return C + return _checkbuffers(C) end # helper functions for these methods and some of those below @inline _densecoloffsets(A::SparseVector) = 0 @@ -297,7 +297,7 @@ end # (5) _map_zeropres!/_map_notzeropres! specialized for a pair of sparse vectors/matrices function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) rowsentinelA = convert(indtype(A), numrows(C) + 1) rowsentinelB = convert(indtype(B), numrows(C) + 1) Ck = 1 @@ -336,7 +336,7 @@ function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVe end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf # Build dense matrix structure in C, expanding storage if necessary @@ -368,13 +368,13 @@ function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMa Cx != fillvalue && (storedvals(C)[jo + Ci] = Cx) end end - return C + return _checkbuffers(C) end # (6) _map_zeropres!/_map_notzeropres! for more than two sparse matrices / vectors function _map_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) rowsentinel = numrows(C) + 1 Ck = 1 stopks = _colstartind_all(1, As) @@ -398,7 +398,7 @@ function _map_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} # Build dense matrix structure in C, expanding storage if necessary @@ -421,7 +421,7 @@ function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{Spars activerow = min(rows...) end end - return C + return _checkbuffers(C) end # helper methods for map/map! methods just above @@ -462,7 +462,7 @@ end # (7) _broadcast_zeropres!/_broadcast_notzeropres! specialized for a single (input) sparse vector/matrix function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where Tf isempty(C) && return _finishempty!(C) - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) # C and A cannot have the same shape, as we directed that case to map in broadcast's # entry point; here we need efficiently handle only heterogeneous C-A combinations where # one or both of C and A has at least one singleton dimension. @@ -509,7 +509,7 @@ function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat) where Tf # For information on this code, see comments in similar code in _broadcast_zeropres! above @@ -540,14 +540,14 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseV end end end - return C + return _checkbuffers(C) end # (8) _broadcast_zeropres!/_broadcast_notzeropres! specialized for a pair of (input) sparse vectors/matrices function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf isempty(C) && return _finishempty!(C) - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) rowsentinelA = convert(indtype(A), numrows(C) + 1) rowsentinelB = convert(indtype(B), numrows(C) + 1) # C, A, and B cannot all have the same shape, as we directed that case to map in broadcast's @@ -711,7 +711,7 @@ function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::Sp end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf # For information on this code, see comments in similar code in _broadcast_zeropres! above @@ -810,7 +810,7 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseV end end end - return C + return _checkbuffers(C) end _finishempty!(C::SparseVector) = C _finishempty!(C::AbstractSparseMatrixCSC) = (fill!(getcolptr(C), 1); C) @@ -861,7 +861,7 @@ end # (9) _broadcast_zeropres!/_broadcast_notzeropres! for more than two (input) sparse vectors/matrices function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} isempty(C) && return _finishempty!(C) - spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) + spaceC::Int = length(nonzeros(C)) expandsverts = _expandsvert_all(C, As) expandshorzs = _expandshorz_all(C, As) rowsentinel = numrows(C) + 1 @@ -909,7 +909,7 @@ function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMa end @inbounds setcolptr!(C, numcols(C) + 1, Ck) trimstorage!(C, Ck - 1) - return C + return _checkbuffers(C) end function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} isempty(C) && return _finishempty!(C) @@ -950,7 +950,7 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg end end end - return C + return _checkbuffers(C) end # helper method for broadcast/broadcast! methods just above diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 0ac2806b77a04..73fc0c7dee03a 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -935,16 +935,15 @@ function triu(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} end rowval = Vector{Ti}(undef, nnz) nzval = Vector{Tv}(undef, nnz) - A = SparseMatrixCSC(m, n, colptr, rowval, nzval) for col = max(k+1,1) : n c1 = getcolptr(S)[col] - for c2 in nzrange(A, col) - rowvals(A)[c2] = rowvals(S)[c1] - nonzeros(A)[c2] = nonzeros(S)[c1] + for c2 in colptr[col]:colptr[col+1]-1 + rowval[c2] = rowvals(S)[c1] + nzval[c2] = nonzeros(S)[c1] c1 += 1 end end - A + SparseMatrixCSC(m, n, colptr, rowval, nzval) end function tril(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} @@ -965,17 +964,16 @@ function tril(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} end rowval = Vector{Ti}(undef, nnz) nzval = Vector{Tv}(undef, nnz) - A = SparseMatrixCSC(m, n, colptr, rowval, nzval) for col = 1 : min(n, m+k) c1 = getcolptr(S)[col+1]-1 - l2 = getcolptr(A)[col+1]-1 - for c2 = 0 : l2 - getcolptr(A)[col] - rowvals(A)[l2 - c2] = rowvals(S)[c1] - nonzeros(A)[l2 - c2] = nonzeros(S)[c1] + l2 = colptr[col+1]-1 + for c2 = 0 : l2 - colptr[col] + rowval[l2 - c2] = rowvals(S)[c1] + nzval[l2 - c2] = nonzeros(S)[c1] c1 -= 1 end end - A + SparseMatrixCSC(m, n, colptr, rowval, nzval) end ## diff @@ -1340,7 +1338,6 @@ end ## kron @inline function kron!(C::SparseMatrixCSC, A::AbstractSparseMatrixCSC, B::AbstractSparseMatrixCSC) - nnzC = nnz(A)*nnz(B) mA, nA = size(A); mB, nB = size(B) mC, nC = mA*mB, nA*nB @@ -1348,11 +1345,9 @@ end nzvalC = nonzeros(C) colptrC = getcolptr(C) - @boundscheck begin - length(colptrC) == nC+1 || throw(DimensionMismatch("expect C to be preallocated with $(nC+1) colptrs ")) - length(rowvalC) == nnzC || throw(DimensionMismatch("expect C to be preallocated with $(nnzC) rowvals")) - length(nzvalC) == nnzC || throw(DimensionMismatch("expect C to be preallocated with $(nnzC) nzvals")) - end + nnzC = nnz(A)*nnz(B) + resize!(nzvalC, nnzC) + resize!(rowvalC, nnzC) col = 1 @inbounds for j = 1:nA @@ -1381,16 +1376,13 @@ end end @inline function kron!(z::SparseVector, x::SparseVector, y::SparseVector) - nnzx = nnz(x); nnzy = nnz(y); nnzz = nnz(z); + nnzx = nnz(x); nnzy = nnz(y); nzind = nonzeroinds(z) nzval = nonzeros(z) - @boundscheck begin - nnzval = length(nzval); nnzind = length(nzind) - nnzz = nnzx*nnzy - nnzval == nnzz || throw(DimensionMismatch("expect z to be preallocated with $nnzz nonzeros")) - nnzind == nnzz || throw(DimensionMismatch("expect z to be preallocated with $nnzz nonzeros")) - end + nnzz = nnzx*nnzy + resize!(nzind, nnzz) + resize!(nzval, nnzz) @inbounds for i = 1:nnzx, j = 1:nnzy this_ind = (i-1)*nnzy+j @@ -1402,17 +1394,12 @@ end # sparse matrix ⊗ sparse matrix function kron(A::AbstractSparseMatrixCSC{T1,S1}, B::AbstractSparseMatrixCSC{T2,S2}) where {T1,S1,T2,S2} - nnzC = nnz(A)*nnz(B) mA, nA = size(A); mB, nB = size(B) mC, nC = mA*mB, nA*nB Tv = typeof(one(T1)*one(T2)) Ti = promote_type(S1,S2) - colptrC = Vector{Ti}(undef, nC+1) - rowvalC = Vector{Ti}(undef, nnzC) - nzvalC = Vector{Tv}(undef, nnzC) - colptrC[1] = 1 - # skip sparse_check - C = SparseMatrixCSC{Tv, Ti}(mC, nC, colptrC, rowvalC, nzvalC) + C = spzeros(Tv, Ti, mC, nC) + sizehint!(C, nnz(A)*nnz(B)) return @inbounds kron!(C, A, B) end diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 888db226ddd14..58dfd88abd339 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -25,10 +25,9 @@ struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti} function SparseMatrixCSC{Tv,Ti}(m::Integer, n::Integer, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv}) where {Tv,Ti<:Integer} - @noinline throwsz(str, lbl, k) = - throw(ArgumentError("number of $str ($lbl) must be ≥ 0, got $k")) - m < 0 && throwsz("rows", 'm', m) - n < 0 && throwsz("columns", 'n', n) + sparse_check_Ti(m, n, Ti) + _goodbuffers(Int(m), Int(n), colptr, rowval, nzval) || + throw(ArgumentError("Illegal buffers for SparseMatrixCSC construction $n $colptr $rowval $nzval")) new(Int(m), Int(n), colptr, rowval, nzval) end end @@ -80,6 +79,15 @@ end size(S::SparseMatrixCSC) = (getfield(S, :m), getfield(S, :n)) +_goodbuffers(S::SparseMatrixCSC) = _goodbuffers(size(S)..., getcolptr(S), getrowval(S), nonzeros(S)) +_checkbuffers(S::SparseMatrixCSC) = (@assert _goodbuffers(S); S) + +function _goodbuffers(m, n, colptr, rowval, nzval) + (length(colptr) == n + 1 && colptr[end] - 1 == length(rowval) == length(nzval)) + # stronger check for debugging purposes + # && all(issorted(@view rowval[colptr[i]:colptr[i+1]-1]) for i=1:n) +end + # Define an alias for views of a SparseMatrixCSC which include all rows and a unit range of the columns. # Also define a union of SparseMatrixCSC and this view since many methods can be defined efficiently for # this union by extracting the fields via the get function: getcolptr, getrowval, and getnzval. The key @@ -220,6 +228,7 @@ Base.replace_in_print_matrix(A::AbstractSparseMatrix, i::Integer, j::Integer, s: Base.isstored(A, i, j) ? s : Base.replace_with_centered_mark(s) function Base.show(io::IO, ::MIME"text/plain", S::AbstractSparseMatrixCSC) + _checkbuffers(S) xnnz = nnz(S) m, n = size(S) print(io, m, "×", n, " ", typeof(S), " with ", xnnz, " stored ", @@ -295,6 +304,7 @@ function _show_with_braille_patterns(io::IOContext, S::AbstractSparseMatrixCSC) end function Base.show(io::IOContext, S::AbstractSparseMatrixCSC) + _checkbuffers(S) if max(size(S)...) < 16 && !(get(io, :compact, false)::Bool) ioc = IOContext(io, :compact => true) println(ioc) @@ -307,7 +317,7 @@ end ## Reshape -function sparse_compute_reshaped_colptr_and_rowval(colptrS::Vector{Ti}, rowvalS::Vector{Ti}, +function sparse_compute_reshaped_colptr_and_rowval!(colptrS::Vector{Ti}, rowvalS::Vector{Ti}, mS::Int, nS::Int, colptrA::Vector{Ti}, rowvalA::Vector{Ti}, mA::Int, nA::Int) where Ti lrowvalA = length(rowvalA) @@ -350,7 +360,7 @@ function copy(ra::ReshapedArray{<:Any,2,<:AbstractSparseMatrixCSC}) rowval = similar(rowvals(a)) nzval = copy(nonzeros(a)) - sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, getcolptr(a), rowvals(a), mA, nA) + sparse_compute_reshaped_colptr_and_rowval!(colptr, rowval, mS, nS, getcolptr(a), rowvals(a), mA, nA) return SparseMatrixCSC(mS, nS, colptr, rowval, nzval) end @@ -377,7 +387,7 @@ function copyto!(A::AbstractSparseMatrixCSC, B::AbstractSparseMatrixCSC) copyto!(rowvals(A), rowvals(B)) else # This is like a "reshape B into A". - sparse_compute_reshaped_colptr_and_rowval(getcolptr(A), rowvals(A), size(A, 1), size(A, 2), getcolptr(B), rowvals(B), size(B, 1), size(B, 2)) + sparse_compute_reshaped_colptr_and_rowval!(getcolptr(A), rowvals(A), size(A, 1), size(A, 2), getcolptr(B), rowvals(B), size(B, 1), size(B, 2)) end else widelength(A) >= widelength(B) || throw(BoundsError()) @@ -407,10 +417,10 @@ function copyto!(A::AbstractSparseMatrixCSC, B::AbstractSparseMatrixCSC) @inbounds for i in 2:length(getcolptr(A)) getcolptr(A)[i] += nnzB - lastmodptrA end - sparse_compute_reshaped_colptr_and_rowval(getcolptr(A), rowvals(A), size(A, 1), lastmodcolA-1, getcolptr(B), rowvals(B), size(B, 1), size(B, 2)) + sparse_compute_reshaped_colptr_and_rowval!(getcolptr(A), rowvals(A), size(A, 1), lastmodcolA-1, getcolptr(B), rowvals(B), size(B, 1), size(B, 2)) end copyto!(nonzeros(A), nonzeros(B)) - return A + return _checkbuffers(A) end copyto!(A::AbstractMatrix, B::AbstractSparseMatrixCSC) = _sparse_copyto!(A, B) @@ -471,7 +481,7 @@ function _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew} end # parent methods for similar that preserves only storage space (for when new dims are 2-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) + sizehint!(spzeros(TvNew, TiNew, dims...), length(nonzeros(S))) # parent method for similar that allocates an empty sparse vector (for when new dims are 1-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) @@ -496,6 +506,12 @@ similar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, m::Integer) wh similar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer) where {TvNew,TiNew} = _sparsesimilar(S, TvNew, TiNew, (m, n)) +function Base.sizehint!(S::SparseMatrixCSC, n::Integer) + nhint = min(n, widelength(S)) + sizehint!(getrowval(S), nhint) + sizehint!(nonzeros(S), nhint) + return S +end # converting between SparseMatrixCSC types SparseMatrixCSC(S::AbstractSparseMatrixCSC) = copy(S) @@ -658,6 +674,7 @@ SparseMatrixCSC{Tv,Ti}(M::Transpose{<:Any,<:AbstractSparseMatrixCSC}) where {Tv, # converting from SparseMatrixCSC to other matrix types function Matrix(S::AbstractSparseMatrixCSC{Tv}) where Tv + _checkbuffers(S) A = Matrix{Tv}(undef, size(S, 1), size(S, 2)) copyto!(A, S) return A @@ -1016,6 +1033,8 @@ respectively. Simultaneously fixes the one-position-forward shift in `getcolptr( """ @noinline function _distributevals_halfperm!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{TvA,Ti}, q::AbstractVector{<:Integer}, f::Function) where {Tv,TvA,Ti} + resize!(nonzeros(X), nnz(A)) + resize!(rowvals(X), nnz(A)) @inbounds for Xi in 1:size(A, 2) Aj = q[Xi] for Ak in nzrange(A, Aj) @@ -1035,16 +1054,8 @@ function ftranspose!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixC throw(DimensionMismatch(string("destination argument `X`'s column count, ", "`size(X, 2) (= $(size(X, 2)))`, must match source argument `A`'s row count, `size(A, 1) (= $(size(A, 1)))`"))) elseif size(X, 1) != size(A, 2) - throw(DimensionMismatch(string("destination argument `X`'s row count, - `size(X, 1) (= $(size(X, 1)))`, must match source argument `A`'s column count, `size(A, 2) (= $(size(A, 2)))`"))) - elseif length(rowvals(X)) < nnz(A) - throw(ArgumentError(string("the length of destination argument `X`'s `rowval` ", - "array, `length(rowvals(X)) (= $(length(rowvals(X))))`, must be greater than or ", - "equal to source argument `A`'s allocated entry count, `nnz(A) (= $(nnz(A)))`"))) - elseif length(nonzeros(X)) < nnz(A) - throw(ArgumentError(string("the length of destination argument `X`'s `nzval` ", - "array, `length(nonzeros(X)) (= $(length(nonzeros(X))))`, must be greater than or ", - "equal to source argument `A`'s allocated entry count, `nnz(A) (= $(nnz(A)))`"))) + throw(DimensionMismatch(string("destination argument `X`'s row count, ", + "`size(X, 1) (= $(size(X, 1)))`, must match source argument `A`'s column count, `size(A, 2) (= $(size(A, 2)))`"))) end halfperm!(X, A, 1:size(A, 2), f) end @@ -1055,8 +1066,9 @@ adjoint!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}) w function ftranspose(A::AbstractSparseMatrixCSC{TvA,Ti}, f::Function, eltype::Type{Tv} = TvA) where {Tv,TvA,Ti} X = SparseMatrixCSC(size(A, 2), size(A, 1), ones(Ti, size(A, 1)+1), - Vector{Ti}(undef, nnz(A)), - Vector{Tv}(undef, nnz(A))) + Vector{Ti}(undef, 0), + Vector{Tv}(undef, 0)) + sizehint!(X, nnz(A)) halfperm!(X, A, 1:size(A, 2), f) end adjoint(A::AbstractSparseMatrixCSC) = Adjoint(A) @@ -1274,10 +1286,11 @@ function permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{ p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatdest_permute!(A, X) _checkargs_sourcecompatperms_permute!(A, p, q) - C = SparseMatrixCSC(size(A, 2), size(A, 1), - ones(Ti, size(A, 1) + 1), - Vector{Ti}(undef, nnz(A)), - Vector{Tv}(undef, nnz(A))) + # bypass strict buffer checking + C = spzeros(Tv, Ti, size(A,2), size(A,1)) + resize!(getrowval(C), nnz(A)) + resize!(getnzval(C), nnz(A)) + _checkargs_permutationsvalid_permute!(p, getcolptr(C), q, getcolptr(X)) unchecked_noalias_permute!(X, A, p, q, C) end @@ -1293,10 +1306,9 @@ end function permute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) - C = SparseMatrixCSC(size(A, 2), size(A, 1), - ones(Ti, size(A, 1) + 1), - Vector{Ti}(undef, nnz(A)), - Vector{Tv}(undef, nnz(A))) + C = spzeros(Tv, Ti, size(A,2), size(A,1)) + resize!(getrowval(C), nnz(A)) + resize!(getnzval(C), nnz(A)) workcolptr = Vector{Ti}(undef, size(A, 2) + 1) _checkargs_permutationsvalid_permute!(p, getcolptr(C), q, workcolptr) unchecked_aliasing_permute!(A, p, q, C, workcolptr) @@ -1355,14 +1367,14 @@ julia> permute(A, [1, 2, 3, 4], [4, 3, 2, 1]) function permute(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) - X = SparseMatrixCSC(size(A, 1), size(A, 2), - ones(Ti, size(A, 2) + 1), - Vector{Ti}(undef, nnz(A)), - Vector{Tv}(undef, nnz(A))) - C = SparseMatrixCSC(size(A, 2), size(A, 1), - ones(Ti, size(A, 1) + 1), - Vector{Ti}(undef, nnz(A)), - Vector{Tv}(undef, nnz(A))) + # bypass strict buffer checking + X = spzeros(Tv, Ti, size(A,1), size(A,2)) + resize!(getrowval(X), nnz(A)) + resize!(getnzval(X), nnz(A)) + # bypass strict buffer checking + C = spzeros(Tv, Ti, size(A,2), size(A,1)) + resize!(getrowval(C), nnz(A)) + resize!(getnzval(C), nnz(A)) _checkargs_permutationsvalid_permute!(p, getcolptr(C), q, getcolptr(X)) unchecked_noalias_permute!(X, A, p, q, C) end @@ -1455,6 +1467,7 @@ For an out-of-place version, see [`dropzeros`](@ref). For algorithmic information, see `fkeep!`. """ dropzeros!(A::AbstractSparseMatrixCSC) = fkeep!(A, (i, j, x) -> !iszero(x)) + """ dropzeros(A::AbstractSparseMatrixCSC;) @@ -2480,7 +2493,7 @@ function permute_rows!(S::AbstractSparseMatrixCSC{Tv,Ti}, pI::Vector{Int}) where k += 1 end end - S + return _checkbuffers(S) end function getindex_general(A::AbstractSparseMatrixCSC, I::AbstractVector, J::AbstractVector) @@ -2634,6 +2647,7 @@ function Base.fill!(V::SubArray{Tv, <:Any, <:AbstractSparseMatrixCSC{Tv}, <:Tupl else _spsetnz_setindex!(A, convert(Tv, x), I, J) end + return _checkbuffers(A) end """ Helper method for immediately preceding fill! method. For all (i,j) such that i in I and @@ -2917,7 +2931,7 @@ function setindex!(A::AbstractSparseMatrixCSC{Tv,Ti}, V::AbstractVecOrMat, Ix::U deleteat!(rowvalA, colptrA[end]:length(rowvalA)) deleteat!(nzvalA, colptrA[end]:length(nzvalA)) - return A + return _checkbuffers(A) end # Logical setindex! @@ -3026,7 +3040,7 @@ function setindex!(A::AbstractSparseMatrixCSC, x::AbstractArray, I::AbstractMatr deleteat!(rowvalB, bidx:n) end end - A + return _checkbuffers(A) end function setindex!(A::AbstractSparseMatrixCSC, x::AbstractArray, Ix::AbstractVector{<:Integer}) @@ -3137,7 +3151,7 @@ function setindex!(A::AbstractSparseMatrixCSC, x::AbstractArray, Ix::AbstractVec deleteat!(rowvalB, bidx:n) end end - A + return _checkbuffers(A) end ## dropstored! methods @@ -3173,7 +3187,7 @@ function dropstored!(A::AbstractSparseMatrixCSC, i::Integer, j::Integer) @inbounds getcolptr(A)[m] -= 1 end end - return A + return _checkbuffers(A) end """ dropstored!(A::AbstractSparseMatrixCSC, I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer}) @@ -3260,7 +3274,7 @@ function dropstored!(A::AbstractSparseMatrixCSC, deleteat!(rowvalA, rowidx:nnzA) deleteat!(nzvalA, rowidx:nnzA) end - return A + return _checkbuffers(A) end dropstored!(A::AbstractSparseMatrixCSC, i::Integer, J::AbstractVector{<:Integer}) = dropstored!(A, [i], J) dropstored!(A::AbstractSparseMatrixCSC, I::AbstractVector{<:Integer}, j::Integer) = dropstored!(A, I, [j]) @@ -3694,74 +3708,6 @@ function tr(A::AbstractSparseMatrixCSC{Tv}) where Tv return s end - -# Sort all the indices in each column of a CSC sparse matrix -# sortSparseMatrixCSC!(A, sortindices = :sortcols) # Sort each column with sort() -# sortSparseMatrixCSC!(A, sortindices = :doubletranspose) # Sort with a double transpose -function sortSparseMatrixCSC!(A::AbstractSparseMatrixCSC{Tv,Ti}; sortindices::Symbol = :sortcols) where {Tv,Ti} - if sortindices === :doubletranspose - nB, mB = size(A) - B = SparseMatrixCSC(mB, nB, Vector{Ti}(undef, nB+1), similar(rowvals(A)), similar(nonzeros(A))) - transpose!(B, A) - transpose!(A, B) - return A - end - - m, n = size(A) - colptr = getcolptr(A); rowval = rowvals(A); nzval = nonzeros(A) - - index = zeros(Ti, m) - row = zeros(Ti, m) - val = zeros(Tv, m) - - perm = Base.Perm(Base.ord(isless, identity, false, Base.Order.Forward), row) - - @inbounds for i = 1:n - nzr = nzrange(A, i) - numrows = length(nzr) - if numrows <= 1 - continue - elseif numrows == 2 - f = first(nzr) - s = f+1 - if rowval[f] > rowval[s] - rowval[f], rowval[s] = rowval[s], rowval[f] - nzval[f], nzval[s] = nzval[s], nzval[f] - end - continue - end - resize!(row, numrows) - resize!(index, numrows) - - jj = 1 - @simd for j = nzr - row[jj] = rowval[j] - val[jj] = nzval[j] - jj += 1 - end - - if numrows <= 16 - alg = Base.Sort.InsertionSort - else - alg = Base.Sort.QuickSort - end - - # Reset permutation - index .= 1:numrows - - sort!(index, alg, perm) - - jj = 1 - @simd for j = nzr - rowval[j] = row[index[jj]] - nzval[j] = val[index[jj]] - jj += 1 - end - end - - return A -end - ## rotations function rot180(A::AbstractSparseMatrixCSC) @@ -3837,7 +3783,7 @@ function circshift!(O::AbstractSparseMatrixCSC, X::AbstractSparseMatrixCSC, (r,c @inbounds for i=1:size(O, 2) subvector_shifter!(rowvals(O), nonzeros(O), getcolptr(O)[i], getcolptr(O)[i+1]-1, size(O, 1), r) end - return O + return _checkbuffers(O) end circshift!(O::AbstractSparseMatrixCSC, X::AbstractSparseMatrixCSC, (r,)::Base.DimsInteger{1}) = circshift!(O, X, (r,0)) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 52142553e5019..f893fb04eadf3 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -84,6 +84,13 @@ rowvals(x::SparseVectorUnion) = nonzeroinds(x) indtype(x::SparseColumnView) = indtype(parent(x)) indtype(x::SparseVectorView) = indtype(parent(x)) + +function Base.sizehint!(v::SparseVector, newlen::Integer) + sizehint!(nonzeroinds(v), newlen) + sizehint!(nonzeros(v), newlen) + return v +end + ## similar # # parent method for similar that preserves stored-entry structure (for when new and old dims match) @@ -92,10 +99,11 @@ _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}) where {TvNew,TiNew # parent method for similar that preserves nothing (for when new dims are 1-d) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) -# parent method for similar that preserves storage space (for when new dims are 2-d) -_sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) - +# parent method for similar that preserves storage space (for old and new dims differ, and new is 2d) +function _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} + S1 = SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) + return sizehint!(S1, min(widelength(S1), length(nonzeroinds(S)))) +end # The following methods hook into the AbstractArray similar hierarchy. The first method # covers similar(A[, Tv]) calls, which preserve stored-entry structure, and the latter # methods cover similar(A[, Tv], shape...) calls, which preserve nothing if the dims diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index a622d2bc8bcc0..f2754ba5ade81 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -48,7 +48,7 @@ end S = sparse(I, 3, 3) fill!(S, 0) @test iszero(S) # test success with stored zeros via fill! - @test iszero(SparseMatrixCSC(2, 2, [1,2,3], [1,2], [0,0,1])) # test success with nonzeros beyond data range + @test_throws ArgumentError iszero(SparseMatrixCSC(2, 2, [1,2,3], [1,2], [0,0,1])) # test failure with nonzeros beyond data range end @testset "isone specialization for SparseMatrixCSC" begin @test isone(sparse(I, 3, 3)) # test success @@ -673,8 +673,6 @@ end @testset "common error checking of [c]transpose! methods (ftranspose!)" begin @test_throws DimensionMismatch transpose!(A[:, 1:(smalldim - 1)], A) @test_throws DimensionMismatch transpose!(A[1:(smalldim - 1), 1], A) - @test_throws ArgumentError transpose!((B = similar(A); resize!(rowvals(B), nnz(A) - 1); B), A) - @test_throws ArgumentError transpose!((B = similar(A); resize!(nonzeros(B), nnz(A) - 1); B), A) end @testset "common error checking of permute[!] methods / source-perm compat" begin @test_throws DimensionMismatch permute(A, p[1:(end - 1)], q) @@ -2416,19 +2414,6 @@ end @test String(take!(io)) == "⠛⠛" end -@testset "check buffers" for n in 1:3 - local A - rowval = [1,2,3] - nzval1 = Int[] - nzval2 = [1,1,1] - A = SparseMatrixCSC(n, n, [1:n+1;], rowval, nzval1) - @test nnz(A) == n - @test_throws BoundsError A[n,n] - A = SparseMatrixCSC(n, n, [1:n+1;], rowval, nzval2) - @test nnz(A) == n - @test A == Matrix(I, n, n) -end - @testset "reverse search direction if step < 0 #21986" begin local A, B A = guardseed(1234) do @@ -2530,8 +2515,6 @@ end # count should throw for sparse arrays for which zero(eltype) does not exist @test_throws MethodError count(SparseMatrixCSC(2, 2, Int[1, 2, 3], Int[1, 2], Any[true, true])) @test_throws MethodError count(SparseVector(2, Int[1], Any[true])) - # count should run only over nonzeros(S)[1:nnz(S)], not nonzeros(S) in full - @test count(SparseMatrixCSC(2, 2, Int[1, 2, 3], Int[1, 2], Bool[true, true, true])) == 2 end @testset "sparse findprev/findnext operations" begin @@ -2599,15 +2582,6 @@ end @test sum(s, dims=2) == reshape([1, 2, 3], 3, 1) end -@testset "mapreduce of sparse matrices with trailing elements in nzval #26534" begin - B = SparseMatrixCSC{Int,Int}(2, 3, - [1, 3, 4, 5], - [1, 2, 1, 2, 999, 999, 999, 999], - [1, 2, 3, 6, 999, 999, 999, 999] - ) - @test maximum(B) == 6 -end - _length_or_count_or_five(::Colon) = 5 _length_or_count_or_five(x::AbstractVector{Bool}) = count(x) _length_or_count_or_five(x) = length(x) @@ -2883,19 +2857,6 @@ end @test sparse(deepwrap(A)) == Matrix(deepwrap(B)) end -@testset "unary operations on matrices where length(nzval)>nnz" begin - # this should create a sparse matrix with length(nzval)>nnz - A = SparseMatrixCSC(Complex{BigInt}[1+im 2+2im]')'[1:1, 2:2] - # ...ensure it does! If necessary, the test needs to be updated to use - # another mechanism to create a suitable A. - resize!(nonzeros(A), 2) - @assert length(nonzeros(A)) > nnz(A) - @test -A == fill(-2-2im, 1, 1) - @test conj(A) == fill(2-2im, 1, 1) - conj!(A) - @test A == fill(2-2im, 1, 1) -end - @testset "issue #31453" for T in [UInt8, Int8, UInt16, Int16, UInt32, Int32] i = Int[1, 2] j = Int[2, 1] @@ -2945,14 +2906,8 @@ end @test_throws ArgumentError SparseMatrixCSC(10, 3, [1,2,1,2], Int[], Float64[]) # rowwal (and nzval) short @test_throws ArgumentError SparseMatrixCSC(10, 3, [1,2,2,4], [1,2], Float64[]) - # nzval short - @test SparseMatrixCSC(10, 3, [1,2,2,4], [1,2,3], Float64[]) !== nothing - # length(rowval) >= typemax - @test_throws ArgumentError SparseMatrixCSC(5, 1, Int8[1,2], fill(Int8(1),127), Int[1,2,3]) - @test SparseMatrixCSC{Int,Int8}(5, 1, Int8[1,2], fill(Int8(1),127), Int[1,2,3]) != 0 # length(nzval) >= typemax - @test_throws ArgumentError SparseMatrixCSC(5, 1, Int8[1,2], Int8[1], fill(7, 127)) - @test SparseMatrixCSC{Int,Int8}(5, 1, Int8[1,2], Int8[1], fill(7, 127)) != 0 + @test_throws ArgumentError SparseMatrixCSC(5, 1, Int8[1,2], fill(Int8(1), 127), fill(7, 127)) # length(I) >= typemax @test_throws ArgumentError sparse(UInt8.(1:255), fill(UInt8(1), 255), fill(1, 255)) diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 6d29633bb04e0..03aed95a43a83 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -1419,14 +1419,14 @@ end # test entry points to similar with entry type, index type, and non-Dims shape specification @test similar(A, Float32, Int8, 6, 6) == similar(A, Float32, Int8, (6, 6)) @test similar(A, Float32, Int8, 6) == similar(A, Float32, Int8, (6,)) - # test similar with Dims{2} specification (preserves storage space only, not stored-entry structure) + # test similar with Dims{2} specification (preserves allocated storage space only, not stored-entry structure) simA = similar(A, (6,6)) @test typeof(simA) == SparseMatrixCSC{eltype(nonzeros(A)),eltype(nonzeroinds(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) @test length(rowvals(simA)) == 0 @test length(nonzeros(simA)) == 0 - # test similar with entry type and Dims{2} specification (preserves storage space only) + # test similar with entry type and Dims{2} specification (preserves allocated storage space only) simA = similar(A, Float32, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32,eltype(nonzeroinds(A))} @test size(simA) == (6,6) diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index af0dff10ed473..d8dafa853702d 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -1094,60 +1094,46 @@ function Vector{T}(D::Dense{T}) where T end Vector(D::Dense{T}) where {T} = Vector{T}(D) +function _extract_args(s) + return (s.nrow, s.ncol, increment(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false)), + increment(unsafe_wrap(Array, s.i, (s.nzmax,), own = false)), + copy(unsafe_wrap(Array, s.x, (s.nzmax,), own = false))) +end + +# Trim extra elements in rowval and nzval left around sometimes by CHOLMOD rutines +function _trim_nz_builder!(m, n, colptr, rowval, nzval) + l = colptr[end] - 1 + resize!(rowval, l) + resize!(nzval, l) + SparseMatrixCSC(m, n, colptr, rowval, nzval) +end + function SparseMatrixCSC{Tv,SuiteSparse_long}(A::Sparse{Tv}) where Tv s = unsafe_load(pointer(A)) if s.stype != 0 throw(ArgumentError("matrix has stype != 0. Convert to matrix " * "with stype == 0 before converting to SparseMatrixCSC")) end - - B = SparseMatrixCSC(s.nrow, s.ncol, - increment(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false)), - increment(unsafe_wrap(Array, s.i, (s.nzmax,), own = false)), - copy(unsafe_wrap(Array, s.x, (s.nzmax,), own = false))) - - if s.sorted == 0 - return SparseArrays.sortSparseMatrixCSC!(B) - else - return B - end + args = _extract_args(s) + s.sorted == 0 && _sort_buffers!(args...); + return _trim_nz_builder!(args...) end function Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A::Sparse{Float64}) s = unsafe_load(pointer(A)) - if !issymmetric(A) - throw(ArgumentError("matrix is not symmetric")) - end - - B = Symmetric(SparseMatrixCSC(s.nrow, s.ncol, - increment(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false)), - increment(unsafe_wrap(Array, s.i, (s.nzmax,), own = false)), - copy(unsafe_wrap(Array, s.x, (s.nzmax,), own = false))), s.stype > 0 ? :U : :L) - - if s.sorted == 0 - return SparseArrays.sortSparseMatrixCSC!(B.data) - else - return B - end + issymmetric(A) || throw(ArgumentError("matrix is not symmetric")) + args = _extract_args(s) + s.sorted == 0 && _sort_buffers!(args...) + Symmetric(_trim_nz_builder!(args...), s.stype > 0 ? :U : :L) end convert(T::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}}, A::Sparse{Float64}) = T(A) function Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}(A::Sparse{Tv}) where Tv<:VTypes s = unsafe_load(pointer(A)) - if !ishermitian(A) - throw(ArgumentError("matrix is not Hermitian")) - end - - B = Hermitian(SparseMatrixCSC(s.nrow, s.ncol, - increment(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false)), - increment(unsafe_wrap(Array, s.i, (s.nzmax,), own = false)), - copy(unsafe_wrap(Array, s.x, (s.nzmax,), own = false))), s.stype > 0 ? :U : :L) - - if s.sorted == 0 - return SparseArrays.sortSparseMatrixCSC!(B.data) - else - return B - end + ishermitian(A) || throw(ArgumentError("matrix is not Hermitian")) + args = _extract_args(s) + s.sorted == 0 && _sort_buffers!(args...) + Hermitian(_trim_nz_builder!(args...), s.stype > 0 ? :U : :L) end convert(T::Type{Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}}, A::Sparse{Tv}) where {Tv<:VTypes} = T(A) @@ -1156,14 +1142,14 @@ function sparse(A::Sparse{Float64}) # Notice! Cannot be type stable because of s if s.stype == 0 return SparseMatrixCSC{Float64,SuiteSparse_long}(A) end - return Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A) + Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A) end function sparse(A::Sparse{ComplexF64}) # Notice! Cannot be type stable because of stype s = unsafe_load(pointer(A)) if s.stype == 0 return SparseMatrixCSC{ComplexF64,SuiteSparse_long}(A) end - return Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,SuiteSparse_long}}(A) + Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,SuiteSparse_long}}(A) end function sparse(F::Factor) s = unsafe_load(pointer(F)) @@ -1175,7 +1161,8 @@ function sparse(F::Factor) L, d = getLd!(LD) A = (L * Diagonal(d)) * L' end - SparseArrays.sortSparseMatrixCSC!(A) + # no need to sort buffers here, as A isa SparseMatrixCSC + # and it is taken care in sparse p = get_perm(F) if p != [1:s.n;] pinv = Vector{Int}(undef, length(p)) @@ -1968,4 +1955,57 @@ end (*)(A::SparseVecOrMat{Float64,Ti}, B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) +# Sort all the indices in each column for the construction of a CSC sparse matrix +function _sort_buffers!(m, n, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv}) where {Ti <: Integer, Tv} + index = Base.zeros(Ti, m) + row = Base.zeros(Ti, m) + val = Base.zeros(Tv, m) + + perm = Base.Perm(Base.ord(isless, identity, false, Base.Order.Forward), row) + + @inbounds for i = 1:n + nzr = colptr[i]:colptr[i+1]-1 + numrows = length(nzr) + if numrows <= 1 + continue + elseif numrows == 2 + f = first(nzr) + s = f+1 + if rowval[f] > rowval[s] + rowval[f], rowval[s] = rowval[s], rowval[f] + nzval[f], nzval[s] = nzval[s], nzval[f] + end + continue + end + resize!(row, numrows) + resize!(index, numrows) + + jj = 1 + @simd for j = nzr + row[jj] = rowval[j] + val[jj] = nzval[j] + jj += 1 + end + + if numrows <= 16 + alg = Base.Sort.InsertionSort + else + alg = Base.Sort.QuickSort + end + + # Reset permutation + index .= 1:numrows + + Base.sort!(index, alg, perm) + + jj = 1 + @simd for j = nzr + rowval[j] = row[index[jj]] + nzval[j] = val[index[jj]] + jj += 1 + end + end +end + + end #module diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index 501be8860436e..edc31f98c5b96 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -795,12 +795,13 @@ end end end -@testset "Check inputs to Sparse. Related to #20024" for A_ in ( - SparseMatrixCSC(2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1,2], Float64[]), - SparseMatrixCSC(2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1,2], Float64[1.0])) - args = (size(A_)..., getcolptr(A_) .- 1, rowvals(A_) .- 1, nonzeros(A_)) - @test_throws ArgumentError CHOLMOD.Sparse(args...) - @test_throws ArgumentError CHOLMOD.Sparse(A_) +@testset "Check inputs to Sparse. Related to #20024" for t_ in ( + (2, 2, [1, 2], CHOLMOD.SuiteSparse_long[], Float64[]), + (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1], Float64[]), + (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[], Float64[1.0]), + (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1], Float64[1.0])) + @test_throws ArgumentError SparseMatrixCSC(t_...) + @test_throws ArgumentError CHOLMOD.Sparse(t_[1], t_[2], t_[3] .- 1, t_[4] .- 1, t_[5]) end @testset "sparse right multiplication of Symmetric and Hermitian matrices #21431" begin From 79920db3ac9f1e1915d836c82bc401ba0cdc322f Mon Sep 17 00:00:00 2001 From: Stephan Hilb Date: Sun, 25 Apr 2021 16:19:32 +0200 Subject: [PATCH 253/439] implement faster floating-point `isless` (#39090) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement faster floating-point `isless` Previously `isless` relied on the C intrinsic `fpislt` in `src/runtime_intrinsics.c`, while the new implementation in Julia arguably generates better code, namely: 1. The NaN-check compiles to a single instruction + branch amenable for branch prediction in arguably most usecases (i.e. comparing non-NaN floats), thus speeding up execution. 2. The compiler now often manages to remove NaN-computation if the embedding code has already proven the arguments to be non-NaN. 3. The actual operation compares both arguments as sign-magnitude integers instead of case analysis based on the sign of one argument. This symmetric treatment may generate vectorized instructions for the sign-magnitude conversion depending on how the arguments are layed out. The actual behaviour of `isless` did not change and apart from the Julia-specific NaN-handling (which may be up for debate) the resulting total order corresponds to the IEEE-754 specified `totalOrder`. While the new implementation no longer generates fully branchless code I did not manage to construct a usecase where this was detrimental: the saved work seems to outweight the potential cost of a branch misprediction in all of my tests with various NaN-polluted data. Also auto-vectorization was not effective on the previous `fpislt` either. Quick benchmarks (AMD A10-7860K) on `sort`, avoiding the specialized algorithm: ```julia a = rand(1000); @btime sort($a, lt=(a,b)->isless(a,b)); # before: 56.030 μs (1 allocation: 7.94 KiB) # after: 40.853 μs (1 allocation: 7.94 KiB) a = rand(1000000); @btime sort($a, lt=(a,b)->isless(a,b)); # before: 159.499 ms (2 allocations: 7.63 MiB) # after: 120.536 ms (2 allocations: 7.63 MiB) a = [rand((rand(), NaN)) for _ in 1:1000000]; @btime sort($a, lt=(a,b)->isless(a,b)); # before: 111.925 ms (2 allocations: 7.63 MiB) # after: 77.669 ms (2 allocations: 7.63 MiB) ``` * Remove old intrinsic fpslt code Co-authored-by: Mustafa Mohamad --- .clang-format | 1 - base/compiler/tfuncs.jl | 1 - base/float.jl | 16 +++++++++++++--- src/intrinsics.cpp | 21 --------------------- src/intrinsics.h | 1 - src/julia_internal.h | 1 - src/runtime_intrinsics.c | 22 ---------------------- 7 files changed, 13 insertions(+), 50 deletions(-) diff --git a/.clang-format b/.clang-format index 0322d0f6749a9..39b5767a50291 100644 --- a/.clang-format +++ b/.clang-format @@ -109,7 +109,6 @@ StatementMacros: - checked_intrinsic_ctype - cvt_iintrinsic - fpiseq_n - - fpislt_n - ter_fintrinsic - ter_intrinsic_ctype - un_fintrinsic diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 921fbdfe32d03..214087781a44f 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -193,7 +193,6 @@ add_tfunc(ne_float, 2, 2, cmp_tfunc, 2) add_tfunc(lt_float, 2, 2, cmp_tfunc, 2) add_tfunc(le_float, 2, 2, cmp_tfunc, 2) add_tfunc(fpiseq, 2, 2, cmp_tfunc, 1) -add_tfunc(fpislt, 2, 2, cmp_tfunc, 1) add_tfunc(eq_float_fast, 2, 2, cmp_tfunc, 1) add_tfunc(ne_float_fast, 2, 2, cmp_tfunc, 1) add_tfunc(lt_float_fast, 2, 2, cmp_tfunc, 1) diff --git a/base/float.jl b/base/float.jl index fd5283fc82ab4..560016d9400f5 100644 --- a/base/float.jl +++ b/base/float.jl @@ -439,9 +439,19 @@ end isequal(x::Float16, y::Float16) = fpiseq(x, y) isequal(x::Float32, y::Float32) = fpiseq(x, y) isequal(x::Float64, y::Float64) = fpiseq(x, y) -isless( x::Float16, y::Float16) = fpislt(x, y) -isless( x::Float32, y::Float32) = fpislt(x, y) -isless( x::Float64, y::Float64) = fpislt(x, y) + +# interpret as sign-magnitude integer +@inline function _fpint(x) + IntT = inttype(typeof(x)) + ix = reinterpret(IntT, x) + return ifelse(ix < zero(IntT), ix ⊻ typemax(IntT), ix) +end + +@inline function isless(a::T, b::T) where T<:IEEEFloat + (isnan(a) || isnan(b)) && return !isnan(a) + + return _fpint(a) < _fpint(b) +end # Exact Float (Tf) vs Integer (Ti) comparisons # Assumes: diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index c0ee6ffad0ab8..d21e84593b5a2 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -58,7 +58,6 @@ static void jl_init_intrinsic_functions_codegen(void) float_func[lt_float_fast] = true; float_func[le_float_fast] = true; float_func[fpiseq] = true; - float_func[fpislt] = true; float_func[abs_float] = true; float_func[copysign_float] = true; float_func[ceil_llvm] = true; @@ -1165,26 +1164,6 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg ctx.builder.CreateICmpEQ(xi, yi)); } - case fpislt: { - *newtyp = jl_bool_type; - Type *it = INTT(t); - Value *xi = ctx.builder.CreateBitCast(x, it); - Value *yi = ctx.builder.CreateBitCast(y, it); - return ctx.builder.CreateOr( - ctx.builder.CreateAnd( - ctx.builder.CreateFCmpORD(x, x), - ctx.builder.CreateFCmpUNO(y, y)), - ctx.builder.CreateAnd( - ctx.builder.CreateFCmpORD(x, y), - ctx.builder.CreateOr( - ctx.builder.CreateAnd( - ctx.builder.CreateICmpSGE(xi, ConstantInt::get(it, 0)), - ctx.builder.CreateICmpSLT(xi, yi)), - ctx.builder.CreateAnd( - ctx.builder.CreateICmpSLT(xi, ConstantInt::get(it, 0)), - ctx.builder.CreateICmpUGT(xi, yi))))); - } - case and_int: return ctx.builder.CreateAnd(x, y); case or_int: return ctx.builder.CreateOr(x, y); case xor_int: return ctx.builder.CreateXor(x, y); diff --git a/src/intrinsics.h b/src/intrinsics.h index 1558769eb3643..a639e06a6316e 100644 --- a/src/intrinsics.h +++ b/src/intrinsics.h @@ -45,7 +45,6 @@ ALIAS(lt_float_fast, lt_float) \ ALIAS(le_float_fast, le_float) \ ADD_I(fpiseq, 2) \ - ADD_I(fpislt, 2) \ /* bitwise operators */ \ ADD_I(and_int, 2) \ ADD_I(or_int, 2) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index dc7236c6b6f40..43617b17dbefe 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1114,7 +1114,6 @@ JL_DLLEXPORT jl_value_t *jl_ne_float(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_lt_float(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_le_float(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_fpiseq(jl_value_t *a, jl_value_t *b); -JL_DLLEXPORT jl_value_t *jl_fpislt(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_not_int(jl_value_t *a); JL_DLLEXPORT jl_value_t *jl_and_int(jl_value_t *a, jl_value_t *b); diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 2337abe7d5704..22c3a8988b580 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -834,33 +834,11 @@ fpiseq_n(double, 64) #define fpiseq(a,b) \ sizeof(a) == sizeof(float) ? fpiseq32(a, b) : fpiseq64(a, b) -#define fpislt_n(c_type, nbits) \ - static inline int fpislt##nbits(c_type a, c_type b) JL_NOTSAFEPOINT \ - { \ - bits##nbits ua, ub; \ - ua.f = a; \ - ub.f = b; \ - if (!isnan(a) && isnan(b)) \ - return 1; \ - if (isnan(a) || isnan(b)) \ - return 0; \ - if (ua.d >= 0 && ua.d < ub.d) \ - return 1; \ - if (ua.d < 0 && ua.ud > ub.ud) \ - return 1; \ - return 0; \ - } -fpislt_n(float, 32) -fpislt_n(double, 64) -#define fpislt(a, b) \ - sizeof(a) == sizeof(float) ? fpislt32(a, b) : fpislt64(a, b) - bool_fintrinsic(eq,eq_float) bool_fintrinsic(ne,ne_float) bool_fintrinsic(lt,lt_float) bool_fintrinsic(le,le_float) bool_fintrinsic(fpiseq,fpiseq) -bool_fintrinsic(fpislt,fpislt) // bitwise operators #define and_op(a,b) a & b From 1425a1187337cd3d988dd7d87ecb753e41f4c5b6 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 25 Apr 2021 22:02:09 +0400 Subject: [PATCH 254/439] kron for Diagonal uses kron for components (#40596) --- stdlib/LinearAlgebra/src/diagonal.jl | 8 +------- stdlib/LinearAlgebra/test/diagonal.jl | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 06bda6495dd0f..7bdcfb7d930e6 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -493,13 +493,7 @@ rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = return C end -function kron(A::Diagonal{T1}, B::Diagonal{T2}) where {T1<:Number, T2<:Number} - valA = A.diag; nA = length(valA) - valB = B.diag; nB = length(valB) - valC = Vector{typeof(zero(T1)*zero(T2))}(undef,nA*nB) - C = Diagonal(valC) - return @inbounds kron!(C, A, B) -end +kron(A::Diagonal{<:Number}, B::Diagonal{<:Number}) = Diagonal(kron(A.diag, B.diag)) @inline function kron!(C::AbstractMatrix, A::Diagonal, B::AbstractMatrix) Base.require_one_based_indexing(B) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index ad2b9e8682077..564cccab9e6ba 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -403,6 +403,23 @@ Random.seed!(1) end +@testset "kron (issue #40595)" begin + # custom array type to test that kron on Diagonal matrices preserves types of the parents if possible + struct KronTestArray{T, N, AT} <: AbstractArray{T, N} + data::AT + end + KronTestArray(data::AbstractArray) = KronTestArray{eltype(data), ndims(data), typeof(data)}(data) + Base.size(A::KronTestArray) = size(A.data) + LinearAlgebra.kron(A::KronTestArray, B::KronTestArray) = KronTestArray(kron(A.data, B.data)) + Base.getindex(K::KronTestArray{<:Any,N}, i::Vararg{Int,N}) where {N} = K.data[i...] + + A = KronTestArray([1, 2, 3]); + @test kron(A, A) isa KronTestArray + Ad = Diagonal(A); + @test kron(Ad, Ad).diag isa KronTestArray + @test kron(Ad, Ad).diag == kron([1, 2, 3], [1, 2, 3]) +end + @testset "svdvals and eigvals (#11120/#11247)" begin D = Diagonal(Matrix{Float64}[randn(3,3), randn(2,2)]) @test sort([svdvals(D)...;], rev = true) ≈ svdvals([D.diag[1] zeros(3,2); zeros(2,3) D.diag[2]]) From 578d51857be15c92a0037302ed3bb24422e27e2b Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Sun, 25 Apr 2021 21:27:49 +0200 Subject: [PATCH 255/439] Make length type match index type in sparse vectors (#39645) --- stdlib/SparseArrays/src/sparsevector.jl | 4 ++-- stdlib/SparseArrays/test/sparsevector.jl | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index f893fb04eadf3..eecda6d72add8 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -15,7 +15,7 @@ import LinearAlgebra: promote_to_array_type, promote_to_arrays_ Vector type for storing sparse vectors. """ struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti} - n::Int # Length of the sparse vector + n::Ti # Length of the sparse vector nzind::Vector{Ti} # Indices of stored values nzval::Vector{Tv} # Stored values, typically nonzeros @@ -23,7 +23,7 @@ struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti} n >= 0 || throw(ArgumentError("The number of elements must be non-negative.")) length(nzind) == length(nzval) || throw(ArgumentError("index and value vectors must be the same length")) - new(convert(Int, n), nzind, nzval) + new(convert(Ti, n), nzind, nzval) end end diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 03aed95a43a83..2dc9738111a87 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -33,6 +33,9 @@ x1_full[SparseArrays.nonzeroinds(spv_x1)] = nonzeros(spv_x1) @test SparseArrays.nonzeroinds(x) == [2, 5, 6] @test nonzeros(x) == [1.25, -0.75, 3.5] @test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2 + y = SparseVector(typemax(Int128), Int128[4], [5]) + @test y isa SparseVector{Int,Int128} + @test @inferred size(y) == (@inferred(length(y)),) end @testset "isstored" begin From f40c4ba5c47e08ce98e784ea06ee2f471f9f2c26 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sun, 25 Apr 2021 17:27:34 -0400 Subject: [PATCH 256/439] Create README.md (#40603) [ci skip] [skip ci] --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index f158ab22f7973..c005edac214ec 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ helpful to start contributing to the Julia codebase. - [**StackOverflow**](https://stackoverflow.com/questions/tagged/julia-lang) - [**Twitter**](https://twitter.com/JuliaLanguage) -- [**Meetup**](https://julia.meetup.com/) - [**Learning resources**](https://julialang.org/learning/) ## Binary Installation From 4e176ac96565a7e72f16689a3d6a5d465e35148a Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 26 Apr 2021 10:26:44 +0200 Subject: [PATCH 257/439] add docstring for Base.load_path() (#40582) --- base/initdefs.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/initdefs.jl b/base/initdefs.jl index a61373c394eec..4c73cfb65dc60 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -307,6 +307,12 @@ function active_project(search_load_path::Bool=true) end end +""" + load_path() + +Return the fully expanded value of [`LOAD_PATH`](@ref) that is searched for projects and +packages. +""" function load_path() paths = String[] for env in LOAD_PATH From 1a12495e3a6969a7a8276dde2f227fc6793b3e18 Mon Sep 17 00:00:00 2001 From: Pramodh Gopalan V Date: Mon, 26 Apr 2021 17:48:27 +0530 Subject: [PATCH 258/439] REPL: Fix incorrect docstring for .. (#40563) (#40607) This PR fixes #40563 . This is essentially a mirror of #39975 . Please refer to it for more information. --- stdlib/REPL/src/docview.jl | 2 +- stdlib/REPL/test/repl.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index d6b523160da1e..cfb554f6cae32 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -224,7 +224,7 @@ function lookup_doc(ex) op = str[1:end-1] eq = isdotted ? ".=" : "=" return Markdown.parse("`x $op= y` is a synonym for `x $eq x $op y`") - elseif isdotted + elseif isdotted && ex !== :(..) op = str[2:end] return Markdown.parse("`x $ex y` is akin to `broadcast($op, x, y)`. See [`broadcast`](@ref).") end diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 40c8617ce655d..cb2d086a30d7f 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -1096,6 +1096,9 @@ end # Issue 39427 @test occursin("does not exist", sprint(show, help_result(":="))) +# Issue #40563 +@test occursin("does not exist", sprint(show, help_result(".."))) + # Issue #25930 # Brief and extended docs (issue #25930) From 728aa90906a8712668120bb6f0912f963678ec63 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Mon, 26 Apr 2021 16:18:30 +0200 Subject: [PATCH 259/439] Revert "faster Float32 and Float16 pow (#40236)" (#40610) This reverts commit 1474566ffc1dfe16f643b446f667178b78b56aa6. --- base/math.jl | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/base/math.jl b/base/math.jl index b8d8a1866c575..c08c25d05f112 100644 --- a/base/math.jl +++ b/base/math.jl @@ -911,19 +911,13 @@ end z end @inline function ^(x::Float32, y::Float32) - z = Float32(exp2_fast(log2(Float64(x))*y)) - if isnan(z) & !isnan(x+y) - throw_exp_domainerror(x) - end - z -end -@inline function ^(x::Float16, y::Float16) - z = Float16(exp2_fast(log2(Float32(x))*y)) + z = ccall("llvm.pow.f32", llvmcall, Float32, (Float32, Float32), x, y) if isnan(z) & !isnan(x+y) throw_exp_domainerror(x) end z end +@inline ^(x::Float16, y::Float16) = Float16(Float32(x)^Float32(y)) # TODO: optimize @inline function ^(x::Float64, y::Integer) y == -1 && return inv(x) @@ -931,7 +925,7 @@ end y == 1 && return x y == 2 && return x*x y == 3 && return x*x*x - return x^Float64(y) + ccall("llvm.pow.f64", llvmcall, Float64, (Float64, Float64), x, Float64(y)) end @inline function ^(x::Float32, y::Integer) y == -1 && return inv(x) @@ -939,7 +933,7 @@ end y == 1 && return x y == 2 && return x*x y == 3 && return x*x*x - x^Float32(y) + ccall("llvm.pow.f32", llvmcall, Float32, (Float32, Float32), x, Float32(y)) end @inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ y) @inline literal_pow(::typeof(^), x::Float16, ::Val{p}) where {p} = Float16(literal_pow(^,Float32(x),Val(p))) From c82c701643af6a6e6d521172eadaf72c77cb33af Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 26 Apr 2021 17:28:12 +0200 Subject: [PATCH 260/439] remove debug logging for the TOML cache in loading (#40581) --- base/loading.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 94cf9623353f3..b2be6d2f75bc2 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -203,7 +203,6 @@ function get_updated_dict(p::TOML.Parser, f::CachedTOMLDict) f.mtime = s.mtime f.size = s.size f.hash = new_hash - @debug "Cache of TOML file $(repr(f.path)) invalid, reparsing..." TOML.reinit!(p, String(content); filepath=f.path) return f.d = TOML.parse(p) end @@ -222,7 +221,6 @@ parsed_toml(project_file::AbstractString) = parsed_toml(project_file, TOML_CACHE function parsed_toml(project_file::AbstractString, toml_cache::TOMLCache, toml_lock::ReentrantLock) lock(toml_lock) do if !haskey(toml_cache.d, project_file) - @debug "Creating new cache for $(repr(project_file))" d = CachedTOMLDict(toml_cache.p, project_file) toml_cache.d[project_file] = d return d.d From a4e1082a96fd503333c930f2d0196221687cdd10 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 27 Apr 2021 06:16:58 +0900 Subject: [PATCH 261/439] improve inferrabilities by telling the compiler relational invariants (#40594) Our compiler doesn't understand these relations automatically yet. --- base/multidimensional.jl | 30 ++++++++++++++++++------------ base/tuple.jl | 12 ++++++++---- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 5ef46bb1da468..bf4e09dd12a49 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -125,9 +125,11 @@ module IteratorsMD # comparison @inline isless(I1::CartesianIndex{N}, I2::CartesianIndex{N}) where {N} = _isless(0, I1.I, I2.I) - @inline function _isless(ret, I1::NTuple{N,Int}, I2::NTuple{N,Int}) where N - newret = ifelse(ret==0, icmp(I1[N], I2[N]), ret) - _isless(newret, Base.front(I1), Base.front(I2)) + @inline function _isless(ret, I1::Tuple{Int,Vararg{Int,N}}, I2::Tuple{Int,Vararg{Int,N}}) where {N} + newret = ifelse(ret==0, icmp(last(I1), last(I2)), ret) + t1, t2 = Base.front(I1), Base.front(I2) + # avoid dynamic dispatch by telling the compiler relational invariants + return isa(t1, Tuple{}) ? _isless(newret, (), ()) : _isless(newret, t1, t2::Tuple{Int,Vararg{Int}}) end _isless(ret, ::Tuple{}, ::Tuple{}) = ifelse(ret==1, true, false) icmp(a, b) = ifelse(isless(a,b), 1, ifelse(a==b, 0, -1)) @@ -168,6 +170,7 @@ module IteratorsMD error("iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`") # Iteration + const OrdinalRangeInt = OrdinalRange{Int, Int} """ CartesianIndices(sz::Dims) -> R CartesianIndices((istart:[istep:]istop, jstart:[jstep:]jstop, ...)) -> R @@ -262,13 +265,13 @@ module IteratorsMD For cartesian to linear index conversion, see [`LinearIndices`](@ref). """ - struct CartesianIndices{N,R<:NTuple{N,OrdinalRange{Int, Int}}} <: AbstractArray{CartesianIndex{N},N} + struct CartesianIndices{N,R<:NTuple{N,OrdinalRangeInt}} <: AbstractArray{CartesianIndex{N},N} indices::R end CartesianIndices(::Tuple{}) = CartesianIndices{0,typeof(())}(()) function CartesianIndices(inds::NTuple{N,OrdinalRange{<:Integer, <:Integer}}) where {N} - indices = map(r->convert(OrdinalRange{Int, Int}, r), inds) + indices = map(r->convert(OrdinalRangeInt, r), inds) CartesianIndices{N, typeof(indices)}(indices) end @@ -394,19 +397,21 @@ module IteratorsMD # `iterate` returns `Union{Nothing, Tuple}`, we explicitly pass a `valid` flag to eliminate # the type instability inside the core `__inc` logic, and this gives better runtime performance. __inc(::Tuple{}, ::Tuple{}) = false, () - @inline function __inc(state::Tuple{Int}, indices::Tuple{<:OrdinalRange}) + @inline function __inc(state::Tuple{Int}, indices::Tuple{OrdinalRangeInt}) rng = indices[1] I = state[1] + step(rng) valid = __is_valid_range(I, rng) && state[1] != last(rng) return valid, (I, ) end - @inline function __inc(state, indices) + @inline function __inc(state::Tuple{Int,Int,Vararg{Int,N}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt,N}}) where {N} rng = indices[1] I = state[1] + step(rng) if __is_valid_range(I, rng) && state[1] != last(rng) return true, (I, tail(state)...) end - valid, I = __inc(tail(state), tail(indices)) + t1, t2 = tail(state), tail(indices) + # avoid dynamic dispatch by telling the compiler relational invariants + valid, I = isa(t1, Tuple{Int}) ? __inc(t1, t2::Tuple{OrdinalRangeInt}) : __inc(t1, t2::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) return valid, (first(rng), I...) end @@ -505,20 +510,21 @@ module IteratorsMD # decrement post check to avoid integer overflow @inline __dec(::Tuple{}, ::Tuple{}) = false, () - @inline function __dec(state::Tuple{Int}, indices::Tuple{<:OrdinalRange}) + @inline function __dec(state::Tuple{Int}, indices::Tuple{OrdinalRangeInt}) rng = indices[1] I = state[1] - step(rng) valid = __is_valid_range(I, rng) && state[1] != first(rng) return valid, (I,) end - - @inline function __dec(state, indices) + @inline function __dec(state::Tuple{Int,Int,Vararg{Int,N}}, indices::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt,N}}) where {N} rng = indices[1] I = state[1] - step(rng) if __is_valid_range(I, rng) && state[1] != first(rng) return true, (I, tail(state)...) end - valid, I = __dec(tail(state), tail(indices)) + t1, t2 = tail(state), tail(indices) + # avoid dynamic dispatch by telling the compiler relational invariants + valid, I = isa(t1, Tuple{Int}) ? __dec(t1, t2::Tuple{OrdinalRangeInt}) : __dec(t1, t2::Tuple{OrdinalRangeInt,OrdinalRangeInt,Vararg{OrdinalRangeInt}}) return valid, (last(rng), I...) end diff --git a/base/tuple.jl b/base/tuple.jl index 6d0ab5157f4c7..ad08bf42f5e1a 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -357,10 +357,14 @@ filter(f, t::Any32) = Tuple(filter(f, collect(t))) ## comparison ## -isequal(t1::Tuple, t2::Tuple) = (length(t1) == length(t2)) && _isequal(t1, t2) -_isequal(t1::Tuple{}, t2::Tuple{}) = true -_isequal(t1::Tuple{Any}, t2::Tuple{Any}) = isequal(t1[1], t2[1]) -_isequal(t1::Tuple, t2::Tuple) = isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2)) +isequal(t1::Tuple, t2::Tuple) = length(t1) == length(t2) && _isequal(t1, t2) +_isequal(::Tuple{}, ::Tuple{}) = true +function _isequal(t1::Tuple{Any,Vararg{Any,N}}, t2::Tuple{Any,Vararg{Any,N}}) where {N} + isequal(t1[1], t2[1]) || return false + t1, t2 = tail(t1), tail(t2) + # avoid dynamic dispatch by telling the compiler relational invariants + return isa(t1, Tuple{}) ? true : _isequal(t1, t2::Tuple{Any,Vararg{Any}}) +end function _isequal(t1::Any32, t2::Any32) for i = 1:length(t1) if !isequal(t1[i], t2[i]) From 75c4f5562a0cd83f47c5695caee33c45630e76fc Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 26 Apr 2021 23:17:52 +0200 Subject: [PATCH 262/439] show(::MersenneTwister) : use module qualification (#40583) show(::MersenneTwister) : use module qualification Instead of always printing `MersenneTwister(...)`, we also prepend `Random.` when not is scope, e.g. ```julia julia> import Random; Random.MersenneTwister(0) Random.MersenneTwister(0) ``` --- stdlib/Random/src/RNGs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index 5c29954f13132..2bdecd92e6a08 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -181,9 +181,9 @@ function show(io::IO, rng::MersenneTwister) seed = from_seed(rng.seed) seed_str = seed <= typemax(Int) ? string(seed) : "0x" * string(seed, base=16) # DWIM if rng.adv_jump == 0 && rng.adv == 0 - return print(io, "MersenneTwister($seed_str)") + return print(io, MersenneTwister, "(", seed_str, ")") end - print(io, "MersenneTwister($seed_str, (") + print(io, MersenneTwister, "(", seed_str, ", (") # state adv = Integer[rng.adv_jump, rng.adv] if rng.adv_vals != -1 || rng.adv_ints != -1 From ff001a4e1f5b7f949f5a2328520a7e78bc1957b4 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Tue, 27 Apr 2021 13:27:23 +0200 Subject: [PATCH 263/439] deprecate `getproperty(::Pairs, s)` (#39448) Co-authored-by: Jameson Nash --- base/accumulate.jl | 12 ++++++------ base/deprecated.jl | 10 ++++++++++ base/iterators.jl | 28 +++++++++++++-------------- base/namedtuple.jl | 2 +- base/reduce.jl | 2 +- stdlib/InteractiveUtils/src/macros.jl | 2 +- test/syntax.jl | 2 +- 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/base/accumulate.jl b/base/accumulate.jl index c1ec372de9033..6f0b6e7d05ba3 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -293,10 +293,10 @@ function accumulate(op, A; dims::Union{Nothing,Integer}=nothing, kw...) # This branch takes care of the cases not handled by `_accumulate!`. return collect(Iterators.accumulate(op, A; kw...)) end - nt = kw.data - if nt isa NamedTuple{()} + nt = values(kw) + if isempty(kw) out = similar(A, promote_op(op, eltype(A), eltype(A))) - elseif nt isa NamedTuple{(:init,)} + elseif keys(nt) === (:init,) out = similar(A, promote_op(op, typeof(nt.init), eltype(A))) else throw(ArgumentError("acccumulate does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) @@ -356,10 +356,10 @@ julia> B ``` """ function accumulate!(op, B, A; dims::Union{Integer, Nothing} = nothing, kw...) - nt = kw.data - if nt isa NamedTuple{()} + nt = values(kw) + if isempty(kw) _accumulate!(op, B, A, dims, nothing) - elseif nt isa NamedTuple{(:init,)} + elseif keys(kw) === (:init,) _accumulate!(op, B, A, dims, Some(nt.init)) else throw(ArgumentError("acccumulate! does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) diff --git a/base/deprecated.jl b/base/deprecated.jl index f1d097678f3a2..5cd32a16e50e2 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -241,3 +241,13 @@ end cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not recursively calls itself # END 1.6 deprecations + +# BEGIN 1.7 deprecations + +# the plan is to eventually overload getproperty to access entries of the dict +@noinline function getproperty(x::Pairs, s::Symbol) + depwarn("use values(kwargs) and keys(kwargs) instead of kwargs.data and kwargs.itr", :getproperty, force=true) + return getfield(x, s) +end + +# END 1.7 deprecations diff --git a/base/iterators.jl b/base/iterators.jl index b9f2aaf882360..dbebe900e0659 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -235,30 +235,30 @@ pairs(A::AbstractArray) = pairs(IndexCartesian(), A) pairs(A::AbstractVector) = pairs(IndexLinear(), A) # pairs(v::Pairs) = v # listed for reference, but already defined from being an AbstractDict -length(v::Pairs) = length(v.itr) -axes(v::Pairs) = axes(v.itr) -size(v::Pairs) = size(v.itr) +length(v::Pairs) = length(getfield(v, :itr)) +axes(v::Pairs) = axes(getfield(v, :itr)) +size(v::Pairs) = size(getfield(v, :itr)) @propagate_inbounds function iterate(v::Pairs{K, V}, state...) where {K, V} - x = iterate(v.itr, state...) + x = iterate(getfield(v, :itr), state...) x === nothing && return x indx, n = x - item = v.data[indx] + item = getfield(v, :data)[indx] return (Pair{K, V}(indx, item), n) end -@inline isdone(v::Pairs, state...) = isdone(v.itr, state...) +@inline isdone(v::Pairs, state...) = isdone(getfield(v, :itr), state...) IteratorSize(::Type{<:Pairs{<:Any, <:Any, I}}) where {I} = IteratorSize(I) IteratorSize(::Type{<:Pairs{<:Any, <:Any, <:Base.AbstractUnitRange, <:Tuple}}) = HasLength() -reverse(v::Pairs) = Pairs(v.data, reverse(v.itr)) +reverse(v::Pairs) = Pairs(getfield(v, :data), reverse(getfield(v, :itr))) -haskey(v::Pairs, key) = (key in v.itr) -keys(v::Pairs) = v.itr -values(v::Pairs) = v.data # TODO: this should be a view of data subset by itr -getindex(v::Pairs, key) = v.data[key] -setindex!(v::Pairs, value, key) = (v.data[key] = value; v) -get(v::Pairs, key, default) = get(v.data, key, default) -get(f::Base.Callable, v::Pairs, key) = get(f, v.data, key) +haskey(v::Pairs, key) = (key in getfield(v, :itr)) +keys(v::Pairs) = getfield(v, :itr) +values(v::Pairs) = getfield(v, :data) # TODO: this should be a view of data subset by itr +getindex(v::Pairs, key) = getfield(v, :data)[key] +setindex!(v::Pairs, value, key) = (getfield(v, :data)[key] = value; v) +get(v::Pairs, key, default) = get(getfield(v, :data), key, default) +get(f::Base.Callable, v::Pairs, key) = get(f, getfield(v, :data), key) # zip diff --git a/base/namedtuple.jl b/base/namedtuple.jl index ff554cae39336..9361fde52619b 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -267,7 +267,7 @@ merge(a::NamedTuple, b::NamedTuple{()}) = a merge(a::NamedTuple{()}, b::NamedTuple{()}) = a merge(a::NamedTuple{()}, b::NamedTuple) = b -merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, b.data) +merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, getfield(b, :data)) merge(a::NamedTuple, b::Iterators.Zip{<:Tuple{Any,Any}}) = merge(a, NamedTuple{Tuple(b.is[1])}(b.is[2])) diff --git a/base/reduce.jl b/base/reduce.jl index ca252a08922c3..6490358214c7e 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -531,7 +531,7 @@ julia> sum(1:20; init = 0.0) """ sum(a; kw...) = sum(identity, a; kw...) sum(a::AbstractArray{Bool}; kw...) = - kw.data === NamedTuple() ? count(a) : reduce(add_sum, a; kw...) + isempty(kw) ? count(a) : reduce(add_sum, a; kw...) ## prod """ diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 79473f6d5bb36..8d70af708cab5 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -4,7 +4,7 @@ import Base: typesof, insert! -separate_kwargs(args...; kwargs...) = (args, kwargs.data) +separate_kwargs(args...; kwargs...) = (args, values(kwargs)) """ Transform a dot expression into one where each argument has been replaced by a diff --git a/test/syntax.jl b/test/syntax.jl index fc79d355e9c11..d934e9358baac 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1863,7 +1863,7 @@ end @test_throws UndefVarError eval(:(1+$(Symbol("")))) # issue #31404 -f31404(a, b; kws...) = (a, b, kws.data) +f31404(a, b; kws...) = (a, b, values(kws)) @test f31404(+, (Type{T} where T,); optimize=false) === (+, (Type,), (optimize=false,)) # issue #28992 From cb22c8ebf695bc4f5ef758feb58ba8c5cf2b87e7 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Tue, 27 Apr 2021 17:30:36 +0200 Subject: [PATCH 264/439] test package completion if already imported (#36552) --- stdlib/REPL/test/replcompletions.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 8a1d2f39a18f4..dd6327e7a34bd 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -117,6 +117,10 @@ let s = "using REP" @test count(isequal("REPL"), c) == 1 # issue #30234 @test !Base.isbindingresolved(M32377, :tanh) + # check what happens if REPL is already imported + M32377.eval(:(using REPL)) + c, r = test_complete_32377(s) + @test count(isequal("REPL"), c) == 1 end let s = "Comp" From c4fc095fffaa5c5a3c4375dca2e93b580a7cb1e3 Mon Sep 17 00:00:00 2001 From: Alexander Stevenson Date: Tue, 27 Apr 2021 13:07:50 -0400 Subject: [PATCH 265/439] doc: git checkout 1.6.1 in README (#40633) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c005edac214ec..0f94447abbc1b 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Julia. However, most users should use the most recent stable version of Julia. You can get this version by changing to the Julia directory and running: - git checkout v1.6.0 + git checkout v1.6.1 Now run `make` to build the `julia` executable. From bc50abeaec8334e0b2ac95ef38a7cc7de33cd662 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 27 Apr 2021 21:33:26 +0200 Subject: [PATCH 266/439] add *(::Missing, ::Char) (#40615) --- base/missing.jl | 4 ++-- test/missing.jl | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index f061bd08d52e0..87a63eb6327dc 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -179,8 +179,8 @@ xor(b::Bool, a::Missing) = missing xor(::Missing, ::Integer) = missing xor(::Integer, ::Missing) = missing -*(d::Missing, x::AbstractString) = missing -*(d::AbstractString, x::Missing) = missing +*(d::Missing, x::Union{AbstractString,AbstractChar}) = missing +*(d::Union{AbstractString,AbstractChar}, x::Missing) = missing function float(A::AbstractArray{Union{T, Missing}}) where {T} U = typeof(float(zero(T))) diff --git a/test/missing.jl b/test/missing.jl index ae08c37b25949..0610377a7e67a 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -164,9 +164,11 @@ end @test ismissing(⊽(1, missing)) end -@testset "* string concatenation" begin +@testset "* string/char concatenation" begin @test ismissing("a" * missing) + @test ismissing('a' * missing) @test ismissing(missing * "a") + @test ismissing(missing * 'a') end # Emulate a unitful type such as Dates.Minute @@ -617,4 +619,4 @@ end @test isequal(sort(X, alg=MergeSort, rev=true), XRP) end -sortperm(reverse([NaN, missing, NaN, missing])) \ No newline at end of file +sortperm(reverse([NaN, missing, NaN, missing])) From 321a3c4e17a8b2f580fccc41424bd9de49e0687c Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 27 Apr 2021 15:12:58 -0700 Subject: [PATCH 267/439] Add some documentation to cli/loaders (#40636) --- cli/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 cli/README.md diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 0000000000000..4021aceb7d839 --- /dev/null +++ b/cli/README.md @@ -0,0 +1,31 @@ +# cli and loader + +This directory contains the code used by the Julia loader, implementing the pieces necessary to isolate ourselves from the native dynamic loader enough to reimplement useful features such as RPATH across all platforms. +This loader comprises the `julia` executable and the `libjulia` library, which are responsible for setting things up such that `libjulia-internal` and any other internal dependencies can be reliably loaded. +The code is organized in three pieces: + +* `loader_exe.c` gets built into the main `julia` executable. It immediately loads `libjulia`. +* `loader_lib.c` gets built into the main `libjulia` shared library. This is the main entrypoint for the Julia runtime loading process, which occurs within `jl_load_repl()`. +* `trampolines/*.S`, which contains assembly definitions for symbol forwarding trampolines. These are used to allow `libjulia` to re-export symbols such that a C linker can use `libjulia` directly for embedding usecases. + +The main requirements of the loader are as follows: + +- **Isolation**: We need to be able to load our own copy of `libgcc_s.so`, etc... + On Linux/macOS, proper application of `RPATH` can influence the linker's decisions, however errant `LD_LIBRARY_PATH` entries or system libraries inserted into the build process can still interfere, not to mention Windows' lack of `RPATH`-like capabilities. + To address this, the loader is built as a stand-alone binary that does not depend on the large set of dependencies that `libjulia-internal` itself does, and manually `dlopen()`'s a list of dependencies using logic similar to that of an `RPATH`. +- **Compatibility**: We need to support embedding usecases without forcing embedders to care about all of these things. + For linking against the Julia runtime by simply providing `-ljulia` on the link line, we must ensure that all public interfaces, whether function symbols or data symbols, must be exported from `libjulia`. + This motivates our usage of function trampolines to re-export functions from `libjulia-internal`, and the reason why all public data symbols are defined within `libjulia`, then imported into `libjulia-internal` for initialization. +- **Flexibility**: We need to be able to make use of system libraries when requested to do so by the user at build time. + Currently, we embed the list of libraries to be `dlopen()`'ed within `libjulia` as a string (See the definition of `DEP_LIBS` in `Make.inc` and its usage in `loader_lib.c`). + This is flexible enough as we do not support changing this configuration at runtime, however in the future, we may need to add some simple parsing logic in `loader_lib.c` to inspect a `LocalPreferences.toml` and construct the list of libraries to load from that. +- **Speed**: This whole process should be fast, especially function trampolines. + To this end, we write everything in low-overhead assembly, borrowing inspiration from the PLT trampolines that the linker already generates when using dynamic libraries. + +## Public interface definition + +The public interface exported by `libjulia` is contained within `.inc` files stored in `src`; one for exported data symbols, [`src/jl_exported_data.inc`](../src/jl_exported_data.inc) and one for exported functions, [`src/jl_exported_funcs.inc`](../src/jl_exported_funcs.inc). +Adding entries to the data list will cause `libjulia` to generate a placeholder variable declaration. +Most symbols are declared to be of type `void *`, however for symbols that are of a different size, they are declared along with their type. +Adding entries to the function list will cause `libjulia` to generate a trampoline definition (using a trampoline according to the architecture of the target processor) and then at runtime, when `libjulia` has successfully loaded `libjulia-internal`, it will `dlsym()` that symbol from within `libjulia-internal` and set it as the target of the trampoline. +All initialization will occur automatically upon successful load of `libjulia`, so there is no need for user code to call an initialization before invoking typical `libjulia-internal` functions (although initialization of the runtime itself is still necessary, e.g. calling `jl_init()`). From 4b7670dbf5c79be827b8aff8db0b8303ab969ad4 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 28 Apr 2021 00:15:20 +0200 Subject: [PATCH 268/439] add some precompile for Artifacts and add a type annotation (#40631) --- contrib/generate_precompile.jl | 5 ++++- stdlib/Artifacts/src/Artifacts.jl | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 049506fd464c2..b5ded199688ee 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -141,7 +141,10 @@ if Artifacts !== nothing precompile_script *= """ using Artifacts, Base.BinaryPlatforms, Libdl artifacts_toml = abspath(joinpath(Sys.STDLIB, "Artifacts", "test", "Artifacts.toml")) - # cd(() -> (name = "HelloWorldC"; @artifact_str(name)), dirname(artifacts_toml)) + artifact_hash("HelloWorldC", artifacts_toml) + oldpwd = pwd(); cd(dirname(artifacts_toml)) + macroexpand(Main, :(@artifact_str("HelloWorldC"))) + cd(oldpwd) artifacts = Artifacts.load_artifacts_toml(artifacts_toml) platforms = [Artifacts.unpack_platform(e, "HelloWorldC", artifacts_toml) for e in artifacts["HelloWorldC"]] best_platform = select_platform(Dict(p => triplet(p) for p in platforms)) diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index fd65494782d92..218f879c767ac 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -418,7 +418,7 @@ collapsed artifact. Returns `nothing` if no mapping can be found. """ function artifact_hash(name::String, artifacts_toml::String; platform::AbstractPlatform = HostPlatform(), - pkg_uuid::Union{Base.UUID,Nothing}=nothing) + pkg_uuid::Union{Base.UUID,Nothing}=nothing)::Union{Nothing, SHA1} meta = artifact_meta(name, artifacts_toml; platform=platform) if meta === nothing return nothing From 33f92d6fe1175659c293cb7199ab82623e0c8a77 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 28 Apr 2021 07:19:52 +0900 Subject: [PATCH 269/439] minor refactor for `Base._which` (#40617) Two minor changes: 1. look up matching methods in a passed world 2. pass the current world by default xref: https://github.com/JuliaDebug/JuliaInterpreter.jl/pull/478 --- base/reflection.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index a8bfb04903816..afe349573114a 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1292,12 +1292,12 @@ end print_statement_costs(args...; kwargs...) = print_statement_costs(stdout, args...; kwargs...) -function _which(@nospecialize(tt::Type), world=typemax(UInt)) +function _which(@nospecialize(tt::Type), world=get_world_counter()) min_valid = RefValue{UInt}(typemin(UInt)) max_valid = RefValue{UInt}(typemax(UInt)) match = ccall(:jl_gf_invoke_lookup_worlds, Any, (Any, UInt, Ptr{Csize_t}, Ptr{Csize_t}), - tt, typemax(UInt), min_valid, max_valid) + tt, world, min_valid, max_valid) if match === nothing error("no unique matching method found for the specified argument types") end From df270637a7a8266dc972faef7642459e6b77eb1a Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 27 Apr 2021 18:50:21 -0400 Subject: [PATCH 270/439] Enable REPL to offer to install missing packages if install hooks are provided (#39026) --- stdlib/REPL/src/REPL.jl | 37 +++++++++++++++++++++++++++++++++++++ stdlib/REPL/test/repl.jl | 27 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index d17482ec453cb..0c5a6c6267cff 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -123,6 +123,12 @@ const softscope! = softscope const repl_ast_transforms = Any[softscope] # defaults for new REPL backends +# Allows an external package to add hooks into the code loading. +# The hook should take a Vector{Symbol} of package names and +# return true if all packages could be installed, false if not +# to e.g. install packages on demand +const install_packages_hooks = Any[] + function eval_user_input(@nospecialize(ast), backend::REPLBackend) lasterr = nothing Base.sigatomic_begin() @@ -133,6 +139,9 @@ function eval_user_input(@nospecialize(ast), backend::REPLBackend) put!(backend.response_channel, Pair{Any, Bool}(lasterr, true)) else backend.in_eval = true + if !isempty(install_packages_hooks) + check_for_missing_packages_and_run_hooks(ast) + end for xf in backend.ast_transforms ast = Base.invokelatest(xf, ast) end @@ -155,6 +164,34 @@ function eval_user_input(@nospecialize(ast), backend::REPLBackend) nothing end +function check_for_missing_packages_and_run_hooks(ast) + mods = modules_to_be_loaded(ast) + filter!(mod -> isnothing(Base.identify_package(String(mod))), mods) # keep missing modules + if !isempty(mods) + for f in install_packages_hooks + Base.invokelatest(f, mods) && return + end + end +end + +function modules_to_be_loaded(ast, mods = Symbol[]) + if ast.head in [:using, :import] + for arg in ast.args + if first(arg.args) isa Symbol # i.e. `Foo` + if first(arg.args) != :. # don't include local imports + push!(mods, first(arg.args)) + end + else # i.e. `Foo: bar` + push!(mods, first(first(arg.args).args)) + end + end + end + for arg in ast.args + arg isa Expr && modules_to_be_loaded(arg, mods) + end + return mods +end + """ start_repl_backend(repl_channel::Channel, response_channel::Channel) diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index cb2d086a30d7f..677d184f99eab 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -1295,3 +1295,30 @@ Base.wait(frontend_task) macro throw_with_linenumbernode(err) Expr(:block, LineNumberNode(42, Symbol("test.jl")), :(() -> throw($err))) end + +@testset "Install missing packages via hooks" begin + @testset "Parse AST for packages" begin + mods = REPL.modules_to_be_loaded(Meta.parse("using Foo")) + @test mods == [:Foo] + mods = REPL.modules_to_be_loaded(Meta.parse("import Foo")) + @test mods == [:Foo] + mods = REPL.modules_to_be_loaded(Meta.parse("using Foo, Bar")) + @test mods == [:Foo, :Bar] + mods = REPL.modules_to_be_loaded(Meta.parse("import Foo, Bar")) + @test mods == [:Foo, :Bar] + + mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo end")) + @test mods == [:Foo] + mods = REPL.modules_to_be_loaded(Meta.parse("if false if false using Foo end end")) + @test mods == [:Foo] + mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo, Bar end")) + @test mods == [:Foo, :Bar] + mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo: bar end")) + @test mods == [:Foo] + + mods = REPL.modules_to_be_loaded(Meta.parse("import Foo.bar as baz")) + @test mods == [:Foo] + mods = REPL.modules_to_be_loaded(Meta.parse("using .Foo")) + @test mods == [] + end +end From 907264be10dbf4e91c8e6b0490273fe63f0ce75b Mon Sep 17 00:00:00 2001 From: Simon Etter Date: Wed, 28 Apr 2021 08:10:30 +0800 Subject: [PATCH 271/439] Make cholmod preserve user-specified permutation (#40560) * Make cholmod preserve user-specified permutation * Ensure all changes to CHOLMOD.common are temporary * Fix spurious comment Co-authored-by: Simon Etter --- NEWS.md | 2 + stdlib/SuiteSparse/src/cholmod.jl | 105 ++++++++++++++++------------- stdlib/SuiteSparse/test/cholmod.jl | 32 +++++++++ 3 files changed, 94 insertions(+), 45 deletions(-) diff --git a/NEWS.md b/NEWS.md index d048c6f2cccd2..089f81c272168 100644 --- a/NEWS.md +++ b/NEWS.md @@ -114,6 +114,8 @@ Standard library changes #### SparseArrays * new `sizehint!(::SparseMatrixCSC, ::Integer)` method ([#30676]). +* `cholesky()` now fully preserves the user-specified permutation. ([#40560]) + #### Dates diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index d8dafa853702d..8bc3b9747f53b 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -45,9 +45,30 @@ macro cholmod_name(nm) string("cholmod_l_", nm) end +# Set a `common` field, execute some code and then safely reset the field to +# its initial value +macro cholmod_param(kwarg, code) + @assert kwarg.head == :(=) + param = kwarg.args[1] + value = kwarg.args[2] + + common_param = # Read `common.param` + Expr(:., :(common[Threads.threadid()]), QuoteNode(param)) + + return quote + default_value = $common_param + try + $common_param = $(esc(value)) + $(esc(code)) + finally + $common_param = default_value + end + end +end + # Julia copy of the cholmod_method_struct # https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L655 -# Keep this synchronized with __init__() below and jl_cholmod_method_offsets in +# Keep this synchronized with `jl_cholmod_method_offsets` in # https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c struct Method lnz::Cdouble @@ -69,7 +90,7 @@ end # Julia copy of the cholmod_common_struct # https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L414 -# Keep this synchronized with __init__() below and jl_cholmod_common_offsets in +# Keep this synchronized with `jl_cholmod_method_offsets` in # https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c mutable struct Common dbound::Cdouble @@ -703,17 +724,19 @@ end ### cholmod_check.h ### function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes isascii(name) || error("non-ASCII name: $name") - common[Threads.threadid()] = 3 - ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), - A, name, common[Threads.threadid()]) + @cholmod_param print = 3 begin + ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, + (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), + A, name, common[Threads.threadid()]) + end nothing end function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes - common[Threads.threadid()] = 3 - ccall((@cholmod_name("print_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), - F, name, common[Threads.threadid()]) + @cholmod_param print = 3 begin + ccall((@cholmod_name("print_factor"),:libcholmod), Cint, + (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), + F, name, common[Threads.threadid()]) + end nothing end @@ -1359,34 +1382,34 @@ end ## Factorization methods ## Compute that symbolic factorization only -function fact_(A::Sparse{<:VTypes}; +function symbolic(A::Sparse{<:VTypes}; perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing, - postorder::Bool=true, userperm_only::Bool=true) + postorder::Bool=isnothing(perm)||isempty(perm), userperm_only::Bool=true) sA = unsafe_load(pointer(A)) sA.stype == 0 && throw(ArgumentError("sparse matrix is not symmetric/Hermitian")) - common[Threads.threadid()].postorder = postorder - - if perm === nothing || isempty(perm) # TODO: deprecate empty perm - F = analyze(A) - else # user permutation provided - if userperm_only # use perm even if it is worse than AMD - common[Threads.threadid()].nmethods = 1 + @cholmod_param postorder = postorder begin + if perm === nothing || isempty(perm) # TODO: deprecate empty perm + return analyze(A) + else # user permutation provided + if userperm_only # use perm even if it is worse than AMD + @cholmod_param nmethods = 1 begin + return analyze_p(A, SuiteSparse_long[p-1 for p in perm]) + end + else + return analyze_p(A, SuiteSparse_long[p-1 for p in perm]) + end end - F = analyze_p(A, SuiteSparse_long[p-1 for p in perm]) end - - return F end function cholesky!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv - # Makes it an LLt - common[Threads.threadid()].final_ll = true - # Compute the numerical factorization - factorize_p!(A, shift, F) + @cholmod_param final_ll = true begin + factorize_p!(A, shift, F) + end check && (issuccess(F) || throw(LinearAlgebra.PosDefException(1))) return F @@ -1419,11 +1442,8 @@ cholesky!(F::Factor, A::Union{SparseMatrixCSC{T}, function cholesky(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults!(common[Threads.threadid()]) - cm.print = 0 - # Compute the symbolic factorization - F = fact_(A; perm = perm) + F = symbolic(A; perm = perm) # Compute the numerical factorization cholesky!(F, A; shift = shift, check = check) @@ -1543,9 +1563,6 @@ cholesky(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, function ldlt!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv - cm = defaults!(common[Threads.threadid()]) - cm.print = 0 - # Makes it an LDLt change_factor!(F, false, false, true, false) @@ -1583,21 +1600,19 @@ ldlt!(F::Factor, A::Union{SparseMatrixCSC{T}, function ldlt(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults!(common[Threads.threadid()]) - cm.print = 0 - # Makes it an LDLt - cm.final_ll = false - # Really make sure it's an LDLt by avoiding supernodal factorization - cm.supernodal = 0 + @cholmod_param final_ll = false begin + # Really make sure it's an LDLt by avoiding supernodal factorization + @cholmod_param supernodal = 0 begin + # Compute the symbolic factorization + F = symbolic(A; perm = perm) - # Compute the symbolic factorization - F = fact_(A; perm = perm) + # Compute the numerical factorization + ldlt!(F, A; shift = shift, check = check) - # Compute the numerical factorization - ldlt!(F, A; shift = shift, check = check) - - return F + return F + end + end end """ diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index edc31f98c5b96..8e2fb231587f1 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -911,3 +911,35 @@ end @test C * C' == Sparse(spzeros(3, 3)) @test C' * C == Sparse(spzeros(0, 0)) end + +@testset "permutation handling" begin + @testset "default permutation" begin + # Assemble arrow matrix + A = sparse(5I,3,3) + A[:,1] .= 1; A[1,:] .= A[:,1] + + # Ensure cholesky eliminates the fill-in + @test cholesky(A).p[1] != 1 + end + + @testset "user-specified permutation" begin + n = 100 + A = sprand(n,n,5/n) |> t -> t't + I + @test cholesky(A, perm=1:n).p == 1:n + end +end + +@testset "Check common is still in default state" begin + # This test intentially depends on all the above tests! + current_common = CHOLMOD.common[Threads.threadid()] + default_common = CHOLMOD.Common() + @test current_common.print == 0 + for name in ( + :nmethods, + :postorder, + :final_ll, + :supernodal, + ) + @test getproperty(current_common, name) == getproperty(default_common, name) + end +end From e4fcdf5b04fd9751ce48b0afc700330475b42443 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 27 Apr 2021 22:44:37 -0700 Subject: [PATCH 272/439] Update CSL to eliminate dependence on `clock_gettime()` (#40499) * Update SuiteSparse checksums to include `aarch64-apple-darwin` * Update CSL to eliminate dependence on newer macOS support functions Our compiler support libraries had been incorrectly built to use symbols available only in macOS 10.12+; this update correctly configures them to not use `clock_gettime()` and `mkostemp`. --- deps/checksums/compilersupportlibraries | 184 +++++++++--------- deps/checksums/suitesparse | 4 + .../CompilerSupportLibraries_jll/Project.toml | 2 +- 3 files changed, 97 insertions(+), 93 deletions(-) diff --git a/deps/checksums/compilersupportlibraries b/deps/checksums/compilersupportlibraries index b23ced42c436c..87a5d98c832f4 100644 --- a/deps/checksums/compilersupportlibraries +++ b/deps/checksums/compilersupportlibraries @@ -1,92 +1,92 @@ -CompilerSupportLibraries.v0.4.0+1.aarch64-apple-darwin-libgfortran5.tar.gz/md5/b095e6f14bc7a1f9aa69a55619797c3b -CompilerSupportLibraries.v0.4.0+1.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/e3383c65fdafa0d58e9573ef008792c71ce77c7126b96b641de4813f679211e057d8d9d2617aedfaa5f73224b5a2656fd72534028201b533d75a21acbf087032 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran3.tar.gz/md5/f619396b91380a986621a35792aaf35b -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/342f8b7aac23a637c3223be7ca56243cf74ab0d21d2a3133a1bf6261efb760daee1288da96a219326c301a594576863668dc8bc726b6b998b92b3ecb152ed236 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran4.tar.gz/md5/83daebefd6c178f398390d765508cd30 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/da483ed5405a124101219e08162f4d6a82dfb7960efedd9462ae006c88446d291d62ddd9b1b9da948733f6f6cec4a55fcc3428edbb7a3b19d9520305813e9b6f -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran5.tar.gz/md5/b826a756dc995cff198e6e2902e6c709 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/761ec5d5403db0299871560add411e2bd1c113d4aca9a2cee6746592606df4c7aed927c987b825ccdfca6fe043af5d84a3f7b76b28e484eb0bf5ded47fe49042 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran3.tar.gz/md5/2e23248297f51bee77dee83e77124d5a -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran3.tar.gz/sha512/8124fa237efa09b30bb846cfd1dd373a9f7b558c7bdd612fb4bd442b6dde80ebf913ef303b53e110a9fd19d3f56fd6b85894e6bf06b5ce4850315684a6f871ec -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran4.tar.gz/md5/871b587fa0dd5cfb9ac137a354a68aca -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran4.tar.gz/sha512/a50d1e55a974e6df1d85155e92b7d3075d2e1ad19167fda6be1f1cfe8964aeea2f66f59dd1bbf7abb361aa3831705132ac2385755321f655de2cbd0cd89f9de2 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran5.tar.gz/md5/a68d999a5aab28aa9760ba3d4c2e9c69 -CompilerSupportLibraries.v0.4.0+1.aarch64-linux-musl-libgfortran5.tar.gz/sha512/141dc1be2e30a511de17eaaf507d5d082ea80b621a635836d0658fd1eb5e5cd37bf0779ff4a920d8322f46da98fd866bd5dbaa7d47c9aa236f26c7d0cfab51cb -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/acb29acfa67701327d81ba9a1f6765d7 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/54f813c3c69e5c8f4fde4ba8762d590315121f377df3512e71bf62b465b6eddc02cb1c4d9003b0c4c88d64ec36a2056363efb3eab9cefeba2b2658cd5f84086c -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/aae1759097c368ec3e12b0ac28c008b0 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/dfcc475f8e375a7fce81550efb12a21ee2589892a2453d094f0fbaa7d7524858b908995157d85123560c46fcd70093503d2b4224c785b57874f0affdaea776de -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/e7bfe1de2b3f9857053dfb61bd3b2698 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/0227a0a2732a3ee66911c42e031429827588746fe96d098cec3efeef2f157267b7e88f49279ca3749fbd487a3acbd3775267132033f8531503bf3b44b91ea347 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/c61cf2433e18b5f7b55fd958248b0640 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/1b6b4b7c413a5d4692ccbde26ece656b1786b07ebc573fb90f15ca00773acbd6f5abd981bd13fefd154deac0d7a718af90aaf85fd3c08ef35a805baccad459c3 -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/1da0f3569c47fb166311bde071fa4bca -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/75e6af64f9f1909ae95ac823d1487a7cc1b47c9415e58c2c8303d21ea923dc11da8a12c8e9c720ea34471273ee7ed99917c7f1775c6e7e4d861726d57954a61a -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/f20c66ad490a9a00cbb7fa7adb62905e -CompilerSupportLibraries.v0.4.0+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/9645aedfe08f381050bebb5a8c3c2510fa0a6a435d249c8c526a0135e597cbb44fd04546504c524c9343e7b3559b3ff2f0a4b207ebafcab20d4405044f3924f1 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/81eb7300e4730b93c6bb5305b983bf31 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/fa170b8311767d77d63161d01991584d4827068f4e8c563d49bb29783ba55a657da65b7c255fbe3b780cbcfe29faa292ee53893c6647e2457cfed7aaae47a7bd -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/add43dada47b0c2fe7191ecb816193aa -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/8368823e5cb1a557603e03ab4e336eb891e8c851f5ad212a7386e171dfd9c1aaec46b5b62d63e0a17df5c83e4b23cd68fe26fe131b9fe487ab7d0a7f426ec1c3 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/6f8ac553deac6733c9084a84a2a9dfb7 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/81b0e931da0787bf34809bca66f641e4f6d40a462d36b34aae3143da7a513b5c8f6abe7da910bda7bf7c1dc88c0eafde6421f07fb5ba171781453c09e9ef2b33 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/38d726f01a0c4c47d37e3a6fd173d8ca -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/227d7d509c44eafae7bacba3d3cc8b1004c0eed2943e3ff39dcd842a6a4fb8d7febe700205b51a85b18a799e801b6106d894881b95ef2780ad029cbd7e17f2f2 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/694772770ed5b196e8399dd4c59a9707 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/dfc66f0313db7e0be22f35d01b7a0e89b7836f2597683f647dcc193195206173c3050089d9e9ef299b96045abbbd8ea6a835af757ec10c95b89eeb4c31846245 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/d6ed143927e826db195e9387bca709a6 -CompilerSupportLibraries.v0.4.0+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/bffdf5d5737c031119bbf316b5718aa3c1b2cb671f446375c7fbf792d37dc8f1477b082515c007480c01789a7af9eca76e083052a6018bc0bdb6143bbf975134 -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran3.tar.gz/md5/34808173bf9105ae1ab9f6e636df5ddf -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran3.tar.gz/sha512/4d501538fbbee3a06b5cc72f19a579c1dc91257c15dff7ef040ca8353d94a013795b8fe3dd3c4e88eb2f2b1650ecc203933ef31b53f3c2cb7a17111e154c3fa3 -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran4.tar.gz/md5/352ea68c7571515ae58bc1b354f53cd3 -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran4.tar.gz/sha512/4f5e04ad93d536171a233f79f93e5e72af8b8a0243c24e1f48ef8f6fb92c47ebb2634a1305324f1a342c6cdf9b58a775a77245f581b64773124089e6ff2364bb -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran5.tar.gz/md5/dbe1270173a4d9c108990ebde51d3bee -CompilerSupportLibraries.v0.4.0+1.i686-linux-gnu-libgfortran5.tar.gz/sha512/f196a5c24a2ca1cd05f56b5e76f425ba0acab4be46311fdb52a3ce81d9e748edcdd8e4ac259a70d8adab9b6ce1a1aea4cee81f95dad2deadd2ac3ee5b199af37 -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran3.tar.gz/md5/c72eab916829d79128ef055c9c657ff7 -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran3.tar.gz/sha512/c2d0b61e01cafe12fca7b969354fbbd26135b5ab8eb7f72a62614570b9d65144c0a51be65e62f5a837147f104c2a4edb0959494505bf33c08b9c6647cfeed5b0 -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran4.tar.gz/md5/a7ebe12727b11220f589faddee5223ac -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran4.tar.gz/sha512/313623ac2471e64891cb363c44e718ed710c92f6e5b8ef7fa0dd650c71f452705cc947e909763f8aeb8aac8597871b91359623398f8528ae4fdc4463de15d182 -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran5.tar.gz/md5/af98f0be67f87c73500eb44bb741253c -CompilerSupportLibraries.v0.4.0+1.i686-linux-musl-libgfortran5.tar.gz/sha512/358182533477e57b39a5c6d8e0213af6a9e68bb871489487408cd72c357e370875aeca8a59131e4303072dc9895f8f74f4fc0421088fb4fbd9801567db77b17b -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran3.tar.gz/md5/ec293a15d294d3ce3700cc85435775d5 -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran3.tar.gz/sha512/f24efd506bab60fad3dcd7c1a086a54471451830aa8b7cbd2b4fb65f6fcf4fbc3de326046df0758b7739ed4038a63d503d87f65c58870c915590c15145ab90b3 -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran4.tar.gz/md5/0f441cfb17e1f7280ce2fb606c30bcd1 -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran4.tar.gz/sha512/283547b14a5facb4f21f02900af64e279818cbf42c64932d3d73a4eb8109f0b7279d334c6991b9071a2d1c9dd5621a719f88137824dab335f83add4b77c4f46d -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran5.tar.gz/md5/c523c690bc0dd37394f3ecd2353b374c -CompilerSupportLibraries.v0.4.0+1.i686-w64-mingw32-libgfortran5.tar.gz/sha512/94b02c6be7fe0db7b71c0895d61540d4a75a0dacc544175b88378ddb4973ee8f98566e9a0ccaf70487dd1fd7d145b0e0b39b90ecd7124f60c2b27ddf7e2bfa65 -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/513231d8cbf949cd673e6940799ec8e4 -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/c1e294b989483f6da25f8e30134aca8516d4851f011ba9ec5e013ef071530586db5b8e2d5cbb26d63a9640d64c315392a0a5a902ebd8b6ed86bd579e89444d8e -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/6ebcb68cd8e48b8a996e61055cede76e -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/b2f6668dad0f17dbbaa8523a4e3f6bdc566995ace229805045624297fd620265fa34ab5f1209c3d6649ab24c471fdf30d8ced7e2ab48c215bac009763dd4e841 -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/4e7463a0692c3e3c2ec240052a890247 -CompilerSupportLibraries.v0.4.0+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/5cd5178825b606cc6641c1f7f1a6de19f4c8c0698e6a231eb8d543de981a3f49f5f4ff6c6f7688b541934db47640bc04d40cd4be8728bea76dff55ad1878c7d7 -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran3.tar.gz/md5/be58605737e90ff2803d8a496d4d4f7b -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/9d239ffc38bbafbfe40fbc0fabd3041220b7d18cb014145839e092031a94c714a584f65d941887f00bf1af6a1e967ccb76486759973adda94a9ab5d632bfc87a -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran4.tar.gz/md5/674f654730ac0277558c7cdb268b60fc -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/9c698e5d448567b6c6455832777b9a9747852ce258c4593ea37f110a880992e66c1f6ecfc3169debd1419daf1fb84f8ac5ff9209d152bf5a9198125ba65f2240 -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran5.tar.gz/md5/d70d29db5ef26da73c9cd56f8b41434c -CompilerSupportLibraries.v0.4.0+1.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/b52acf460687b74e9d7bcf12c119fd05986c30b76bf24ab1a207b5cb03ef531617577501ec051c79a7c647fcaf57756f92a3af1b4d6c0a5128f94742ffc8548c -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran3.tar.gz/md5/afbcf12c24b005d67b5e9392835c7b1c -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/682241805f6172071fd17905fd6caec4c64e872da6872aa55f5ef4c28bc492b58063b9eda023c7ddc2929b567f4cf9d7c28194aae5d4ab8a5f2426b94999d1db -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran4.tar.gz/md5/38084c6c747f95f23e01dbde2070f845 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/5995edc58b24f46fbf4ebf95ddc241c471bf1cf7cba33850dd31af84fffa397a97115da46ea34f462c51d3cb405c453c9c346dbbe9c8e0d3add077b801c8bec0 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran5.tar.gz/md5/9aba286d21dbd494e9b8cf2c5016af65 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/1854b43d8fe64da1ff2b2f5f40797fc3ae124d5b58969151947ab29c10a25c93df70ffbf794cfed3b76ed087d43912d5ae22e229455301bbc9599a1d376c3458 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran3.tar.gz/md5/dbf6c90f2d0364f8a8de269cd77caaef -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran3.tar.gz/sha512/360ef9d60b245df2f615f8f0bb3029e69b6a94f1eefd47846328fe6b6aea3819cdc2cf7638bc728a82593be64463ed24db4ed7b05c30ac295110a0f5cc23dcf3 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran4.tar.gz/md5/627a2b70b598a75c802831df08a0f70b -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran4.tar.gz/sha512/1b1f67d0af05dfb42e38736a21e8e73453322daf31183fdc9bbb7c86ee2a94e2aed9429fa5356e4d9095b10d08435134ebf7a34ee159bebf4ab3f1db646ed11e -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran5.tar.gz/md5/d58f6944d8e5c67a0b083c0f0d657ef3 -CompilerSupportLibraries.v0.4.0+1.x86_64-linux-musl-libgfortran5.tar.gz/sha512/8fff42ad9c0541bcdab8fdbfa9aa53cb5cf571e4076c7dbfa2801f1cc0d3710099e4257791253ff095cfe6268572bd675e1ba337639f0ddee25cb0c3880cc947 -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/e9d35321725b43bb9af51a36e8789eaf -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/2ee318a4db9f3c5b56187b9682d45b5fd8fd0e81dd63dfb39edfeabcb3b6acb77c97ec64dab6f8edf75fd0d689072a70c8438114772fce7d56a52bc97a19596d -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/8aed7f77e1488d3d88958330d7c97198 -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/ac22acc565d766f7ab18efcbea5adb1cc08c7a07c40bdb31208e084aad837fbba4b664a0d4ffc15e950d1aecb71e16b194c74f5027420a1aa231375fa70d1d56 -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/721fbc4c32245fc61c1cc6fa5c058e60 -CompilerSupportLibraries.v0.4.0+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/a99850a6b7cd7c7f7c1c38aab445b3f7bc4ad0af7b6d6589cfc98010c9e94dbde9d3f61e0c8bceed9e63b55344e854d0474df062c4714261c7d38608af12d5f6 -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/d97a2d7ea6f9f47be8bfbc03126a5e4a -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/bdbb297e0ce5872017b099cbd029334bb487c72b8d318041aa2994bbb0288712bcd42f1417051f498579ca0a387e3640d429ff6253ef642be4fe91139b7ecf9e -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/27f254507185ec2d1633405d8ae4c208 -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/c2e186d223f70b4aa0f8253af2831f6fe25598d89221136c41af5a9bbf1b64c185631cdf33c5f4e521fb02a477bed4cd3f0b770a2f5e01e4e78f279213e82468 -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/ae6057d7d7f67917910925904ef02f46 -CompilerSupportLibraries.v0.4.0+1.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/90b2620e20c02b970d4f6ca0cd13a2693ff4236048ee967edc1446e35c69f1f9d21acb992f61a613d4a88e29d25fb19628ef8af297c1eef9aa85b473632eaf5d +CompilerSupportLibraries.v0.4.2+1.aarch64-apple-darwin-libgfortran5.tar.gz/md5/da6b125a14c8afc701510ef495ec48a4 +CompilerSupportLibraries.v0.4.2+1.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/607fe8dd0e18301c4ae39b3dc4a53a3f5e262ef5e1dca85c57bf621bba0458839abb4dc8a35468ba4f30e199a2430c79f74836649ee1de33d5017e33266ed531 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran3.tar.gz/md5/d99a6e58fa807d660d6c05ce9ed0302c +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/b2d23ed345f42a3f6704cc075b86bf9d0cd0e471b538337ddb6c696ac1f25fcb809f52a01beab807e44e5bb57a4b2c790931bb251d29795e74046a69149f3eba +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran4.tar.gz/md5/92d99e83e51b7d74a7c757897af218ac +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/1e0caa6ac57def1ea2fb15cdee2617227e9610ec285254c2882064fc876b35a1ec07ffaad469ad75e86141dfa45ffee63d130183f2b7ace331ff96917641d68f +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran5.tar.gz/md5/d850abc973fc99cc9d814e2a9d634b62 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/1150fec9b23e7d33963e3f48837fcbe3bc57ce75defb8820d40fe841a96b92bb2ae2f8bfd68a236bf2644e827d97770a3f82cfa847a2eee393fbca20ac7eb1e0 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran3.tar.gz/md5/4a46df38821119323610dc3a3de89991 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran3.tar.gz/sha512/4e6879736bd642fefe7b15e53130ecfad0555d06a7bc65c8f9f2b406853945b0683986e04da110b2bf936beb0ecc686ac7bc85248d121e2ebf8925973c62583f +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran4.tar.gz/md5/e2426e6e1bb801b49805f44f890b6769 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran4.tar.gz/sha512/b7cb4adf76d34543c468f42a84f421db7a3ddfa9ad6b677705b010e7cd14d44a454b6e91e2f748b8d7d862b32be17732d88c2c15d3d4c43be12f9a798cf17d63 +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran5.tar.gz/md5/89f6ca21d2208dfaa7137511dd5a3a4a +CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran5.tar.gz/sha512/7a4f861ffb066b1644ba18d86f744f6b9d546a35e89d4ee31d3515e164df313c17fc7894dbcd36fa29541cb85a0063cd405da84d5c00401c4047407568a746f2 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/3c6aa40c3103cf4421ce31da6436731a +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/d6df143490d601023fbd81b9eee671f22857d3a8da34cf4ddef7d81a75c65c5a28b8be957f0ecfa78da5ddc119b419a9a313fdb9f76ad15ceffd07d29d03f17e +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/0e61fe0790e4bef56def41808370285c +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/3a4b3d7e4f0fde8c5ca82145d0b5b534c852b9db3fa3414f5eafa8969636ecbe46623fc7047ef1832de4314c188513b6014ca22dabef39f94773e4e8525e9133 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/fd4de3c2926f16ba1ad522b6fbbd82aa +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/f4557719615d12034ca66c55521366c34f555bf69da87263c12e137f2778a17861cf980c3c2c51bbb07cc7873a04aa14b4fc0b3452ddd7d84efbe51d74f68ff6 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/abe8c779a1ee2eaf15a5f0e1a3435b88 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/50b9531bed2a137f06d1b8a08ce24404bd2e9c0438eeec1e6805dc1dfeb47e26193f6bd32e125e17a1f5390c44da08c75414029aac6b723b68d57ffee8f2d7e6 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/295ff16df4d4f1d95e4b34a7c15ea3aa +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/036a985fd449f37cd9c7e9977d13c176b039276b0a23867084582970d85aa6692fc33a7512b2ff77add180ca7ecca7fa99dfcd251fb57972967cfd7c1dac0c35 +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/cd4c4db7896d087bdccf17db917d654f +CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/eba18b632136f95dc17c07d9fdf926251cdc17d963993516e439ad6a65187f976a28c0fa53e2a6aad7158e817f6b262b6786d8a483a0a575aa8efc3019dfe1fe +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/53cf17a61872002baf4978f6ff2cf799 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/ed13268cdfce6c37c55637cdf534092ce9b0309e4f998627a65e37238c17c1c6fb031e74f10865b5355172a1624debf1cec1b6c6487ae1c9a6f29e06b98194e4 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/88cfbbae6d8d694e1174aad15e06fd9f +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/f4cd5d4e46cbcc28fab7ad853c03b3bc1c71bcb2cb7e295f183311e1bc4c3790ba8cb8cc50c3ba8751ffde92e7d23d66a119b62cf110ae3ee2f59c162dc09de8 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/a97498d00965c13d69ae9b0ef6af6e92 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/fa6b0a05b507ffbb67f2b247512b38523f9454c12755a26b18f80d5868e3a09f139943dde08e1c658fc6ad63986713281cc523ab677fffe1d48c0af9121c8cf0 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/9b7f2c17daff254f4492ed6c94af2de7 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/e42789807f2a17783fcfdfe08c80939f233db696ec03c6fe2f73ed113257bc2977cac84c5b731c6e4f18c52bafe0b85348a99720dd2815e5697903ab4f16d968 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/5df4ba6a775a231d3067dc5126222b9b +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/a89af0d35943e79b7588ca4794384680939182d413997dfe5642a672efb13622560a5c36a0eeafee1dbab3eebfa69a5dadaa2e93370bc14a9767f9b4abb0584f +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/342270a5bb44984aea91e857ce7b4379 +CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/14a60f0173bb10215463fd9a88f310bcd0a9c5d411fd72d5aa3ff0bf6c6ecc9590e0e51471088d907e0f22291920cff570f2b2da5e64f790ff1d1ff4824ae935 +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran3.tar.gz/md5/6f71074bfbaea42e65b8d54a03485f7d +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran3.tar.gz/sha512/33dd5656ca6bc78c2c151e593c3fc63b2962d4776f0f3bd18de988931dc386caa3e3c248ca913fcb249d938423fc32a7f7364ab21b936674a772b264f8c4eee7 +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran4.tar.gz/md5/a0d6b7c929cad48710f431458e9fd906 +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran4.tar.gz/sha512/0ac88f8f9158822f41761cd59e406d9d978d6b6e6858dc7e3b57484200dca5b2f8cca7dd2521e0ea1ebf3f781b04f31848fc124a96eea0e7f37f59d03732bade +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran5.tar.gz/md5/980fac5e2db2401e5a83d3e09bdcf90b +CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran5.tar.gz/sha512/b7ffa357ac8deb9c1458526473e1878e9668ad7ae0ce984b0fa3c42acddda126cb7c1e0d3a1bf84e845f94daa9432d8fe989d51617ce9fb8e66e13e59022e27a +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran3.tar.gz/md5/4076ddcfa6c2f23c301666e26f36174a +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran3.tar.gz/sha512/18cdb52d8e99bfd7f81700dee3c7a1752d4cc097ee00c640cd378fe6621c32b4bad9da81e159432079525c54370518feacf74e9338ee32af4bc04908b7664585 +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran4.tar.gz/md5/df0d1c7c9cae6416d4eb55af9af2dd1f +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran4.tar.gz/sha512/6cf9bb0318270448074abc4edb0a373ea4ab17a4e363006f70477e4a9e3f847608344fa23ed9205adafa0c754daccd5d4c4b7628322351727900f12835b7e619 +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran5.tar.gz/md5/6451c7b007ee4914fa96e152132dd6e5 +CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran5.tar.gz/sha512/ce15a66f47704cc1a7e002b89c74580a2cf6e7ed391ac0bcb56e6a913c6abdfd1f2e61721fe25c871fd7543a3a466f030647c8867786c53f39fdc14c17f398a5 +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran3.tar.gz/md5/0db39343cff6f5a3e62535f914937c8e +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran3.tar.gz/sha512/5499161fb358af90fe0287226ef1e11a72b64d412f5c89e38da2c367270bef520d0ea0622c37088a4a729093a5b6601a808f54dfdc6f64b6f24c3c1e05f81297 +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran4.tar.gz/md5/4ce35cb3838e32862d21a528b3850279 +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran4.tar.gz/sha512/601b569aa569dc68f7e4a4509ae233bd88b461da373e127b459768f6c22100b7cb5905c0025a3d32919854ac02b9d3073952bc1d68a1dd1b973978682cb70c52 +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran5.tar.gz/md5/e8d6ff85569ce872142e55d6fff97309 +CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran5.tar.gz/sha512/894c4fc5e57bcd59958b536566ba04b27204fe31c854e7d8f82fd7b59eda84792d86379e1f994f6574c8120bf85c6608f69083c660180064ba1148928914e6ae +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/b9ba022254d0945179b89fe214897312 +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/e141b870f3fd2bb69a2a5227aad3987a32caaa2280e3d59e70e3a1498a0e71eb30f454aaa1c2a5df0d72f18876ec8a336494707d04fa817eec3a8dc8f5dedf9f +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/352054f4b9be20ae4e7bb8f41e3ea547 +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/7fab7e059ff57e1c76a919cf52dd6849850d918f8859208658f6b85bbbcef04567a576b4d824264d0743895391e1bb3a33c385cc196bb98081699a6b0c5e3420 +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/c28cf8dddf0208fdb7bf981f3539413a +CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/dbf6ffbbab2569dee117ed8d249c510fba31d0738dea173e7fa146f56a0a8602112467cbac3f83aef1743737aa63bc2f2ab40b9393dbe0a2efbe6a031c152a97 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran3.tar.gz/md5/3a3b0b2d283ed9bc502c58c07a9c7ad3 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/072e743b89a8609d0651b9d1ed2880d7a804bd1c6a13e5ac3d23e0212e721adceb764678a22af715e5f35a74434bdfdbb87c9370c282f3f8193a0bd354a03d91 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran4.tar.gz/md5/1531545b7c2234be3e6c24a9e3dc7fd5 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/51c3892be0adbea098daf66ee3afff6da2172f65af63cce24bf968c8e237409b0ad3a3ca89abce5c4b27ec96d89f347b45f4fb26f50d84e23835da3963ab1d86 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran5.tar.gz/md5/3529a60ccc713a9a825fad7d2f3d07e8 +CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/6e5fae2d39569634d7b9d583d6a8d785e5689a65e30adb0ecded87a3235586dc4fe210e76153e26e9ef2a583183834a312e84991134949000516a2accb3dee4c +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran3.tar.gz/md5/ea74cd089e94203a6ef33754388c786a +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/30a72e2a50ff152ceb4e9764c60bcc5113845a918eb69a08b8a70e54e9df6b7923f697f39c2e576c553108dfff2cc14a27078c698cc325fc69736ebd67d403ab +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran4.tar.gz/md5/68075a244cb9f2c055a4b7b2ec6fab27 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/b49c77dfd2bf54587023eadc8cb64e2600fa826c99fb49c74325f1a631b2edf845870715bbd7a8bd4fe94233c78df632f9a8e433650c9a168c8fbc4894b6532a +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran5.tar.gz/md5/b2751b7c72c0ba52d8a252e2d1f01dd1 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/454fc2ab7bb604e2a424507ff35f213414f286382963e0dd29443c0bf21772a9a5923bd81c77317977ca0cec826ee46408b079aedad8ade87db3f35353125c20 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran3.tar.gz/md5/e691c3d13d5cd7265bbc830a28adaf14 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran3.tar.gz/sha512/62d5e3928bcc00e2741705403d39c96236b7e578b63256f67b5e36d9a60c960007c18c499e33487559e1b677b01445af0541a1ac6236bc724809aa757eb55f61 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran4.tar.gz/md5/0a1a41e1591bcb654a60fee50c041236 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran4.tar.gz/sha512/ef4ce20e72418e72293b5a6836b90dac4a8975c50db4204eef6e6c6660588a8c5769998462f758232c54ba4067ca4d0a1172bee3460f92cb41bb75a75d76f96d +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran5.tar.gz/md5/2ceecbfa72398c12532403fbf731f108 +CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran5.tar.gz/sha512/ff15be3083eb86159cbc5df969305e7990fa2f22f86f73a090db6ff25ab1671288ac37d8b54ae95acaca0f281dfda48de702c87cd0126114626a954f7b0516a2 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/49dcf29be7810799c2d36e1f89e97ca7 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/daf2fc70f8bace0b83b0317ada7444b6ef6188105fee403f76ddb043f2aee4c1f4bc04787d6a920abd583eaf32a078dcf680cae09e6f751b43a64567af4e7672 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/b446db483a6aa734c0dffe1f7f1f5c65 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/d707d5af3c5407ae47d1d55745259855ba899dfbebf71e528fcade4830fbdbf0e8d215c41c745594b9db3dc1bc846e46222571dcf8eea8639a6037510e3bef06 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/2ae1eac30f638c88eef1fc6621740069 +CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/c6585232b6adadc5b78c870f516a3ed1381b421fa58735b74e096afc69b6d08a169bd06662eeac70f63a52ea6b9f1f94d96aa86eee8b026419a59a231317637b +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/1cffa4d37629e62c17ae78f88b3ba3ed +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/164aff25e92fab85a4df4ae43b0dcc628e4e8ff0afe59721a98ab9dfff01edbaf93370d8c3079f4c9cbbb3ffdd9050f85a53cd336f9947f19cf4a3b3ff8b4394 +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/0511722afd53392fcafe72932b7d1bc9 +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/4edc52b6e15f19896019e0227b3c95c73b50cc16544c70d7506e05b1a20ba2a694ae8cfb460df453d062939bef3b09693d209922247a585c48043f269c40e8d7 +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/42fe08fa435e5e0bc71bd3135fa23d6e +CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/051c20c7f6c7c6f22fb467786b031c43c53ff17d67a87d82e2f0c01c7623a1787afa3bc46eb347cc2eecee199953976b6f7119f371ba8d05d1a8d4e11161cdae diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 4cf1787854293..71603a22ccea5 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,6 +1,8 @@ SuiteSparse-5.8.1.tar.gz/md5/c414679bbc9432a3def01b31ad921140 SuiteSparse-5.8.1.tar.gz/sha512/3d986157acd39968216880c2de30c54d72e0addd7318a04948c1b842ad9c876bcde32f292504d4540a4baa998a368dfc0db000606a2d00f61760a92d5b8c1cb8 SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/md5/57fa5164c7ee989ff95571037c0dfcc0 +SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/md5/57fa5164c7ee989ff95571037c0dfcc0 +SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/sha512/a12ac3ec77ac0b78595bc247a4fc37b9136e9a5095abf061b3fade60130b153d61b5a3c602be87c7334660b67f3539075975a9d4a1545d8ee5fd62c734941032 SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/sha512/a12ac3ec77ac0b78595bc247a4fc37b9136e9a5095abf061b3fade60130b153d61b5a3c602be87c7334660b67f3539075975a9d4a1545d8ee5fd62c734941032 SuiteSparse.v5.8.1+0.aarch64-linux-gnu.tar.gz/md5/a932269a0fb499d931867acc9505e49b SuiteSparse.v5.8.1+0.aarch64-linux-gnu.tar.gz/sha512/2983c095533f7d8c2fa81779bf907e9024b1bfef58e934a4d524d767911a41f3006babc20530b3b23854d87adce02eb5e7e8a98d4ad3d853b03abc64cd8d5e6b @@ -26,6 +28,8 @@ SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/md5/d266370cc574c8ca8b2b8a94d6b8 SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/sha512/2377d662f91d01229e3c44ec1c5624b6361e823ff90d625acc3bab8f68ada1b3b7b67f4e56c8896f890e5780bd2fcb494b5a1f91c9c7803715eac2a2a4bb938f SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 +SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 diff --git a/stdlib/CompilerSupportLibraries_jll/Project.toml b/stdlib/CompilerSupportLibraries_jll/Project.toml index 6f340407b6afb..86a66afc17ed0 100644 --- a/stdlib/CompilerSupportLibraries_jll/Project.toml +++ b/stdlib/CompilerSupportLibraries_jll/Project.toml @@ -1,6 +1,6 @@ name = "CompilerSupportLibraries_jll" uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.4.0+1" +version = "0.4.2+1" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From b5177e70941ea9f0149d5df3481825e53f969a86 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 28 Apr 2021 18:41:50 +0900 Subject: [PATCH 273/439] REPL: fix #27184, ensure macro existence before lowering (#40621) --- stdlib/REPL/src/REPLCompletions.jl | 6 ++++++ stdlib/REPL/test/replcompletions.jl | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index fa5fd8434bec7..5412f6f157ada 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -384,6 +384,7 @@ function get_value(sym::Expr, fn) end get_value(sym::Symbol, fn) = isdefined(fn, sym) ? (getfield(fn, sym), true) : (nothing, false) get_value(sym::QuoteNode, fn) = isdefined(fn, sym.value) ? (getfield(fn, sym.value), true) : (nothing, false) +get_value(sym::GlobalRef, fn) = get_value(sym.name, sym.mod) get_value(sym, fn) = (sym, true) # Return the value of a getfield call expression @@ -456,6 +457,11 @@ function get_type(sym::Expr, fn::Module) # try to analyze nests of calls. if this fails, try using the expanded form. val, found = try_get_type(sym, fn) found && return val, found + # https://github.com/JuliaLang/julia/issues/27184 + if isexpr(sym, :macrocall) + _, found = get_type(first(sym.args), fn) + found || return Any, false + end return try_get_type(Meta.lower(fn, sym), fn) end diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index dd6327e7a34bd..97eee61579142 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -1113,3 +1113,10 @@ let s = "test_dict[\"ab" c, r = test_complete_context(s) @test c == Any["\"abc\"", "\"abcd\""] end + +# https://github.com/JuliaLang/julia/issues/27184 +let + (test_complete("@noexist."); @test true) + (test_complete("Main.@noexist."); @test true) + (test_complete("@Main.noexist."); @test true) +end From e9ef2805bbd7f2c46e569fe3e6cdea8e9554c862 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 28 Apr 2021 13:44:19 +0400 Subject: [PATCH 274/439] Fix showindices for IdentityUnitRange (#40608) --- base/show.jl | 2 +- test/show.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index dca5f97f99830..595af52a5fc1c 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2848,7 +2848,7 @@ function showarg(io::IO, v::SubArray, toplevel) toplevel && print(io, " with eltype ", eltype(v)) return nothing end -showindices(io, ::Union{Slice,IdentityUnitRange}, inds...) = +showindices(io, ::Slice, inds...) = (print(io, ", :"); showindices(io, inds...)) showindices(io, ind1, inds...) = (print(io, ", ", ind1); showindices(io, inds...)) diff --git a/test/show.jl b/test/show.jl index 65b5441841f9c..2c8a6fd67bd4a 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1667,6 +1667,11 @@ end @test summary(p) == "2-element reinterpret(reshape, Tuple{Float32, Float32}, ::Matrix{Float32}) with eltype Tuple{Float32, Float32}" @test Base.showarg(io, p, false) === nothing @test String(take!(io)) == "reinterpret(reshape, Tuple{Float32, Float32}, ::Matrix{Float32})" + + r = Base.IdentityUnitRange(2:2) + B = @view ones(2)[r] + Base.showarg(io, B, false) + @test String(take!(io)) == "view(::Vector{Float64}, $(repr(r)))" end @testset "Methods" begin From fb5e04cec18b8076b3f57022e1e4dde095591f5b Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Wed, 28 Apr 2021 21:11:29 +0900 Subject: [PATCH 275/439] add docstring for VecElement (#40019) Co-authored-by: Jameson Nash --- base/baseext.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/base/baseext.jl b/base/baseext.jl index 75ef96caa94be..8ebd599312453 100644 --- a/base/baseext.jl +++ b/base/baseext.jl @@ -2,6 +2,17 @@ # extensions to Core types to add features in Base +""" + VecElement{T} + +A wrapper type that holds a single value of type `T`. When used in the context of an +`NTuple{N, VecElement{T}} where {T, N}` object, it provides a hint to the runtime +system to align that struct to be more amenable to vectorization optimization +opportunities. In `ccall`, such an NTuple in the type signature will also use the +vector register ABI, rather than the usual struct ABI. +""" +VecElement + # hook up VecElement constructor to Base.convert VecElement{T}(arg) where {T} = VecElement{T}(convert(T, arg)) convert(::Type{T}, arg::T) where {T<:VecElement} = arg From c31afce42d99f2be67ff97d7ad4f45216bf91818 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 28 Apr 2021 05:15:45 -0700 Subject: [PATCH 276/439] Include all exported functions in Test.jl documentation (#37361) --- doc/src/base/base.md | 1 + stdlib/Test/docs/src/index.md | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 0eac8913542da..3cb71ace680e6 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -243,6 +243,7 @@ Core.Module Core.Function Base.hasmethod Core.applicable +Base.isambiguous Core.invoke Base.@invoke Base.invokelatest diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index 82922773f899b..510654c69ecd1 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -102,6 +102,7 @@ or could not be evaluated due to an error, the test set will then throw a `TestS ```@docs Test.@testset +Test.TestSetException ``` We can put our tests for the `foo(x)` function in a test set: @@ -295,6 +296,18 @@ And using that testset looks like: end ``` +## Test utilities + +```@docs +Test.GenericArray +Test.GenericDict +Test.GenericOrder +Test.GenericSet +Test.GenericString +Test.detect_ambiguities +Test.detect_unbound_args +``` + ```@meta DocTestSetup = nothing ``` From e43895393b1366e434e494247d4564cfcbc645bb Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Wed, 28 Apr 2021 21:49:58 +0900 Subject: [PATCH 277/439] Fix typo in opaque_closure.c (#40647) paramters -> parameters --- src/opaque_closure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opaque_closure.c b/src/opaque_closure.c index a7298e3805218..9f2662f32eb25 100644 --- a/src/opaque_closure.c +++ b/src/opaque_closure.c @@ -53,7 +53,7 @@ JL_CALLABLE(jl_new_opaque_closure_jlcall) // check whether the specified number of arguments is compatible with the -// specified number of paramters of the tuple type +// specified number of parameters of the tuple type STATIC_INLINE int jl_tupletype_length_compat(jl_value_t *v, size_t nargs) JL_NOTSAFEPOINT { v = jl_unwrap_unionall(v); From 5162023b9b67265ddb0bbbc0f4bd6b225c429aa0 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 28 Apr 2021 10:12:07 -0400 Subject: [PATCH 278/439] [LLVM] Drop support for versions prior to LLVM 11 (#40634) --- deps/llvm.mk | 71 - deps/patches/llvm-10-r_aarch64_prel32.patch | 66 - deps/patches/llvm-10-r_ppc_rel.patch | 116 - .../llvm-10.0-PPC-LI-Elimination.patch | 161 -- deps/patches/llvm-10.0-PPC_SELECT_CC.patch | 135 -- deps/patches/llvm-8.0-D50167-scev-umin.patch | 1870 ----------------- .../llvm-8.0-D55758-tablegen-cond.patch | 794 ------- .../llvm-8.0-D59389-refactor-wmma.patch | 899 -------- .../llvm-8.0-D59393-mma-ptx63-fix.patch | 510 ----- .../llvm-8.0-D63688-wasm-isLocal.patch | 39 - .../llvm-8.0-D65174-limit-merge-stores.patch | 119 -- .../patches/llvm-8.0-D66401-mingw-reloc.patch | 69 - .../llvm-8.0-D66657-codegen-degenerate.patch | 65 - .../llvm-8.0-D71495-vectorize-freduce.patch | 94 - .../llvm-8.0-D75072-SCEV-add-type.patch | 415 ---- .../llvm-9.0-D65174-limit-merge-stores.patch | 116 - deps/patches/llvm-9.0-D78196.patch | 15 - deps/patches/llvm-9.0-D85499.patch | 425 ---- deps/patches/llvm-D57118-powerpc.patch | 30 - deps/patches/llvm-exegesis-mingw.patch | 24 - deps/patches/llvm-symver-jlprefix.patch | 18 - deps/patches/llvm-test-plugin-mingw.patch | 24 - deps/patches/llvm7-D50010-VNCoercion-ni.patch | 67 - deps/patches/llvm7-windows-race.patch | 15 - .../llvm9-D71443-PPC-MC-redef-symbol.patch | 47 - doc/src/devdocs/llvm.md | 2 +- src/abi_aarch64.cpp | 5 - src/abi_ppc64le.cpp | 4 - src/aotcompile.cpp | 21 - src/ccall.cpp | 8 - src/cgutils.cpp | 24 +- src/clangsa/GCChecker.cpp | 9 - src/codegen.cpp | 36 +- src/codegen_shared.h | 5 - src/debuginfo.cpp | 29 - src/disasm.cpp | 42 +- src/intrinsics.cpp | 4 - src/jitlayers.h | 4 - src/llvm-alloc-opt.cpp | 19 - src/llvm-api.cpp | 3 - src/llvm-gc-invariant-verifier.cpp | 3 - src/llvm-late-gc-lowering.cpp | 35 - src/llvm-propagate-addrspaces.cpp | 3 - src/llvm-remove-addrspaces.cpp | 9 +- src/llvm-version.h | 7 +- src/processor_arm.cpp | 10 +- 46 files changed, 11 insertions(+), 6475 deletions(-) delete mode 100644 deps/patches/llvm-10-r_aarch64_prel32.patch delete mode 100644 deps/patches/llvm-10-r_ppc_rel.patch delete mode 100644 deps/patches/llvm-10.0-PPC-LI-Elimination.patch delete mode 100644 deps/patches/llvm-10.0-PPC_SELECT_CC.patch delete mode 100644 deps/patches/llvm-8.0-D50167-scev-umin.patch delete mode 100644 deps/patches/llvm-8.0-D55758-tablegen-cond.patch delete mode 100644 deps/patches/llvm-8.0-D59389-refactor-wmma.patch delete mode 100644 deps/patches/llvm-8.0-D59393-mma-ptx63-fix.patch delete mode 100644 deps/patches/llvm-8.0-D63688-wasm-isLocal.patch delete mode 100644 deps/patches/llvm-8.0-D65174-limit-merge-stores.patch delete mode 100644 deps/patches/llvm-8.0-D66401-mingw-reloc.patch delete mode 100644 deps/patches/llvm-8.0-D66657-codegen-degenerate.patch delete mode 100644 deps/patches/llvm-8.0-D71495-vectorize-freduce.patch delete mode 100644 deps/patches/llvm-8.0-D75072-SCEV-add-type.patch delete mode 100644 deps/patches/llvm-9.0-D65174-limit-merge-stores.patch delete mode 100644 deps/patches/llvm-9.0-D78196.patch delete mode 100644 deps/patches/llvm-9.0-D85499.patch delete mode 100644 deps/patches/llvm-D57118-powerpc.patch delete mode 100644 deps/patches/llvm-exegesis-mingw.patch delete mode 100644 deps/patches/llvm-symver-jlprefix.patch delete mode 100644 deps/patches/llvm-test-plugin-mingw.patch delete mode 100644 deps/patches/llvm7-D50010-VNCoercion-ni.patch delete mode 100644 deps/patches/llvm7-windows-race.patch delete mode 100644 deps/patches/llvm9-D71443-PPC-MC-redef-symbol.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 1990110d64117..7e2b7357db3d0 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -457,77 +457,6 @@ $$(LLVM_BUILDDIR_withtype)/build-compiled: $$(LLVM_SRC_DIR)/$1.patch-applied LLVM_PATCH_PREV := $$(LLVM_SRC_DIR)/$1.patch-applied endef -ifeq ($(LLVM_VER_SHORT),8.0) -$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_6.0.1)) -$(eval $(call LLVM_PATCH,llvm8-D34078-vectorize-fdiv)) -$(eval $(call LLVM_PATCH,llvm-7.0-D44650)) # mingw32 build fix -$(eval $(call LLVM_PATCH,llvm-6.0-DISABLE_ABI_CHECKS)) -$(eval $(call LLVM_PATCH,llvm7-D50010-VNCoercion-ni)) -$(eval $(call LLVM_PATCH,llvm-8.0-D50167-scev-umin)) -$(eval $(call LLVM_PATCH,llvm7-windows-race)) -$(eval $(call LLVM_PATCH,llvm-D57118-powerpc)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm-exegesis-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm-test-plugin-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm-8.0-D66401-mingw-reloc)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm7-revert-D44485)) -$(eval $(call LLVM_PATCH,llvm-8.0-D63688-wasm-isLocal)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D55758-tablegen-cond)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D59389-refactor-wmma)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D59393-mma-ptx63-fix)) # remove for 9.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D66657-codegen-degenerate)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D71495-vectorize-freduce)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D75072-SCEV-add-type)) -$(eval $(call LLVM_PATCH,llvm-8.0-D65174-limit-merge-stores)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-julia-tsan-custom-as)) -endif # LLVM_VER 8.0 - -ifeq ($(LLVM_VER_SHORT),9.0) -$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_6.0.1)) -$(eval $(call LLVM_PATCH,llvm8-D34078-vectorize-fdiv)) -$(eval $(call LLVM_PATCH,llvm-7.0-D44650)) # mingw32 build fix -$(eval $(call LLVM_PATCH,llvm-6.0-DISABLE_ABI_CHECKS)) -$(eval $(call LLVM_PATCH,llvm9-D50010-VNCoercion-ni)) -$(eval $(call LLVM_PATCH,llvm-exegesis-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm-test-plugin-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm7-revert-D44485)) -$(eval $(call LLVM_PATCH,llvm-8.0-D66657-codegen-degenerate)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-8.0-D71495-vectorize-freduce)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-D75072-SCEV-add-type)) -$(eval $(call LLVM_PATCH,llvm-9.0-D65174-limit-merge-stores)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm9-D71443-PPC-MC-redef-symbol)) # remove for 10.0 -$(eval $(call LLVM_PATCH,llvm-9.0-D78196)) # remove for 11.0 -$(eval $(call LLVM_PATCH,llvm-julia-tsan-custom-as)) -$(eval $(call LLVM_PATCH,llvm-9.0-D85499)) # landed as D85553 -$(eval $(call LLVM_PATCH,llvm-D80101)) # remove for LLVM 12 -$(eval $(call LLVM_PATCH,llvm-D84031)) # remove for LLVM 12 -$(eval $(call LLVM_PATCH,llvm-rGb498303066a6-gcc11-header-fix)) # remove for LLVM 12 -endif # LLVM_VER 9.0 - -ifeq ($(LLVM_VER_SHORT),10.0) -$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_6.0.1)) -$(eval $(call LLVM_PATCH,llvm8-D34078-vectorize-fdiv)) -$(eval $(call LLVM_PATCH,llvm-7.0-D44650)) # mingw32 build fix -$(eval $(call LLVM_PATCH,llvm-6.0-DISABLE_ABI_CHECKS)) -$(eval $(call LLVM_PATCH,llvm9-D50010-VNCoercion-ni)) -$(eval $(call LLVM_PATCH,llvm-exegesis-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm-test-plugin-mingw)) # mingw build -$(eval $(call LLVM_PATCH,llvm7-revert-D44485)) -$(eval $(call LLVM_PATCH,llvm-D75072-SCEV-add-type)) -$(eval $(call LLVM_PATCH,llvm-10.0-PPC_SELECT_CC)) # delete for LLVM 11 -$(eval $(call LLVM_PATCH,llvm-10.0-PPC-LI-Elimination)) # delete for LLVM 11 -$(eval $(call LLVM_PATCH,llvm-julia-tsan-custom-as)) -$(eval $(call LLVM_PATCH,llvm-D80101)) # remove for LLVM 12 -$(eval $(call LLVM_PATCH,llvm-D84031)) # remove for LLVM 12 -$(eval $(call LLVM_PATCH,llvm-10-D85553)) # remove for LLVM 12 -$(eval $(call LLVM_PATCH,llvm-10-r_aarch64_prel32)) # remove for LLVM 11 -$(eval $(call LLVM_PATCH,llvm-10-r_ppc_rel)) # remove for LLVM 11 -$(eval $(call LLVM_PATCH,llvm-10-unique_function_clang-sa)) -ifeq ($(BUILD_LLVM_CLANG),1) -$(eval $(call LLVM_PATCH,llvm-D88630-clang-cmake)) -endif -$(eval $(call LLVM_PATCH,llvm-rGb498303066a6-gcc11-header-fix)) # remove for LLVM 12 -endif # LLVM_VER 10.0 - ifeq ($(LLVM_VER_SHORT),11.0) ifeq ($(LLVM_VER_PATCH), 0) $(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_6.0.1)) # remove for LLVM 12 diff --git a/deps/patches/llvm-10-r_aarch64_prel32.patch b/deps/patches/llvm-10-r_aarch64_prel32.patch deleted file mode 100644 index 7236574b3311d..0000000000000 --- a/deps/patches/llvm-10-r_aarch64_prel32.patch +++ /dev/null @@ -1,66 +0,0 @@ -From c530dd687328d4208f91e62b600d25ec6e7f0f39 Mon Sep 17 00:00:00 2001 -From: Fangrui Song -Date: Fri, 17 Jul 2020 23:49:15 -0700 -Subject: [PATCH 2/2] [RelocationResolver] Support R_AARCH64_PREL32 - -Code from D83800 by Yichao Yu ---- - llvm/lib/Object/RelocationResolver.cpp | 6 ++++++ - llvm/test/DebugInfo/AArch64/eh-frame.ll | 21 +++++++++++++++++++++ - 2 files changed, 27 insertions(+) - create mode 100644 llvm/test/DebugInfo/AArch64/eh-frame.ll - -diff --git llvm/lib/Object/RelocationResolver.cpp llvm/lib/Object/RelocationResolver.cpp -index eedb236f83d..80339ebf7b9 100644 ---- llvm/lib/Object/RelocationResolver.cpp -+++ llvm/lib/Object/RelocationResolver.cpp -@@ -62,6 +62,8 @@ static bool supportsAArch64(uint64_t Type) { - switch (Type) { - case ELF::R_AARCH64_ABS32: - case ELF::R_AARCH64_ABS64: -+ case ELF::R_AARCH64_PREL32: -+ case ELF::R_AARCH64_PREL64: - return true; - default: - return false; -@@ -74,6 +76,10 @@ static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { - return (S + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_AARCH64_ABS64: - return S + getELFAddend(R); -+ case ELF::R_AARCH64_PREL32: -+ return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; -+ case ELF::R_AARCH64_PREL64: -+ return S + getELFAddend(R) - R.getOffset(); - default: - llvm_unreachable("Invalid relocation type"); - } -diff --git llvm/test/DebugInfo/AArch64/eh-frame.ll llvm/test/DebugInfo/AArch64/eh-frame.ll -new file mode 100644 -index 00000000000..9651159271e ---- /dev/null -+++ llvm/test/DebugInfo/AArch64/eh-frame.ll -@@ -0,0 +1,21 @@ -+; RUN: llc -filetype=obj -mtriple=aarch64 %s -o %t.o -+; RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefix=REL32 -+; RUN: llvm-dwarfdump --eh-frame %t.o 2>&1 | FileCheck %s -+ -+; REL32: R_AARCH64_PREL32 .text 0x0 -+; REL32-NEXT: R_AARCH64_PREL32 .text 0x4 -+ -+; CHECK-NOT: warning: -+; CHECK: FDE cie=00000000 pc=00000000...00000004 -+;; TODO Take relocation into consideration -+; CHECK: FDE cie=00000000 pc=00000000...00000004 -+ -+define void @foo() { -+entry: -+ ret void -+} -+ -+define void @bar() { -+entry: -+ ret void -+} --- -2.28.0 - diff --git a/deps/patches/llvm-10-r_ppc_rel.patch b/deps/patches/llvm-10-r_ppc_rel.patch deleted file mode 100644 index f86ee75bb845e..0000000000000 --- a/deps/patches/llvm-10-r_ppc_rel.patch +++ /dev/null @@ -1,116 +0,0 @@ -From b7f604447cbd76c803ccff5c0ff1b699b9c1504e Mon Sep 17 00:00:00 2001 -From: Fangrui Song -Date: Fri, 17 Jul 2020 23:29:50 -0700 -Subject: [PATCH 1/2] [RelocationResolver] Support R_PPC_REL32 & - R_PPC64_REL{32,64} - -This suppresses `failed to compute relocation: R_PPC_REL32, Invalid data was encountered while parsing the file` -and its 64-bit variants when running llvm-dwarfdump on a PowerPC object file with .eh_frame - -Unfortunately it is difficult to test the computation: -DWARFDataExtractor::getEncodedPointer does not use the relocated value -and even if it does, we need to teach llvm-dwarfdump --eh-frame to do -some linker job to report a reasonable address. ---- - llvm/lib/Object/RelocationResolver.cpp | 20 +++++++++++-- - llvm/test/DebugInfo/PowerPC/eh-frame.ll | 39 +++++++++++++++++++++++++ - 2 files changed, 57 insertions(+), 2 deletions(-) - create mode 100644 llvm/test/DebugInfo/PowerPC/eh-frame.ll - -diff --git llvm/lib/Object/RelocationResolver.cpp llvm/lib/Object/RelocationResolver.cpp -index 31478be7899..eedb236f83d 100644 ---- llvm/lib/Object/RelocationResolver.cpp -+++ llvm/lib/Object/RelocationResolver.cpp -@@ -131,6 +131,8 @@ static bool supportsPPC64(uint64_t Type) { - switch (Type) { - case ELF::R_PPC64_ADDR32: - case ELF::R_PPC64_ADDR64: -+ case ELF::R_PPC64_REL32: -+ case ELF::R_PPC64_REL64: - return true; - default: - return false; -@@ -143,6 +145,10 @@ static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { - return (S + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_PPC64_ADDR64: - return S + getELFAddend(R); -+ case ELF::R_PPC64_REL32: -+ return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; -+ case ELF::R_PPC64_REL64: -+ return S + getELFAddend(R) - R.getOffset(); - default: - llvm_unreachable("Invalid relocation type"); - } -@@ -238,12 +244,22 @@ static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { - } - - static bool supportsPPC32(uint64_t Type) { -- return Type == ELF::R_PPC_ADDR32; -+ switch (Type) { -+ case ELF::R_PPC_ADDR32: -+ case ELF::R_PPC_REL32: -+ return true; -+ default: -+ return false; -+ } - } - - static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { -- if (R.getType() == ELF::R_PPC_ADDR32) -+ switch (R.getType()) { -+ case ELF::R_PPC_ADDR32: - return (S + getELFAddend(R)) & 0xFFFFFFFF; -+ case ELF::R_PPC_REL32: -+ return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; -+ } - llvm_unreachable("Invalid relocation type"); - } - -diff --git llvm/test/DebugInfo/PowerPC/eh-frame.ll llvm/test/DebugInfo/PowerPC/eh-frame.ll -new file mode 100644 -index 00000000000..3a8f7df6b61 ---- /dev/null -+++ llvm/test/DebugInfo/PowerPC/eh-frame.ll -@@ -0,0 +1,39 @@ -+; RUN: llc -filetype=obj -mtriple=powerpc %s -o %t32.o -+; RUN: llvm-readobj -r %t32.o | FileCheck %s --check-prefix=PPC_REL -+; RUN: llvm-dwarfdump --eh-frame %t32.o 2>&1 | FileCheck %s --check-prefix=PPC -+ -+; PPC_REL: R_PPC_REL32 .text 0x0 -+; PPC_REL-NEXT: R_PPC_REL32 .text 0x4 -+ -+; PPC-NOT: warning: -+; PPC: FDE cie=00000000 pc=00000000...00000004 -+;; TODO Take relocation into consideration -+; PPC: FDE cie=00000000 pc=00000000...00000004 -+ -+; RUN: llc -filetype=obj -mtriple=ppc64 %s -o %t64.o -+; RUN: llvm-readobj -r %t64.o | FileCheck %s --check-prefix=PPC64_REL -+; RUN: llvm-dwarfdump --eh-frame %t64.o 2>&1 | FileCheck %s --check-prefix=PPC64 -+ -+; PPC64_REL: R_PPC64_REL32 .text 0x0 -+; PPC64_REL-NEXT: R_PPC64_REL32 .text 0x10 -+ -+; PPC64-NOT: warning: -+; PPC64: FDE cie=00000000 pc=00000000...00000010 -+; PPC64: FDE cie=00000000 pc=00000000...00000010 -+ -+; RUN: llc -filetype=obj -mtriple=ppc64le -code-model=large %s -o %t64l.o -+; RUN: llvm-readobj -r %t64l.o | FileCheck %s --check-prefix=PPC64L_REL -+; RUN: llvm-dwarfdump --eh-frame %t64l.o 2>&1 | FileCheck %s --check-prefix=PPC64 -+ -+; PPC64L_REL: R_PPC64_REL64 .text 0x0 -+; PPC64L_REL-NEXT: R_PPC64_REL64 .text 0x10 -+ -+define void @foo() { -+entry: -+ ret void -+} -+ -+define void @bar() { -+entry: -+ ret void -+} --- -2.28.0 - diff --git a/deps/patches/llvm-10.0-PPC-LI-Elimination.patch b/deps/patches/llvm-10.0-PPC-LI-Elimination.patch deleted file mode 100644 index f47a2c97f0e37..0000000000000 --- a/deps/patches/llvm-10.0-PPC-LI-Elimination.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 5423496713e84dea2650e1703821de620f934573 Mon Sep 17 00:00:00 2001 -From: Nemanja Ivanovic -Date: Thu, 9 Apr 2020 21:34:30 -0500 -Subject: [PATCH] [PowerPC] Bail out of redundant LI elimination on an implicit - kill - -The transformation currently does not differentiate between explicit -and implicit kills. However, it is not valid to later simply clear -an implicit kill flag since the kill could be due to a call or return. - -Fixes: https://bugs.llvm.org/show_bug.cgi?id=45374 ---- - .../lib/Target/PowerPC/PPCPreEmitPeephole.cpp | 10 ++ - .../remove-redundant-li-skip-imp-kill.mir | 114 ++++++++++++++++++ - 2 files changed, 124 insertions(+) - create mode 100644 llvm/test/CodeGen/PowerPC/remove-redundant-li-skip-imp-kill.mir - -diff --git llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp -index a4b4bf2973d..4ea714ff15f 100644 ---- llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp -+++ llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp -@@ -109,6 +109,16 @@ namespace { - // Track the operand that kill Reg. We would unset the kill flag of - // the operand if there is a following redundant load immediate. - int KillIdx = AfterBBI->findRegisterUseOperandIdx(Reg, true, TRI); -+ -+ // We can't just clear implicit kills, so if we encounter one, stop -+ // looking further. -+ if (KillIdx != -1 && AfterBBI->getOperand(KillIdx).isImplicit()) { -+ LLVM_DEBUG(dbgs() -+ << "Encountered an implicit kill, cannot proceed: "); -+ LLVM_DEBUG(AfterBBI->dump()); -+ break; -+ } -+ - if (KillIdx != -1) { - assert(!DeadOrKillToUnset && "Shouldn't kill same register twice"); - DeadOrKillToUnset = &AfterBBI->getOperand(KillIdx); -diff --git llvm/test/CodeGen/PowerPC/remove-redundant-li-skip-imp-kill.mir llvm/test/CodeGen/PowerPC/remove-redundant-li-skip-imp-kill.mir -new file mode 100644 -index 00000000000..78091d027ce ---- /dev/null -+++ llvm/test/CodeGen/PowerPC/remove-redundant-li-skip-imp-kill.mir -@@ -0,0 +1,114 @@ -+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -+# RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown -run-pass \ -+# RUN: ppc-pre-emit-peephole %s -o - | FileCheck %s -+--- | -+ ; ModuleID = 'a.ll' -+ source_filename = "a.ll" -+ target datalayout = "e-m:e-i64:64-n32:64" -+ -+ ; Function Attrs: nounwind -+ define dso_local signext i32 @b(i32 signext %a, i32* nocapture %b) local_unnamed_addr #0 { -+ entry: -+ %call = tail call signext i32 @g(i32 signext %a) -+ store i32 %call, i32* %b, align 4 -+ %call1 = tail call signext i32 @g(i32 signext %a) -+ ret i32 %call1 -+ } -+ -+ ; Function Attrs: nounwind -+ declare signext i32 @g(i32 signext) local_unnamed_addr #0 -+ -+ ; Function Attrs: nounwind -+ declare void @llvm.stackprotector(i8*, i8**) #0 -+ -+ attributes #0 = { nounwind } -+ -+... -+--- -+name: b -+alignment: 16 -+exposesReturnsTwice: false -+legalized: false -+regBankSelected: false -+selected: false -+failedISel: false -+tracksRegLiveness: true -+hasWinCFI: false -+registers: [] -+liveins: -+ - { reg: '$x3', virtual-reg: '' } -+ - { reg: '$x4', virtual-reg: '' } -+frameInfo: -+ isFrameAddressTaken: false -+ isReturnAddressTaken: false -+ hasStackMap: false -+ hasPatchPoint: false -+ stackSize: 64 -+ offsetAdjustment: 0 -+ maxAlignment: 1 -+ adjustsStack: true -+ hasCalls: true -+ stackProtector: '' -+ maxCallFrameSize: 32 -+ cvBytesOfCalleeSavedRegisters: 0 -+ hasOpaqueSPAdjustment: false -+ hasVAStart: false -+ hasMustTailInVarArgFunc: false -+ localFrameSize: 0 -+ savePoint: '' -+ restorePoint: '' -+fixedStack: -+ - { id: 0, type: spill-slot, offset: -80, size: 8, alignment: 16, stack-id: default, -+ callee-saved-register: '$x30', callee-saved-restored: true, debug-info-variable: '', -+ debug-info-expression: '', debug-info-location: '' } -+ - { id: 1, type: spill-slot, offset: -88, size: 8, alignment: 8, stack-id: default, -+ callee-saved-register: '$x29', callee-saved-restored: true, debug-info-variable: '', -+ debug-info-expression: '', debug-info-location: '' } -+stack: [] -+callSites: [] -+constants: [] -+machineFunctionInfo: {} -+body: | -+ bb.0.entry: -+ liveins: $x3, $x4, $x29, $x30 -+ -+ ; CHECK-LABEL: name: b -+ ; CHECK: liveins: $x3, $x4, $x29, $x30 -+ ; CHECK: $x0 = MFLR8 implicit $lr8 -+ ; CHECK: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.0) -+ ; CHECK: STD killed $x30, -16, $x1 :: (store 8 into %fixed-stack.1, align 16) -+ ; CHECK: STD killed $x0, 16, $x1 -+ ; CHECK: $x1 = STDU $x1, -64, $x1 -+ ; CHECK: $x30 = OR8 killed $x4, $x4 -+ ; CHECK: dead $r4 = LI 10, implicit-def $x4 -+ ; CHECK: $x29 = OR8 $x3, $x3 -+ ; CHECK: BL8_NOP @g, csr_ppc64_r2_altivec, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit killed $x4, implicit $x2, implicit-def $r1, implicit-def $x3 -+ ; CHECK: STW8 killed renamable $x3, 0, killed renamable $x30 :: (store 4 into %ir.b) -+ ; CHECK: $x3 = OR8 killed $x29, $x29 -+ ; CHECK: BL8_NOP @g, csr_ppc64_r2_altivec, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1, implicit-def $x3 -+ ; CHECK: $x1 = ADDI8 $x1, 64 -+ ; CHECK: $x0 = LD 16, $x1 -+ ; CHECK: $x30 = LD -16, $x1 :: (load 8 from %fixed-stack.1, align 16) -+ ; CHECK: $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.0) -+ ; CHECK: MTLR8 killed $x0, implicit-def $lr8 -+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3 -+ $x0 = MFLR8 implicit $lr8 -+ STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.1) -+ STD killed $x30, -16, $x1 :: (store 8 into %fixed-stack.0, align 16) -+ STD killed $x0, 16, $x1 -+ $x1 = STDU $x1, -64, $x1 -+ $x30 = OR8 killed $x4, $x4 -+ dead $r4 = LI 10, implicit-def $x4 -+ $x29 = OR8 $x3, $x3 -+ BL8_NOP @g, csr_ppc64_r2_altivec, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit killed $x4, implicit $x2, implicit-def $r1, implicit-def $x3 -+ STW8 killed renamable $x3, 0, killed renamable $x30 :: (store 4 into %ir.b) -+ $x3 = OR8 killed $x29, $x29 -+ BL8_NOP @g, csr_ppc64_r2_altivec, implicit-def dead $lr8, implicit $rm, implicit killed $x3, implicit $x2, implicit-def $r1, implicit-def $x3 -+ $x1 = ADDI8 $x1, 64 -+ $x0 = LD 16, $x1 -+ $x30 = LD -16, $x1 :: (load 8 from %fixed-stack.0, align 16) -+ $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.1) -+ MTLR8 killed $x0, implicit-def $lr8 -+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3 -+ -+... --- -2.26.0 - diff --git a/deps/patches/llvm-10.0-PPC_SELECT_CC.patch b/deps/patches/llvm-10.0-PPC_SELECT_CC.patch deleted file mode 100644 index a56b20eb064f0..0000000000000 --- a/deps/patches/llvm-10.0-PPC_SELECT_CC.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 4765db99fa35257a4209e2976903d81087a3f0d7 Mon Sep 17 00:00:00 2001 -From: Nemanja Ivanovic -Date: Thu, 9 Apr 2020 13:53:02 -0500 -Subject: [PATCH] [PowerPC] Don't assert on SELECT_CC with i1 type - -When we try to select a SELECT_CC on Power9, we check if it can be matched to a -SETB instruction. In that function, we assert that the output type is i32/i64. -This is unnecessary as it is perfectly reasonable to have an i1 SELECT_CC. -Change that from an assert to an early exit condition. -Fixes: https://bugs.llvm.org/show_bug.cgi?id=45448 ---- - llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 7 +- - llvm/test/CodeGen/PowerPC/pr45448.ll | 90 +++++++++++++++++++++ - 2 files changed, 92 insertions(+), 5 deletions(-) - create mode 100644 llvm/test/CodeGen/PowerPC/pr45448.ll - -diff --git llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp -index 776ec52e260..9230ce4118b 100644 ---- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp -+++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp -@@ -4241,13 +4241,10 @@ static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG, - SDValue TrueRes = N->getOperand(2); - SDValue FalseRes = N->getOperand(3); - ConstantSDNode *TrueConst = dyn_cast(TrueRes); -- if (!TrueConst) -+ if (!TrueConst || (N->getSimpleValueType(0) != MVT::i64 && -+ N->getSimpleValueType(0) != MVT::i32)) - return false; - -- assert((N->getSimpleValueType(0) == MVT::i64 || -- N->getSimpleValueType(0) == MVT::i32) && -- "Expecting either i64 or i32 here."); -- - // We are looking for any of: - // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, cc2)), cc1) - // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, cc2)), cc1) -diff --git llvm/test/CodeGen/PowerPC/pr45448.ll llvm/test/CodeGen/PowerPC/pr45448.ll -new file mode 100644 -index 00000000000..eb0a61cb075 ---- /dev/null -+++ llvm/test/CodeGen/PowerPC/pr45448.ll -@@ -0,0 +1,90 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ -+; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ -+; RUN: FileCheck %s -+define hidden void @julia_tryparse_internal_45896() #0 { -+; CHECK-LABEL: julia_tryparse_internal_45896: -+; CHECK: # %bb.0: # %top -+; CHECK-NEXT: ld r3, 0(r3) -+; CHECK-NEXT: cmpldi r3, 0 -+; CHECK-NEXT: beq cr0, .LBB0_3 -+; CHECK-NEXT: # %bb.1: # %top -+; CHECK-NEXT: cmpldi r3, 10 -+; CHECK-NEXT: beq cr0, .LBB0_4 -+; CHECK-NEXT: # %bb.2: # %top -+; CHECK-NEXT: .LBB0_3: # %fail194 -+; CHECK-NEXT: .LBB0_4: # %L294 -+; CHECK-NEXT: bc 12, 4*cr5+lt, .LBB0_6 -+; CHECK-NEXT: # %bb.5: # %L294 -+; CHECK-NEXT: bc 4, 4*cr5+lt, .LBB0_7 -+; CHECK-NEXT: .LBB0_6: # %L1057.preheader -+; CHECK-NEXT: .LBB0_7: # %L670 -+; CHECK-NEXT: lis r5, 4095 -+; CHECK-NEXT: ori r5, r5, 65533 -+; CHECK-NEXT: sldi r5, r5, 4 -+; CHECK-NEXT: cmpdi r3, 0 -+; CHECK-NEXT: sradi r4, r3, 63 -+; CHECK-NEXT: mulhdu r3, r3, r5 -+; CHECK-NEXT: maddld r6, r4, r5, r3 -+; CHECK-NEXT: crnor 4*cr5+gt, eq, eq -+; CHECK-NEXT: cmpld r6, r3 -+; CHECK-NEXT: mulld r3, r4, r5 -+; CHECK-NEXT: cmpldi cr1, r3, 0 -+; CHECK-NEXT: crandc 4*cr5+lt, lt, 4*cr1+eq -+; CHECK-NEXT: mulhdu. r3, r4, r5 -+; CHECK-NEXT: bc 4, 4*cr5+gt, .LBB0_10 -+; CHECK-NEXT: # %bb.8: # %L670 -+; CHECK-NEXT: crorc 4*cr5+lt, 4*cr5+lt, eq -+; CHECK-NEXT: bc 4, 4*cr5+lt, .LBB0_10 -+; CHECK-NEXT: # %bb.9: # %L917 -+; CHECK-NEXT: .LBB0_10: # %L994 -+top: -+ %0 = load i64, i64* undef, align 8 -+ %1 = icmp ne i64 %0, 0 -+ %2 = sext i64 %0 to i128 -+ switch i64 %0, label %pass195 [ -+ i64 10, label %L294 -+ i64 16, label %L294.fold.split -+ i64 0, label %fail194 -+ ] -+ -+L294.fold.split: ; preds = %top -+ unreachable -+ -+L294: ; preds = %top -+ %3 = add nsw i32 0, -48 -+ %4 = zext i32 %3 to i128 -+ %5 = add i128 %4, 0 -+ switch i32 undef, label %L670 [ -+ i32 -1031471104, label %L1057.preheader -+ i32 536870912, label %L1057.preheader -+ ] -+ -+L670: ; preds = %L294 -+ br label %L898 -+ -+L1057.preheader: ; preds = %L294, %L294 -+ unreachable -+ -+L898: ; preds = %L670 -+ %umul = call { i128, i1 } @llvm.umul.with.overflow.i128(i128 %2, i128 %5) -+ %umul.ov = extractvalue { i128, i1 } %umul, 1 -+ %value_phi102 = and i1 %1, %umul.ov -+ %6 = or i1 %value_phi102, false -+ br i1 %6, label %L917, label %L994 -+ -+L917: ; preds = %L898 -+ unreachable -+ -+L994: ; preds = %L898 -+ unreachable -+ -+fail194: ; preds = %top -+ unreachable -+ -+pass195: ; preds = %top -+ unreachable -+} -+ -+; Function Attrs: nounwind readnone speculatable willreturn -+declare { i128, i1 } @llvm.umul.with.overflow.i128(i128, i128) #1 --- -2.26.0 - diff --git a/deps/patches/llvm-8.0-D50167-scev-umin.patch b/deps/patches/llvm-8.0-D50167-scev-umin.patch deleted file mode 100644 index f11fd546bb72c..0000000000000 --- a/deps/patches/llvm-8.0-D50167-scev-umin.patch +++ /dev/null @@ -1,1870 +0,0 @@ -commit 18e563f695dd561c32393512fbdb8ce8771d7e5f -Author: Keno Fischer -Date: Thu May 2 08:35:22 2019 -0400 - - [SCEV] Add explicit representations of umin/smin - - Summary: - Currently we express umin as `~umax(~x, ~y)`. However, this becomes - a problem for operands in non-integral pointer spaces, because `~x` - is not something we can compute for `x` non-integral. However, since - comparisons are generally still allowed, we are actually able to - express `umin(x, y)` directly as long as we don't try to express is - as a umax. Support this by adding an explicit umin/smin representation - to SCEV. We do this by factoring the existing getUMax/getSMax functions - into a new function that does all four. The previous two functions were - largely identical. - - Reviewers: reames, sanjoy, mkazantsev - - Reviewed By: sanjoy - - Subscribers: tvvikram, dmgreen, vchuravy, javed.absar, llvm-commits - - Tags: #llvm - - Differential Revision: https://reviews.llvm.org/D50167 - -diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h -index 8f4200b07e5..6b76a16a2b4 100644 ---- a/include/llvm/Analysis/ScalarEvolution.h -+++ b/include/llvm/Analysis/ScalarEvolution.h -@@ -582,6 +582,8 @@ public: - /// \p IndexExprs The expressions for the indices. - const SCEV *getGEPExpr(GEPOperator *GEP, - const SmallVectorImpl &IndexExprs); -+ const SCEV *getMinMaxExpr(unsigned Kind, -+ SmallVectorImpl &Operands); - const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); - const SCEV *getSMaxExpr(SmallVectorImpl &Operands); - const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); -diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h -index 58d42680d6b..57d658b157d 100644 ---- a/include/llvm/Analysis/ScalarEvolutionExpander.h -+++ b/include/llvm/Analysis/ScalarEvolutionExpander.h -@@ -368,6 +368,10 @@ namespace llvm { - - Value *visitUMaxExpr(const SCEVUMaxExpr *S); - -+ Value *visitSMinExpr(const SCEVSMinExpr *S); -+ -+ Value *visitUMinExpr(const SCEVUMinExpr *S); -+ - Value *visitUnknown(const SCEVUnknown *S) { - return S->getValue(); - } -diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h -index 42e76094eb2..99e39d484c5 100644 ---- a/include/llvm/Analysis/ScalarEvolutionExpressions.h -+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h -@@ -40,7 +40,7 @@ class Type; - // These should be ordered in terms of increasing complexity to make the - // folders simpler. - scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, -- scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, -+ scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr, - scUnknown, scCouldNotCompute - }; - -@@ -183,10 +183,9 @@ class Type; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { -- return S->getSCEVType() == scAddExpr || -- S->getSCEVType() == scMulExpr || -- S->getSCEVType() == scSMaxExpr || -- S->getSCEVType() == scUMaxExpr || -+ return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || -+ S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr || -+ S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr || - S->getSCEVType() == scAddRecExpr; - } - }; -@@ -201,10 +200,9 @@ class Type; - public: - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { -- return S->getSCEVType() == scAddExpr || -- S->getSCEVType() == scMulExpr || -- S->getSCEVType() == scSMaxExpr || -- S->getSCEVType() == scUMaxExpr; -+ return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || -+ S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr || -+ S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr; - } - - /// Set flags for a non-recurrence without clearing previously set flags. -@@ -358,17 +356,53 @@ class Type; - } - }; - -- /// This class represents a signed maximum selection. -- class SCEVSMaxExpr : public SCEVCommutativeExpr { -+ /// This node is the base class min/max selections. -+ class SCEVMinMaxExpr : public SCEVCommutativeExpr { - friend class ScalarEvolution; - -- SCEVSMaxExpr(const FoldingSetNodeIDRef ID, -- const SCEV *const *O, size_t N) -- : SCEVCommutativeExpr(ID, scSMaxExpr, O, N) { -- // Max never overflows. -+ static bool isMinMaxType(enum SCEVTypes T) { -+ return T == scSMaxExpr || T == scUMaxExpr || T == scSMinExpr || -+ T == scUMinExpr; -+ } -+ -+ protected: -+ /// Note: Constructing subclasses via this constructor is allowed -+ SCEVMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T, -+ const SCEV *const *O, size_t N) -+ : SCEVCommutativeExpr(ID, T, O, N) { -+ assert(isMinMaxType(T)); -+ // Min and max nenver overflow - setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); - } - -+ public: -+ static bool classof(const SCEV *S) { -+ return isMinMaxType(static_cast(S->getSCEVType())); -+ } -+ -+ static enum SCEVTypes negate(enum SCEVTypes T) { -+ switch (T) { -+ case scSMaxExpr: -+ return scSMinExpr; -+ case scSMinExpr: -+ return scSMaxExpr; -+ case scUMaxExpr: -+ return scUMaxExpr; -+ case scUMinExpr: -+ return scUMinExpr; -+ default: -+ llvm_unreachable("Not a min or max SCEV type!"); -+ } -+ } -+ }; -+ -+ /// This class represents a signed maximum selection. -+ class SCEVSMaxExpr : public SCEVMinMaxExpr { -+ friend class ScalarEvolution; -+ -+ SCEVSMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) -+ : SCEVMinMaxExpr(ID, scSMaxExpr, O, N) {} -+ - public: - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { -@@ -377,15 +411,11 @@ class Type; - }; - - /// This class represents an unsigned maximum selection. -- class SCEVUMaxExpr : public SCEVCommutativeExpr { -+ class SCEVUMaxExpr : public SCEVMinMaxExpr { - friend class ScalarEvolution; - -- SCEVUMaxExpr(const FoldingSetNodeIDRef ID, -- const SCEV *const *O, size_t N) -- : SCEVCommutativeExpr(ID, scUMaxExpr, O, N) { -- // Max never overflows. -- setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); -- } -+ SCEVUMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) -+ : SCEVMinMaxExpr(ID, scUMaxExpr, O, N) {} - - public: - /// Methods for support type inquiry through isa, cast, and dyn_cast: -@@ -394,6 +424,34 @@ class Type; - } - }; - -+ /// This class represents a signed minimum selection. -+ class SCEVSMinExpr : public SCEVMinMaxExpr { -+ friend class ScalarEvolution; -+ -+ SCEVSMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) -+ : SCEVMinMaxExpr(ID, scSMinExpr, O, N) {} -+ -+ public: -+ /// Methods for support type inquiry through isa, cast, and dyn_cast: -+ static bool classof(const SCEV *S) { -+ return S->getSCEVType() == scSMinExpr; -+ } -+ }; -+ -+ /// This class represents an unsigned minimum selection. -+ class SCEVUMinExpr : public SCEVMinMaxExpr { -+ friend class ScalarEvolution; -+ -+ SCEVUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) -+ : SCEVMinMaxExpr(ID, scUMinExpr, O, N) {} -+ -+ public: -+ /// Methods for support type inquiry through isa, cast, and dyn_cast: -+ static bool classof(const SCEV *S) { -+ return S->getSCEVType() == scUMinExpr; -+ } -+ }; -+ - /// This means that we are dealing with an entirely unknown SCEV - /// value, and only represent it as its LLVM Value. This is the - /// "bottom" value for the analysis. -@@ -466,6 +524,10 @@ class Type; - return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S); - case scUMaxExpr: - return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S); -+ case scSMinExpr: -+ return ((SC *)this)->visitSMinExpr((const SCEVSMinExpr *)S); -+ case scUMinExpr: -+ return ((SC *)this)->visitUMinExpr((const SCEVUMinExpr *)S); - case scUnknown: - return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); - case scCouldNotCompute: -@@ -519,6 +581,8 @@ class Type; - case scMulExpr: - case scSMaxExpr: - case scUMaxExpr: -+ case scSMinExpr: -+ case scUMinExpr: - case scAddRecExpr: - for (const auto *Op : cast(S)->operands()) - push(Op); -@@ -681,6 +745,26 @@ class Type; - return !Changed ? Expr : SE.getUMaxExpr(Operands); - } - -+ const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) { -+ SmallVector Operands; -+ bool Changed = false; -+ for (auto *Op : Expr->operands()) { -+ Operands.push_back(((SC *)this)->visit(Op)); -+ Changed |= Op != Operands.back(); -+ } -+ return !Changed ? Expr : SE.getSMinExpr(Operands); -+ } -+ -+ const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) { -+ SmallVector Operands; -+ bool Changed = false; -+ for (auto *Op : Expr->operands()) { -+ Operands.push_back(((SC *)this)->visit(Op)); -+ Changed |= Op != Operands.back(); -+ } -+ return !Changed ? Expr : SE.getUMinExpr(Operands); -+ } -+ - const SCEV *visitUnknown(const SCEVUnknown *Expr) { - return Expr; - } -diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp -index e5134f2eeda..f2553de0af1 100644 ---- a/lib/Analysis/ScalarEvolution.cpp -+++ b/lib/Analysis/ScalarEvolution.cpp -@@ -273,7 +273,9 @@ void SCEV::print(raw_ostream &OS) const { - case scAddExpr: - case scMulExpr: - case scUMaxExpr: -- case scSMaxExpr: { -+ case scSMaxExpr: -+ case scUMinExpr: -+ case scSMinExpr: { - const SCEVNAryExpr *NAry = cast(this); - const char *OpStr = nullptr; - switch (NAry->getSCEVType()) { -@@ -281,6 +283,12 @@ void SCEV::print(raw_ostream &OS) const { - case scMulExpr: OpStr = " * "; break; - case scUMaxExpr: OpStr = " umax "; break; - case scSMaxExpr: OpStr = " smax "; break; -+ case scUMinExpr: -+ OpStr = " umin "; -+ break; -+ case scSMinExpr: -+ OpStr = " smin "; -+ break; - } - OS << "("; - for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); -@@ -349,6 +357,8 @@ Type *SCEV::getType() const { - case scMulExpr: - case scUMaxExpr: - case scSMaxExpr: -+ case scUMinExpr: -+ case scSMinExpr: - return cast(this)->getType(); - case scAddExpr: - return cast(this)->getType(); -@@ -713,7 +723,9 @@ static int CompareSCEVComplexity( - case scAddExpr: - case scMulExpr: - case scSMaxExpr: -- case scUMaxExpr: { -+ case scUMaxExpr: -+ case scSMinExpr: -+ case scUMinExpr: { - const SCEVNAryExpr *LC = cast(LHS); - const SCEVNAryExpr *RC = cast(RHS); - -@@ -913,6 +925,8 @@ public: - void visitUDivExpr(const SCEVUDivExpr *Numerator) {} - void visitSMaxExpr(const SCEVSMaxExpr *Numerator) {} - void visitUMaxExpr(const SCEVUMaxExpr *Numerator) {} -+ void visitSMinExpr(const SCEVSMinExpr *Numerator) {} -+ void visitUMinExpr(const SCEVUMinExpr *Numerator) {} - void visitUnknown(const SCEVUnknown *Numerator) {} - void visitCouldNotCompute(const SCEVCouldNotCompute *Numerator) {} - -@@ -3493,209 +3507,153 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, - return getAddExpr(BaseExpr, TotalOffset, Wrap); - } - --const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, -- const SCEV *RHS) { -- SmallVector Ops = {LHS, RHS}; -- return getSMaxExpr(Ops); --} -- --const SCEV * --ScalarEvolution::getSMaxExpr(SmallVectorImpl &Ops) { -- assert(!Ops.empty() && "Cannot get empty smax!"); -+const SCEV *ScalarEvolution::getMinMaxExpr(unsigned Kind, -+ SmallVectorImpl &Ops) { -+ assert(!Ops.empty() && "Cannot get empty (u|s)(min|max)!"); - if (Ops.size() == 1) return Ops[0]; - #ifndef NDEBUG - Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); - for (unsigned i = 1, e = Ops.size(); i != e; ++i) - assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && -- "SCEVSMaxExpr operand types don't match!"); -+ "Operand types don't match!"); - #endif - -+ bool IsSigned = Kind == scSMaxExpr || Kind == scSMinExpr; -+ bool IsMax = Kind == scSMaxExpr || Kind == scUMaxExpr; -+ - // Sort by complexity, this groups all similar expression types together. - GroupByComplexity(Ops, &LI, DT); - -+ -+ -+ -+ -+ - // If there are any constants, fold them together. - unsigned Idx = 0; - if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { - ++Idx; - assert(Idx < Ops.size()); -+ auto FoldOp = [&](const APInt &LHS, const APInt &RHS) { -+ if (Kind == scSMaxExpr) -+ return APIntOps::smax(LHS, RHS); -+ else if (Kind == scSMinExpr) -+ return APIntOps::smin(LHS, RHS); -+ else if (Kind == scUMaxExpr) -+ return APIntOps::umax(LHS, RHS); -+ else if (Kind == scUMinExpr) -+ return APIntOps::umin(LHS, RHS); -+ llvm_unreachable("Unknown SCEV min/max opcode"); -+ }; -+ - while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { - // We found two constants, fold them together! - ConstantInt *Fold = ConstantInt::get( -- getContext(), APIntOps::smax(LHSC->getAPInt(), RHSC->getAPInt())); -+ getContext(), FoldOp(LHSC->getAPInt(), RHSC->getAPInt())); - Ops[0] = getConstant(Fold); - Ops.erase(Ops.begin()+1); // Erase the folded element - if (Ops.size() == 1) return Ops[0]; - LHSC = cast(Ops[0]); - } - -- // If we are left with a constant minimum-int, strip it off. -- if (cast(Ops[0])->getValue()->isMinValue(true)) { -+ bool IsMinV = LHSC->getValue()->isMinValue(IsSigned); -+ bool IsMaxV = LHSC->getValue()->isMaxValue(IsSigned); -+ -+ if (IsMax ? IsMinV : IsMaxV) { -+ // If we are left with a constant minimum(/maximum)-int, strip it off. - Ops.erase(Ops.begin()); - --Idx; -- } else if (cast(Ops[0])->getValue()->isMaxValue(true)) { -- // If we have an smax with a constant maximum-int, it will always be -- // maximum-int. -- return Ops[0]; -+ } else if (IsMax ? IsMaxV : IsMinV) { -+ // If we have a max(/min) with a constant maximum(/minimum)-int, -+ // it will always be the extremum. -+ return LHSC; - } - - if (Ops.size() == 1) return Ops[0]; - } - -- // Find the first SMax -- while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scSMaxExpr) -+ // Find the first operation of the same kind -+ while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < Kind) - ++Idx; - -- // Check to see if one of the operands is an SMax. If so, expand its operands -- // onto our operand list, and recurse to simplify. -+ // Check to see if one of the operands is of the same kind. If so, expand its -+ // operands onto our operand list, and recurse to simplify. - if (Idx < Ops.size()) { -- bool DeletedSMax = false; -- while (const SCEVSMaxExpr *SMax = dyn_cast(Ops[Idx])) { -+ bool DeletedAny = false; -+ while (Ops[Idx]->getSCEVType() == Kind) { -+ const SCEVMinMaxExpr *SMME = cast(Ops[Idx]); - Ops.erase(Ops.begin()+Idx); -- Ops.append(SMax->op_begin(), SMax->op_end()); -- DeletedSMax = true; -+ Ops.append(SMME->op_begin(), SMME->op_end()); -+ DeletedAny = true; - } - -- if (DeletedSMax) -- return getSMaxExpr(Ops); -+ if (DeletedAny) -+ return getMinMaxExpr(Kind, Ops); - } - - // Okay, check to see if the same value occurs in the operand list twice. If - // so, delete one. Since we sorted the list, these values are required to - // be adjacent. -- for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) -- // X smax Y smax Y --> X smax Y -- // X smax Y --> X, if X is always greater than Y -- if (Ops[i] == Ops[i+1] || -- isKnownPredicate(ICmpInst::ICMP_SGE, Ops[i], Ops[i+1])) { -- Ops.erase(Ops.begin()+i+1, Ops.begin()+i+2); -- --i; --e; -- } else if (isKnownPredicate(ICmpInst::ICMP_SLE, Ops[i], Ops[i+1])) { -- Ops.erase(Ops.begin()+i, Ops.begin()+i+1); -- --i; --e; -+ llvm::CmpInst::Predicate GEPred = -+ IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; -+ llvm::CmpInst::Predicate LEPred = -+ IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; -+ llvm::CmpInst::Predicate FirstPred = IsMax ? GEPred : LEPred; -+ llvm::CmpInst::Predicate SecondPred = IsMax ? LEPred : GEPred; -+ for (unsigned i = 0, e = Ops.size() - 1; i != e; ++i) { -+ if (Ops[i] == Ops[i + 1] || -+ isKnownViaNonRecursiveReasoning(FirstPred, Ops[i], Ops[i + 1])) { -+ // X op Y op Y --> X op Y -+ // X op Y --> X, if we know X, Y are ordered appropriately -+ Ops.erase(Ops.begin() + i + 1, Ops.begin() + i + 2); -+ --i; -+ --e; -+ } else if (isKnownViaNonRecursiveReasoning(SecondPred, Ops[i], -+ Ops[i + 1])) { -+ // X op Y --> Y, if we know X, Y are ordered appropriately -+ Ops.erase(Ops.begin() + i, Ops.begin() + i + 1); -+ --i; -+ --e; - } -+ } - - if (Ops.size() == 1) return Ops[0]; - - assert(!Ops.empty() && "Reduced smax down to nothing!"); - -- // Okay, it looks like we really DO need an smax expr. Check to see if we -+ // Okay, it looks like we really DO need an expr. Check to see if we - // already have one, otherwise create a new one. - FoldingSetNodeID ID; -- ID.AddInteger(scSMaxExpr); -+ ID.AddInteger(Kind); - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - ID.AddPointer(Ops[i]); - void *IP = nullptr; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - const SCEV **O = SCEVAllocator.Allocate(Ops.size()); - std::uninitialized_copy(Ops.begin(), Ops.end(), O); -- SCEV *S = new (SCEVAllocator) SCEVSMaxExpr(ID.Intern(SCEVAllocator), -- O, Ops.size()); -+ SCEV *S = new (SCEVAllocator) SCEVMinMaxExpr( -+ ID.Intern(SCEVAllocator), static_cast(Kind), O, Ops.size()); - UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); - return S; - } - --const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, -- const SCEV *RHS) { -+const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, const SCEV *RHS) { - SmallVector Ops = {LHS, RHS}; -- return getUMaxExpr(Ops); -+ return getSMaxExpr(Ops); - } - --const SCEV * --ScalarEvolution::getUMaxExpr(SmallVectorImpl &Ops) { -- assert(!Ops.empty() && "Cannot get empty umax!"); -- if (Ops.size() == 1) return Ops[0]; --#ifndef NDEBUG -- Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); -- for (unsigned i = 1, e = Ops.size(); i != e; ++i) -- assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && -- "SCEVUMaxExpr operand types don't match!"); --#endif -- -- // Sort by complexity, this groups all similar expression types together. -- GroupByComplexity(Ops, &LI, DT); -- -- // If there are any constants, fold them together. -- unsigned Idx = 0; -- if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { -- ++Idx; -- assert(Idx < Ops.size()); -- while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { -- // We found two constants, fold them together! -- ConstantInt *Fold = ConstantInt::get( -- getContext(), APIntOps::umax(LHSC->getAPInt(), RHSC->getAPInt())); -- Ops[0] = getConstant(Fold); -- Ops.erase(Ops.begin()+1); // Erase the folded element -- if (Ops.size() == 1) return Ops[0]; -- LHSC = cast(Ops[0]); -- } -- -- // If we are left with a constant minimum-int, strip it off. -- if (cast(Ops[0])->getValue()->isMinValue(false)) { -- Ops.erase(Ops.begin()); -- --Idx; -- } else if (cast(Ops[0])->getValue()->isMaxValue(false)) { -- // If we have an umax with a constant maximum-int, it will always be -- // maximum-int. -- return Ops[0]; -- } -- -- if (Ops.size() == 1) return Ops[0]; -- } -- -- // Find the first UMax -- while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scUMaxExpr) -- ++Idx; -- -- // Check to see if one of the operands is a UMax. If so, expand its operands -- // onto our operand list, and recurse to simplify. -- if (Idx < Ops.size()) { -- bool DeletedUMax = false; -- while (const SCEVUMaxExpr *UMax = dyn_cast(Ops[Idx])) { -- Ops.erase(Ops.begin()+Idx); -- Ops.append(UMax->op_begin(), UMax->op_end()); -- DeletedUMax = true; -- } -- -- if (DeletedUMax) -- return getUMaxExpr(Ops); -- } -- -- // Okay, check to see if the same value occurs in the operand list twice. If -- // so, delete one. Since we sorted the list, these values are required to -- // be adjacent. -- for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) -- // X umax Y umax Y --> X umax Y -- // X umax Y --> X, if X is always greater than Y -- if (Ops[i] == Ops[i + 1] || isKnownViaNonRecursiveReasoning( -- ICmpInst::ICMP_UGE, Ops[i], Ops[i + 1])) { -- Ops.erase(Ops.begin() + i + 1, Ops.begin() + i + 2); -- --i; --e; -- } else if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, Ops[i], -- Ops[i + 1])) { -- Ops.erase(Ops.begin() + i, Ops.begin() + i + 1); -- --i; --e; -- } -- -- if (Ops.size() == 1) return Ops[0]; -+const SCEV *ScalarEvolution::getSMaxExpr(SmallVectorImpl &Ops) { -+ return getMinMaxExpr(scSMaxExpr, Ops); -+} - -- assert(!Ops.empty() && "Reduced umax down to nothing!"); -+const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, const SCEV *RHS) { -+ SmallVector Ops = {LHS, RHS}; -+ return getUMaxExpr(Ops); -+} - -- // Okay, it looks like we really DO need a umax expr. Check to see if we -- // already have one, otherwise create a new one. -- FoldingSetNodeID ID; -- ID.AddInteger(scUMaxExpr); -- for (unsigned i = 0, e = Ops.size(); i != e; ++i) -- ID.AddPointer(Ops[i]); -- void *IP = nullptr; -- if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; -- const SCEV **O = SCEVAllocator.Allocate(Ops.size()); -- std::uninitialized_copy(Ops.begin(), Ops.end(), O); -- SCEV *S = new (SCEVAllocator) SCEVUMaxExpr(ID.Intern(SCEVAllocator), -- O, Ops.size()); -- UniqueSCEVs.InsertNode(S, IP); -- addToLoopUseLists(S); -- return S; -+const SCEV *ScalarEvolution::getUMaxExpr(SmallVectorImpl &Ops) { -+ return getMinMaxExpr(scUMaxExpr, Ops); - } - - const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS, -@@ -3705,11 +3663,7 @@ const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS, - } - - const SCEV *ScalarEvolution::getSMinExpr(SmallVectorImpl &Ops) { -- // ~smax(~x, ~y, ~z) == smin(x, y, z). -- SmallVector NotOps; -- for (auto *S : Ops) -- NotOps.push_back(getNotSCEV(S)); -- return getNotSCEV(getSMaxExpr(NotOps)); -+ return getMinMaxExpr(scSMinExpr, Ops); - } - - const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, -@@ -3719,16 +3673,7 @@ const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, - } - - const SCEV *ScalarEvolution::getUMinExpr(SmallVectorImpl &Ops) { -- assert(!Ops.empty() && "At least one operand must be!"); -- // Trivial case. -- if (Ops.size() == 1) -- return Ops[0]; -- -- // ~umax(~x, ~y, ~z) == umin(x, y, z). -- SmallVector NotOps; -- for (auto *S : Ops) -- NotOps.push_back(getNotSCEV(S)); -- return getNotSCEV(getUMaxExpr(NotOps)); -+ return getMinMaxExpr(scUMinExpr, Ops); - } - - const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) { -@@ -3970,12 +3915,45 @@ const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V, - V, getConstant(cast(Constant::getAllOnesValue(Ty))), Flags); - } - -+/// If Expr computes ~A, return A else return nullptr -+static const SCEV *MatchNotExpr(const SCEV *Expr) { -+ const SCEVAddExpr *Add = dyn_cast(Expr); -+ if (!Add || Add->getNumOperands() != 2 || -+ !Add->getOperand(0)->isAllOnesValue()) -+ return nullptr; -+ -+ const SCEVMulExpr *AddRHS = dyn_cast(Add->getOperand(1)); -+ if (!AddRHS || AddRHS->getNumOperands() != 2 || -+ !AddRHS->getOperand(0)->isAllOnesValue()) -+ return nullptr; -+ -+ return AddRHS->getOperand(1); -+} -+ - /// Return a SCEV corresponding to ~V = -1-V - const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { - if (const SCEVConstant *VC = dyn_cast(V)) - return getConstant( - cast(ConstantExpr::getNot(VC->getValue()))); - -+ // Fold ~(u|s)(min|max)(~x, ~y) to (u|s)(max|min)(x, y) -+ if (const SCEVMinMaxExpr *MME = dyn_cast(V)) { -+ auto MatchMinMaxNegation = [&](const SCEVMinMaxExpr *MME) { -+ SmallVector MatchedOperands; -+ for (const SCEV *Operand : MME->operands()) { -+ const SCEV *Matched = MatchNotExpr(Operand); -+ if (!Matched) -+ return (const SCEV *)nullptr; -+ MatchedOperands.push_back(Matched); -+ } -+ return getMinMaxExpr( -+ SCEVMinMaxExpr::negate(static_cast(MME->getSCEVType())), -+ MatchedOperands); -+ }; -+ if (const SCEV *Replaced = MatchMinMaxNegation(MME)) -+ return Replaced; -+ } -+ - Type *Ty = V->getType(); - Ty = getEffectiveSCEVType(Ty); - const SCEV *AllOnes = -@@ -5196,6 +5174,8 @@ static bool IsAvailableOnEntry(const Loop *L, DominatorTree &DT, const SCEV *S, - switch (S->getSCEVType()) { - case scConstant: case scTruncate: case scZeroExtend: case scSignExtend: - case scAddExpr: case scMulExpr: case scUMaxExpr: case scSMaxExpr: -+ case scUMinExpr: -+ case scSMinExpr: - // These expressions are available if their operand(s) is/are. - return true; - -@@ -8075,7 +8055,9 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) { - } - case scSMaxExpr: - case scUMaxExpr: -- break; // TODO: smax, umax. -+ case scSMinExpr: -+ case scUMinExpr: -+ break; // TODO: smax, umax, smin, umax. - } - return nullptr; - } -@@ -8201,10 +8183,8 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { - return getAddExpr(NewOps); - if (isa(Comm)) - return getMulExpr(NewOps); -- if (isa(Comm)) -- return getSMaxExpr(NewOps); -- if (isa(Comm)) -- return getUMaxExpr(NewOps); -+ if (isa(Comm)) -+ return getMinMaxExpr(Comm->getSCEVType(), NewOps); - llvm_unreachable("Unknown commutative SCEV type!"); - } - } -@@ -10045,41 +10025,15 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, - getNotSCEV(FoundLHS)); - } - --/// If Expr computes ~A, return A else return nullptr --static const SCEV *MatchNotExpr(const SCEV *Expr) { -- const SCEVAddExpr *Add = dyn_cast(Expr); -- if (!Add || Add->getNumOperands() != 2 || -- !Add->getOperand(0)->isAllOnesValue()) -- return nullptr; -- -- const SCEVMulExpr *AddRHS = dyn_cast(Add->getOperand(1)); -- if (!AddRHS || AddRHS->getNumOperands() != 2 || -- !AddRHS->getOperand(0)->isAllOnesValue()) -- return nullptr; -- -- return AddRHS->getOperand(1); --} -- --/// Is MaybeMaxExpr an SMax or UMax of Candidate and some other values? --template --static bool IsMaxConsistingOf(const SCEV *MaybeMaxExpr, -- const SCEV *Candidate) { -- const MaxExprType *MaxExpr = dyn_cast(MaybeMaxExpr); -- if (!MaxExpr) return false; -- -- return find(MaxExpr->operands(), Candidate) != MaxExpr->op_end(); --} -- --/// Is MaybeMinExpr an SMin or UMin of Candidate and some other values? --template --static bool IsMinConsistingOf(ScalarEvolution &SE, -- const SCEV *MaybeMinExpr, -- const SCEV *Candidate) { -- const SCEV *MaybeMaxExpr = MatchNotExpr(MaybeMinExpr); -- if (!MaybeMaxExpr) -+/// Is MaybeMinMaxExpr an (U|S)(Min|Max) of Candidate and some other values? -+template -+static bool IsMinMaxConsistingOf(const SCEV *MaybeMinMaxExpr, -+ const SCEV *Candidate) { -+ const MinMaxExprType *MinMaxExpr = dyn_cast(MaybeMinMaxExpr); -+ if (!MinMaxExpr) - return false; - -- return IsMaxConsistingOf(MaybeMaxExpr, SE.getNotSCEV(Candidate)); -+ return find(MinMaxExpr->operands(), Candidate) != MinMaxExpr->op_end(); - } - - static bool IsKnownPredicateViaAddRecStart(ScalarEvolution &SE, -@@ -10128,20 +10082,20 @@ static bool IsKnownPredicateViaMinOrMax(ScalarEvolution &SE, - LLVM_FALLTHROUGH; - case ICmpInst::ICMP_SLE: - return -- // min(A, ...) <= A -- IsMinConsistingOf(SE, LHS, RHS) || -- // A <= max(A, ...) -- IsMaxConsistingOf(RHS, LHS); -+ // min(A, ...) <= A -+ IsMinMaxConsistingOf(LHS, RHS) || -+ // A <= max(A, ...) -+ IsMinMaxConsistingOf(RHS, LHS); - - case ICmpInst::ICMP_UGE: - std::swap(LHS, RHS); - LLVM_FALLTHROUGH; - case ICmpInst::ICMP_ULE: - return -- // min(A, ...) <= A -- IsMinConsistingOf(SE, LHS, RHS) || -- // A <= max(A, ...) -- IsMaxConsistingOf(RHS, LHS); -+ // min(A, ...) <= A -+ IsMinMaxConsistingOf(LHS, RHS) || -+ // A <= max(A, ...) -+ IsMinMaxConsistingOf(RHS, LHS); - } - - llvm_unreachable("covered switch fell through?!"); -@@ -11611,7 +11565,9 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) { - case scAddExpr: - case scMulExpr: - case scUMaxExpr: -- case scSMaxExpr: { -+ case scSMaxExpr: -+ case scUMinExpr: -+ case scSMinExpr: { - bool HasVarying = false; - for (auto *Op : cast(S)->operands()) { - LoopDisposition D = getLoopDisposition(Op, L); -@@ -11698,7 +11654,9 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) { - case scAddExpr: - case scMulExpr: - case scUMaxExpr: -- case scSMaxExpr: { -+ case scSMaxExpr: -+ case scUMinExpr: -+ case scSMinExpr: { - const SCEVNAryExpr *NAry = cast(S); - bool Proper = true; - for (const SCEV *NAryOp : NAry->operands()) { -diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp -index ca5cf1663b8..b56ec40ab75 100644 ---- a/lib/Analysis/ScalarEvolutionExpander.cpp -+++ b/lib/Analysis/ScalarEvolutionExpander.cpp -@@ -1634,7 +1634,8 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { - for (int i = S->getNumOperands()-2; i >= 0; --i) { - // In the case of mixed integer and pointer types, do the - // rest of the comparisons as integer. -- if (S->getOperand(i)->getType() != Ty) { -+ Type *OpTy = S->getOperand(i)->getType(); -+ if (OpTy->isIntegerTy() != Ty->isIntegerTy()) { - Ty = SE.getEffectiveSCEVType(Ty); - LHS = InsertNoopCastOfTo(LHS, Ty); - } -@@ -1658,7 +1659,8 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { - for (int i = S->getNumOperands()-2; i >= 0; --i) { - // In the case of mixed integer and pointer types, do the - // rest of the comparisons as integer. -- if (S->getOperand(i)->getType() != Ty) { -+ Type *OpTy = S->getOperand(i)->getType(); -+ if (OpTy->isIntegerTy() != Ty->isIntegerTy()) { - Ty = SE.getEffectiveSCEVType(Ty); - LHS = InsertNoopCastOfTo(LHS, Ty); - } -@@ -1676,6 +1678,56 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { - return LHS; - } - -+Value *SCEVExpander::visitSMinExpr(const SCEVSMinExpr *S) { -+ Value *LHS = expand(S->getOperand(S->getNumOperands() - 1)); -+ Type *Ty = LHS->getType(); -+ for (int i = S->getNumOperands() - 2; i >= 0; --i) { -+ // In the case of mixed integer and pointer types, do the -+ // rest of the comparisons as integer. -+ Type *OpTy = S->getOperand(i)->getType(); -+ if (OpTy->isIntegerTy() != Ty->isIntegerTy()) { -+ Ty = SE.getEffectiveSCEVType(Ty); -+ LHS = InsertNoopCastOfTo(LHS, Ty); -+ } -+ Value *RHS = expandCodeFor(S->getOperand(i), Ty); -+ Value *ICmp = Builder.CreateICmpSLT(LHS, RHS); -+ rememberInstruction(ICmp); -+ Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smin"); -+ rememberInstruction(Sel); -+ LHS = Sel; -+ } -+ // In the case of mixed integer and pointer types, cast the -+ // final result back to the pointer type. -+ if (LHS->getType() != S->getType()) -+ LHS = InsertNoopCastOfTo(LHS, S->getType()); -+ return LHS; -+} -+ -+Value *SCEVExpander::visitUMinExpr(const SCEVUMinExpr *S) { -+ Value *LHS = expand(S->getOperand(S->getNumOperands() - 1)); -+ Type *Ty = LHS->getType(); -+ for (int i = S->getNumOperands() - 2; i >= 0; --i) { -+ // In the case of mixed integer and pointer types, do the -+ // rest of the comparisons as integer. -+ Type *OpTy = S->getOperand(i)->getType(); -+ if (OpTy->isIntegerTy() != Ty->isIntegerTy()) { -+ Ty = SE.getEffectiveSCEVType(Ty); -+ LHS = InsertNoopCastOfTo(LHS, Ty); -+ } -+ Value *RHS = expandCodeFor(S->getOperand(i), Ty); -+ Value *ICmp = Builder.CreateICmpULT(LHS, RHS); -+ rememberInstruction(ICmp); -+ Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umin"); -+ rememberInstruction(Sel); -+ LHS = Sel; -+ } -+ // In the case of mixed integer and pointer types, cast the -+ // final result back to the pointer type. -+ if (LHS->getType() != S->getType()) -+ LHS = InsertNoopCastOfTo(LHS, S->getType()); -+ return LHS; -+} -+ - Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty, - Instruction *IP) { - setInsertPoint(IP); -@@ -2102,7 +2154,7 @@ bool SCEVExpander::isHighCostExpansionHelper( - - // HowManyLessThans uses a Max expression whenever the loop is not guarded by - // the exit condition. -- if (isa(S) || isa(S)) -+ if (isa(S)) - return true; - - // Recurse past nary expressions, which commonly occur in the -diff --git a/test/Analysis/LoopAccessAnalysis/memcheck-ni.ll b/test/Analysis/LoopAccessAnalysis/memcheck-ni.ll -new file mode 100644 -index 00000000000..a08632f38d1 ---- /dev/null -+++ b/test/Analysis/LoopAccessAnalysis/memcheck-ni.ll -@@ -0,0 +1,50 @@ -+; RUN: opt -loop-versioning -S < %s | FileCheck %s -+ -+; NB: addrspaces 10-13 are non-integral -+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13" -+ -+%jl_value_t = type opaque -+%jl_array_t = type { i8 addrspace(13)*, i64, i16, i16, i32 } -+ -+define void @"japi1_permutedims!_33509"(%jl_value_t addrspace(10)**) { -+; CHECK: [[CMP:%[^ ]*]] = icmp ult double addrspace(13)* [[A:%[^ ]*]], [[B:%[^ ]*]] -+; CHECK: [[SELECT:%[^ ]*]] = select i1 %18, double addrspace(13)* [[A]], double addrspace(13)* [[B]] -+top: -+ %1 = alloca [3 x i64], align 8 -+ %2 = load %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %0, align 8 -+ %3 = getelementptr inbounds %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %0, i64 1 -+ %4 = load %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %3, align 8 -+ %5 = getelementptr inbounds [3 x i64], [3 x i64]* %1, i64 0, i64 0 -+ store i64 1, i64* %5, align 8 -+ %6 = getelementptr inbounds [3 x i64], [3 x i64]* %1, i64 0, i64 1 -+ %7 = load i64, i64* inttoptr (i64 24 to i64*), align 8 -+ %8 = addrspacecast %jl_value_t addrspace(10)* %4 to %jl_value_t addrspace(11)* -+ %9 = bitcast %jl_value_t addrspace(11)* %8 to double addrspace(13)* addrspace(11)* -+ %10 = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %9, align 8 -+ %11 = addrspacecast %jl_value_t addrspace(10)* %2 to %jl_value_t addrspace(11)* -+ %12 = bitcast %jl_value_t addrspace(11)* %11 to double addrspace(13)* addrspace(11)* -+ %13 = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %12, align 8 -+ %14 = load i64, i64* %6, align 8 -+ br label %L74 -+ -+L74: -+ %value_phi20 = phi i64 [ 1, %top ], [ %22, %L74 ] -+ %value_phi21 = phi i64 [ 1, %top ], [ %23, %L74 ] -+ %value_phi22 = phi i64 [ 1, %top ], [ %25, %L74 ] -+ %15 = add i64 %value_phi21, -1 -+ %16 = getelementptr inbounds double, double addrspace(13)* %10, i64 %15 -+ %17 = bitcast double addrspace(13)* %16 to i64 addrspace(13)* -+ %18 = load i64, i64 addrspace(13)* %17, align 8 -+ %19 = add i64 %value_phi20, -1 -+ %20 = getelementptr inbounds double, double addrspace(13)* %13, i64 %19 -+ %21 = bitcast double addrspace(13)* %20 to i64 addrspace(13)* -+ store i64 %18, i64 addrspace(13)* %21, align 8 -+ %22 = add i64 %value_phi20, 1 -+ %23 = add i64 %14, %value_phi21 -+ %24 = icmp eq i64 %value_phi22, %7 -+ %25 = add i64 %value_phi22, 1 -+ br i1 %24, label %L94, label %L74 -+ -+L94: -+ ret void -+} -diff --git a/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll -index 405a47554e4..4285ef0f117 100644 ---- a/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll -+++ b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll -@@ -58,7 +58,7 @@ for.end: ; preds = %for.body - - ; Here it is not obvious what the limits are, since 'step' could be negative. - --; CHECK: Low: (-1 + (-1 * ((-60001 + (-1 * %a)) umax (-60001 + (40000 * %step) + (-1 * %a))))) -+; CHECK: Low: ((60000 + %a) umin (60000 + (-40000 * %step) + %a)) - ; CHECK: High: (4 + ((60000 + %a) umax (60000 + (-40000 * %step) + %a))) - - define void @g(i64 %step) { -diff --git a/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll b/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll -index 3542ad2a41e..d930706d7d2 100644 ---- a/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll -+++ b/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll -@@ -22,5 +22,5 @@ afterfor: ; preds = %forinc, %entry - ret i32 %j.0.lcssa - } - --; CHECK: backedge-taken count is (-2147483632 + ((-1 + (-1 * %{{[xy]}})) smax (-1 + (-1 * %{{[xy]}})))) -+; CHECK: backedge-taken count is (-2147483633 + (-1 * (%{{[xy]}} smin %{{[xy]}}))) - -diff --git a/test/Analysis/ScalarEvolution/min-max-exprs.ll b/test/Analysis/ScalarEvolution/min-max-exprs.ll -index e8c1e33e095..51f72c643cc 100644 ---- a/test/Analysis/ScalarEvolution/min-max-exprs.ll -+++ b/test/Analysis/ScalarEvolution/min-max-exprs.ll -@@ -33,7 +33,7 @@ bb2: ; preds = %bb1 - %tmp9 = select i1 %tmp4, i64 %tmp5, i64 %tmp6 - ; min(N, i+3) - ; CHECK: select i1 %tmp4, i64 %tmp5, i64 %tmp6 --; CHECK-NEXT: --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}<%bb1> to i64))) smax (-1 + (-1 * (sext i32 %N to i64)))))) -+; CHECK-NEXT: --> ((sext i32 {3,+,1}<%bb1> to i64) smin (sext i32 %N to i64)) - %tmp11 = getelementptr inbounds i32, i32* %A, i64 %tmp9 - %tmp12 = load i32, i32* %tmp11, align 4 - %tmp13 = shl nsw i32 %tmp12, 1 -diff --git a/test/Analysis/ScalarEvolution/predicated-trip-count.ll b/test/Analysis/ScalarEvolution/predicated-trip-count.ll -index a0afcf457d2..b07662ed95f 100644 ---- a/test/Analysis/ScalarEvolution/predicated-trip-count.ll -+++ b/test/Analysis/ScalarEvolution/predicated-trip-count.ll -@@ -80,7 +80,7 @@ return: ; preds = %bb5 - ; CHECK-NEXT: --> (sext i16 {%Start,+,-1}<%bb3> to i32) - ; CHECK: Loop %bb3: Unpredictable backedge-taken count. - ; CHECK-NEXT: Loop %bb3: Unpredictable max backedge-taken count. --; CHECK-NEXT: Loop %bb3: Predicated backedge-taken count is (2 + (sext i16 %Start to i32) + ((-2 + (-1 * (sext i16 %Start to i32))) smax (-1 + (-1 * %M)))) -+; CHECK-NEXT: Loop %bb3: Predicated backedge-taken count is (1 + (sext i16 %Start to i32) + (-1 * ((1 + (sext i16 %Start to i32)) smin %M))) - ; CHECK-NEXT: Predicates: - ; CHECK-NEXT: {%Start,+,-1}<%bb3> Added Flags: - -diff --git a/test/Analysis/ScalarEvolution/trip-count14.ll b/test/Analysis/ScalarEvolution/trip-count14.ll -index 5e6cfe85101..15080613881 100644 ---- a/test/Analysis/ScalarEvolution/trip-count14.ll -+++ b/test/Analysis/ScalarEvolution/trip-count14.ll -@@ -81,7 +81,7 @@ if.end: - br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times - - ; CHECK-LABEL: Determining loop execution counts for: @s32_max2_unpredictable_exit --; CHECK-NEXT: Loop %do.body: backedge-taken count is (-1 + (-1 * ((-1 + (-1 * ((2 + %n) smax %n)) + %n) umax (-1 + (-1 * %x) + %n)))) -+; CHECK-NEXT: Loop %do.body: backedge-taken count is (((-1 * %n) + ((2 + %n) smax %n)) umin ((-1 * %n) + %x)) - ; CHECK-NEXT: Loop %do.body: max backedge-taken count is 2{{$}} - - do.end: -@@ -169,7 +169,7 @@ if.end: - br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times - - ; CHECK-LABEL: Determining loop execution counts for: @u32_max2_unpredictable_exit --; CHECK-NEXT: Loop %do.body: backedge-taken count is (-1 + (-1 * ((-1 + (-1 * ((2 + %n) umax %n)) + %n) umax (-1 + (-1 * %x) + %n)))) -+; CHECK-NEXT: Loop %do.body: backedge-taken count is (((-1 * %n) + ((2 + %n) umax %n)) umin ((-1 * %n) + %x)) - ; CHECK-NEXT: Loop %do.body: max backedge-taken count is 2{{$}} - - do.end: -diff --git a/test/Analysis/ScalarEvolution/trip-count3.ll b/test/Analysis/ScalarEvolution/trip-count3.ll -index df6637a4ced..e10012c0c32 100644 ---- a/test/Analysis/ScalarEvolution/trip-count3.ll -+++ b/test/Analysis/ScalarEvolution/trip-count3.ll -@@ -4,7 +4,7 @@ - ; dividing by the stride will have a remainder. This could theoretically - ; be teaching it how to use a more elaborate trip count computation. - --; CHECK: Loop %bb3.i: backedge-taken count is ((64 + (-64 smax (-1 + (-1 * %0))) + %0) /u 64) -+; CHECK: Loop %bb3.i: backedge-taken count is ((63 + (-1 * (63 smin %0)) + %0) /u 64) - ; CHECK: Loop %bb3.i: max backedge-taken count is 33554431 - - %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } -diff --git a/test/Transforms/IRCE/conjunctive-checks.ll b/test/Transforms/IRCE/conjunctive-checks.ll -index 60a0af83174..8711c1b00e8 100644 ---- a/test/Transforms/IRCE/conjunctive-checks.ll -+++ b/test/Transforms/IRCE/conjunctive-checks.ll -@@ -5,17 +5,15 @@ define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) { - ; CHECK-LABEL: @f_0( - - ; CHECK: loop.preheader: --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len --; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_n]], [[not_safe_range_end]] --; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_n]], i32 [[not_safe_range_end]] --; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]] -+; CHECK: [[len_sub:[^ ]+]] = add i32 %len, -4 -+; CHECK: [[exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp slt i32 %n, [[len_sub]] -+; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[exit_main_loop_at_hiclamp_cmp]], i32 %n, i32 [[len_sub]] - ; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0 - ; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0 - ; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]] --; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit -+; CHECK: br i1 [[enter_main_loop]], label %[[loop_preheader2:[^ ,]+]], label %main.pseudo.exit - --; CHECK: loop.preheader2: -+; CHECK: [[loop_preheader2]]: - ; CHECK: br label %loop - - entry: -@@ -35,9 +33,9 @@ define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) { - ; CHECK: loop: - ; CHECK: %cond = load volatile i1, i1* %cond_buf - ; CHECK: %abc = and i1 %cond, true --; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit3, !prof !1 -+; CHECK: br i1 %abc, label %in.bounds, label %[[loop_exit:[^ ,]+]], !prof !1 - --; CHECK: out.of.bounds.loopexit: -+; CHECK: [[loop_exit]]: - ; CHECK: br label %out.of.bounds - - in.bounds: -@@ -58,14 +56,10 @@ define void @f_1( - ; CHECK-LABEL: @f_1( - - ; CHECK: loop.preheader: --; CHECK: [[not_len_b:[^ ]+]] = sub i32 -1, %len.b --; CHECK: [[not_len_a:[^ ]+]] = sub i32 -1, %len.a --; CHECK: [[smax_not_len_cond:[^ ]+]] = icmp sgt i32 [[not_len_b]], [[not_len_a]] --; CHECK: [[smax_not_len:[^ ]+]] = select i1 [[smax_not_len_cond]], i32 [[not_len_b]], i32 [[not_len_a]] --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_upper_limit_cond_loclamp:[^ ]+]] = icmp sgt i32 [[smax_not_len]], [[not_n]] --; CHECK: [[not_upper_limit_loclamp:[^ ]+]] = select i1 [[not_upper_limit_cond_loclamp]], i32 [[smax_not_len]], i32 [[not_n]] --; CHECK: [[upper_limit_loclamp:[^ ]+]] = sub i32 -1, [[not_upper_limit_loclamp]] -+; CHECK: [[smax_len_cond:[^ ]+]] = icmp slt i32 %len.b, %len.a -+; CHECK: [[smax_len:[^ ]+]] = select i1 [[smax_len_cond]], i32 %len.b, i32 %len.a -+; CHECK: [[upper_limit_cond_loclamp:[^ ]+]] = icmp slt i32 [[smax_len]], %n -+; CHECK: [[upper_limit_loclamp:[^ ]+]] = select i1 [[upper_limit_cond_loclamp]], i32 [[smax_len]], i32 %n - ; CHECK: [[upper_limit_cmp:[^ ]+]] = icmp sgt i32 [[upper_limit_loclamp]], 0 - ; CHECK: [[upper_limit:[^ ]+]] = select i1 [[upper_limit_cmp]], i32 [[upper_limit_loclamp]], i32 0 - -@@ -85,9 +79,9 @@ define void @f_1( - - ; CHECK: loop: - ; CHECK: %abc = and i1 true, true --; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit4, !prof !1 -+; CHECK: br i1 %abc, label %in.bounds, label %[[oob_loopexit:[^ ,]+]], !prof !1 - --; CHECK: out.of.bounds.loopexit: -+; CHECK: [[oob_loopexit]]: - ; CHECK-NEXT: br label %out.of.bounds - - -diff --git a/test/Transforms/IRCE/decrementing-loop.ll b/test/Transforms/IRCE/decrementing-loop.ll -index 4c82cd3e341..2994a432a71 100644 ---- a/test/Transforms/IRCE/decrementing-loop.ll -+++ b/test/Transforms/IRCE/decrementing-loop.ll -@@ -29,11 +29,8 @@ define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) { - ret void - - ; CHECK: loop.preheader: --; CHECK: [[not_len:[^ ]+]] = sub i32 -1, %len --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_len_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_len]], [[not_n]] --; CHECK: [[not_len_hiclamp:[^ ]+]] = select i1 [[not_len_hiclamp_cmp]], i32 [[not_len]], i32 [[not_n]] --; CHECK: [[len_hiclamp:[^ ]+]] = sub i32 -1, [[not_len_hiclamp]] -+; CHECK: [[len_hiclamp_cmp:[^ ]+]] = icmp slt i32 %len, %n -+; CHECK: [[len_hiclamp:[^ ]+]] = select i1 [[len_hiclamp_cmp]], i32 %len, i32 %n - ; CHECK: [[not_exit_preloop_at_cmp:[^ ]+]] = icmp sgt i32 [[len_hiclamp]], 0 - ; CHECK: [[not_exit_preloop_at:[^ ]+]] = select i1 [[not_exit_preloop_at_cmp]], i32 [[len_hiclamp]], i32 0 - ; CHECK: %exit.preloop.at = add i32 [[not_exit_preloop_at]], -1 -diff --git a/test/Transforms/IRCE/multiple-access-no-preloop.ll b/test/Transforms/IRCE/multiple-access-no-preloop.ll -index 000d1ab36f2..3bde9bd8668 100644 ---- a/test/Transforms/IRCE/multiple-access-no-preloop.ll -+++ b/test/Transforms/IRCE/multiple-access-no-preloop.ll -@@ -38,14 +38,10 @@ define void @multiple_access_no_preloop( - ; CHECK-LABEL: @multiple_access_no_preloop( - - ; CHECK: loop.preheader: --; CHECK: [[not_len_b:[^ ]+]] = sub i32 -1, %len.b --; CHECK: [[not_len_a:[^ ]+]] = sub i32 -1, %len.a --; CHECK: [[smax_not_len_cond:[^ ]+]] = icmp sgt i32 [[not_len_b]], [[not_len_a]] --; CHECK: [[smax_not_len:[^ ]+]] = select i1 [[smax_not_len_cond]], i32 [[not_len_b]], i32 [[not_len_a]] --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_upper_limit_cond_loclamp:[^ ]+]] = icmp sgt i32 [[smax_not_len]], [[not_n]] --; CHECK: [[not_upper_limit_loclamp:[^ ]+]] = select i1 [[not_upper_limit_cond_loclamp]], i32 [[smax_not_len]], i32 [[not_n]] --; CHECK: [[upper_limit_loclamp:[^ ]+]] = sub i32 -1, [[not_upper_limit_loclamp]] -+; CHECK: [[smax_len_cond:[^ ]+]] = icmp slt i32 %len.b, %len.a -+; CHECK: [[smax_len:[^ ]+]] = select i1 [[smax_len_cond]], i32 %len.b, i32 %len.a -+; CHECK: [[upper_limit_cond_loclamp:[^ ]+]] = icmp slt i32 [[smax_len]], %n -+; CHECK: [[upper_limit_loclamp:[^ ]+]] = select i1 [[upper_limit_cond_loclamp]], i32 [[smax_len]], i32 %n - ; CHECK: [[upper_limit_cmp:[^ ]+]] = icmp sgt i32 [[upper_limit_loclamp]], 0 - ; CHECK: [[upper_limit:[^ ]+]] = select i1 [[upper_limit_cmp]], i32 [[upper_limit_loclamp]], i32 0 - -diff --git a/test/Transforms/IRCE/ranges_of_different_types.ll b/test/Transforms/IRCE/ranges_of_different_types.ll -index 5c8161369f2..46bd94ce687 100644 ---- a/test/Transforms/IRCE/ranges_of_different_types.ll -+++ b/test/Transforms/IRCE/ranges_of_different_types.ll -@@ -23,12 +23,11 @@ define void @test_01(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NOT: preloop - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 12, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102 --; CHECK-NEXT: [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX]] --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0 --; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB2]], i32 0 -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = add i32 %len, -13 -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -+; CHECK-NEXT: [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 101 -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SMAX]], 0 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SMAX]], i32 0 - ; CHECK-NEXT: [[GOTO_LOOP:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at - ; CHECK-NEXT: br i1 [[GOTO_LOOP]], label %loop.preheader, label %main.pseudo.exit - ; CHECK: loop -@@ -83,13 +82,11 @@ define void @test_02(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NEXT: [[LEN_MINUS_SMAX:%[^ ]+]] = add i32 %len, -2147483647 - ; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[LEN_MINUS_SMAX]], -13 - ; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13 --; CHECK-NEXT: [[ADD1:%[^ ]+]] = add i32 [[SMAX1]], -1 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 [[ADD1]], %len --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102 --; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX2]] --; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0 --; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SUB2]], i32 0 -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 %len, [[SMAX1]] -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -+; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 101 -+; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SMAX2]], 0 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SMAX2]], i32 0 - ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader - ; CHECK: loop.preloop: - ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 0, %loop.preloop.preheader ] -@@ -151,14 +148,11 @@ define void @test_03(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NOT: preloop - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 -2, %len --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB2]], -14 --; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB2]], i32 -14 --; CHECK-NEXT: [[SUB3:%[^ ]+]] = sub i32 [[SUB1]], [[SMAX1]] --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp ugt i32 [[SUB3]], -102 --; CHECK-NEXT: [[UMAX1:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB3]], i32 -102 --; CHECK-NEXT: %exit.mainloop.at = sub i32 -1, [[UMAX1]] -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp slt i32 %len, 13 -+; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 %len, i32 13 -+; CHECK-NEXT: [[SUB3:%[^ ]+]] = sub i32 %len, [[SMAX1]] -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp ult i32 [[SUB3]], 101 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB3]], i32 101 - ; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at - ; CHECK-NEXT: br i1 [[CMP3]], label %loop.preheader, label %main.pseudo.exit - ; CHECK: postloop: -@@ -208,10 +202,9 @@ define void @test_04(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-LABEL: test_04( - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 -14, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp ugt i32 [[SUB1]], -102 --; CHECK-NEXT: [[UMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: %exit.mainloop.at = sub i32 -1, [[UMAX1]] -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = add i32 %len, 13 -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp ult i32 [[SUB1]], 101 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP1]], i32 [[SUB1]], i32 101 - ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader - ; CHECK: in.bounds.preloop: - ; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop -@@ -252,12 +245,11 @@ define void @test_05(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NOT: preloop - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 12, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102 --; CHECK-NEXT: [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX]] --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0 --; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB2]], i32 0 -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = add i32 %len, -13 -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -+; CHECK-NEXT: [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 101 -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SMAX]], 0 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SMAX]], i32 0 - ; CHECK-NEXT: [[GOTO_LOOP:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at - ; CHECK-NEXT: br i1 [[GOTO_LOOP]], label %loop.preheader, label %main.pseudo.exit - ; CHECK: loop -@@ -297,13 +289,11 @@ define void @test_06(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NEXT: [[LEN_MINUS_SMAX:%[^ ]+]] = add i32 %len, -2147483647 - ; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[LEN_MINUS_SMAX]], -13 - ; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13 --; CHECK-NEXT: [[ADD1:%[^ ]+]] = add i32 [[SMAX1]], -1 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 [[ADD1]], %len --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102 --; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX2]] --; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0 --; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SUB2]], i32 0 -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 %len, [[SMAX1]] -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -+; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 101 -+; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SMAX2]], 0 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SMAX2]], i32 0 - ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader - ; CHECK: in.bounds.preloop: - ; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop -@@ -344,14 +334,11 @@ define void @test_07(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-NOT: preloop - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 -2, %len --; CHECK-NEXT: [[SUB2:%[^ ]+]] = sub i32 -1, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB2]], -14 --; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB2]], i32 -14 --; CHECK-NEXT: [[SUB3:%[^ ]+]] = sub i32 [[SUB1]], [[SMAX1]] --; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp ugt i32 [[SUB3]], -102 --; CHECK-NEXT: [[UMAX1:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB3]], i32 -102 --; CHECK-NEXT: %exit.mainloop.at = sub i32 -1, [[UMAX1]] -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp slt i32 %len, 13 -+; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 %len, i32 13 -+; CHECK-NEXT: [[SUB3:%[^ ]+]] = sub i32 %len, [[SMAX1]] -+; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp ult i32 [[SUB3]], 101 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB3]], i32 101 - ; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at - ; CHECK-NEXT: br i1 [[CMP3]], label %loop.preheader, label %main.pseudo.exit - ; CHECK: loop -@@ -388,10 +375,9 @@ define void @test_08(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK-LABEL: test_08( - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 --; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 -14, %len --; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp ugt i32 [[SUB1]], -102 --; CHECK-NEXT: [[UMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102 --; CHECK-NEXT: %exit.mainloop.at = sub i32 -1, [[UMAX1]] -+; CHECK-NEXT: [[SUB1:%[^ ]+]] = add i32 %len, 13 -+; CHECK-NEXT: [[CMP1:%[^ ]+]] = icmp ult i32 [[SUB1]], 101 -+; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP1]], i32 [[SUB1]], i32 101 - ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader - ; CHECK: in.bounds.preloop: - ; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop -diff --git a/test/Transforms/IRCE/rc-negative-bound.ll b/test/Transforms/IRCE/rc-negative-bound.ll -index bfc0cd14778..d226bffeaae 100644 ---- a/test/Transforms/IRCE/rc-negative-bound.ll -+++ b/test/Transforms/IRCE/rc-negative-bound.ll -@@ -114,49 +114,44 @@ define void @test_03(i32 *%arr, i32 %n, i32 %bound) { - ; CHECK: loop.preheader: - ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647 - ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0 --; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 --; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]] --; CHECK-NEXT: [[TMP3:%.*]] = sub i32 -1, [[BOUND]] --; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1 --; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1 --; CHECK-NEXT: [[TMP5:%.*]] = sub i32 -1, [[SMAX1]] --; CHECK-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1 --; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1 --; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[SMAX2]], 1 --; CHECK-NEXT: [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]] --; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[TMP8]] --; CHECK-NEXT: [[TMP10:%.*]] = sub i32 -1, [[N]] --; CHECK-NEXT: [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] --; CHECK-NEXT: [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]] --; CHECK-NEXT: [[TMP12:%.*]] = sub i32 -1, [[SMAX3]] --; CHECK-NEXT: [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0 --; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0 --; CHECK-NEXT: [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] --; CHECK: loop.preheader5: -+; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 -+; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMIN]] -+; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[BOUND]], 0 -+; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP3]], i32 [[BOUND]], i32 0 -+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[SMAX]], -1 -+; CHECK-NEXT: [[SMIN1:%.*]] = select i1 [[TMP4]], i32 [[SMAX]], i32 -1 -+; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[SMIN1]], 1 -+; CHECK-NEXT: [[TMP6:%.*]] = mul i32 [[TMP2]], [[TMP5]] -+; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[N]], [[TMP6]] -+; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP7]], i32 [[N]], i32 [[TMP6]] -+; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[SMAX2]], 0 -+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP8]], i32 [[SMAX2]], i32 0 -+; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP9]], label [[LOOP_PREHEADER4:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] -+; CHECK: loop.preheader4: - ; CHECK-NEXT: br label [[LOOP:%.*]] - ; CHECK: loop: --; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ] -+; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER4]] ] - ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 - ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]] --; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0 -+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof !0 - ; CHECK: in.bounds: - ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] - ; CHECK-NEXT: store i32 0, i32* [[ADDR]] - ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] --; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] -+; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] - ; CHECK: main.exit.selector: - ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] --; CHECK-NEXT: [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] --; CHECK-NEXT: br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] -+; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] -+; CHECK-NEXT: br i1 [[TMP11]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] - ; CHECK: main.pseudo.exit: - ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: br label [[POSTLOOP:%.*]] - ; CHECK: out.of.bounds.loopexit: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] --; CHECK: out.of.bounds.loopexit6: -+; CHECK: out.of.bounds.loopexit5: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] - ; CHECK: out.of.bounds: - ; CHECK-NEXT: ret void -@@ -211,47 +206,41 @@ define void @test_04(i32 *%arr, i32 %n, i32 %bound) { - ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 - ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] - ; CHECK: loop.preheader: --; CHECK-NEXT: [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]] --; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1 --; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1 --; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]] --; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 --; CHECK-NEXT: [[TMP4:%.*]] = sub i32 -1, [[SMAX]] --; CHECK-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1 --; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1 --; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[SMAX1]], 1 --; CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]] --; CHECK-NEXT: [[TMP8:%.*]] = sub i32 -1, [[TMP7]] --; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[N]] --; CHECK-NEXT: [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]] --; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]] --; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]] --; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] --; CHECK: loop.preheader2: -+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[BOUND:%.*]], 0 -+; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[BOUND]], i32 0 -+; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[BOUND]], [[SMAX]] -+; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[SMAX]], -1 -+; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[TMP2]], i32 [[SMAX]], i32 -1 -+; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[SMIN]], 1 -+; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP1]], [[TMP3]] -+; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[N]], [[TMP4]] -+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP5]], i32 [[N]], i32 [[TMP4]] -+; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] -+; CHECK: loop.preheader1: - ; CHECK-NEXT: br label [[LOOP:%.*]] - ; CHECK: loop: --; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ] -+; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER1]] ] - ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 - ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]] --; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0 -+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT2:%.*]], !prof !0 - ; CHECK: in.bounds: - ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] - ; CHECK-NEXT: store i32 0, i32* [[ADDR]] - ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] --; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] -+; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] - ; CHECK: main.exit.selector: - ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] --; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] --; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] -+; CHECK-NEXT: [[TMP8:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] -+; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] - ; CHECK: main.pseudo.exit: - ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: br label [[POSTLOOP:%.*]] - ; CHECK: out.of.bounds.loopexit: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] --; CHECK: out.of.bounds.loopexit3: -+; CHECK: out.of.bounds.loopexit2: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] - ; CHECK: out.of.bounds: - ; CHECK-NEXT: ret void -@@ -413,49 +402,44 @@ define void @test_07(i32 *%arr, i32 %n, i32 %bound) { - ; CHECK: loop.preheader: - ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647 - ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0 --; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 --; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]] --; CHECK-NEXT: [[TMP3:%.*]] = sub i32 -1, [[BOUND]] --; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1 --; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1 --; CHECK-NEXT: [[TMP5:%.*]] = sub i32 -1, [[SMAX1]] --; CHECK-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1 --; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1 --; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[SMAX2]], 1 --; CHECK-NEXT: [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]] --; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[TMP8]] --; CHECK-NEXT: [[TMP10:%.*]] = sub i32 -1, [[N]] --; CHECK-NEXT: [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] --; CHECK-NEXT: [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]] --; CHECK-NEXT: [[TMP12:%.*]] = sub i32 -1, [[SMAX3]] --; CHECK-NEXT: [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0 --; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0 --; CHECK-NEXT: [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] --; CHECK: loop.preheader5: -+; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 -+; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMIN]] -+; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[BOUND]], 0 -+; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP3]], i32 [[BOUND]], i32 0 -+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[SMAX]], -1 -+; CHECK-NEXT: [[SMIN1:%.*]] = select i1 [[TMP4]], i32 [[SMAX]], i32 -1 -+; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[SMIN1]], 1 -+; CHECK-NEXT: [[TMP6:%.*]] = mul i32 [[TMP2]], [[TMP5]] -+; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[N]], [[TMP6]] -+; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP7]], i32 [[N]], i32 [[TMP6]] -+; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[SMAX2]], 0 -+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP8]], i32 [[SMAX2]], i32 0 -+; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP9]], label [[LOOP_PREHEADER4:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] -+; CHECK: loop.preheader4: - ; CHECK-NEXT: br label [[LOOP:%.*]] - ; CHECK: loop: --; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ] -+; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER4]] ] - ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 - ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]] --; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0 -+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof !0 - ; CHECK: in.bounds: - ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] - ; CHECK-NEXT: store i32 0, i32* [[ADDR]] - ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] --; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] -+; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] - ; CHECK: main.exit.selector: - ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] --; CHECK-NEXT: [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] --; CHECK-NEXT: br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] -+; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] -+; CHECK-NEXT: br i1 [[TMP11]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] - ; CHECK: main.pseudo.exit: - ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: br label [[POSTLOOP:%.*]] - ; CHECK: out.of.bounds.loopexit: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] --; CHECK: out.of.bounds.loopexit6: -+; CHECK: out.of.bounds.loopexit5: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] - ; CHECK: out.of.bounds: - ; CHECK-NEXT: ret void -@@ -512,47 +496,41 @@ define void @test_08(i32 *%arr, i32 %n, i32 %bound) { - ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 - ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] - ; CHECK: loop.preheader: --; CHECK-NEXT: [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]] --; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1 --; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1 --; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]] --; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 --; CHECK-NEXT: [[TMP4:%.*]] = sub i32 -1, [[SMAX]] --; CHECK-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1 --; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1 --; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[SMAX1]], 1 --; CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]] --; CHECK-NEXT: [[TMP8:%.*]] = sub i32 -1, [[TMP7]] --; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[N]] --; CHECK-NEXT: [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]] --; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]] --; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]] --; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] --; CHECK: loop.preheader2: -+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[BOUND:%.*]], 0 -+; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[BOUND]], i32 0 -+; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[BOUND]], [[SMAX]] -+; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[SMAX]], -1 -+; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[TMP2]], i32 [[SMAX]], i32 -1 -+; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[SMIN]], 1 -+; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP1]], [[TMP3]] -+; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[N]], [[TMP4]] -+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP5]], i32 [[N]], i32 [[TMP4]] -+; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] -+; CHECK: loop.preheader1: - ; CHECK-NEXT: br label [[LOOP:%.*]] - ; CHECK: loop: --; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ] -+; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER1]] ] - ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 - ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]] --; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0 -+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT2:%.*]], !prof !0 - ; CHECK: in.bounds: - ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] - ; CHECK-NEXT: store i32 0, i32* [[ADDR]] - ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] --; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] --; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] -+; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] -+; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] - ; CHECK: main.exit.selector: - ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] --; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] --; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] -+; CHECK-NEXT: [[TMP8:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] -+; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] - ; CHECK: main.pseudo.exit: - ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] - ; CHECK-NEXT: br label [[POSTLOOP:%.*]] - ; CHECK: out.of.bounds.loopexit: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] --; CHECK: out.of.bounds.loopexit3: -+; CHECK: out.of.bounds.loopexit2: - ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] - ; CHECK: out.of.bounds: - ; CHECK-NEXT: ret void -diff --git a/test/Transforms/IRCE/single-access-no-preloop.ll b/test/Transforms/IRCE/single-access-no-preloop.ll -index fb643139c6d..7bf36f7c254 100644 ---- a/test/Transforms/IRCE/single-access-no-preloop.ll -+++ b/test/Transforms/IRCE/single-access-no-preloop.ll -@@ -86,15 +86,13 @@ define void @single_access_no_preloop_with_offset(i32 *%arr, i32 *%a_len_ptr, i3 - ; CHECK-LABEL: @single_access_no_preloop_with_offset( - - ; CHECK: loop.preheader: --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len --; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_n]], [[not_safe_range_end]] --; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_n]], i32 [[not_safe_range_end]] --; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]] -+; CHECK: [[safe_range_end:[^ ]+]] = add i32 %len, -4 -+; CHECK: [[exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp slt i32 %n, [[safe_range_end]] -+; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[exit_main_loop_at_hiclamp_cmp]], i32 %n, i32 [[safe_range_end]] - ; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0 - ; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0 - ; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]] --; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit -+; CHECK: br i1 [[enter_main_loop]], label %[[loop_preheader:[^ ,]+]], label %main.pseudo.exit - - ; CHECK: loop: - ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds -diff --git a/test/Transforms/IRCE/single-access-with-preloop.ll b/test/Transforms/IRCE/single-access-with-preloop.ll -index 6f3b0324e39..bd235aa4a73 100644 ---- a/test/Transforms/IRCE/single-access-with-preloop.ll -+++ b/test/Transforms/IRCE/single-access-with-preloop.ll -@@ -34,11 +34,9 @@ define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 - ; CHECK: [[check_min_sint_offset:[^ ]+]] = icmp sgt i32 %offset, -2147483647 - ; CHECK: [[safe_offset_preloop:[^ ]+]] = select i1 [[check_min_sint_offset]], i32 %offset, i32 -2147483647 - ; If Offset was a SINT_MIN, we could have an overflow here. That is why we calculated its safe version. --; CHECK: [[not_safe_start:[^ ]+]] = add i32 [[safe_offset_preloop]], -1 --; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n --; CHECK: [[not_exit_preloop_at_cond_loclamp:[^ ]+]] = icmp sgt i32 [[not_safe_start]], [[not_n]] --; CHECK: [[not_exit_preloop_at_loclamp:[^ ]+]] = select i1 [[not_exit_preloop_at_cond_loclamp]], i32 [[not_safe_start]], i32 [[not_n]] --; CHECK: [[exit_preloop_at_loclamp:[^ ]+]] = sub i32 -1, [[not_exit_preloop_at_loclamp]] -+; CHECK: [[safe_start:[^ ]+]] = sub i32 0, [[safe_offset_preloop]] -+; CHECK: [[exit_preloop_at_cond_loclamp:[^ ]+]] = icmp slt i32 %n, [[safe_start]] -+; CHECK: [[exit_preloop_at_loclamp:[^ ]+]] = select i1 [[exit_preloop_at_cond_loclamp]], i32 %n, i32 [[safe_start]] - ; CHECK: [[exit_preloop_at_cond:[^ ]+]] = icmp sgt i32 [[exit_preloop_at_loclamp]], 0 - ; CHECK: [[exit_preloop_at:[^ ]+]] = select i1 [[exit_preloop_at_cond]], i32 [[exit_preloop_at_loclamp]], i32 0 - -@@ -46,17 +44,15 @@ define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 - ; CHECK: [[len_minus_sint_max:[^ ]+]] = add i32 %len, -2147483647 - ; CHECK: [[check_len_min_sint_offset:[^ ]+]] = icmp sgt i32 %offset, [[len_minus_sint_max]] - ; CHECK: [[safe_offset_mainloop:[^ ]+]] = select i1 [[check_len_min_sint_offset]], i32 %offset, i32 [[len_minus_sint_max]] --; CHECK: [[not_safe_start_2:[^ ]+]] = add i32 [[safe_offset_mainloop]], -1 - ; If Offset was a SINT_MIN, we could have an overflow here. That is why we calculated its safe version. --; CHECK: [[not_safe_upper_end:[^ ]+]] = sub i32 [[not_safe_start_2]], %len --; CHECK: [[not_exit_mainloop_at_cond_loclamp:[^ ]+]] = icmp sgt i32 [[not_safe_upper_end]], [[not_n]] --; CHECK: [[not_exit_mainloop_at_loclamp:[^ ]+]] = select i1 [[not_exit_mainloop_at_cond_loclamp]], i32 [[not_safe_upper_end]], i32 [[not_n]] -+; CHECK: [[safe_upper_end:[^ ]+]] = sub i32 %len, [[safe_offset_mainloop]] -+; CHECK: [[exit_mainloop_at_cond_loclamp:[^ ]+]] = icmp slt i32 %n, [[safe_upper_end]] -+; CHECK: [[exit_mainloop_at_loclamp:[^ ]+]] = select i1 [[exit_mainloop_at_cond_loclamp]], i32 %n, i32 [[safe_upper_end]] - ; CHECK: [[check_offset_mainloop_2:[^ ]+]] = icmp sgt i32 %offset, 0 - ; CHECK: [[safe_offset_mainloop_2:[^ ]+]] = select i1 [[check_offset_mainloop_2]], i32 %offset, i32 0 --; CHECK: [[not_safe_lower_end:[^ ]+]] = add i32 [[safe_offset_mainloop_2]], -2147483648 --; CHECK: [[not_exit_mainloop_at_cond_hiclamp:[^ ]+]] = icmp sgt i32 [[not_exit_mainloop_at_loclamp]], [[not_safe_lower_end]] --; CHECK: [[not_exit_mainloop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_mainloop_at_cond_hiclamp]], i32 [[not_exit_mainloop_at_loclamp]], i32 [[not_safe_lower_end]] --; CHECK: [[exit_mainloop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_mainloop_at_hiclamp]] -+; CHECK: [[safe_lower_end:[^ ]+]] = sub i32 2147483647, [[safe_offset_mainloop_2]] -+; CHECK: [[exit_mainloop_at_cond_hiclamp:[^ ]+]] = icmp slt i32 [[exit_mainloop_at_loclamp]], [[safe_lower_end]] -+; CHECK: [[exit_mainloop_at_hiclamp:[^ ]+]] = select i1 [[exit_mainloop_at_cond_hiclamp]], i32 [[exit_mainloop_at_loclamp]], i32 [[safe_lower_end]] - ; CHECK: [[exit_mainloop_at_cmp:[^ ]+]] = icmp sgt i32 [[exit_mainloop_at_hiclamp]], 0 - ; CHECK: [[exit_mainloop_at:[^ ]+]] = select i1 [[exit_mainloop_at_cmp]], i32 [[exit_mainloop_at_hiclamp]], i32 0 - -@@ -67,7 +63,7 @@ define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 - ; CHECK: %abc.high = icmp slt i32 %array.idx, %len - ; CHECK: %abc.low = icmp sge i32 %array.idx, 0 - ; CHECK: %abc = and i1 true, true --; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit11 -+; CHECK: br i1 %abc, label %in.bounds, label %[[loopexit:[^ ,]+]] - - ; CHECK: in.bounds: - ; CHECK: [[continue_mainloop_cond:[^ ]+]] = icmp slt i32 %idx.next, [[exit_mainloop_at]] -diff --git a/test/Transforms/IRCE/unsigned_comparisons_ugt.ll b/test/Transforms/IRCE/unsigned_comparisons_ugt.ll -index 8f00c733569..3451d65c7bb 100644 ---- a/test/Transforms/IRCE/unsigned_comparisons_ugt.ll -+++ b/test/Transforms/IRCE/unsigned_comparisons_ugt.ll -@@ -58,8 +58,8 @@ define void @test_02(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 - ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1 --; CHECK-NEXT: %umax = select i1 [[COND1]], i32 %len, i32 1 --; CHECK-NEXT: %exit.preloop.at = add i32 %umax, -1 -+; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1 -+; CHECK-NEXT: %exit.preloop.at = add i32 [[UMIN]], -1 - ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at - ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit - ; CHECK: mainloop: -@@ -149,8 +149,8 @@ define void @test_04(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 - ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1 --; CHECK-NEXT: %umax = select i1 [[COND1]], i32 %len, i32 1 --; CHECK-NEXT: %exit.preloop.at = add i32 %umax, -1 -+; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1 -+; CHECK-NEXT: %exit.preloop.at = add i32 [[UMIN]], -1 - ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at - ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit - ; CHECK: mainloop: -diff --git a/test/Transforms/IRCE/unsigned_comparisons_ult.ll b/test/Transforms/IRCE/unsigned_comparisons_ult.ll -index dc59c11df1b..aca3c3d192e 100644 ---- a/test/Transforms/IRCE/unsigned_comparisons_ult.ll -+++ b/test/Transforms/IRCE/unsigned_comparisons_ult.ll -@@ -61,8 +61,8 @@ define void @test_02(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 - ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1 --; CHECK-NEXT: %umax = select i1 [[COND1]], i32 %len, i32 1 --; CHECK-NEXT: %exit.preloop.at = add i32 %umax, -1 -+; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1 -+; CHECK-NEXT: %exit.preloop.at = add i32 [[UMIN]], -1 - ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at - ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit - ; CHECK: mainloop: -@@ -194,8 +194,8 @@ define void @test_05(i32* %arr, i32* %a_len_ptr) #0 { - ; CHECK: entry: - ; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, !range !0 - ; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1 --; CHECK-NEXT: %umax = select i1 [[COND1]], i32 %len, i32 1 --; CHECK-NEXT: %exit.preloop.at = add i32 %umax, -1 -+; CHECK-NEXT: [[UMIN:%[^ ]+]] = select i1 [[COND1]], i32 %len, i32 1 -+; CHECK-NEXT: %exit.preloop.at = add i32 [[UMIN]], -1 - ; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at - ; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit - ; CHECK: mainloop: -diff --git a/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll -index ea3f6077231..d5232e1874c 100644 ---- a/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll -+++ b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll -@@ -14,8 +14,6 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 - ; current LSR cost model. - ; CHECK-NOT: = ptrtoint i8* undef to i64 - ; CHECK: .lr.ph --; CHECK: [[TMP:%[^ ]+]] = add i64 %tmp{{[0-9]+}}, -1 --; CHECK: sub i64 [[TMP]], %tmp{{[0-9]+}} - ; CHECK: ret void - define void @VerifyDiagnosticConsumerTest() unnamed_addr nounwind uwtable align 2 { - bb: -diff --git a/test/Transforms/LoopVectorize/X86/pr35432.ll b/test/Transforms/LoopVectorize/X86/pr35432.ll -index 1f2a2061586..6aaa13c183a 100644 ---- a/test/Transforms/LoopVectorize/X86/pr35432.ll -+++ b/test/Transforms/LoopVectorize/X86/pr35432.ll -@@ -27,7 +27,6 @@ define i32 @main() local_unnamed_addr #0 { - ; CHECK-NEXT: [[CMP8:%.*]] = icmp eq i32 [[CONV17]], 0 - ; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END12:%.*]] - ; CHECK: for.body.lr.ph: --; CHECK-NEXT: [[TMP3:%.*]] = sub i32 -1, [[TMP2]] - ; CHECK-NEXT: br label [[FOR_BODY:%.*]] - ; CHECK: for.body: - ; CHECK-NEXT: [[STOREMERGE_IN9:%.*]] = phi i32 [ [[TMP2]], [[FOR_BODY_LR_PH]] ], [ [[ADD:%.*]], [[FOR_INC9:%.*]] ] -@@ -37,77 +36,74 @@ define i32 @main() local_unnamed_addr #0 { - ; CHECK: for.body8.lr.ph: - ; CHECK-NEXT: [[CONV3:%.*]] = trunc i32 [[STOREMERGE_IN9]] to i8 - ; CHECK-NEXT: [[DOTPROMOTED:%.*]] = load i32, i32* getelementptr inbounds ([192 x [192 x i32]], [192 x [192 x i32]]* @a, i64 0, i64 0, i64 0), align 16 --; CHECK-NEXT: [[TMP4:%.*]] = add i8 [[CONV3]], -1 --; CHECK-NEXT: [[TMP5:%.*]] = zext i8 [[TMP4]] to i32 --; CHECK-NEXT: [[TMP6:%.*]] = sub i32 -1, [[TMP5]] --; CHECK-NEXT: [[TMP7:%.*]] = icmp ugt i32 [[TMP3]], [[TMP6]] --; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP7]], i32 [[TMP3]], i32 [[TMP6]] --; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[UMAX]], 2 --; CHECK-NEXT: [[TMP9:%.*]] = add i32 [[TMP8]], [[TMP5]] --; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP9]], 8 -+; CHECK-NEXT: [[TMP3:%.*]] = add i8 [[CONV3]], -1 -+; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 -+; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], 1 -+; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i32 [[TMP2]], [[TMP4]] -+; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP6]], i32 [[TMP2]], i32 [[TMP4]] -+; CHECK-NEXT: [[TMP7:%.*]] = sub i32 [[TMP5]], [[UMAX]] -+; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP7]], 8 - ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]] - ; CHECK: vector.scevcheck: --; CHECK-NEXT: [[TMP10:%.*]] = add i8 [[CONV3]], -1 --; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 --; CHECK-NEXT: [[TMP12:%.*]] = sub i32 -1, [[TMP11]] --; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i32 [[TMP3]], [[TMP12]] --; CHECK-NEXT: [[UMAX1:%.*]] = select i1 [[TMP13]], i32 [[TMP3]], i32 [[TMP12]] --; CHECK-NEXT: [[TMP14:%.*]] = add i32 [[UMAX1]], 1 --; CHECK-NEXT: [[TMP15:%.*]] = add i32 [[TMP14]], [[TMP11]] --; CHECK-NEXT: [[TMP16:%.*]] = trunc i32 [[TMP15]] to i8 --; CHECK-NEXT: [[MUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 [[TMP16]]) -+; CHECK-NEXT: [[TMP8:%.*]] = add i8 [[CONV3]], -1 -+; CHECK-NEXT: [[TMP9:%.*]] = zext i8 [[TMP8]] to i32 -+; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i32 [[TMP2]], [[TMP9]] -+; CHECK-NEXT: [[UMAX1:%.*]] = select i1 [[TMP10]], i32 [[TMP2]], i32 [[TMP9]] -+; CHECK-NEXT: [[TMP11:%.*]] = sub i32 [[TMP9]], [[UMAX1]] -+; CHECK-NEXT: [[TMP12:%.*]] = trunc i32 [[TMP11]] to i8 -+; CHECK-NEXT: [[MUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 [[TMP12]]) - ; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i8, i1 } [[MUL]], 0 - ; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i8, i1 } [[MUL]], 1 --; CHECK-NEXT: [[TMP17:%.*]] = add i8 [[TMP10]], [[MUL_RESULT]] --; CHECK-NEXT: [[TMP18:%.*]] = sub i8 [[TMP10]], [[MUL_RESULT]] --; CHECK-NEXT: [[TMP19:%.*]] = icmp ugt i8 [[TMP18]], [[TMP10]] --; CHECK-NEXT: [[TMP20:%.*]] = icmp ult i8 [[TMP17]], [[TMP10]] --; CHECK-NEXT: [[TMP21:%.*]] = select i1 true, i1 [[TMP19]], i1 [[TMP20]] --; CHECK-NEXT: [[TMP22:%.*]] = icmp ugt i32 [[TMP15]], 255 --; CHECK-NEXT: [[TMP23:%.*]] = or i1 [[TMP21]], [[TMP22]] --; CHECK-NEXT: [[TMP24:%.*]] = or i1 [[TMP23]], [[MUL_OVERFLOW]] --; CHECK-NEXT: [[TMP25:%.*]] = or i1 false, [[TMP24]] --; CHECK-NEXT: br i1 [[TMP25]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] -+; CHECK-NEXT: [[TMP13:%.*]] = add i8 [[TMP8]], [[MUL_RESULT]] -+; CHECK-NEXT: [[TMP14:%.*]] = sub i8 [[TMP8]], [[MUL_RESULT]] -+; CHECK-NEXT: [[TMP15:%.*]] = icmp ugt i8 [[TMP14]], [[TMP8]] -+; CHECK-NEXT: [[TMP16:%.*]] = icmp ult i8 [[TMP13]], [[TMP8]] -+; CHECK-NEXT: [[TMP17:%.*]] = select i1 true, i1 [[TMP15]], i1 [[TMP16]] -+; CHECK-NEXT: [[TMP18:%.*]] = icmp ugt i32 [[TMP11]], 255 -+; CHECK-NEXT: [[TMP19:%.*]] = or i1 [[TMP17]], [[TMP18]] -+; CHECK-NEXT: [[TMP20:%.*]] = or i1 [[TMP19]], [[MUL_OVERFLOW]] -+; CHECK-NEXT: [[TMP21:%.*]] = or i1 false, [[TMP20]] -+; CHECK-NEXT: br i1 [[TMP21]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] - ; CHECK: vector.ph: --; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP9]], 8 --; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP9]], [[N_MOD_VF]] -+; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP7]], 8 -+; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP7]], [[N_MOD_VF]] - ; CHECK-NEXT: [[CAST_CRD:%.*]] = trunc i32 [[N_VEC]] to i8 - ; CHECK-NEXT: [[IND_END:%.*]] = sub i8 [[CONV3]], [[CAST_CRD]] --; CHECK-NEXT: [[TMP26:%.*]] = insertelement <4 x i32> zeroinitializer, i32 [[DOTPROMOTED]], i32 0 -+; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i32> zeroinitializer, i32 [[DOTPROMOTED]], i32 0 - ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] - ; CHECK: vector.body: - ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] --; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP26]], [[VECTOR_PH]] ], [ [[TMP30:%.*]], [[VECTOR_BODY]] ] --; CHECK-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP31:%.*]], [[VECTOR_BODY]] ] --; CHECK-NEXT: [[TMP27:%.*]] = trunc i32 [[INDEX]] to i8 --; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i8 [[CONV3]], [[TMP27]] -+; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP22]], [[VECTOR_PH]] ], [ [[TMP26:%.*]], [[VECTOR_BODY]] ] -+; CHECK-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP27:%.*]], [[VECTOR_BODY]] ] -+; CHECK-NEXT: [[TMP23:%.*]] = trunc i32 [[INDEX]] to i8 -+; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i8 [[CONV3]], [[TMP23]] - ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i8> undef, i8 [[OFFSET_IDX]], i32 0 - ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i8> [[BROADCAST_SPLATINSERT]], <4 x i8> undef, <4 x i32> zeroinitializer - ; CHECK-NEXT: [[INDUCTION:%.*]] = add <4 x i8> [[BROADCAST_SPLAT]], - ; CHECK-NEXT: [[INDUCTION3:%.*]] = add <4 x i8> [[BROADCAST_SPLAT]], --; CHECK-NEXT: [[TMP28:%.*]] = add i8 [[OFFSET_IDX]], 0 --; CHECK-NEXT: [[TMP29:%.*]] = add i8 [[OFFSET_IDX]], -4 --; CHECK-NEXT: [[TMP30]] = add <4 x i32> [[VEC_PHI]], --; CHECK-NEXT: [[TMP31]] = add <4 x i32> [[VEC_PHI2]], --; CHECK-NEXT: [[TMP32:%.*]] = add i8 [[TMP28]], -1 --; CHECK-NEXT: [[TMP33:%.*]] = add i8 [[TMP29]], -1 --; CHECK-NEXT: [[TMP34:%.*]] = zext i8 [[TMP32]] to i32 --; CHECK-NEXT: [[TMP35:%.*]] = zext i8 [[TMP33]] to i32 -+; CHECK-NEXT: [[TMP24:%.*]] = add i8 [[OFFSET_IDX]], 0 -+; CHECK-NEXT: [[TMP25:%.*]] = add i8 [[OFFSET_IDX]], -4 -+; CHECK-NEXT: [[TMP26]] = add <4 x i32> [[VEC_PHI]], -+; CHECK-NEXT: [[TMP27]] = add <4 x i32> [[VEC_PHI2]], -+; CHECK-NEXT: [[TMP28:%.*]] = add i8 [[TMP24]], -1 -+; CHECK-NEXT: [[TMP29:%.*]] = add i8 [[TMP25]], -1 -+; CHECK-NEXT: [[TMP30:%.*]] = zext i8 [[TMP28]] to i32 -+; CHECK-NEXT: [[TMP31:%.*]] = zext i8 [[TMP29]] to i32 - ; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8 --; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] --; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 -+; CHECK-NEXT: [[TMP32:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] -+; CHECK-NEXT: br i1 [[TMP32]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 - ; CHECK: middle.block: --; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP31]], [[TMP30]] -+; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP27]], [[TMP26]] - ; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <4 x i32> [[BIN_RDX]], <4 x i32> undef, <4 x i32> - ; CHECK-NEXT: [[BIN_RDX4:%.*]] = add <4 x i32> [[BIN_RDX]], [[RDX_SHUF]] - ; CHECK-NEXT: [[RDX_SHUF5:%.*]] = shufflevector <4 x i32> [[BIN_RDX4]], <4 x i32> undef, <4 x i32> - ; CHECK-NEXT: [[BIN_RDX6:%.*]] = add <4 x i32> [[BIN_RDX4]], [[RDX_SHUF5]] --; CHECK-NEXT: [[TMP37:%.*]] = extractelement <4 x i32> [[BIN_RDX6]], i32 0 --; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP9]], [[N_VEC]] -+; CHECK-NEXT: [[TMP33:%.*]] = extractelement <4 x i32> [[BIN_RDX6]], i32 0 -+; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP7]], [[N_VEC]] - ; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND4_FOR_INC9_CRIT_EDGE:%.*]], label [[SCALAR_PH]] - ; CHECK: scalar.ph: - ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i8 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[CONV3]], [[FOR_BODY8_LR_PH]] ], [ [[CONV3]], [[VECTOR_SCEVCHECK]] ] --; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[DOTPROMOTED]], [[FOR_BODY8_LR_PH]] ], [ [[DOTPROMOTED]], [[VECTOR_SCEVCHECK]] ], [ [[TMP37]], [[MIDDLE_BLOCK]] ] -+; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[DOTPROMOTED]], [[FOR_BODY8_LR_PH]] ], [ [[DOTPROMOTED]], [[VECTOR_SCEVCHECK]] ], [ [[TMP33]], [[MIDDLE_BLOCK]] ] - ; CHECK-NEXT: br label [[FOR_BODY8:%.*]] - ; CHECK: for.body8: - ; CHECK-NEXT: [[INC5:%.*]] = phi i32 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY8]] ] -@@ -118,7 +114,7 @@ define i32 @main() local_unnamed_addr #0 { - ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult i32 [[TMP2]], [[CONV5]] - ; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY8]], label [[FOR_COND4_FOR_INC9_CRIT_EDGE]], !llvm.loop !2 - ; CHECK: for.cond4.for.inc9_crit_edge: --; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[FOR_BODY8]] ], [ [[TMP37]], [[MIDDLE_BLOCK]] ] -+; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[FOR_BODY8]] ], [ [[TMP33]], [[MIDDLE_BLOCK]] ] - ; CHECK-NEXT: store i32 [[INC_LCSSA]], i32* getelementptr inbounds ([192 x [192 x i32]], [192 x [192 x i32]]* @a, i64 0, i64 0, i64 0), align 16 - ; CHECK-NEXT: br label [[FOR_INC9]] - ; CHECK: for.inc9: diff --git a/deps/patches/llvm-8.0-D55758-tablegen-cond.patch b/deps/patches/llvm-8.0-D55758-tablegen-cond.patch deleted file mode 100644 index ae9e610883d7c..0000000000000 --- a/deps/patches/llvm-8.0-D55758-tablegen-cond.patch +++ /dev/null @@ -1,794 +0,0 @@ -From 95135c5a18ee14ca091d3513cc7801521d4eb204 Mon Sep 17 00:00:00 2001 -From: Javed Absar -Date: Fri, 25 Jan 2019 10:25:25 +0000 -Subject: [PATCH] [TblGen] Extend !if semantics through new feature !cond - -This patch extends TableGen language with !cond operator. -Instead of embedding !if inside !if which can get cumbersome, -one can now use !cond. -Below is an example to convert an integer 'x' into a string: - - !cond(!lt(x,0) : "Negative", - !eq(x,0) : "Zero", - !eq(x,1) : "One, - 1 : "MoreThanOne") - -Reviewed By: hfinkel, simon_tatham, greened -Differential Revision: https://reviews.llvm.org/D55758 - -llvm-svn: 352185 ---- - docs/TableGen/LangIntro.rst | 14 +++ - docs/TableGen/LangRef.rst | 10 +- - include/llvm/TableGen/Record.h | 78 ++++++++++++++++ - lib/TableGen/Record.cpp | 131 +++++++++++++++++++++++++++ - lib/TableGen/TGLexer.cpp | 1 + - lib/TableGen/TGLexer.h | 2 +- - lib/TableGen/TGParser.cpp | 90 ++++++++++++++++++ - lib/TableGen/TGParser.h | 1 + - test/TableGen/cond-bitlist.td | 27 ++++++ - test/TableGen/cond-default.td | 11 +++ - test/TableGen/cond-empty-list-arg.td | 8 ++ - test/TableGen/cond-inheritance.td | 22 +++++ - test/TableGen/cond-let.td | 36 ++++++++ - test/TableGen/cond-list.td | 38 ++++++++ - test/TableGen/cond-subclass.td | 27 ++++++ - test/TableGen/cond-type.td | 11 +++ - test/TableGen/cond-usage.td | 29 ++++++ - test/TableGen/condsbit.td | 15 +++ - 18 files changed, 549 insertions(+), 2 deletions(-) - create mode 100644 llvm/test/TableGen/cond-bitlist.td - create mode 100644 llvm/test/TableGen/cond-default.td - create mode 100644 llvm/test/TableGen/cond-empty-list-arg.td - create mode 100644 llvm/test/TableGen/cond-inheritance.td - create mode 100644 llvm/test/TableGen/cond-let.td - create mode 100644 llvm/test/TableGen/cond-list.td - create mode 100644 llvm/test/TableGen/cond-subclass.td - create mode 100644 llvm/test/TableGen/cond-type.td - create mode 100644 llvm/test/TableGen/cond-usage.td - create mode 100644 llvm/test/TableGen/condsbit.td - -diff --git a/docs/TableGen/LangIntro.rst b/docs/TableGen/LangIntro.rst -index ea46550ffc0..390f941f0ca 100644 ---- a/docs/TableGen/LangIntro.rst -+++ b/docs/TableGen/LangIntro.rst -@@ -258,6 +258,20 @@ supported include: - ``!if(a,b,c)`` - 'b' if the result of 'int' or 'bit' operator 'a' is nonzero, 'c' otherwise. - -+``!cond(condition_1 : val1, condition_2 : val2, ..., condition_n : valn)`` -+ Instead of embedding !if inside !if which can get cumbersome, -+ one can use !cond. !cond returns 'val1' if the result of 'int' or 'bit' -+ operator 'condition1' is nonzero. Otherwise, it checks 'condition2'. -+ If 'condition2' is nonzero, returns 'val2', and so on. -+ If all conditions are zero, it reports an error. -+ -+ Below is an example to convert an integer 'x' into a string: -+ -+ !cond(!lt(x,0) : "Negative", -+ !eq(x,0) : "Zero", -+ !eq(x,1) : "One, -+ 1 : "MoreThanOne") -+ - ``!eq(a,b)`` - 'bit 1' if string a is equal to string b, 0 otherwise. This only operates - on string, int and bit objects. Use !cast to compare other types of -diff --git a/docs/TableGen/LangRef.rst b/docs/TableGen/LangRef.rst -index 2efee12ec9d..a3dbf363151 100644 ---- a/docs/TableGen/LangRef.rst -+++ b/docs/TableGen/LangRef.rst -@@ -102,6 +102,12 @@ wide variety of meanings: - :!isa !dag !le !lt !ge - :!gt !ne - -+TableGen also has !cond operator that needs a slightly different -+syntax compared to other "bang operators": -+ -+.. productionlist:: -+ CondOperator: !cond -+ - - Syntax - ====== -@@ -140,7 +146,7 @@ considered to define the class if any of the following is true: - #. The :token:`Body` in the :token:`ObjectBody` is present and is not empty. - #. The :token:`BaseClassList` in the :token:`ObjectBody` is present. - --You can declare an empty class by giving and empty :token:`TemplateArgList` -+You can declare an empty class by giving an empty :token:`TemplateArgList` - and an empty :token:`ObjectBody`. This can serve as a restricted form of - forward declaration: note that records deriving from the forward-declared - class will inherit no fields from it since the record expansion is done -@@ -315,6 +321,8 @@ The initial :token:`DagArg` is called the "operator" of the dag. - - .. productionlist:: - SimpleValue: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")" -+ :| `CondOperator` "(" `CondVal` ("," `CondVal`)* ")" -+ CondVal: `Value` ":" `Value` - - Bodies - ------ -diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h -index e022bc82b4e..3ca67ec72bd 100644 ---- a/include/llvm/TableGen/Record.h -+++ b/include/llvm/TableGen/Record.h -@@ -316,6 +316,7 @@ protected: - IK_TernOpInit, - IK_UnOpInit, - IK_LastOpInit, -+ IK_CondOpInit, - IK_FoldOpInit, - IK_IsAOpInit, - IK_StringInit, -@@ -912,6 +913,83 @@ public: - std::string getAsString() const override; - }; - -+/// !cond(condition_1: value1, ... , condition_n: value) -+/// Selects the first value for which condition is true. -+/// Otherwise reports an error. -+class CondOpInit final : public TypedInit, public FoldingSetNode, -+ public TrailingObjects { -+ unsigned NumConds; -+ RecTy *ValType; -+ -+ CondOpInit(unsigned NC, RecTy *Type) -+ : TypedInit(IK_CondOpInit, Type), -+ NumConds(NC), ValType(Type) {} -+ -+ size_t numTrailingObjects(OverloadToken) const { -+ return 2*NumConds; -+ } -+ -+public: -+ CondOpInit(const CondOpInit &) = delete; -+ CondOpInit &operator=(const CondOpInit &) = delete; -+ -+ static bool classof(const Init *I) { -+ return I->getKind() == IK_CondOpInit; -+ } -+ -+ static CondOpInit *get(ArrayRef C, ArrayRef V, -+ RecTy *Type); -+ -+ void Profile(FoldingSetNodeID &ID) const; -+ -+ RecTy *getValType() const { return ValType; } -+ -+ unsigned getNumConds() const { return NumConds; } -+ -+ Init *getCond(unsigned Num) const { -+ assert(Num < NumConds && "Condition number out of range!"); -+ return getTrailingObjects()[Num]; -+ } -+ -+ Init *getVal(unsigned Num) const { -+ assert(Num < NumConds && "Val number out of range!"); -+ return getTrailingObjects()[Num+NumConds]; -+ } -+ -+ ArrayRef getConds() const { -+ return makeArrayRef(getTrailingObjects(), NumConds); -+ } -+ -+ ArrayRef getVals() const { -+ return makeArrayRef(getTrailingObjects()+NumConds, NumConds); -+ } -+ -+ Init *Fold(Record *CurRec) const; -+ -+ Init *resolveReferences(Resolver &R) const override; -+ -+ bool isConcrete() const override; -+ bool isComplete() const override; -+ std::string getAsString() const override; -+ -+ using const_case_iterator = SmallVectorImpl::const_iterator; -+ using const_val_iterator = SmallVectorImpl::const_iterator; -+ -+ inline const_case_iterator arg_begin() const { return getConds().begin(); } -+ inline const_case_iterator arg_end () const { return getConds().end(); } -+ -+ inline size_t case_size () const { return NumConds; } -+ inline bool case_empty() const { return NumConds == 0; } -+ -+ inline const_val_iterator name_begin() const { return getVals().begin();} -+ inline const_val_iterator name_end () const { return getVals().end(); } -+ -+ inline size_t val_size () const { return NumConds; } -+ inline bool val_empty() const { return NumConds == 0; } -+ -+ Init *getBit(unsigned Bit) const override; -+}; -+ - /// !foldl (a, b, expr, start, lst) - Fold over a list. - class FoldOpInit : public TypedInit, public FoldingSetNode { - private: -diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp -index cf1685a2e8c..26ffe761b66 100644 ---- a/lib/TableGen/Record.cpp -+++ b/lib/TableGen/Record.cpp -@@ -1694,6 +1694,137 @@ Init *FieldInit::Fold(Record *CurRec) const { - return const_cast(this); - } - -+static void ProfileCondOpInit(FoldingSetNodeID &ID, -+ ArrayRef CondRange, -+ ArrayRef ValRange, -+ const RecTy *ValType) { -+ assert(CondRange.size() == ValRange.size() && -+ "Number of conditions and values must match!"); -+ ID.AddPointer(ValType); -+ ArrayRef::iterator Case = CondRange.begin(); -+ ArrayRef::iterator Val = ValRange.begin(); -+ -+ while (Case != CondRange.end()) { -+ ID.AddPointer(*Case++); -+ ID.AddPointer(*Val++); -+ } -+} -+ -+void CondOpInit::Profile(FoldingSetNodeID &ID) const { -+ ProfileCondOpInit(ID, -+ makeArrayRef(getTrailingObjects(), NumConds), -+ makeArrayRef(getTrailingObjects() + NumConds, NumConds), -+ ValType); -+} -+ -+CondOpInit * -+CondOpInit::get(ArrayRef CondRange, -+ ArrayRef ValRange, RecTy *Ty) { -+ assert(CondRange.size() == ValRange.size() && -+ "Number of conditions and values must match!"); -+ -+ static FoldingSet ThePool; -+ FoldingSetNodeID ID; -+ ProfileCondOpInit(ID, CondRange, ValRange, Ty); -+ -+ void *IP = nullptr; -+ if (CondOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) -+ return I; -+ -+ void *Mem = Allocator.Allocate(totalSizeToAlloc(2*CondRange.size()), -+ alignof(BitsInit)); -+ CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty); -+ -+ std::uninitialized_copy(CondRange.begin(), CondRange.end(), -+ I->getTrailingObjects()); -+ std::uninitialized_copy(ValRange.begin(), ValRange.end(), -+ I->getTrailingObjects()+CondRange.size()); -+ ThePool.InsertNode(I, IP); -+ return I; -+} -+ -+Init *CondOpInit::resolveReferences(Resolver &R) const { -+ SmallVector NewConds; -+ bool Changed = false; -+ for (const Init *Case : getConds()) { -+ Init *NewCase = Case->resolveReferences(R); -+ NewConds.push_back(NewCase); -+ Changed |= NewCase != Case; -+ } -+ -+ SmallVector NewVals; -+ for (const Init *Val : getVals()) { -+ Init *NewVal = Val->resolveReferences(R); -+ NewVals.push_back(NewVal); -+ Changed |= NewVal != Val; -+ } -+ -+ if (Changed) -+ return (CondOpInit::get(NewConds, NewVals, -+ getValType()))->Fold(R.getCurrentRecord()); -+ -+ return const_cast(this); -+} -+ -+Init *CondOpInit::Fold(Record *CurRec) const { -+ for ( unsigned i = 0; i < NumConds; ++i) { -+ Init *Cond = getCond(i); -+ Init *Val = getVal(i); -+ -+ if (IntInit *CondI = dyn_cast_or_null( -+ Cond->convertInitializerTo(IntRecTy::get()))) { -+ if (CondI->getValue()) -+ return Val->convertInitializerTo(getValType()); -+ } else -+ return const_cast(this); -+ } -+ -+ PrintFatalError(CurRec->getLoc(), -+ CurRec->getName() + -+ " does not have any true condition in:" + -+ this->getAsString()); -+ return nullptr; -+} -+ -+bool CondOpInit::isConcrete() const { -+ for (const Init *Case : getConds()) -+ if (!Case->isConcrete()) -+ return false; -+ -+ for (const Init *Val : getVals()) -+ if (!Val->isConcrete()) -+ return false; -+ -+ return true; -+} -+ -+bool CondOpInit::isComplete() const { -+ for (const Init *Case : getConds()) -+ if (!Case->isComplete()) -+ return false; -+ -+ for (const Init *Val : getVals()) -+ if (!Val->isConcrete()) -+ return false; -+ -+ return true; -+} -+ -+std::string CondOpInit::getAsString() const { -+ std::string Result = "!cond("; -+ for (unsigned i = 0; i < getNumConds(); i++) { -+ Result += getCond(i)->getAsString() + ": "; -+ Result += getVal(i)->getAsString(); -+ if (i != getNumConds()-1) -+ Result += ", "; -+ } -+ return Result + ")"; -+} -+ -+Init *CondOpInit::getBit(unsigned Bit) const { -+ return VarBitInit::get(const_cast(this), Bit); -+} -+ - static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN, - ArrayRef ArgRange, - ArrayRef NameRange) { -diff --git a/lib/TableGen/TGLexer.cpp b/lib/TableGen/TGLexer.cpp -index 16aeee56107..f733cc3c134 100644 ---- a/lib/TableGen/TGLexer.cpp -+++ b/lib/TableGen/TGLexer.cpp -@@ -545,6 +545,7 @@ tgtok::TokKind TGLexer::LexExclaim() { - .Case("ge", tgtok::XGe) - .Case("gt", tgtok::XGt) - .Case("if", tgtok::XIf) -+ .Case("cond", tgtok::XCond) - .Case("isa", tgtok::XIsA) - .Case("head", tgtok::XHead) - .Case("tail", tgtok::XTail) -diff --git a/lib/TableGen/TGLexer.h b/lib/TableGen/TGLexer.h -index e9980b36b97..9bdb01cf3dd 100644 ---- a/lib/TableGen/TGLexer.h -+++ b/lib/TableGen/TGLexer.h -@@ -51,7 +51,7 @@ namespace tgtok { - - // !keywords. - XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, -- XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag, -+ XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, - XNe, XLe, XLt, XGe, XGt, - - // Integer value. -diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp -index 1d1f3603c83..200190acd59 100644 ---- a/lib/TableGen/TGParser.cpp -+++ b/lib/TableGen/TGParser.cpp -@@ -1445,6 +1445,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { - return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec); - } - -+ case tgtok::XCond: -+ return ParseOperationCond(CurRec, ItemType); -+ - case tgtok::XFoldl: { - // Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')' - Lex.Lex(); // eat the operation -@@ -1603,6 +1606,91 @@ RecTy *TGParser::ParseOperatorType() { - return Type; - } - -+Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) { -+ Lex.Lex(); // eat the operation 'cond' -+ -+ if (Lex.getCode() != tgtok::l_paren) { -+ TokError("expected '(' after !cond operator"); -+ return nullptr; -+ } -+ Lex.Lex(); // eat the '(' -+ -+ // Parse through '[Case: Val,]+' -+ SmallVector Case; -+ SmallVector Val; -+ while (true) { -+ if (Lex.getCode() == tgtok::r_paren) { -+ Lex.Lex(); // eat the ')' -+ break; -+ } -+ -+ Init *V = ParseValue(CurRec); -+ if (!V) -+ return nullptr; -+ Case.push_back(V); -+ -+ if (Lex.getCode() != tgtok::colon) { -+ TokError("expected ':' following a condition in !cond operator"); -+ return nullptr; -+ } -+ Lex.Lex(); // eat the ':' -+ -+ V = ParseValue(CurRec, ItemType); -+ if (!V) -+ return nullptr; -+ Val.push_back(V); -+ -+ if (Lex.getCode() == tgtok::r_paren) { -+ Lex.Lex(); // eat the ')' -+ break; -+ } -+ -+ if (Lex.getCode() != tgtok::comma) { -+ TokError("expected ',' or ')' following a value in !cond operator"); -+ return nullptr; -+ } -+ Lex.Lex(); // eat the ',' -+ } -+ -+ if (Case.size() < 1) { -+ TokError("there should be at least 1 'condition : value' in the !cond operator"); -+ return nullptr; -+ } -+ -+ // resolve type -+ RecTy *Type = nullptr; -+ for (Init *V : Val) { -+ RecTy *VTy = nullptr; -+ if (TypedInit *Vt = dyn_cast(V)) -+ VTy = Vt->getType(); -+ if (BitsInit *Vbits = dyn_cast(V)) -+ VTy = BitsRecTy::get(Vbits->getNumBits()); -+ if (isa(V)) -+ VTy = BitRecTy::get(); -+ -+ if (Type == nullptr) { -+ if (!isa(V)) -+ Type = VTy; -+ } else { -+ if (!isa(V)) { -+ RecTy *RType = resolveTypes(Type, VTy); -+ if (!RType) { -+ TokError(Twine("inconsistent types '") + Type->getAsString() + -+ "' and '" + VTy->getAsString() + "' for !cond"); -+ return nullptr; -+ } -+ Type = RType; -+ } -+ } -+ } -+ -+ if (!Type) { -+ TokError("could not determine type for !cond from its arguments"); -+ return nullptr; -+ } -+ return CondOpInit::get(Case, Val, Type)->Fold(CurRec); -+} -+ - /// ParseSimpleValue - Parse a tblgen value. This returns null on error. - /// - /// SimpleValue ::= IDValue -@@ -1621,6 +1709,7 @@ RecTy *TGParser::ParseOperatorType() { - /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' - /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')' - /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' -+/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')' - /// - Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, - IDParseMode Mode) { -@@ -1933,6 +2022,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, - case tgtok::XListConcat: - case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' - case tgtok::XIf: -+ case tgtok::XCond: - case tgtok::XFoldl: - case tgtok::XForEach: - case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' -diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h -index e3849043513..215b9dad770 100644 ---- a/lib/TableGen/TGParser.h -+++ b/lib/TableGen/TGParser.h -@@ -194,6 +194,7 @@ private: // Parser methods. - bool ParseRangePiece(SmallVectorImpl &Ranges); - RecTy *ParseType(); - Init *ParseOperation(Record *CurRec, RecTy *ItemType); -+ Init *ParseOperationCond(Record *CurRec, RecTy *ItemType); - RecTy *ParseOperatorType(); - Init *ParseObjectName(MultiClass *CurMultiClass); - Record *ParseClassID(); -diff --git a/test/TableGen/cond-bitlist.td b/test/TableGen/cond-bitlist.td -new file mode 100644 -index 00000000000..bce615838df ---- /dev/null -+++ b/test/TableGen/cond-bitlist.td -@@ -0,0 +1,27 @@ -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+class S { -+ bits<2> val = !cond(!eq(s, 8): {0, 0}, -+ !eq(s, 16): 0b01, -+ !eq(s, 32): 2, -+ !eq(s, 64): {1, 1}, -+ 1 : ?); -+} -+ -+def D8 : S<8>; -+def D16 : S<16>; -+def D32 : S<32>; -+def D64 : S<64>; -+def D128: S<128>; -+// CHECK: def D128 -+// CHECK-NEXT: bits<2> val = { ?, ? }; -+// CHECK: def D16 -+// CHECK-NEXT: bits<2> val = { 0, 1 }; -+// CHECK: def D32 -+// CHECK-NEXT: bits<2> val = { 1, 0 }; -+// CHECK: def D64 -+// CHECK-NEXT: bits<2> val = { 1, 1 }; -+// CHECK: def D8 -+// CHECK-NEXT: bits<2> val = { 0, 0 }; -+ -diff --git a/test/TableGen/cond-default.td b/test/TableGen/cond-default.td -new file mode 100644 -index 00000000000..816bf10676f ---- /dev/null -+++ b/test/TableGen/cond-default.td -@@ -0,0 +1,11 @@ -+// Check that not specifying a valid condition results in error -+ -+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s -+// XFAIL: vg_leak -+ -+class C { -+ string s = !cond(!lt(x,0) : "negative", !gt(x,0) : "positive"); -+} -+ -+def Zero : C<0>; -+//CHECK: error: Zero does not have any true condition in:!cond(0: "negative", 0: "positive") -diff --git a/test/TableGen/cond-empty-list-arg.td b/test/TableGen/cond-empty-list-arg.td -new file mode 100644 -index 00000000000..5f4ccade169 ---- /dev/null -+++ b/test/TableGen/cond-empty-list-arg.td -@@ -0,0 +1,8 @@ -+// RUN: llvm-tblgen %s -+// XFAIL: vg_leak -+ -+class C { -+ bit true = 1; -+ list X = !cond(cond: [1, 2, 3], true : []); -+ list Y = !cond(cond: [], true : [4, 5, 6]); -+} -diff --git a/test/TableGen/cond-inheritance.td b/test/TableGen/cond-inheritance.td -new file mode 100644 -index 00000000000..4b4abdf72f3 ---- /dev/null -+++ b/test/TableGen/cond-inheritance.td -@@ -0,0 +1,22 @@ -+// Make sure !cond gets propagated across multiple layers of inheritance. -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+class getInt { -+ int ret = !cond(c: 0, 1 : 1); -+} -+ -+class I1 { -+ int i = getInt.ret; -+} -+ -+class I2 : I1; -+ -+def DI1: I1<1>; -+// CHECK: def DI1 { // I1 -+// CHECK-NEXT: int i = 0; -+ -+// CHECK: def DI2 { // I1 I2 -+// CHECK-NEXT: int i = 0; -+def DI2: I2<1>; -+ -diff --git a/test/TableGen/cond-let.td b/test/TableGen/cond-let.td -new file mode 100644 -index 00000000000..044878f2ab8 ---- /dev/null -+++ b/test/TableGen/cond-let.td -@@ -0,0 +1,36 @@ -+// Check support for `!cond' operator as part of a `let' statement. -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+ -+class C x, bits<4> y, bit z> { -+ bits<16> n; -+ -+ let n{11} = !cond(y{3}: 1, -+ y{2}: x{0}, -+ y{1}: x{1}, -+ y{0}: x{2}, -+ {1} :?); -+ let n{10-9}= !cond(x{2}: y{3-2}, -+ x{1}: y{2-1}, -+ x{1}: y{1-0}, -+ {1} : ?); -+ let n{8-6} = !cond(x{2}: 0b010, 1 : 0b110); -+ let n{5-4} = !cond(x{1}: y{3-2}, 1 : {0, 1}); -+ let n{3-0} = !cond(x{0}: y{3-0}, 1 : {z, y{2}, y{1}, y{0}}); -+} -+ -+ -+def C1 : C<{1, 0, 1}, {0, 1, 0, 1}, 0>; -+def C2 : C<{0, 1, 0}, {1, 0, 1, 0}, 1>; -+def C3 : C<{0, 0, 0}, {1, 0, 1, 0}, 0>; -+def C4 : C<{0, 0, 0}, {0, 0, 0, 0}, 0>; -+ -+// CHECK: def C1 -+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }; -+// CHECK: def C2 -+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0 }; -+// CHECK: def C3 -+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, ?, ?, 1, 1, 0, 0, 1, 0, 0, 1, 0 }; -+// CHECK: def C4 -+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, 1, 1, 0, 0, 1, 0, 0, 0, 0 }; -diff --git a/test/TableGen/cond-list.td b/test/TableGen/cond-list.td -new file mode 100644 -index 00000000000..aa013cea4e1 ---- /dev/null -+++ b/test/TableGen/cond-list.td -@@ -0,0 +1,38 @@ -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+ -+class A> vals> { -+ list first = vals[0]; -+ list rest = !cond(!empty(!tail(vals)): vals[0], -+ 1 : vals[1]); -+} -+ -+def A_OneEl : A<[[1,2,3]]>; -+// CHECK: def A_OneEl { // A -+// CHECK-NEXT: list first = [1, 2, 3]; -+// CHECK-NEXT: list rest = [1, 2, 3]; -+// CHECK-NEXT: } -+ -+def A_TwoEl : A<[[1,2,3], [4,5,6]]>; -+// CHECK: def A_TwoEl { // A -+// CHECK-NEXT: list first = [1, 2, 3]; -+// CHECK-NEXT: list rest = [4, 5, 6]; -+// CHECK-NEXT: } -+ -+ -+class B v> { -+ list vals = v; -+} -+class BB> vals> : B; -+class BBB> vals> : BB; -+ -+def B_OneEl : BBB<[[1,2,3]]>; -+// CHECK: def B_OneEl { // B BB BBB -+// CHECK-NEXT: list vals = [1, 2, 3]; -+// CHECK-NEXT: } -+ -+def B_TwoEl : BBB<[[1,2,3],[4,5,6]]>; -+// CHECK: def B_TwoEl { // B BB BBB -+// CHECK-NEXT: list vals = [4, 5, 6]; -+// CHECK-NEXT: } -diff --git a/test/TableGen/cond-subclass.td b/test/TableGen/cond-subclass.td -new file mode 100644 -index 00000000000..9f6f6e2cb8c ---- /dev/null -+++ b/test/TableGen/cond-subclass.td -@@ -0,0 +1,27 @@ -+// Check that !cond with operands of different subtypes can -+// initialize a supertype variable. -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+class E {} -+class E1 : E {} -+class E2 : E {} -+ -+class EX { -+ E x = !cond(cc: b, 1 : c); -+} -+ -+def E1d : E1<0>; -+def E2d : E2<0>; -+ -+def EXd1 : EX<1, E1d, E2d>; -+def EXd2 : EX<0, E1d, E2d>; -+ -+// CHECK: def EXd1 { -+// CHECK: E x = E1d; -+// CHECK: } -+// -+// CHECK: def EXd2 { -+// CHECK: E x = E2d; -+// CHECK: } -+ -diff --git a/test/TableGen/cond-type.td b/test/TableGen/cond-type.td -new file mode 100644 -index 00000000000..fd2a3cc52b7 ---- /dev/null -+++ b/test/TableGen/cond-type.td -@@ -0,0 +1,11 @@ -+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s -+// XFAIL: vg_leak -+ -+class A {} -+class B : A {} -+class C : A {} -+ -+// CHECK: Value 'x' of type 'C' is incompatible with initializer '{{.*}}' of type 'A' -+class X { -+ C x = !cond(cc: b, 1 : c); -+} -diff --git a/test/TableGen/cond-usage.td b/test/TableGen/cond-usage.td -new file mode 100644 -index 00000000000..055fd6d7c69 ---- /dev/null -+++ b/test/TableGen/cond-usage.td -@@ -0,0 +1,29 @@ -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+ -+// Check that !cond picks the first true value -+// CHECK: class A -+// CHECK-NEXT: string S = !cond(!eq(A:x, 10): "ten", !eq(A:x, 11): "eleven", !eq(A:x, 10): "TEN", !gt(A:x, 9): "MoreThanNine", 1: "unknown"); -+// CHECK: B1 -+// CHECK-NEXT: string S = "unknown" -+// CHECK: B10 -+// CHECK-NEXT: string S = "ten"; -+// CHECK: def B11 -+// CHECK-NEXT: string S = "eleven"; -+// CHECK: def B12 -+// CHECK-NEXT: string S = "MoreThanNine"; -+// CHECK: def B9 -+// CHECK-NEXT: string S = "unknown" -+ -+class A { -+ string S = !cond(!eq(x,10) : "ten", -+ !eq(x,11) : "eleven", -+ !eq(x,10) : "TEN", -+ !gt(x,9) : "MoreThanNine", -+ !eq(1,1) : "unknown"); -+} -+def B1 : A<1>; -+def B9 : A<9>; -+def B10 : A<10>; -+def B11 : A<11>; -+def B12 : A<12>; -diff --git a/test/TableGen/condsbit.td b/test/TableGen/condsbit.td -new file mode 100644 -index 00000000000..e08ac97f68b ---- /dev/null -+++ b/test/TableGen/condsbit.td -@@ -0,0 +1,15 @@ -+// check that !cond works well with bit conditional values -+// RUN: llvm-tblgen %s | FileCheck %s -+// XFAIL: vg_leak -+// CHECK: a = 6 -+// CHECK: a = 5 -+ -+class A { -+ bit true = 1; -+ int a = !cond(b: 5, true : 6); -+ bit c = !cond(b: 0, true : 1); -+ bits<1> d = !cond(b: 0, true : 1); -+} -+ -+def X : A<0>; -+def Y : A; --- -2.17.1 - diff --git a/deps/patches/llvm-8.0-D59389-refactor-wmma.patch b/deps/patches/llvm-8.0-D59389-refactor-wmma.patch deleted file mode 100644 index 31af5246715a1..0000000000000 --- a/deps/patches/llvm-8.0-D59389-refactor-wmma.patch +++ /dev/null @@ -1,899 +0,0 @@ -From e9737bf498597707d084398b9485676dc7421644 Mon Sep 17 00:00:00 2001 -From: Artem Belevich -Date: Thu, 25 Apr 2019 22:27:35 +0000 -Subject: [PATCH] [NVPTX] Refactor generation of MMA intrinsics and - instructions. NFC. - -Generalized constructions of 'fragments' of MMA operations to provide -common primitives for construction of the ops. This will make it easier -to add new variants of the instructions that operate on integer types. - -Use nested foreach loops which makes it possible to better control -naming of the intrinsics. - -This patch does not affect LLVM's output, so there are no test changes. - -Differential Revision: https://reviews.llvm.org/D59389 - -llvm-svn: 359245 ---- - include/llvm/IR/IntrinsicsNVVM.td | 258 ++++++-------- - lib/Target/NVPTX/NVPTXIntrinsics.td | 512 ++++++++++------------------ - 2 files changed, 295 insertions(+), 475 deletions(-) - -diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td -index 7f694f68969..e30a27613a6 100644 ---- a/include/llvm/IR/IntrinsicsNVVM.td -+++ b/include/llvm/IR/IntrinsicsNVVM.td -@@ -38,6 +38,69 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType; // (space)i64* - // MISC - // - -+// Helper class for construction of n-element list [t,t,...,t] -+class RepLLVMType { -+ list ret = !if(N, !listconcat(RepLLVMType.ret, [T]), []); -+} -+ -+// Helper class that represents a 'fragment' of an NVPTX *MMA instruction. -+// Geom: mnk. E.g. m8n32k16 -+// Frag: [abcd] -+// PtxEltType: PTX type for the element. -+class WMMA_REGS { -+ string geom = Geom; -+ string frag = Frag; -+ string ptx_elt_type = PtxEltType; -+ string ft = frag#":"#ptx_elt_type; -+ list regs = !cond( -+ // fp16 -> fp16/fp32 @ m16n16k16/m8n32k16/m32n8k16 -+ // All currently supported geometries use the same fragment format, -+ // so we only need to consider {fragment, type}. -+ !eq(ft,"a:f16") : RepLLVMType<8, llvm_v2f16_ty>.ret, -+ !eq(ft,"b:f16") : RepLLVMType<8, llvm_v2f16_ty>.ret, -+ !eq(ft,"c:f16") : RepLLVMType<4, llvm_v2f16_ty>.ret, -+ !eq(ft,"d:f16") : RepLLVMType<4, llvm_v2f16_ty>.ret, -+ !eq(ft,"c:f32") : RepLLVMType<8, llvm_float_ty>.ret, -+ !eq(ft,"d:f32") : RepLLVMType<8, llvm_float_ty>.ret); -+} -+ -+class WMMA_NAME_LDST { -+ string intr = "llvm.nvvm.wmma." -+ # Frag.geom -+ # "." # Op -+ # "." # Frag.frag -+ # "." # Layout -+ # !if(WithStride, ".stride", "") -+ # "." # Frag.ptx_elt_type -+ ; -+ // TODO(tra): record name should ideally use the same field order as the intrinsic. -+ // E.g. string record = !subst("llvm", "int", -+ // !subst(".", "_", llvm)); -+ string record = "int_nvvm_wmma_" -+ # Frag.geom -+ # "_" # Op -+ # "_" # Frag.frag -+ # "_" # Frag.ptx_elt_type -+ # "_" # Layout -+ # !if(WithStride, "_stride", ""); -+} -+ -+class WMMA_NAME_MMA { -+ string llvm = "llvm.nvvm.wmma." -+ # C.geom -+ # ".mma" -+ # "." # ALayout -+ # "." # BLayout -+ # "." # D.ptx_elt_type // Intrinsic encodes 'd' first. -+ # "." # C.ptx_elt_type -+ # !if(Satfinite, ".satfinite", ""); -+ -+ string record = !subst(".", "_", -+ !subst("llvm.", "int_", llvm)); -+} -+ - let TargetPrefix = "nvvm" in { - def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], -@@ -3882,166 +3945,69 @@ def int_nvvm_match_all_sync_i64p : - // - // WMMA instructions - // -- - // WMMA.LOAD --class NVVM_WMMA_LD_GALSTS -- : Intrinsic -+ : Intrinsic, NoCapture<0>], -- "llvm.nvvm.wmma." -- # Geometry -- # ".load" -- # "." # Abc -- # "." # Layout -- # !if(WithStride, ".stride", "") -- # "." # Type>; -- --multiclass NVVM_WMMA_LD_GALT { -- def _stride: NVVM_WMMA_LD_GALSTS; -- def NAME : NVVM_WMMA_LD_GALSTS; --} -- --multiclass NVVM_WMMA_LD_GAT { -- defm _row: NVVM_WMMA_LD_GALT; -- defm _col: NVVM_WMMA_LD_GALT; --} -- --multiclass NVVM_WMMA_LD_G { -- defm _a_f16: NVVM_WMMA_LD_GAT; -- defm _b_f16: NVVM_WMMA_LD_GAT; -- defm _c_f16: NVVM_WMMA_LD_GAT; -- defm _c_f32: NVVM_WMMA_LD_GAT; --} -- --multiclass NVVM_WMMA_LD { -- defm _m32n8k16_load: NVVM_WMMA_LD_G<"m32n8k16">; -- defm _m16n16k16_load: NVVM_WMMA_LD_G<"m16n16k16">; -- defm _m8n32k16_load: NVVM_WMMA_LD_G<"m8n32k16">; --} -- --defm int_nvvm_wmma: NVVM_WMMA_LD; -+ WMMA_NAME_LDST<"load", Frag, Layout, WithStride>.intr>; - - // WMMA.STORE.D --class NVVM_WMMA_STD_GLSTSEmpty=[]> -+class NVVM_WMMA_ST - : Intrinsic<[], - !listconcat( - [llvm_anyptr_ty], -- !if(!eq(Type,"f16"), -- [regty, regty, regty, regty], -- [regty, regty, regty, regty, -- regty, regty, regty, regty]), -- !if(WithStride, [llvm_i32_ty], Empty)), -+ Frag.regs, -+ !if(WithStride, [llvm_i32_ty], [])), - [IntrWriteMem, IntrArgMemOnly, WriteOnly<0>, NoCapture<0>], -- "llvm.nvvm.wmma." -- # Geometry -- # ".store.d" -- # "." # Layout -- # !if(WithStride, ".stride", "") -- # "." # Type>; -- --multiclass NVVM_WMMA_STD_GLT { -- def _stride: NVVM_WMMA_STD_GLSTS; -- def NAME: NVVM_WMMA_STD_GLSTS; --} -- --multiclass NVVM_WMMA_STD_GT { -- defm _row: NVVM_WMMA_STD_GLT; -- defm _col: NVVM_WMMA_STD_GLT; --} --multiclass NVVM_WMMA_STD_G { -- defm _d_f16: NVVM_WMMA_STD_GT; -- defm _d_f32: NVVM_WMMA_STD_GT; --} -- --multiclass NVVM_WMMA_STD { -- defm _m32n8k16_store: NVVM_WMMA_STD_G<"m32n8k16">; -- defm _m16n16k16_store: NVVM_WMMA_STD_G<"m16n16k16">; -- defm _m8n32k16_store: NVVM_WMMA_STD_G<"m8n32k16">; -+ WMMA_NAME_LDST<"store", Frag, Layout, WithStride>.intr>; -+ -+// Create all load/store variants -+foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout = ["row", "col"] in { -+ foreach stride = [0, 1] in { -+ foreach frag = [WMMA_REGS, -+ WMMA_REGS, -+ WMMA_REGS, -+ WMMA_REGS] in { -+ def WMMA_NAME_LDST<"load", frag, layout, stride>.record -+ : NVVM_WMMA_LD; -+ } -+ foreach frag = [WMMA_REGS, -+ WMMA_REGS] in { -+ def WMMA_NAME_LDST<"store", frag, layout, stride>.record -+ : NVVM_WMMA_ST; -+ } -+ } -+ } - } - --defm int_nvvm_wmma: NVVM_WMMA_STD; -- - // WMMA.MMA --class NVVM_WMMA_MMA_GABDCS -- : Intrinsic -+ : Intrinsic.regs, -+ WMMA_REGS.regs, -+ C.regs), - [IntrNoMem], -- "llvm.nvvm.wmma." -- # Geometry -- # ".mma" -- # "." # ALayout -- # "." # BLayout -- # "." # DType -- # "." # CType -- # Satfinite> { --} -- --multiclass NVVM_WMMA_MMA_GABDC { -- def NAME : NVVM_WMMA_MMA_GABDCS; -- def _satfinite: NVVM_WMMA_MMA_GABDCS; --} -- --multiclass NVVM_WMMA_MMA_GABD { -- defm _f16: NVVM_WMMA_MMA_GABDC; -- defm _f32: NVVM_WMMA_MMA_GABDC; --} -- --multiclass NVVM_WMMA_MMA_GAB { -- defm _f16: NVVM_WMMA_MMA_GABD; -- defm _f32: NVVM_WMMA_MMA_GABD; --} -- --multiclass NVVM_WMMA_MMA_GA { -- defm _col: NVVM_WMMA_MMA_GAB; -- defm _row: NVVM_WMMA_MMA_GAB; --} -- --multiclass NVVM_WMMA_MMA_G { -- defm _col: NVVM_WMMA_MMA_GA; -- defm _row: NVVM_WMMA_MMA_GA; --} -- --multiclass NVVM_WMMA_MMA { -- defm _m32n8k16_mma : NVVM_WMMA_MMA_G<"m32n8k16">; -- defm _m16n16k16_mma : NVVM_WMMA_MMA_G<"m16n16k16">; -- defm _m8n32k16_mma : NVVM_WMMA_MMA_G<"m8n32k16">; -+ WMMA_NAME_MMA.llvm>; -+ -+foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout_a = ["row", "col"] in { -+ foreach layout_b = ["row", "col"] in { -+ foreach frag_c = [WMMA_REGS, -+ WMMA_REGS] in { -+ foreach frag_d = [WMMA_REGS, -+ WMMA_REGS] in { -+ foreach satf = [0, 1] in { -+ def WMMA_NAME_MMA.record -+ : NVVM_WMMA_MMA; -+ } -+ } -+ } -+ } -+ } - } - --defm int_nvvm_wmma : NVVM_WMMA_MMA; -- - } // let TargetPrefix = "nvvm" -diff --git a/lib/Target/NVPTX/NVPTXIntrinsics.td b/lib/Target/NVPTX/NVPTXIntrinsics.td -index 47dcdcf6e0b..b9a67ba5ed3 100644 ---- a/lib/Target/NVPTX/NVPTXIntrinsics.td -+++ b/lib/Target/NVPTX/NVPTXIntrinsics.td -@@ -27,7 +27,17 @@ def immDouble1 : PatLeaf<(fpimm), [{ - return (d==1.0); - }]>; - -- -+def AS_match { -+ code generic = [{ -+ return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GENERIC); -+ }]; -+ code shared = [{ -+ return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_SHARED); -+ }]; -+ code global = [{ -+ return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GLOBAL); -+ }]; -+} - - //----------------------------------- - // Synchronization and shuffle functions -@@ -1007,17 +1017,11 @@ def INT_FNS_iii : INT_FNS_MBO<(ins i32imm:$mask, i32imm:$base, i32imm:$ - //----------------------------------- - - class ATOMIC_GLOBAL_CHK -- : PatFrag; -+ : PatFrag; - class ATOMIC_SHARED_CHK -- : PatFrag; -+ : PatFrag; - class ATOMIC_GENERIC_CHK -- : PatFrag; -+ : PatFrag; - - multiclass F_ATOMIC_2_imp; - --// --// wmma.load.[a|b|c].sync.[row|col].m16n16k16[|.global|.shared].[f16|f32] --// -- - class EmptyNVPTXInst : NVPTXInst<(outs), (ins), "?", []>; -+// Generates list of n sequential register names. -+class RegSeq { -+ list ret = !if(n, !listconcat(RegSeq.ret, -+ [prefix # !add(n, -1)]), -+ []); -+} - --class WMMA_LOAD_GALSTOS -- : EmptyNVPTXInst, -- Requires<[!if(!eq(Geometry, "m16n16k16"), -- hasPTX60, -- hasPTX61), -- hasSM70]> { -- // Pattern (created by WMMA_LOAD_INTR_HELPER below) that matches the intrinsic -- // for this function. -- PatFrag IntrMatcher = !cast("INT_WMMA_" -- # Geometry # "_load_" -- # !subst("c", "c_" # Type, Abc) -- # "_" # Layout -- # !subst(".", "_", Space) -- # !if(WithStride,"_stride", "") -- # "_Intr"); -- dag OutsR03 = (outs regclass:$r0, regclass:$r1, regclass:$r2, regclass:$r3); -- dag OutsR47 = (outs regclass:$r4, regclass:$r5, regclass:$r6, regclass:$r7); -- dag Outs = !if(!eq(Abc#Type,"cf16"), OutsR03, !con(OutsR03, OutsR47)); -- -- dag StrideArg = !if(WithStride, (ins Int32Regs:$ldm), (ins)); -- dag Ins = !con((ins SrcOp:$src), StrideArg); -+// Helper class that represents a 'fragment' of an NVPTX *MMA instruction. -+// In addition to target-independent fields provided by WMMA_REGS, it adds -+// the fields commonly used to implement specific PTX instruction -- register -+// types and names, constraints, parts of assembly, etc. -+class WMMA_REGINFO -+ : WMMA_REGS { -+ // NVPTX register types used to carry fragment data. -+ NVPTXRegClass regclass = !cond( -+ !eq(PtxEltType, "f16") : Float16x2Regs, -+ !eq(PtxEltType, "f32") : Float32Regs); -+ -+ // Instruction input/output arguments for the fragment. -+ list ptx_regs = !foreach(tmp, regs, regclass); -+ -+ // List of register names for the fragment -- ["ra0", "ra1",...] -+ list reg_names = RegSeq.ret; -+ // Generates "{{$r0, $r1,.... $rN-1}}" for use in asm string construction. -+ string regstring = "{{$" # !head(reg_names) -+ # !foldl("", !tail(reg_names), a, b, -+ !strconcat(a, ", $", b)) -+ # "}}"; -+ -+ // Predicates for particular fragment variant. Technically those are -+ // per-instruction predicates, but currently all fragments that can be used in -+ // a given instruction are subject to the same constraints, so an instruction -+ // can use predicates from any of its fragments. If/when this is no -+ // longer the case, we can concat all per-fragment predicates to enforce that -+ // all fragments of the instruction are viable. -+ list Predicates = !cond( -+ // fp16 -> fp16/fp32 @ m16n16k16 -+ !and(!eq(Geom, "m16n16k16"), -+ !or(!eq(PtxEltType, "f16"), -+ !eq(PtxEltType, "f32"))) : [hasSM70, hasPTX60], -+ -+ // fp16 -> fp16/fp32 @ m8n32k16/m32n8k16 -+ !and(!or(!eq(Geom, "m8n32k16"), -+ !eq(Geom, "m32n8k16")), -+ !or(!eq(PtxEltType, "f16"), -+ !eq(PtxEltType, "f32"))) : [hasSM70, hasPTX61]); -+ -+ // template DAGs for instruction inputs/output. -+ dag Outs = !dag(outs, ptx_regs, reg_names); -+ dag Ins = !dag(ins, ptx_regs, reg_names); -+} - -+class BuildPattern { - // Build a dag pattern that matches the intrinsic call. - // We want a dag that looks like this: - // (set , (intrinsic )) where input and -@@ -7431,277 +7459,127 @@ class WMMA_LOAD_GALSTOS -+// -+// wmma.load.[a|b|c].sync.[row|col].m16n16k16[|.global|.shared].[f16|f32] -+// -+ -+class WMMA_LOAD_INTR_HELPER - : PatFrag <(ops),(ops)> { - // Intrinsic that matches this instruction. -- Intrinsic Intr = !cast("int_nvvm_wmma" -- # "_" # Geometry # "_load_" -- # Abc # "_" # Type # "_" # Layout -- # !if(WithStride,"_stride", "")); -- code match_generic = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GENERIC); -- }]; -- code match_shared = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_SHARED); -- }]; -- code match_global = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GLOBAL); -- }]; -- -+ Intrinsic Intr = !cast(WMMA_NAME_LDST<"load", Frag, Layout, -+ WithStride>.record); - let Operands = !if(WithStride, (ops node:$src, node:$ldm), (ops node:$src)); - let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))]; -- let PredicateCode = !if(!eq(Space, ".shared"), match_shared, -- !if(!eq(Space, ".global"), match_global, match_generic)); --} -- --multiclass WMMA_LOAD_GALSTS { -- def _avar: WMMA_LOAD_GALSTOS; -- def _areg: WMMA_LOAD_GALSTOS; -- def _areg64: WMMA_LOAD_GALSTOS; -- def _ari: WMMA_LOAD_GALSTOS; -- def _ari64: WMMA_LOAD_GALSTOS; -+ let PredicateCode = !cond(!eq(Space, ".shared"): AS_match.shared, -+ !eq(Space, ".global"): AS_match.global, -+ 1: AS_match.generic); - } - --multiclass WMMA_LOAD_GALSTSh { -- // Define a PatFrag that matches appropriate intrinsic that loads from the -- // given address space. -- def _Intr: WMMA_LOAD_INTR_HELPER; -- defm NAME: WMMA_LOAD_GALSTS; --} -- --multiclass WMMA_LOAD_GALST { -- defm _stride: WMMA_LOAD_GALSTSh; -- defm NAME: WMMA_LOAD_GALSTSh; --} -- --multiclass WMMA_LOAD_GALT { -- defm _global: WMMA_LOAD_GALST; -- defm _shared: WMMA_LOAD_GALST; -- defm NAME: WMMA_LOAD_GALST; --} -- --multiclass WMMA_LOAD_GAT { -- defm _row: WMMA_LOAD_GALT; -- defm _col: WMMA_LOAD_GALT; --} -+class WMMA_LOAD -+ : EmptyNVPTXInst, -+ Requires { -+ // Pattern that matches the intrinsic for this instruction variant. -+ PatFrag IntrMatcher = WMMA_LOAD_INTR_HELPER; -+ dag Ins = !con((ins SrcOp:$src), !if(WithStride, (ins Int32Regs:$ldm), (ins))); - --multiclass WMMA_LOAD_G { -- defm _load_a: WMMA_LOAD_GAT; -- defm _load_b: WMMA_LOAD_GAT; -- defm _load_c_f16: WMMA_LOAD_GAT; -- defm _load_c_f32: WMMA_LOAD_GAT; -+ let Pattern = [BuildPattern.ret]; -+ let OutOperandList = Frag.Outs; -+ let InOperandList = Ins; -+ let AsmString = "wmma.load." -+ # Frag.frag -+ # ".sync" -+ # "." # Layout -+ # "." # Frag.geom -+ # Space -+ # "." # Frag.ptx_elt_type # " \t" -+ # Frag.regstring -+ # ", [$src]" -+ # !if(WithStride, ", $ldm", "") -+ # ";"; - } - --defm INT_WMMA_m32n8k16: WMMA_LOAD_G<"m32n8k16">; --defm INT_WMMA_m16n16k16: WMMA_LOAD_G<"m16n16k16">; --defm INT_WMMA_m8n32k16: WMMA_LOAD_G<"m8n32k16">; -- - // - // wmma.store.d.sync.[row|col].m16n16k16[|.global|.shared].[f16|f32] - // --class WMMA_STORE_D_GLSTSO -+class WMMA_STORE_INTR_HELPER -+ : PatFrag <(ops),(ops)> { -+ // Intrinsic that matches this instruction. -+ Intrinsic Intr = !cast(WMMA_NAME_LDST<"store", Frag, Layout, -+ WithStride>.record); -+ let Operands = !con((ops node:$dst), -+ !dag(ops, !foreach(tmp, Frag.regs, node), Frag.reg_names), -+ !if(WithStride, (ops node:$ldm), (ops))); -+ let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))]; -+ let PredicateCode = !cond(!eq(Space, ".shared"): AS_match.shared, -+ !eq(Space, ".global"): AS_match.global, -+ 1: AS_match.generic); -+} -+ -+class WMMA_STORE - : EmptyNVPTXInst, -- Requires<[!if(!eq(Geometry, "m16n16k16"), -- hasPTX60, -- hasPTX61), -- hasSM70]> { -- PatFrag IntrMatcher = !cast("INT_WMMA" -- # "_" # Geometry # "_store_d" -- # "_" # Type -- # "_" # Layout -- # !subst(".", "_", Space) -- # !if(WithStride,"_stride", "") -- # "_Intr"); -- dag InsR03 = (ins DstOp:$src, regclass:$r0, regclass:$r1, -- regclass:$r2, regclass:$r3); -- dag InsR47 = (ins regclass:$r4, regclass:$r5, -- regclass:$r6, regclass:$r7); -- dag InsR = !if(!eq(Type,"f16"), InsR03, !con(InsR03, InsR47)); -- dag StrideArg = !if(WithStride, (ins Int32Regs:$ldm), (ins)); -- dag Ins = !con(InsR, StrideArg); -- -- // Construct the pattern to match corresponding intrinsic call. See the -- // details in the comments in WMMA_LOAD_ALSTOS. -- dag PatArgs = !foreach(tmp, Ins, -- !subst(imem, ADDRvar, -- !subst(MEMri64, ADDRri64, -- !subst(MEMri, ADDRri, -- !subst(ins, IntrMatcher, tmp))))); -- let Pattern = [PatArgs]; -+ Requires { -+ PatFrag IntrMatcher = WMMA_STORE_INTR_HELPER; -+ dag Ins = !con((ins DstOp:$src), -+ Frag.Ins, -+ !if(WithStride, (ins Int32Regs:$ldm), (ins))); -+ let Pattern = [BuildPattern<(set), IntrMatcher, Ins>.ret]; - let OutOperandList = (outs); - let InOperandList = Ins; - let AsmString = "wmma.store.d.sync." - # Layout -- # "." # Geometry -+ # "." # Frag.geom - # Space -- # "." # Type -+ # "." # Frag.ptx_elt_type - # " \t[$src]," -- # !if(!eq(Type,"f16"), -- "{{$r0, $r1, $r2, $r3}}", -- "{{$r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7}}") -+ # Frag.regstring - # !if(WithStride, ", $ldm", "") - # ";"; -- - } - --class WMMA_STORE_INTR_HELPER -- : PatFrag <(ops),(ops)> { -- // Intrinsic that matches this instruction. -- Intrinsic Intr = !cast("int_nvvm_wmma_" -- # Geometry -- # "_store_d" -- # "_" # Type -- # "_" # Layout -- # !if(WithStride, "_stride", "")); -- code match_generic = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GENERIC); -- }]; -- code match_shared = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_SHARED); -- }]; -- code match_global = [{ -- return ChkMemSDNodeAddressSpace(N, llvm::ADDRESS_SPACE_GLOBAL); -- }]; -- -- dag Args = !if(!eq(Type,"f16"), -- (ops node:$dst, node:$r0, node:$r1, node:$r2, node:$r3), -- (ops node:$dst, node:$r0, node:$r1, node:$r2, node:$r3, -- node:$r4, node:$r5, node:$r6, node:$r7)); -- dag StrideArg = !if(WithStride, (ops node:$ldm), (ops)); -- let Operands = !con(Args, StrideArg); -- let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))]; -- let PredicateCode = !if(!eq(Space, ".shared"), match_shared, -- !if(!eq(Space, ".global"), match_global, match_generic)); --} -- --multiclass WMMA_STORE_D_GLSTS { -- def _avar: WMMA_STORE_D_GLSTSO; -- def _areg: WMMA_STORE_D_GLSTSO; -- def _areg64: WMMA_STORE_D_GLSTSO; -- def _ari: WMMA_STORE_D_GLSTSO; -- def _ari64: WMMA_STORE_D_GLSTSO; --} -- --multiclass WMMA_STORE_D_GLSTSh { -- // Define a PatFrag that matches appropriate intrinsic that loads from the -- // given address space. -- def _Intr: WMMA_STORE_INTR_HELPER; -- defm NAME: WMMA_STORE_D_GLSTS; --} -- --multiclass WMMA_STORE_D_GLST { -- defm _stride: WMMA_STORE_D_GLSTSh; -- defm NAME: WMMA_STORE_D_GLSTSh; --} -- --multiclass WMMA_STORE_D_GLT { -- defm _global: WMMA_STORE_D_GLST; -- defm _shared: WMMA_STORE_D_GLST; -- defm NAME: WMMA_STORE_D_GLST; --} -- --multiclass WMMA_STORE_D_GT { -- defm _row: WMMA_STORE_D_GLT; -- defm _col: WMMA_STORE_D_GLT; --} -- --multiclass WMMA_STORE_D_G { -- defm _store_d_f16: WMMA_STORE_D_GT; -- defm _store_d_f32: WMMA_STORE_D_GT; --} -- --defm INT_WMMA_m32n8k16: WMMA_STORE_D_G<"m32n8k16">; --defm INT_WMMA_m16n16k16: WMMA_STORE_D_G<"m16n16k16">; --defm INT_WMMA_m8n32k16: WMMA_STORE_D_G<"m8n32k16">; -+// Create all load/store variants -+foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout = ["row", "col"] in { -+ foreach stride = [0, 1] in { -+ foreach space = [".global", ".shared", ""] in { -+ foreach addr = [imem, Int32Regs, Int64Regs, MEMri, MEMri64] in { -+ foreach frag = [WMMA_REGINFO, -+ WMMA_REGINFO, -+ WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ def : WMMA_LOAD; -+ } -+ foreach frag = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ def : WMMA_STORE; -+ } -+ } // addr -+ } // space -+ } // stride -+ } // layout -+} // geom - - // WMMA.MMA --class WMMA_MMA_GABDCS -+class WMMA_MMA - : EmptyNVPTXInst, -- Requires<[!if(!eq(Geometry, "m16n16k16"), -- hasPTX60, -- hasPTX61), -- hasSM70]> { -- Intrinsic Intr = !cast("int_nvvm_wmma_" -- # Geometry -- # "_mma" -- # "_" # ALayout -- # "_" # BLayout -- # "_" # DType -- # "_" # CType -- # !subst(".", "_", Satfinite)); -- dag Outs = !if(!eq(DType,"f16"), -- (outs d_reg:$d0, d_reg:$d1, d_reg:$d2, d_reg:$d3), -- (outs d_reg:$d0, d_reg:$d1, d_reg:$d2, d_reg:$d3, -- d_reg:$d4, d_reg:$d5, d_reg:$d6, d_reg:$d7)); -- dag InsExtraCArgs = !if(!eq(CType,"f16"), -- (ins), -- (ins c_reg:$c4, c_reg:$c5, c_reg:$c6, c_reg:$c7)); -- dag Ins = !con((ins ab_reg:$a0, ab_reg:$a1, ab_reg:$a2, ab_reg:$a3, -- ab_reg:$a4, ab_reg:$a5, ab_reg:$a6, ab_reg:$a7, -- ab_reg:$b0, ab_reg:$b1, ab_reg:$b2, ab_reg:$b3, -- ab_reg:$b4, ab_reg:$b5, ab_reg:$b6, ab_reg:$b7, -- c_reg:$c0, c_reg:$c1, c_reg:$c2, c_reg:$c3), -- InsExtraCArgs); -- -- // Construct the pattern to match corresponding intrinsic call. See the -- // details in the comments in WMMA_LOAD_ALSTOS. -+ Requires { -+ //Intrinsic Intr = int_nvvm_suld_1d_v4i32_zero; -+ Intrinsic Intr = !cast(WMMA_NAME_MMA.record); -+ dag Outs = FragD.Outs; -+ dag Ins = !con(FragA.Ins, -+ FragB.Ins, -+ FragC.Ins); -+ -+ // Construct the pattern to match corresponding intrinsic call. -+ // mma does not load/store anything, so we don't need complex operand matching here. - dag PatOuts = !foreach(tmp, Outs, !subst(outs, set, tmp)); - dag PatArgs = !foreach(tmp, Ins, !subst(ins, Intr, tmp)); - let Pattern = [!con(PatOuts, (set PatArgs))]; -@@ -7710,54 +7588,30 @@ class WMMA_MMA_GABDCS { -- def _satfinite: WMMA_MMA_GABDCS; -- def NAME: WMMA_MMA_GABDCS; --} -- --multiclass WMMA_MMA_GABD { -- defm _f16: WMMA_MMA_GABDC; -- defm _f32: WMMA_MMA_GABDC; --} -- --multiclass WMMA_MMA_GAB { -- defm _f16: WMMA_MMA_GABD; -- defm _f32: WMMA_MMA_GABD; --} -- --multiclass WMMA_MMA_GA { -- defm _col: WMMA_MMA_GAB; -- defm _row: WMMA_MMA_GAB; --} -- --multiclass WMMA_MMA_G { -- defm _col: WMMA_MMA_GA; -- defm _row: WMMA_MMA_GA; -+ # "." # FragA.geom -+ # "." # FragD.ptx_elt_type -+ # "." # FragC.ptx_elt_type -+ # !if(Satfinite, ".satfinite", "") # "\n\t\t" -+ # FragD.regstring # ",\n\t\t" -+ # FragA.regstring # ",\n\t\t" -+ # FragB.regstring # ",\n\t\t" -+ # FragC.regstring # ";"; - } - --defm INT_WMMA_MMA_m32n8k16 : WMMA_MMA_G<"m32n8k16">; --defm INT_WMMA_MMA_m16n16k16 : WMMA_MMA_G<"m16n16k16">; --defm INT_WMMA_MMA_m8n32k16 : WMMA_MMA_G<"m8n32k16">; -+foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout_a = ["row", "col"] in { -+ foreach layout_b = ["row", "col"] in { -+ foreach frag_c = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ foreach frag_d = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ foreach satf = [0, 1] in { -+ def : WMMA_MMA, -+ WMMA_REGINFO, -+ frag_c, frag_d, layout_a, layout_b, satf>; -+ } // satf -+ } // frag_d -+ } // frag_c -+ } // layout_b -+ } // layout_a -+} // geom --- -2.17.1 - diff --git a/deps/patches/llvm-8.0-D59393-mma-ptx63-fix.patch b/deps/patches/llvm-8.0-D59393-mma-ptx63-fix.patch deleted file mode 100644 index 10e6cd7b6f98d..0000000000000 --- a/deps/patches/llvm-8.0-D59393-mma-ptx63-fix.patch +++ /dev/null @@ -1,510 +0,0 @@ -From be924be7f9e699775fe7690d4b421bebfed73aa9 Mon Sep 17 00:00:00 2001 -From: Artem Belevich -Date: Thu, 25 Apr 2019 22:27:46 +0000 -Subject: [PATCH] [NVPTX] generate correct MMA instruction mnemonics with - PTX63+. - -PTX 6.3 requires using ".aligned" in the MMA instruction names. -In order to generate correct name, now we pass current -PTX version to each instruction as an extra constant operand -and InstPrinter adjusts its output accordingly. - -Differential Revision: https://reviews.llvm.org/D59393 - -llvm-svn: 359246 ---- - .../NVPTX/InstPrinter/NVPTXInstPrinter.cpp | 14 + - .../NVPTX/InstPrinter/NVPTXInstPrinter.h | 2 + - lib/Target/NVPTX/NVPTXInstrInfo.td | 4 + - lib/Target/NVPTX/NVPTXIntrinsics.td | 279 ++++++++++-------- - test/CodeGen/NVPTX/wmma.py | 17 +- - 5 files changed, 184 insertions(+), 132 deletions(-) - -diff --git a/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.cpp b/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.cpp -index b774fe169d7..6fb577d5499 100644 ---- a/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.cpp -+++ b/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.cpp -@@ -270,6 +270,20 @@ void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum, - llvm_unreachable("Empty Modifier"); - } - -+void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, -+ const char *Modifier) { -+ const MCOperand &MO = MI->getOperand(OpNum); -+ int Imm = (int)MO.getImm(); -+ if (Modifier == nullptr || strcmp(Modifier, "version") == 0) { -+ O << Imm; // Just print out PTX version -+ } else if (strcmp(Modifier, "aligned") == 0) { -+ // PTX63 requires '.aligned' in the name of the instruction. -+ if (Imm >= 63) -+ O << ".aligned"; -+ } else -+ llvm_unreachable("Unknown Modifier"); -+} -+ - void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum, - raw_ostream &O, const char *Modifier) { - printOperand(MI, OpNum, O); -diff --git a/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h b/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h -index f0f223aa057..588439137f9 100644 ---- a/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h -+++ b/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h -@@ -41,6 +41,8 @@ public: - const char *Modifier = nullptr); - void printLdStCode(const MCInst *MI, int OpNum, - raw_ostream &O, const char *Modifier = nullptr); -+ void printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, -+ const char *Modifier = nullptr); - void printMemOperand(const MCInst *MI, int OpNum, - raw_ostream &O, const char *Modifier = nullptr); - void printProtoIdent(const MCInst *MI, int OpNum, -diff --git a/lib/Target/NVPTX/NVPTXInstrInfo.td b/lib/Target/NVPTX/NVPTXInstrInfo.td -index 02a40b9f526..603d3212395 100644 ---- a/lib/Target/NVPTX/NVPTXInstrInfo.td -+++ b/lib/Target/NVPTX/NVPTXInstrInfo.td -@@ -1549,6 +1549,10 @@ def LdStCode : Operand { - let PrintMethod = "printLdStCode"; - } - -+def MmaCode : Operand { -+ let PrintMethod = "printMmaCode"; -+} -+ - def SDTWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - def Wrapper : SDNode<"NVPTXISD::Wrapper", SDTWrapper>; - -diff --git a/lib/Target/NVPTX/NVPTXIntrinsics.td b/lib/Target/NVPTX/NVPTXIntrinsics.td -index b9a67ba5ed3..5cd534914f7 100644 ---- a/lib/Target/NVPTX/NVPTXIntrinsics.td -+++ b/lib/Target/NVPTX/NVPTXIntrinsics.td -@@ -39,6 +39,24 @@ def AS_match { - }]; - } - -+// A node that will be replaced with the current PTX version. -+class PTX { -+ SDNodeXForm PTXVerXform = SDNodeXFormgetPTXVersion(), SDLoc(N)); -+ }]>; -+ // (i32 0) will be XForm'ed to the currently used PTX version. -+ dag version = (PTXVerXform (i32 0)); -+} -+def ptx : PTX; -+ -+// Generates list of n sequential register names. -+// E.g. RegNames<3,"r">.ret -> ["r0", "r1", "r2" ] -+class RegSeq { -+ list ret = !if(n, !listconcat(RegSeq.ret, -+ [prefix # !add(n, -1)]), -+ []); -+} -+ - //----------------------------------- - // Synchronization and shuffle functions - //----------------------------------- -@@ -7385,14 +7403,6 @@ def INT_PTX_SREG_WARPSIZE : - NVPTXInst<(outs Int32Regs:$dst), (ins), "mov.u32 \t$dst, WARP_SZ;", - [(set Int32Regs:$dst, (int_nvvm_read_ptx_sreg_warpsize))]>; - --class EmptyNVPTXInst : NVPTXInst<(outs), (ins), "?", []>; --// Generates list of n sequential register names. --class RegSeq { -- list ret = !if(n, !listconcat(RegSeq.ret, -- [prefix # !add(n, -1)]), -- []); --} -- - // Helper class that represents a 'fragment' of an NVPTX *MMA instruction. - // In addition to target-independent fields provided by WMMA_REGS, it adds - // the fields commonly used to implement specific PTX instruction -- register -@@ -7409,6 +7419,7 @@ class WMMA_REGINFO - - // List of register names for the fragment -- ["ra0", "ra1",...] - list reg_names = RegSeq.ret; -+ - // Generates "{{$r0, $r1,.... $rN-1}}" for use in asm string construction. - string regstring = "{{$" # !head(reg_names) - # !foldl("", !tail(reg_names), a, b, -@@ -7438,61 +7449,65 @@ class WMMA_REGINFO - dag Ins = !dag(ins, ptx_regs, reg_names); - } - --class BuildPattern { -+// Convert dag of arguments into a dag to match given intrinsic. -+class BuildPatternI { -+ // Build a dag pattern that matches the intrinsic call. -+ dag ret = !foreach(tmp, Ins, -+ !subst(imem, ADDRvar, -+ !subst(MEMri64, ADDRri64, -+ !subst(MEMri, ADDRri, -+ !subst(ins, Intr, tmp))))); -+} -+ -+// Same as above, but uses PatFrag instead of an Intrinsic. -+class BuildPatternPF { - // Build a dag pattern that matches the intrinsic call. -- // We want a dag that looks like this: -- // (set , (intrinsic )) where input and -- // output arguments are named patterns that would match corresponding -- // input/output arguments of the instruction. -- // -- // First we construct (set ) from instruction's outs dag by -- // replacing dag operator 'outs' with 'set'. -- dag PatOuts = !foreach(tmp, Outs, !subst(outs, set, tmp)); -- // Similarly, construct (intrinsic ) sub-dag from -- // instruction's input arguments, only now we also need to replace operands -- // with patterns that would match them and the operator 'ins' with the -- // intrinsic. -- dag PatArgs = !foreach(tmp, Ins, -- !subst(imem, ADDRvar, -- !subst(MEMri64, ADDRri64, -- !subst(MEMri, ADDRri, -- !subst(ins, IntrMatcher, tmp))))); -- // Finally, consatenate both parts together. !con() requires both dags to have -- // the same operator, so we wrap PatArgs in a (set ...) dag. -- dag ret = !con(PatOuts, (set PatArgs)); -+ dag ret = !foreach(tmp, Ins, -+ !subst(imem, ADDRvar, -+ !subst(MEMri64, ADDRri64, -+ !subst(MEMri, ADDRri, -+ !subst(ins, Intr, tmp))))); -+} -+ -+// Common WMMA-related fields used for building patterns for all MMA instructions. -+class WMMA_INSTR _Args> -+ : NVPTXInst<(outs), (ins), "?", []> { -+ Intrinsic Intr = !cast(_Intr); -+ // Concatenate all arguments into a single dag. -+ dag Args = !foldl((ins), _Args, a, b, !con(a,b)); -+ // Pre-build the pattern to match (intrinsic arg0, arg1, ...). -+ dag IntrinsicPattern = BuildPatternI(Intr), Args>.ret; - } - - // - // wmma.load.[a|b|c].sync.[row|col].m16n16k16[|.global|.shared].[f16|f32] - // - --class WMMA_LOAD_INTR_HELPER -- : PatFrag <(ops),(ops)> { -- // Intrinsic that matches this instruction. -- Intrinsic Intr = !cast(WMMA_NAME_LDST<"load", Frag, Layout, -- WithStride>.record); -- let Operands = !if(WithStride, (ops node:$src, node:$ldm), (ops node:$src)); -- let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))]; -- let PredicateCode = !cond(!eq(Space, ".shared"): AS_match.shared, -- !eq(Space, ".global"): AS_match.global, -- 1: AS_match.generic); --} -- - class WMMA_LOAD -- : EmptyNVPTXInst, -+ : WMMA_INSTR.record, -+ [!con((ins SrcOp:$src), -+ !if(WithStride, (ins Int32Regs:$ldm), (ins)))]>, - Requires { -- // Pattern that matches the intrinsic for this instruction variant. -- PatFrag IntrMatcher = WMMA_LOAD_INTR_HELPER; -- dag Ins = !con((ins SrcOp:$src), !if(WithStride, (ins Int32Regs:$ldm), (ins))); -+ // Load/store intrinsics are overloaded on pointer's address space. -+ // To match the right intrinsic, we need to build AS-constrained PatFrag. -+ // Operands is a dag equivalent in shape to Args, but using (ops node:$name, .....). -+ dag PFOperands = !if(WithStride, (ops node:$src, node:$ldm), (ops node:$src)); -+ // Build PatFrag that only matches particular address space. -+ PatFrag IntrFrag = PatFrag; -+ // Build AS-constrained pattern. -+ let IntrinsicPattern = BuildPatternPF.ret; - -- let Pattern = [BuildPattern.ret]; - let OutOperandList = Frag.Outs; -- let InOperandList = Ins; -+ let InOperandList = !con(Args, (ins MmaCode:$ptx)); - let AsmString = "wmma.load." - # Frag.frag - # ".sync" -+ # "${ptx:aligned}" - # "." # Layout - # "." # Frag.geom - # Space -@@ -7506,87 +7521,79 @@ class WMMA_LOAD -- : PatFrag <(ops),(ops)> { -- // Intrinsic that matches this instruction. -- Intrinsic Intr = !cast(WMMA_NAME_LDST<"store", Frag, Layout, -- WithStride>.record); -- let Operands = !con((ops node:$dst), -- !dag(ops, !foreach(tmp, Frag.regs, node), Frag.reg_names), -- !if(WithStride, (ops node:$ldm), (ops))); -- let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))]; -- let PredicateCode = !cond(!eq(Space, ".shared"): AS_match.shared, -- !eq(Space, ".global"): AS_match.global, -- 1: AS_match.generic); --} -- --class WMMA_STORE -- : EmptyNVPTXInst, -+class WMMA_STORE_D -+ : WMMA_INSTR.record, -+ [!con((ins DstOp:$dst), -+ Frag.Ins, -+ !if(WithStride, (ins Int32Regs:$ldm), (ins)))]>, - Requires { -- PatFrag IntrMatcher = WMMA_STORE_INTR_HELPER; -- dag Ins = !con((ins DstOp:$src), -- Frag.Ins, -- !if(WithStride, (ins Int32Regs:$ldm), (ins))); -- let Pattern = [BuildPattern<(set), IntrMatcher, Ins>.ret]; -+ -+ // Load/store intrinsics are overloaded on pointer's address space. -+ // To match the right intrinsic, we need to build AS-constrained PatFrag. -+ // Operands is a dag equivalent in shape to Args, but using (ops node:$name, .....). -+ dag PFOperands = !con((ops node:$dst), -+ !dag(ops, !foreach(tmp, Frag.regs, node), Frag.reg_names), -+ !if(WithStride, (ops node:$ldm), (ops))); -+ // Build PatFrag that only matches particular address space. -+ PatFrag IntrFrag = PatFrag; -+ // Build AS-constrained pattern. -+ let IntrinsicPattern = BuildPatternPF.ret; -+ -+ let InOperandList = !con(Args, (ins MmaCode:$ptx)); - let OutOperandList = (outs); -- let InOperandList = Ins; -- let AsmString = "wmma.store.d.sync." -- # Layout -+ let AsmString = "wmma.store.d.sync" -+ # "${ptx:aligned}" -+ # "." # Layout - # "." # Frag.geom - # Space - # "." # Frag.ptx_elt_type -- # " \t[$src]," -+ # " \t[$dst]," - # Frag.regstring - # !if(WithStride, ", $ldm", "") - # ";"; - } - - // Create all load/store variants --foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -- foreach layout = ["row", "col"] in { -- foreach stride = [0, 1] in { -- foreach space = [".global", ".shared", ""] in { -- foreach addr = [imem, Int32Regs, Int64Regs, MEMri, MEMri64] in { -- foreach frag = [WMMA_REGINFO, -- WMMA_REGINFO, -- WMMA_REGINFO, -- WMMA_REGINFO] in { -- def : WMMA_LOAD; -- } -- foreach frag = [WMMA_REGINFO, -- WMMA_REGINFO] in { -- def : WMMA_STORE; -- } -- } // addr -- } // space -- } // stride -- } // layout --} // geom -+defset list MMA_LDSTs = { -+ foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout = ["row", "col"] in { -+ foreach stride = [0, 1] in { -+ foreach space = [".global", ".shared", ""] in { -+ foreach addr = [imem, Int32Regs, Int64Regs, MEMri, MEMri64] in { -+ foreach frag = [WMMA_REGINFO, -+ WMMA_REGINFO, -+ WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ def : WMMA_LOAD; -+ } -+ foreach frag = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ def : WMMA_STORE_D; -+ } -+ } // addr -+ } // space -+ } // stride -+ } // layout -+ } // geom -+} // defset - - // WMMA.MMA - class WMMA_MMA -- : EmptyNVPTXInst, -+ : WMMA_INSTR.record, -+ [FragA.Ins, FragB.Ins, FragC.Ins]>, - Requires { -- //Intrinsic Intr = int_nvvm_suld_1d_v4i32_zero; -- Intrinsic Intr = !cast(WMMA_NAME_MMA.record); -- dag Outs = FragD.Outs; -- dag Ins = !con(FragA.Ins, -- FragB.Ins, -- FragC.Ins); -- -- // Construct the pattern to match corresponding intrinsic call. -- // mma does not load/store anything, so we don't need complex operand matching here. -- dag PatOuts = !foreach(tmp, Outs, !subst(outs, set, tmp)); -- dag PatArgs = !foreach(tmp, Ins, !subst(ins, Intr, tmp)); -- let Pattern = [!con(PatOuts, (set PatArgs))]; -- let OutOperandList = Outs; -- let InOperandList = Ins; -- let AsmString = "wmma.mma.sync." -- # ALayout -+ let OutOperandList = FragD.Outs; -+ let InOperandList = !con(Args, (ins MmaCode:$ptx)); -+ let AsmString = "wmma.mma.sync" -+ # "${ptx:aligned}" -+ # "." # ALayout - # "." # BLayout - # "." # FragA.geom - # "." # FragD.ptx_elt_type -@@ -7598,20 +7605,34 @@ class WMMA_MMA, -- WMMA_REGINFO] in { -- foreach frag_d = [WMMA_REGINFO, -- WMMA_REGINFO] in { -- foreach satf = [0, 1] in { -- def : WMMA_MMA, -- WMMA_REGINFO, -- frag_c, frag_d, layout_a, layout_b, satf>; -- } // satf -- } // frag_d -- } // frag_c -- } // layout_b -- } // layout_a --} // geom -+defset list MMAs = { -+ foreach geom = ["m16n16k16", "m32n8k16", "m8n32k16" ] in { -+ foreach layout_a = ["row", "col"] in { -+ foreach layout_b = ["row", "col"] in { -+ foreach frag_c = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ foreach frag_d = [WMMA_REGINFO, -+ WMMA_REGINFO] in { -+ foreach satf = [0, 1] in { -+ def : WMMA_MMA, -+ WMMA_REGINFO, -+ frag_c, frag_d, layout_a, layout_b, satf>; -+ } // satf -+ } // frag_d -+ } // frag_c -+ } // layout_b -+ } // layout_a -+ } // geom -+} // defset -+ -+// Constructing non-flat DAGs is still a pain. I can't !subst a dag node with a -+// dag, so the ptx.version must be appended *after* foreach replaces 'ins' with -+// the instruction record. -+class WMMA_PAT -+ : Pat; -+ -+// Build intrinsic->instruction patterns for all MMA instructions. -+foreach mma = !listconcat(MMAs, MMA_LDSTs) in -+ def : WMMA_PAT; -diff --git a/test/CodeGen/NVPTX/wmma.py b/test/CodeGen/NVPTX/wmma.py -index 14bbfd7df09..72d189ca050 100644 ---- a/test/CodeGen/NVPTX/wmma.py -+++ b/test/CodeGen/NVPTX/wmma.py -@@ -3,9 +3,12 @@ - - # RUN: python %s > %t.ll - # RUN: llc < %t.ll -march=nvptx64 -mcpu=sm_70 -mattr=+ptx61 | FileCheck %t.ll -+# RUN: python %s --ptx=63 > %t-ptx63.ll -+# RUN: llc < %t-ptx63.ll -march=nvptx64 -mcpu=sm_70 -mattr=+ptx63 | FileCheck %t-ptx63.ll - - from __future__ import print_function - -+import argparse - from itertools import product - from string import Template - -@@ -64,7 +67,7 @@ define ${ret_ty} @test_${function}_o(i8 ${as}* %src ${extra_args}) { - } - """ - intrinsic_template = "llvm.nvvm.wmma.${geom}.load.${abc}.${layout}${stride}.${itype}.${pspace}" -- instruction_template = "wmma.load.${abc}.sync.${layout}.${geom}${space}.${itype}" -+ instruction_template = "wmma.load.${abc}.sync${aligned}.${layout}.${geom}${space}.${itype}" - - for geom, abc, layout, space, stride, itype in product( - known_geoms, -@@ -76,6 +79,7 @@ define ${ret_ty} @test_${function}_o(i8 ${as}* %src ${extra_args}) { - - params = { - "abc" : abc, -+ "aligned" : ".aligned" if ptx_version >= 63 else "", - "layout" : layout, - "space" : space, - "stride" : stride, -@@ -135,7 +139,7 @@ define void @test_${function}_o(i8 ${as}* %src, ${args}${extra_args}) { - } - """ - intrinsic_template = "llvm.nvvm.wmma.${geom}.store.${abc}.${layout}${stride}.${itype}.${pspace}" -- instruction_template = "wmma.store.${abc}.sync.${layout}.${geom}${space}.${itype}" -+ instruction_template = "wmma.store.${abc}.sync${aligned}.${layout}.${geom}${space}.${itype}" - - for geom, abc, layout, space, stride, itype in product( - known_geoms, -@@ -147,6 +151,7 @@ define void @test_${function}_o(i8 ${as}* %src, ${args}${extra_args}) { - - params = { - "abc" : abc, -+ "aligned" : ".aligned" if ptx_version >= 63 else "", - "layout" : layout, - "space" : space, - "stride" : stride, -@@ -191,7 +196,7 @@ define ${ret_ty} @test_${function}( - } - """ - intrinsic_template = "llvm.nvvm.wmma.${geom}.mma.${alayout}.${blayout}.${dtype}.${ctype}${satf}" -- instruction_template = "wmma.mma.sync.${alayout}.${blayout}.${geom}.${dtype}.${ctype}${satf}" -+ instruction_template = "wmma.mma.sync${aligned}.${alayout}.${blayout}.${geom}.${dtype}.${ctype}${satf}" - - for geom, alayout, blayout, ctype, dtype, satf in product( - known_geoms, -@@ -202,6 +207,7 @@ define ${ret_ty} @test_${function}( - [".satfinite", ""]): - - params = { -+ "aligned" : ".aligned" if ptx_version >= 63 else "", - "alayout" : alayout, - "blayout" : blayout, - "ctype" : ctype, -@@ -230,4 +236,9 @@ def main(): - gen_wmma_store_tests() - gen_wmma_mma_tests() - -+parser = argparse.ArgumentParser() -+parser.add_argument('--ptx', type=int, default=60) -+args = parser.parse_args() -+ptx_version = args.ptx -+ - main() --- -2.17.1 - diff --git a/deps/patches/llvm-8.0-D63688-wasm-isLocal.patch b/deps/patches/llvm-8.0-D63688-wasm-isLocal.patch deleted file mode 100644 index 820363d305424..0000000000000 --- a/deps/patches/llvm-8.0-D63688-wasm-isLocal.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 83d5085a7fcbb4596d964dbe037c5ebf4de02b69 Mon Sep 17 00:00:00 2001 -From: Keno Fischer -Date: Sun, 23 Jun 2019 00:29:59 +0000 -Subject: [PATCH] [Support] Fix build under Emscripten - -Summary: -Emscripten's libc doesn't define MNT_LOCAL, thus causing a build -failure in the fallback path. However, to the best of my knowledge, -it also doesn't support remote file system mounts, so we may simply -return `true` here (as we do for e.g. Fuchsia). With this fix, the -core LLVM libraries build correctly under emscripten (though some -of the tools and utils do not). - -Reviewers: kripken -Differential Revision: https://reviews.llvm.org/D63688 - -llvm-svn: 364143 -(cherry picked from commit 5f4ae7c45718618c4c571495e7d910d5722f70ad) ---- - llvm/lib/Support/Unix/Path.inc | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc -index d7cc0d627d0..eb38a71fffb 100644 ---- a/lib/Support/Unix/Path.inc -+++ b/lib/Support/Unix/Path.inc -@@ -398,6 +398,9 @@ static bool is_local_impl(struct STATVFS &Vfs) { - #elif defined(__Fuchsia__) - // Fuchsia doesn't yet support remote filesystem mounts. - return true; -+#elif defined(__EMSCRIPTEN__) -+ // Emscripten doesn't currently support remote filesystem mounts. -+ return true; - #elif defined(__HAIKU__) - // Haiku doesn't expose this information. - return false; --- -2.24.0 - diff --git a/deps/patches/llvm-8.0-D65174-limit-merge-stores.patch b/deps/patches/llvm-8.0-D65174-limit-merge-stores.patch deleted file mode 100644 index 646c44f454641..0000000000000 --- a/deps/patches/llvm-8.0-D65174-limit-merge-stores.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 19992a8c7f2df2000ea7fd4a284ec7b407400fb0 Mon Sep 17 00:00:00 2001 -From: Wei Mi -Date: Sun, 29 Mar 2020 17:14:12 -0400 -Subject: [PATCH] [DAGCombine] Limit the number of times for the same store and - root nodes to bail out in store merging dependence check. - -We run into a case where dependence check in store merging bail out many times -for the same store and root nodes in a huge basicblock. That increases compile -time by almost 100x. The patch add a map to track how many times the bailing -out happen for the same store and root, and if it is over a limit, stop -considering the store with the same root as a merging candidate. - -Differential Revision: https://reviews.llvm.org/D65174 ---- - llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 45 +++++++++++++++++-- - 1 file changed, 42 insertions(+), 3 deletions(-) - -diff --git llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -index 6af01423ca1..9c7e37d6945 100644 ---- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -@@ -112,6 +112,11 @@ static cl::opt - MaySplitLoadIndex("combiner-split-load-index", cl::Hidden, cl::init(true), - cl::desc("DAG combiner may split indexing from loads")); - -+static cl::opt StoreMergeDependenceLimit( -+ "combiner-store-merge-dependence-limit", cl::Hidden, cl::init(10), -+ cl::desc("Limit the number of times for the same StoreNode and RootNode " -+ "to bail out in store merging dependence check")); -+ - namespace { - - class DAGCombiner { -@@ -145,6 +150,14 @@ namespace { - /// which have not yet been combined to the worklist. - SmallPtrSet CombinedNodes; - -+ /// Map from candidate StoreNode to the pair of RootNode and count. -+ /// The count is used to track how many times we have seen the StoreNode -+ /// with the same RootNode bail out in dependence check. If we have seen -+ /// the bail out for the same pair many times over a limit, we won't -+ /// consider the StoreNode with the same RootNode as store merging -+ /// candidate again. -+ DenseMap> StoreRootCountMap; -+ - // AA - Used for DAG load/store alias analysis. - AliasAnalysis *AA; - -@@ -190,6 +203,7 @@ namespace { - /// Remove all instances of N from the worklist. - void removeFromWorklist(SDNode *N) { - CombinedNodes.erase(N); -+ StoreRootCountMap.erase(N); - - auto It = WorklistMap.find(N); - if (It == WorklistMap.end()) -@@ -14423,6 +14437,18 @@ void DAGCombiner::getStoreMergeCandidates( - return (BasePtr.equalBaseIndex(Ptr, DAG, Offset)); - }; - -+ // Check if the pair of StoreNode and the RootNode already bail out many -+ // times which is over the limit in dependence check. -+ auto OverLimitInDependenceCheck = [&](SDNode *StoreNode, -+ SDNode *RootNode) -> bool { -+ auto RootCount = StoreRootCountMap.find(StoreNode); -+ if (RootCount != StoreRootCountMap.end() && -+ RootCount->second.first == RootNode && -+ RootCount->second.second > StoreMergeDependenceLimit) -+ return true; -+ return false; -+ }; -+ - // We looking for a root node which is an ancestor to all mergable - // stores. We search up through a load, to our root and then down - // through all children. For instance we will find Store{1,2,3} if -@@ -14450,7 +14476,8 @@ void DAGCombiner::getStoreMergeCandidates( - if (StoreSDNode *OtherST = dyn_cast(*I2)) { - BaseIndexOffset Ptr; - int64_t PtrDiff; -- if (CandidateMatch(OtherST, Ptr, PtrDiff)) -+ if (CandidateMatch(OtherST, Ptr, PtrDiff) && -+ !OverLimitInDependenceCheck(OtherST, RootNode)) - StoreNodes.push_back(MemOpLink(OtherST, PtrDiff)); - } - } else -@@ -14459,7 +14486,8 @@ void DAGCombiner::getStoreMergeCandidates( - if (StoreSDNode *OtherST = dyn_cast(*I)) { - BaseIndexOffset Ptr; - int64_t PtrDiff; -- if (CandidateMatch(OtherST, Ptr, PtrDiff)) -+ if (CandidateMatch(OtherST, Ptr, PtrDiff) && -+ !OverLimitInDependenceCheck(OtherST, RootNode)) - StoreNodes.push_back(MemOpLink(OtherST, PtrDiff)); - } - } -@@ -14517,8 +14545,19 @@ bool DAGCombiner::checkMergeStoreCandidatesForDependencies( - // Search through DAG. We can stop early if we find a store node. - for (unsigned i = 0; i < NumStores; ++i) - if (SDNode::hasPredecessorHelper(StoreNodes[i].MemNode, Visited, Worklist, -- Max)) -+ Max)) { -+ // If the searching bail out, record the StoreNode and RootNode in the -+ // StoreRootCountMap. If we have seen the pair many times over a limit, -+ // we won't add the StoreNode into StoreNodes set again. -+ if (Visited.size() >= Max) { -+ auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode]; -+ if (RootCount.first == RootNode) -+ RootCount.second++; -+ else -+ RootCount = {RootNode, 1}; -+ } - return false; -+ } - return true; - } - --- -2.25.2 - diff --git a/deps/patches/llvm-8.0-D66401-mingw-reloc.patch b/deps/patches/llvm-8.0-D66401-mingw-reloc.patch deleted file mode 100644 index 384399f2162f2..0000000000000 --- a/deps/patches/llvm-8.0-D66401-mingw-reloc.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/test/CodeGen/X86/mingw-refptr.ll b/test/CodeGen/X86/mingw-refptr.ll ---- a/test/CodeGen/X86/mingw-refptr.ll -+++ b/test/CodeGen/X86/mingw-refptr.ll -@@ -1,5 +1,6 @@ - ; RUN: llc < %s -mtriple=x86_64-w64-mingw32 | FileCheck %s -check-prefix=CHECK-X64 - ; RUN: llc < %s -mtriple=i686-w64-mingw32 | FileCheck %s -check-prefix=CHECK-X86 -+; RUN: llc < %s -mtriple=i686-w64-mingw32-none-elf | FileCheck %s -check-prefix=CHECK-X86-ELF - - @var = external local_unnamed_addr global i32, align 4 - @dsolocalvar = external dso_local local_unnamed_addr global i32, align 4 -@@ -16,6 +17,9 @@ - ; CHECK-X86: movl .refptr._var, %eax - ; CHECK-X86: movl (%eax), %eax - ; CHECK-X86: retl -+; CHECK-X86-ELF-LABEL: getVar: -+; CHECK-X86-ELF: movl var, %eax -+; CHECK-X86-ELF: retl - entry: - %0 = load i32, i32* @var, align 4 - ret i32 %0 -@@ -66,6 +70,9 @@ - ; CHECK-X86: movl __imp__extvar, %eax - ; CHECK-X86: movl (%eax), %eax - ; CHECK-X86: retl -+; CHECK-X86-ELF-LABEL: getExtVar: -+; CHECK-X86-ELF: movl extvar, %eax -+; CHECK-X86-ELF: retl - entry: - %0 = load i32, i32* @extvar, align 4 - ret i32 %0 -diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp ---- a/lib/Target/X86/X86Subtarget.cpp -+++ b/lib/Target/X86/X86Subtarget.cpp -@@ -146,6 +146,9 @@ - return X86II::MO_DLLIMPORT; - return X86II::MO_COFFSTUB; - } -+ // Some JIT users use *-win32-elf triples; these shouldn't use GOT tables. -+ if (isOSWindows()) -+ return X86II::MO_NO_FLAG; - - if (is64Bit()) { - // ELF supports a large, truly PIC code model with non-PC relative GOT -diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp ---- a/lib/Target/TargetMachine.cpp -+++ b/lib/Target/TargetMachine.cpp -@@ -128,8 +128,8 @@ - // don't assume the variables to be DSO local unless we actually know - // that for sure. This only has to be done for variables; for functions - // the linker can insert thunks for calling functions from another DLL. -- if (TT.isWindowsGNUEnvironment() && GV && GV->isDeclarationForLinker() && -- isa(GV)) -+ if (TT.isWindowsGNUEnvironment() && TT.isOSBinFormatCOFF() && GV && -+ GV->isDeclarationForLinker() && isa(GV)) - return false; - - // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols -@@ -142,7 +142,9 @@ - // Make an exception for windows OS in the triple: Some firmware builds use - // *-win32-macho triples. This (accidentally?) produced windows relocations - // without GOT tables in older clang versions; Keep this behaviour. -- if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) -+ // Some JIT users use *-win32-elf triples; these shouldn't use GOT tables -+ // either. -+ if (TT.isOSBinFormatCOFF() || TT.isOSWindows()) - return true; - - // Most PIC code sequences that assume that a symbol is local cannot - diff --git a/deps/patches/llvm-8.0-D66657-codegen-degenerate.patch b/deps/patches/llvm-8.0-D66657-codegen-degenerate.patch deleted file mode 100644 index ddcf4dc7ddaa6..0000000000000 --- a/deps/patches/llvm-8.0-D66657-codegen-degenerate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4c7e1defbddafcfcfe1211b041d43a36114a8f48 Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Sat, 14 Dec 2019 10:33:30 -0500 -Subject: [PATCH 2/2] [CodegenPrepare] Guard against degenerate branches - -Summary: -Guard against a potential crash observed in https://github.com/JuliaLang/julia/issues/32994#issuecomment-524249628 -If two branches are collapsed we can encounter a degenerate conditional branch `TBB==FBB`. -The subsequent code assumes that they differ, so we exit out early. - -Reviewers: ributzka, spatel - -Subscribers: loladiro, dexonsmith, hiraditya, llvm-commits - -Tags: #llvm - -Differential Revision: https://reviews.llvm.org/D66657 ---- - llvm/lib/CodeGen/CodeGenPrepare.cpp | 4 ++++ - .../CodeGen/X86/codegen-prepare-collapse.ll | 18 ++++++++++++++++++ - 2 files changed, 22 insertions(+) - create mode 100644 llvm/test/CodeGen/X86/codegen-prepare-collapse.ll - -diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp -index c35f8666fa3..3647641c594 100644 ---- a/lib/CodeGen/CodeGenPrepare.cpp -+++ b/lib/CodeGen/CodeGenPrepare.cpp -@@ -6929,6 +6929,10 @@ bool CodeGenPrepare::splitBranchCondition(Function &F) { - if (Br1->getMetadata(LLVMContext::MD_unpredictable)) - continue; - -+ // The merging of mostly empty BB can cause a degenerate branch. -+ if (TBB == FBB) -+ continue; -+ - unsigned Opc; - Value *Cond1, *Cond2; - if (match(LogicOp, m_And(m_OneUse(m_Value(Cond1)), -diff --git a/test/CodeGen/X86/codegen-prepare-collapse.ll b/test/CodeGen/X86/codegen-prepare-collapse.ll -new file mode 100644 -index 00000000000..18e3ef7afbd ---- /dev/null -+++ b/test/CodeGen/X86/codegen-prepare-collapse.ll -@@ -0,0 +1,18 @@ -+; RUN: llc -fast-isel=true -O1 -mtriple=x86_64-unkown-linux-gnu -start-before=codegenprepare -stop-after=codegenprepare -o - < %s | FileCheck %s -+ -+; CHECK-LABEL: @foo -+define void @foo() { -+top: -+; CHECK: br label %L34 -+ br label %L34 -+ -+L34: ; preds = %L34, %L34, %top -+ %.sroa.075.0 = phi i64 [ undef, %top ], [ undef, %L34 ], [ undef, %L34 ] -+ %0 = icmp sgt i8 undef, -1 -+ %cond5896 = icmp eq i8 0, 2 -+ %cond58 = and i1 %cond5896, %0 -+; During codegenprepare such degenerate branches can occur and should not -+; lead to crashes. -+; CHECK: br label %L34 -+ br i1 %cond58, label %L34, label %L34 -+} --- -2.24.1 - diff --git a/deps/patches/llvm-8.0-D71495-vectorize-freduce.patch b/deps/patches/llvm-8.0-D71495-vectorize-freduce.patch deleted file mode 100644 index fb461920c176f..0000000000000 --- a/deps/patches/llvm-8.0-D71495-vectorize-freduce.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 7c30e23f115ae285b497ef11af0153703111dff2 Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Sun, 22 Dec 2019 14:25:50 -0500 -Subject: [PATCH 1/2] [SelectionDAG] Copy FP flags when visiting a binary - instruction. - -Summary: -We noticed in Julia that the sequence below no longer turned into -a sequence of FMA instructions in LLVM 7+, but it did in LLVM 6. - -``` - %29 = fmul contract <4 x double> %wide.load, %wide.load16 - %30 = fmul contract <4 x double> %wide.load13, %wide.load17 - %31 = fmul contract <4 x double> %wide.load14, %wide.load18 - %32 = fmul contract <4 x double> %wide.load15, %wide.load19 - %33 = fadd fast <4 x double> %vec.phi, %29 - %34 = fadd fast <4 x double> %vec.phi10, %30 - %35 = fadd fast <4 x double> %vec.phi11, %31 - %36 = fadd fast <4 x double> %vec.phi12, %32 -``` - -Unlike Clang, Julia doesn't set the `unsafe-fp-math=true` function -attribute, but rather emits more local instruction flags. - -This partially undoes https://reviews.llvm.org/D46854 and if required I can try to minimize the test further. - -Reviewers: spatel, mcberg2017 - -Reviewed By: spatel - -Subscribers: chriselrod, merge_guards_bot, hiraditya, llvm-commits - -Tags: #llvm - -Differential Revision: https://reviews.llvm.org/D71495 ---- - .../SelectionDAG/SelectionDAGBuilder.cpp | 7 +++++ - llvm/test/CodeGen/X86/fmf-reduction.ll | 26 +++++++++++++++++++ - 2 files changed, 33 insertions(+) - create mode 100644 llvm/test/CodeGen/X86/fmf-reduction.ll - -diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -index bfeb3d1bc2b..e6362c19691 100644 ---- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -@@ -2833,6 +2833,13 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned Opcode) { - if (isVectorReductionOp(&I)) { - Flags.setVectorReduction(true); - LLVM_DEBUG(dbgs() << "Detected a reduction operation:" << I << "\n"); -+ -+ // If no flags are set we will propagate the incoming flags, if any flags -+ // are set, we will intersect them with the incoming flag and so we need to -+ // copy the FMF flags here. -+ if (auto *FPOp = dyn_cast(&I)) { -+ Flags.copyFMF(*FPOp); -+ } - } - - SDValue Op1 = getValue(I.getOperand(0)); -diff --git a/test/CodeGen/X86/fmf-reduction.ll b/test/CodeGen/X86/fmf-reduction.ll -new file mode 100644 -index 00000000000..1d669d2a924 ---- /dev/null -+++ b/test/CodeGen/X86/fmf-reduction.ll -@@ -0,0 +1,26 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc < %s -mtriple=x86_64-- -mattr=fma | FileCheck %s -+ -+; Propagation of IR FMF should not drop flags when adding the DAG reduction flag. -+; This should include an FMA instruction, not separate FMUL/FADD. -+ -+define double @julia_dotf(<4 x double> %x, <4 x double> %y, <4 x double> %z, i1 %t3) { -+; CHECK-LABEL: julia_dotf: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vfmadd213pd {{.*#+}} ymm0 = (ymm1 * ymm0) + ymm2 -+; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm1 -+; CHECK-NEXT: vaddpd %xmm1, %xmm0, %xmm0 -+; CHECK-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,0] -+; CHECK-NEXT: vaddsd %xmm1, %xmm0, %xmm0 -+; CHECK-NEXT: vzeroupper -+; CHECK-NEXT: retq -+ %t1 = fmul contract <4 x double> %x, %y -+ %t2 = fadd fast <4 x double> %z, %t1 -+ %rdx.shuf = shufflevector <4 x double> %t2, <4 x double> undef, <4 x i32> -+ %bin.rdx22 = fadd fast <4 x double> %t2, %rdx.shuf -+ %rdx.shuf23 = shufflevector <4 x double> %bin.rdx22, <4 x double> undef, <4 x i32> -+ %bin.rdx24 = fadd fast <4 x double> %bin.rdx22, %rdx.shuf23 -+ %t4 = extractelement <4 x double> %bin.rdx24, i32 0 -+ ret double %t4 -+} -+ --- -2.24.1 - diff --git a/deps/patches/llvm-8.0-D75072-SCEV-add-type.patch b/deps/patches/llvm-8.0-D75072-SCEV-add-type.patch deleted file mode 100644 index 6418eca5d28b6..0000000000000 --- a/deps/patches/llvm-8.0-D75072-SCEV-add-type.patch +++ /dev/null @@ -1,415 +0,0 @@ -From f11f45a45ce8b90c798dd939d2782205e4291360 Mon Sep 17 00:00:00 2001 -From: Keno Fischer -Date: Fri, 6 Mar 2020 10:29:20 -0500 -Subject: [PATCH] [SCEV] Record NI types in add exprs - -Summary: -(Rebased to LLVM 8 from the original LLVM 9 patch) -This fixes a case where loop-reduce introduces ptrtoint/inttoptr for -non-integral address space pointers. Over the past several years, we -have gradually improved the SCEVExpander to actually do something -sensible for non-integral pointer types. However, that obviously -relies on the expander knowing what the type of the SCEV expression is. -That is usually the case, but there is one important case where it's -not: The type of an add expression is just the type of the last operand, -so if the non-integral pointer is not the last operand, later uses of -that SCEV may not realize that the given add expression contains -non-integral pointers and may try to expand it as integers. - -One interesting observation is that we do get away with this scheme in -shockingly many cases. The reason for this is that SCEV expressions -often have an `scUnknown` pointer base, which our sort order on the -operands of add expressions sort behind basically everything else, -so it usually ends up as the last operand. - -One situation where this fails is included as a test case. This test -case was bugpoint-reduced from the issue reported at -https://github.com/JuliaLang/julia/issues/31156. What happens here -is that the pointer base is an scAddRec from an outer loop, plus an -scUnknown integer offset. By our sort order, the scUnknown gets sorted -after the scAddRec pointer base, thus making an add expression of these -two operands have integer type. This then confuses the expander, into -attempting to expand the whole thing as integers, which will obviously -fail when reaching the non-integral pointer. - -I considered a few options to solve this, but here's what I ended up -settling on: The AddExpr class gains a new subclass that explicitly -stores the type of the expression. This subclass is used whenever one -of the operands is a non-integral pointer. To reduce the impact for the -regular case (where the SCEV expression contains no non-integral -pointers), a bit flag is kept in each flag expression to indicate -whether it is of non-integral pointer type (this should give the same -answer as asking if getType() is non-integral, but performing that -query may involve a pointer chase and requires the DataLayout). For -add expressions that flag is also used to indicate whether we're using -the subclass or not. This is slightly inefficient, because it uses -the subclass even in the (not uncommon) case where the last operand -does actually accurately reflect the non-integral pointer type. However, -it didn't seem worth the extra flag bit and complexity to do this -micro-optimization. - -I had hoped that we could additionally restrict mul exprs from -containing any non-integral pointers, and also require add exprs to -only have one operand containg such pointers (but not more), but this -turned out not to work. The reason for this is that SCEV wants to -form differences between pointers, which it represents as `A + B*-1`, -so we need to allow both multiplication by `-1` and addition with -multiple non-integral pointer arguments. I'm not super happy with -that situation, but I think it exposes a more general problem with -non-integral pointers in LLVM. We don't actually have a way to express -the difference between two non-integral pointers at the IR level. -In theory this is a problem for SCEV, because it means that we can't -materialize such SCEV expression. However, in practice, these -expressions generally have the same base pointer, so SCEV will -appropriately simplify them to just the integer components. -Nevertheless it is a bit unsatisfying. Perhaps we could have an -intrinsic that takes the byte difference between two pointers to the -same allocated object (in the same sense as is used in getelementptr), -which should be a sensible operation even for non-integral pointers. -However, given the practical considerations above, that's a project -for another time. For now, simply allowing the existing pointer-diff -pattern for non-integral pointers seems to work ok. - -Reviewers: sanjoy, reames, vtjnash, vchuravy - -Subscribers: hiraditya, javed.absar, llvm-commits - -Tags: #llvm, #julialang - -Differential Revision: https://reviews.llvm.org/D75072 ---- - llvm/include/llvm/Analysis/ScalarEvolution.h | 26 +++++-- - .../Analysis/ScalarEvolutionExpressions.h | 70 ++++++++++++++++--- - llvm/lib/Analysis/ScalarEvolution.cpp | 44 +++++++++--- - .../LoopStrengthReduce/nonintegral.ll | 35 +++++++++- - 4 files changed, 150 insertions(+), 25 deletions(-) - -diff --git llvm/include/llvm/Analysis/ScalarEvolution.h llvm/include/llvm/Analysis/ScalarEvolution.h -index 5286f6a220e..f27fceb70d2 100644 ---- llvm/include/llvm/Analysis/ScalarEvolution.h -+++ llvm/include/llvm/Analysis/ScalarEvolution.h -@@ -116,6 +116,19 @@ public: - NoWrapMask = (1 << 3) - 1 - }; - -+ /// HasNonIntegralPointerFlag are bitfield indices into SubclassData. -+ /// -+ /// When constructing SCEV expressions for LLVM expressions with non-integral -+ /// pointer types, some additional processing is required to ensure that we -+ /// don't introduce any illegal transformations. However, non-integral pointer -+ /// types are a very rarely used feature, so we want to make sure to only do -+ /// such processing if they are actually used. To ensure minimal performance -+ /// impact, we memoize that fact in using these flags. -+ enum HasNonIntegralPointerFlag { -+ FlagNoNIPointers = 0, -+ FlagHasNIPointers = (1 << 3) -+ }; -+ - explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) - : FastID(ID), SCEVType(SCEVTy) {} - SCEV(const SCEV &) = delete; -@@ -138,6 +138,10 @@ public: - /// Return true if the specified scev is negated, but not a constant. - bool isNonConstantNegative() const; - -+ bool hasNonIntegralPointers() const { -+ return SubclassData & FlagHasNIPointers; -+ } -+ - /// Print out the internal representation of this scalar to the specified - /// stream. This should really only be used for debugging purposes. - void print(raw_ostream &OS) const; -diff --git llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h -index 876d68438ef..b9ea23c0086 100644 ---- llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h -+++ llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h -@@ -181,6 +184,13 @@ class Type; - return getNoWrapFlags(FlagNW) != FlagAnyWrap; - } - -+ void setHasNIPtr(bool HasNIPtr) { -+ if (HasNIPtr) -+ SubclassData |= FlagHasNIPointers; -+ else -+ SubclassData &= ~FlagHasNIPointers; -+ } -+ - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { - return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || -@@ -215,24 +220,54 @@ class Type; - class SCEVAddExpr : public SCEVCommutativeExpr { - friend class ScalarEvolution; - -+ protected: - SCEVAddExpr(const FoldingSetNodeIDRef ID, - const SCEV *const *O, size_t N) - : SCEVCommutativeExpr(ID, scAddExpr, O, N) {} - - public: -- Type *getType() const { -- // Use the type of the last operand, which is likely to be a pointer -- // type, if there is one. This doesn't usually matter, but it can help -- // reduce casts when the expressions are expanded. -- return getOperand(getNumOperands() - 1)->getType(); -+ /// Returns the type of the add expression, by looking either at the last -+ /// operand or deferring to the SCEVAddNIExpr subclass for non-integral -+ /// pointers. -+ Type *getType() const; -+ -+ /// Methods for support type inquiry through isa, cast, and dyn_cast: -+ static bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr; } -+ }; -+ -+ /// This node represents an addition of some number of SCEVs, one which -+ /// is a non-integral pointer type, requiring us to know the type exactly for -+ /// correctness. -+ class SCEVAddNIExpr : public SCEVAddExpr { -+ friend class ScalarEvolution; -+ PointerType *NIType; -+ -+ SCEVAddNIExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N, -+ PointerType *NIType) -+ : SCEVAddExpr(ID, O, N), NIType(NIType) { -+ SubclassData |= FlagHasNIPointers; - } - -+ public: -+ Type *getType() const { return NIType; } -+ - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { -- return S->getSCEVType() == scAddExpr; -+ return S->getSCEVType() == scAddExpr && S->hasNonIntegralPointers(); - } - }; - -+ inline Type *SCEVAddExpr::getType() const { -+ // In general, use the type of the last operand, which is likely to be a -+ // pointer type, if there is one. This doesn't usually matter, but it can -+ // help reduce casts when the expressions are expanded. In the (unusual) -+ // case that we're working with non-integral pointers, we have a subclass -+ // that stores that type explicitly. -+ if (hasNonIntegralPointers()) -+ return cast(this)->getType(); -+ return getOperand(getNumOperands() - 1)->getType(); -+ } -+ - /// This node represents multiplication of some number of SCEVs. - class SCEVMulExpr : public SCEVCommutativeExpr { - friend class ScalarEvolution; -@@ -242,6 +273,18 @@ class Type; - : SCEVCommutativeExpr(ID, scMulExpr, O, N) {} - - public: -+ Type *getType() const { -+ // In general, we can't form SCEVMulExprs with non-integral pointer types, -+ // but for the moment we need to allow a special case: Multiplying by -+ // -1 to be able express the difference between two pointers. In order -+ // to maintain the invariant that SCEVs with the NI flag set should have -+ // a type corresponding to the contained NI ptr, we need to return the -+ // type of the pointer here. -+ if (hasNonIntegralPointers()) -+ return getOperand(getNumOperands() - 1)->getType(); -+ return SCEVCommutativeExpr::getType(); -+ } -+ - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const SCEV *S) { - return S->getSCEVType() == scMulExpr; -@@ -467,9 +690,12 @@ class Type; - /// instances owned by a ScalarEvolution. - SCEVUnknown *Next; - -- SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, -- ScalarEvolution *se, SCEVUnknown *next) : -- SCEV(ID, scUnknown), CallbackVH(V), SE(se), Next(next) {} -+ SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, ScalarEvolution *se, -+ SCEVUnknown *next, bool ValueIsNIPtr) -+ : SCEV(ID, scUnknown), CallbackVH(V), SE(se), Next(next) { -+ if (ValueIsNIPtr) -+ SubclassData |= FlagHasNIPointers; -+ } - - // Implement CallbackVH. - void deleted() override; -diff --git llvm/lib/Analysis/ScalarEvolution.cpp llvm/lib/Analysis/ScalarEvolution.cpp -index cd74815a895..09e98345d0f 100644 ---- llvm/lib/Analysis/ScalarEvolution.cpp -+++ llvm/lib/Analysis/ScalarEvolution.cpp -@@ -354,12 +354,13 @@ Type *SCEV::getType() const { - case scSignExtend: - return cast(this)->getType(); - case scAddRecExpr: -- case scMulExpr: - case scUMaxExpr: - case scSMaxExpr: - case scUMinExpr: - case scSMinExpr: - return cast(this)->getType(); -+ case scMulExpr: -+ return cast(this)->getType(); - case scAddExpr: - return cast(this)->getType(); - case scUDivExpr: -@@ -2419,8 +2420,9 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, - } - - // Limit recursion calls depth. -- if (Depth > MaxArithDepth) -+ if (Depth > MaxArithDepth) { - return getOrCreateAddExpr(Ops, Flags); -+ } - - // Okay, check to see if the same value occurs in the operand list more than - // once. If so, merge them together into an multiply expression. Since we -@@ -2761,16 +2763,27 @@ ScalarEvolution::getOrCreateAddExpr(ArrayRef Ops, - SCEV::NoWrapFlags Flags) { - FoldingSetNodeID ID; - ID.AddInteger(scAddExpr); -- for (const SCEV *Op : Ops) -- ID.AddPointer(Op); -+ bool HasNIPtr = false; -+ PointerType *NIPtrType = nullptr; -+ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { -+ ID.AddPointer(Ops[i]); -+ if (Ops[i]->hasNonIntegralPointers()) { -+ HasNIPtr = true; -+ NIPtrType = cast(Ops[i]->getType()); -+ } -+ } - void *IP = nullptr; - SCEVAddExpr *S = - static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); - if (!S) { - const SCEV **O = SCEVAllocator.Allocate(Ops.size()); - std::uninitialized_copy(Ops.begin(), Ops.end(), O); -- S = new (SCEVAllocator) -- SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size()); -+ if (HasNIPtr) -+ S = new (SCEVAllocator) -+ SCEVAddNIExpr(ID.Intern(SCEVAllocator), O, Ops.size(), NIPtrType); -+ else -+ S = new (SCEVAllocator) -+ SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size()); - UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); - } -@@ -2783,8 +2763,10 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef Ops, - const Loop *L, SCEV::NoWrapFlags Flags) { - FoldingSetNodeID ID; - ID.AddInteger(scAddRecExpr); -- for (unsigned i = 0, e = Ops.size(); i != e; ++i) -+ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { -+ assert(i == 0 || !Ops[i]->hasNonIntegralPointers()); - ID.AddPointer(Ops[i]); -+ } - ID.AddPointer(L); - void *IP = nullptr; - SCEVAddRecExpr *S = -@@ -2798,6 +2813,7 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef Ops, - addToLoopUseLists(S); - } - S->setNoWrapFlags(Flags); -+ S->setHasNIPtr(Ops[0]->hasNonIntegralPointers()); - return S; - } - -@@ -2806,8 +2822,11 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef Ops, - SCEV::NoWrapFlags Flags) { - FoldingSetNodeID ID; - ID.AddInteger(scMulExpr); -- for (unsigned i = 0, e = Ops.size(); i != e; ++i) -+ bool HasNIPtr = false; -+ for (unsigned i = 0, e = Ops.size(); i != e; ++i) { -+ HasNIPtr |= Ops[i]->hasNonIntegralPointers(); - ID.AddPointer(Ops[i]); -+ } - void *IP = nullptr; - SCEVMulExpr *S = - static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); -@@ -2820,6 +2839,7 @@ ScalarEvolution::getOrCreateMulExpr(ArrayRef Ops, - addToLoopUseLists(S); - } - S->setNoWrapFlags(Flags); -+ S->setHasNIPtr(HasNIPtr); - return S; - } - -@@ -3631,8 +3591,11 @@ const SCEV *ScalarEvolution::getMinMaxExpr(unsigned Kind, - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - const SCEV **O = SCEVAllocator.Allocate(Ops.size()); - std::uninitialized_copy(Ops.begin(), Ops.end(), O); -- SCEV *S = new (SCEVAllocator) SCEVMinMaxExpr( -+ SCEVMinMaxExpr *S = new (SCEVAllocator) SCEVMinMaxExpr( - ID.Intern(SCEVAllocator), static_cast(Kind), O, Ops.size()); -+ // For MinMaxExprs it's sufficient to see if the first Op has NI data, as the -+ // operands all need to be of the same type. -+ S->setHasNIPtr(Ops[0]->hasNonIntegralPointers()); - UniqueSCEVs.InsertNode(S, IP); - addToLoopUseLists(S); - return S; -@@ -3708,8 +3731,9 @@ const SCEV *ScalarEvolution::getUnknown(Value *V) { - "Stale SCEVUnknown in uniquing map!"); - return S; - } -+ bool ValueIsNIPtr = getDataLayout().isNonIntegralPointerType(V->getType()); - SCEV *S = new (SCEVAllocator) SCEVUnknown(ID.Intern(SCEVAllocator), V, this, -- FirstUnknown); -+ FirstUnknown, ValueIsNIPtr); - FirstUnknown = cast(S); - UniqueSCEVs.InsertNode(S, IP); - return S; -diff --git llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll -index 5648e3aa74a..6936521f3a6 100644 ---- llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll -+++ llvm/test/Transforms/LoopStrengthReduce/nonintegral.ll -@@ -2,7 +2,7 @@ - - ; Address Space 10 is non-integral. The optimizer is not allowed to use - ; ptrtoint/inttoptr instructions. Make sure that this doesn't happen --target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12" -+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13" - target triple = "x86_64-unknown-linux-gnu" - - define void @japi1__unsafe_getindex_65028(i64 addrspace(10)* %arg) { -@@ -43,3 +43,36 @@ if38: ; preds = %L119 - done: ; preds = %if38 - ret void - } -+ -+; This is a bugpoint-reduced regression test - It doesn't make too much sense by itself, -+; but creates the correct SCEV expressions to reproduce the issue. See -+; https://github.com/JuliaLang/julia/issues/31156 for the original bug report. -+define void @"japi1_permutedims!_4259"(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i1 %g, i8 addrspace(13)* %base) #0 { -+; CHECK-NOT: inttoptr -+; CHECK-NOT: ptrtoint -+; CHECK: getelementptr i8, i8 addrspace(13)* {{.*}}, i64 {{.*}} -+top: -+ br label %L42.L46_crit_edge.us -+ -+L42.L46_crit_edge.us: ; preds = %L82.us.us.loopexit, %top -+ %value_phi11.us = phi i64 [ %a, %top ], [ %2, %L82.us.us.loopexit ] -+ %0 = sub i64 %value_phi11.us, %b -+ %1 = add i64 %0, %c -+ %spec.select = select i1 %g, i64 %d, i64 0 -+ br label %L62.us.us -+ -+L82.us.us.loopexit: ; preds = %L62.us.us -+ %2 = add i64 %e, %value_phi11.us -+ br label %L42.L46_crit_edge.us -+ -+L62.us.us: ; preds = %L62.us.us, %L42.L46_crit_edge.us -+ %value_phi21.us.us = phi i64 [ %6, %L62.us.us ], [ %spec.select, %L42.L46_crit_edge.us ] -+ %3 = add i64 %1, %value_phi21.us.us -+ %4 = getelementptr inbounds i8, i8 addrspace(13)* %base, i64 %3 -+ %5 = load i8, i8 addrspace(13)* %4, align 1 -+ %6 = add i64 %f, %value_phi21.us.us -+ br i1 %g, label %L82.us.us.loopexit, label %L62.us.us, !llvm.loop !1 -+} -+ -+!1 = distinct !{!1, !2} -+!2 = !{!"llvm.loop.isvectorized", i32 1} --- -2.25.1 - diff --git a/deps/patches/llvm-9.0-D65174-limit-merge-stores.patch b/deps/patches/llvm-9.0-D65174-limit-merge-stores.patch deleted file mode 100644 index 6d6cfb4acd800..0000000000000 --- a/deps/patches/llvm-9.0-D65174-limit-merge-stores.patch +++ /dev/null @@ -1,116 +0,0 @@ -commit f49c107f06c6a98d11a09d758f08554c78b9b933 -Author: Wei Mi -Date: Wed Jul 31 19:59:24 2019 +0000 - - [DAGCombine] Limit the number of times for the same store and root nodes - to bail out in store merging dependence check. - - We run into a case where dependence check in store merging bail out many times - for the same store and root nodes in a huge basicblock. That increases compile - time by almost 100x. The patch add a map to track how many times the bailing - out happen for the same store and root, and if it is over a limit, stop - considering the store with the same root as a merging candidate. - - Differential Revision: https://reviews.llvm.org/D65174 - - llvm-svn: 367472 - -diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -index bf62aa86509..2e5ba82af22 100644 ---- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp -@@ -120,6 +120,11 @@ static cl::opt TokenFactorInlineLimit( - "combiner-tokenfactor-inline-limit", cl::Hidden, cl::init(2048), - cl::desc("Limit the number of operands to inline for Token Factors")); - -+static cl::opt StoreMergeDependenceLimit( -+ "combiner-store-merge-dependence-limit", cl::Hidden, cl::init(10), -+ cl::desc("Limit the number of times for the same StoreNode and RootNode " -+ "to bail out in store merging dependence check")); -+ - namespace { - - class DAGCombiner { -@@ -157,6 +162,14 @@ namespace { - /// which have not yet been combined to the worklist. - SmallPtrSet CombinedNodes; - -+ /// Map from candidate StoreNode to the pair of RootNode and count. -+ /// The count is used to track how many times we have seen the StoreNode -+ /// with the same RootNode bail out in dependence check. If we have seen -+ /// the bail out for the same pair many times over a limit, we won't -+ /// consider the StoreNode with the same RootNode as store merging -+ /// candidate again. -+ DenseMap> StoreRootCountMap; -+ - // AA - Used for DAG load/store alias analysis. - AliasAnalysis *AA; - -@@ -241,6 +254,7 @@ namespace { - void removeFromWorklist(SDNode *N) { - CombinedNodes.erase(N); - PruningList.remove(N); -+ StoreRootCountMap.erase(N); - - auto It = WorklistMap.find(N); - if (It == WorklistMap.end()) -@@ -15423,6 +15437,18 @@ void DAGCombiner::getStoreMergeCandidates( - return (BasePtr.equalBaseIndex(Ptr, DAG, Offset)); - }; - -+ // Check if the pair of StoreNode and the RootNode already bail out many -+ // times which is over the limit in dependence check. -+ auto OverLimitInDependenceCheck = [&](SDNode *StoreNode, -+ SDNode *RootNode) -> bool { -+ auto RootCount = StoreRootCountMap.find(StoreNode); -+ if (RootCount != StoreRootCountMap.end() && -+ RootCount->second.first == RootNode && -+ RootCount->second.second > StoreMergeDependenceLimit) -+ return true; -+ return false; -+ }; -+ - // We looking for a root node which is an ancestor to all mergable - // stores. We search up through a load, to our root and then down - // through all children. For instance we will find Store{1,2,3} if -@@ -15452,7 +15478,8 @@ void DAGCombiner::getStoreMergeCandidates( - if (StoreSDNode *OtherST = dyn_cast(*I2)) { - BaseIndexOffset Ptr; - int64_t PtrDiff; -- if (CandidateMatch(OtherST, Ptr, PtrDiff)) -+ if (CandidateMatch(OtherST, Ptr, PtrDiff) && -+ !OverLimitInDependenceCheck(OtherST, RootNode)) - StoreNodes.push_back(MemOpLink(OtherST, PtrDiff)); - } - } else -@@ -15462,7 +15489,8 @@ void DAGCombiner::getStoreMergeCandidates( - if (StoreSDNode *OtherST = dyn_cast(*I)) { - BaseIndexOffset Ptr; - int64_t PtrDiff; -- if (CandidateMatch(OtherST, Ptr, PtrDiff)) -+ if (CandidateMatch(OtherST, Ptr, PtrDiff) && -+ !OverLimitInDependenceCheck(OtherST, RootNode)) - StoreNodes.push_back(MemOpLink(OtherST, PtrDiff)); - } - } -@@ -15520,8 +15548,19 @@ bool DAGCombiner::checkMergeStoreCandidatesForDependencies( - // Search through DAG. We can stop early if we find a store node. - for (unsigned i = 0; i < NumStores; ++i) - if (SDNode::hasPredecessorHelper(StoreNodes[i].MemNode, Visited, Worklist, -- Max)) -+ Max)) { -+ // If the searching bail out, record the StoreNode and RootNode in the -+ // StoreRootCountMap. If we have seen the pair many times over a limit, -+ // we won't add the StoreNode into StoreNodes set again. -+ if (Visited.size() >= Max) { -+ auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode]; -+ if (RootCount.first == RootNode) -+ RootCount.second++; -+ else -+ RootCount = {RootNode, 1}; -+ } - return false; -+ } - return true; - } - diff --git a/deps/patches/llvm-9.0-D78196.patch b/deps/patches/llvm-9.0-D78196.patch deleted file mode 100644 index 6ae23fd7d8600..0000000000000 --- a/deps/patches/llvm-9.0-D78196.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp ---- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp -+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp -@@ -210,6 +210,10 @@ - for (auto *Sym : UpdateOther) - if (Sym->isVariable()) - copyLocalEntry(Sym, Sym->getVariableValue()); -+ -+ // Clear the set of symbols that needs to be updated so the streamer can -+ // be reused without issues. -+ UpdateOther.clear(); - } - - private: - diff --git a/deps/patches/llvm-9.0-D85499.patch b/deps/patches/llvm-9.0-D85499.patch deleted file mode 100644 index 1be91fc4717f5..0000000000000 --- a/deps/patches/llvm-9.0-D85499.patch +++ /dev/null @@ -1,425 +0,0 @@ -commit ac8729e23232d0fd3933b76093a40b7c65332aff -Author: Keno Fischer -Date: Fri Aug 7 00:31:43 2020 -0400 - - [X86] Canonicalize andnp for bitmask arithmetic - - We have a DAG combine that tries to fold (vselect cond, 0000..., X) -> (andnp cond, x). - However, it does so by attempting to create an i64 vector with the number - of elements obtained by truncating division by 64 from the bitwidth. This is - bad for mask vectors like v8i1, since that division is just zero. Besides, - we don't want i64 vectors anyway. The easy change is just to avoid changing - the VT, but this is slightly problematic because the canonical pattern for - `kandn` is `(and (vnot a) b)` rather than `(x86andnp a b)`, so this fails - to select. Rather than playing games here with having the mask vectors - use a different canonical representation, the bulk of this commit switches - the canonical ISD representation for `kandn` to `(x86andnp a b)` such - that all vector types may be handled equally here. To avoid regressing - other tests, we need to extend a few other folds to handle `x86andnp` in - addition to plain `and`. However, that should be generally a good - improvement, since x86andnp is already canonical for non-i1 vectors - prior to this commit, and said folds were just missing. - - When all is said and done, fixes the issue reported in - https://github.com/JuliaLang/julia/issues/36955. - - Differential Revision: https://reviews.llvm.org/D85499 - -diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp -index 34ad589d205..eb21b0de89d 100644 ---- a/lib/Target/X86/X86ISelDAGToDAG.cpp -+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp -@@ -503,7 +503,7 @@ namespace { - bool isMaskZeroExtended(SDNode *N) const; - bool tryShiftAmountMod(SDNode *N); - bool tryShrinkShlLogicImm(SDNode *N); -- bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask); -+ bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask, bool Invert); - - MachineSDNode *emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad, - const SDLoc &dl, MVT VT, SDNode *Node); -@@ -2998,7 +2998,7 @@ bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) { - bool IsNegOne = isAllOnesConstant(StoredVal.getOperand(1)); - // ADD/SUB with 1/-1 and carry flag isn't used can use inc/dec. - if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.getValue(1))) { -- unsigned NewOpc = -+ unsigned NewOpc = - ((Opc == X86ISD::ADD) == IsOne) - ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m) - : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m); -@@ -3999,8 +3999,8 @@ static unsigned getVPTESTMOpc(MVT TestVT, bool IsTestN, bool FoldedLoad, - - // Try to create VPTESTM instruction. If InMask is not null, it will be used - // to form a masked operation. --bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root, SDValue Setcc, -- SDValue InMask) { -+bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue InMask, -+ bool Invert) { - assert(Subtarget->hasAVX512() && "Expected AVX512!"); - assert(Setcc.getSimpleValueType().getVectorElementType() == MVT::i1 && - "Unexpected VT!"); -@@ -4140,6 +4140,9 @@ bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root, SDValue Setcc, - } - - bool IsTestN = CC == ISD::SETEQ; -+ if (Invert) -+ IsTestN = !IsTestN; -+ - unsigned Opc = getVPTESTMOpc(CmpVT, IsTestN, FoldedLoad, FoldedBCast, - IsMasked); - -@@ -4309,16 +4312,27 @@ void X86DAGToDAGISel::Select(SDNode *Node) { - return; - break; - -+ case X86ISD::ANDNP: -+ if (NVT.isVector() && NVT.getVectorElementType() == MVT::i1) { -+ SDValue N0 = Node->getOperand(0); -+ SDValue N1 = Node->getOperand(1); -+ // Try to form a masked VPTESTM -+ if (N0.getOpcode() == ISD::SETCC && N0.hasOneUse() && -+ tryVPTESTM(Node, N0, N1, true)) -+ return; -+ } -+ break; -+ - case ISD::AND: - if (NVT.isVector() && NVT.getVectorElementType() == MVT::i1) { - // Try to form a masked VPTESTM. Operands can be in either order. - SDValue N0 = Node->getOperand(0); - SDValue N1 = Node->getOperand(1); - if (N0.getOpcode() == ISD::SETCC && N0.hasOneUse() && -- tryVPTESTM(Node, N0, N1)) -+ tryVPTESTM(Node, N0, N1, false)) - return; - if (N1.getOpcode() == ISD::SETCC && N1.hasOneUse() && -- tryVPTESTM(Node, N1, N0)) -+ tryVPTESTM(Node, N1, N0, false)) - return; - } - -@@ -5000,7 +5014,7 @@ void X86DAGToDAGISel::Select(SDNode *Node) { - } - - case ISD::SETCC: { -- if (NVT.isVector() && tryVPTESTM(Node, SDValue(Node, 0), SDValue())) -+ if (NVT.isVector() && tryVPTESTM(Node, SDValue(Node, 0), SDValue(), false)) - return; - - break; -diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp -index 920cdd7e625..6b9738074c7 100644 ---- a/lib/Target/X86/X86ISelLowering.cpp -+++ b/lib/Target/X86/X86ISelLowering.cpp -@@ -196,7 +196,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, - // Integer absolute. - if (Subtarget.hasCMov()) { - setOperationAction(ISD::ABS , MVT::i16 , Custom); -- setOperationAction(ISD::ABS , MVT::i32 , Custom); -+ setOperationAction(ISD::ABS , MVT::i32 , Custom); - } - setOperationAction(ISD::ABS , MVT::i64 , Custom); - -@@ -26053,7 +26053,7 @@ X86TargetLowering::lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *AI) const { - - // If this is a canonical idempotent atomicrmw w/no uses, we have a better - // lowering available in lowerAtomicArith. -- // TODO: push more cases through this path. -+ // TODO: push more cases through this path. - if (auto *C = dyn_cast(AI->getValOperand())) - if (AI->getOperation() == AtomicRMWInst::Or && C->isZero() && - AI->use_empty()) -@@ -26111,7 +26111,7 @@ X86TargetLowering::lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *AI) const { - /// Emit a locked operation on a stack location which does not change any - /// memory location, but does involve a lock prefix. Location is chosen to be - /// a) very likely accessed only by a single thread to minimize cache traffic, --/// and b) definitely dereferenceable. Returns the new Chain result. -+/// and b) definitely dereferenceable. Returns the new Chain result. - static SDValue emitLockedStackOp(SelectionDAG &DAG, - const X86Subtarget &Subtarget, - SDValue Chain, SDLoc DL) { -@@ -26120,22 +26120,22 @@ static SDValue emitLockedStackOp(SelectionDAG &DAG, - // operations issued by the current processor. As such, the location - // referenced is not relevant for the ordering properties of the instruction. - // See: Intel® 64 and IA-32 ArchitecturesSoftware Developer’s Manual, -- // 8.2.3.9 Loads and Stores Are Not Reordered with Locked Instructions -+ // 8.2.3.9 Loads and Stores Are Not Reordered with Locked Instructions - // 2) Using an immediate operand appears to be the best encoding choice - // here since it doesn't require an extra register. - // 3) OR appears to be very slightly faster than ADD. (Though, the difference - // is small enough it might just be measurement noise.) - // 4) When choosing offsets, there are several contributing factors: - // a) If there's no redzone, we default to TOS. (We could allocate a cache -- // line aligned stack object to improve this case.) -+ // line aligned stack object to improve this case.) - // b) To minimize our chances of introducing a false dependence, we prefer -- // to offset the stack usage from TOS slightly. -+ // to offset the stack usage from TOS slightly. - // c) To minimize concerns about cross thread stack usage - in particular, - // the idiomatic MyThreadPool.run([&StackVars]() {...}) pattern which - // captures state in the TOS frame and accesses it from many threads - - // we want to use an offset such that the offset is in a distinct cache - // line from the TOS frame. -- // -+ // - // For a general discussion of the tradeoffs and benchmark results, see: - // https://shipilev.net/blog/2014/on-the-fence-with-dependencies/ - -@@ -26188,7 +26188,7 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, const X86Subtarget &Subtarget, - if (Subtarget.hasMFence()) - return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0)); - -- SDValue Chain = Op.getOperand(0); -+ SDValue Chain = Op.getOperand(0); - return emitLockedStackOp(DAG, Subtarget, Chain, dl); - } - -@@ -26677,12 +26677,12 @@ static SDValue lowerAtomicArith(SDValue N, SelectionDAG &DAG, - // seq_cst which isn't SingleThread, everything just needs to be preserved - // during codegen and then dropped. Note that we expect (but don't assume), - // that orderings other than seq_cst and acq_rel have been canonicalized to -- // a store or load. -+ // a store or load. - if (AN->getOrdering() == AtomicOrdering::SequentiallyConsistent && - AN->getSyncScopeID() == SyncScope::System) { - // Prefer a locked operation against a stack location to minimize cache - // traffic. This assumes that stack locations are very likely to be -- // accessed only by the owning thread. -+ // accessed only by the owning thread. - SDValue NewChain = emitLockedStackOp(DAG, Subtarget, Chain, DL); - assert(!N->hasAnyUseOfValue(0)); - // NOTE: The getUNDEF is needed to give something for the unused result 0. -@@ -35620,7 +35620,7 @@ static SDValue scalarizeExtEltFP(SDNode *ExtElt, SelectionDAG &DAG) { - } - - // TODO: This switch could include FNEG and the x86-specific FP logic ops -- // (FAND, FANDN, FOR, FXOR). But that may require enhancements to avoid -+ // (FAND, FANDN, FOR, FXOR). But that may require enhancements to avoid - // missed load folding and fma+fneg combining. - switch (Vec.getOpcode()) { - case ISD::FMA: // Begin 3 operands -@@ -35935,10 +35935,8 @@ combineVSelectWithAllOnesOrZeros(SDNode *N, SelectionDAG &DAG, - - // vselect Cond, 000..., X -> andn Cond, X - if (TValIsAllZeros) { -- MVT AndNVT = MVT::getVectorVT(MVT::i64, CondVT.getSizeInBits() / 64); -- SDValue CastCond = DAG.getBitcast(AndNVT, Cond); -- SDValue CastRHS = DAG.getBitcast(AndNVT, RHS); -- SDValue AndN = DAG.getNode(X86ISD::ANDNP, DL, AndNVT, CastCond, CastRHS); -+ SDValue CastRHS = DAG.getBitcast(CondVT, RHS); -+ SDValue AndN = DAG.getNode(X86ISD::ANDNP, DL, CondVT, Cond, CastRHS); - return DAG.getBitcast(VT, AndN); - } - -@@ -38147,12 +38145,17 @@ static SDValue IsNOT(SDValue V, SelectionDAG &DAG) { - return SDValue(); - } - --/// Try to fold: (and (xor X, -1), Y) -> (andnp X, Y). --static SDValue combineANDXORWithAllOnesIntoANDNP(SDNode *N, SelectionDAG &DAG) { -+ -+/// Try to fold: -+/// (and (not X), Y) -> (andnp X, Y) -+/// (and (xor X, -1), Y) -> (andnp X, Y). -+static SDValue combineANDXORWithAllOnesIntoANDNP(SDNode *N, SelectionDAG &DAG, -+ const X86Subtarget &Subtarget) { - assert(N->getOpcode() == ISD::AND); - - MVT VT = N->getSimpleValueType(0); -- if (!VT.is128BitVector() && !VT.is256BitVector() && !VT.is512BitVector()) -+ if (!VT.is128BitVector() && !VT.is256BitVector() && !VT.is512BitVector() && -+ !(VT.isVector() && VT.getVectorElementType() == MVT::i1 && Subtarget.hasAVX512())) - return SDValue(); - - SDValue X, Y; -@@ -38558,7 +38561,7 @@ static SDValue combineAnd(SDNode *N, SelectionDAG &DAG, - if (SDValue FPLogic = convertIntLogicToFPLogic(N, DAG, Subtarget)) - return FPLogic; - -- if (SDValue R = combineANDXORWithAllOnesIntoANDNP(N, DAG)) -+ if (SDValue R = combineANDXORWithAllOnesIntoANDNP(N, DAG, Subtarget)) - return R; - - if (SDValue ShiftRight = combineAndMaskToShift(N, DAG, Subtarget)) -diff --git a/lib/Target/X86/X86InstrAVX512.td b/lib/Target/X86/X86InstrAVX512.td -index 54eddeacaa1..91027fa903f 100644 ---- a/lib/Target/X86/X86InstrAVX512.td -+++ b/lib/Target/X86/X86InstrAVX512.td -@@ -2978,7 +2978,6 @@ multiclass avx512_mask_binop_all opc, string OpcodeStr, - def andn : PatFrag<(ops node:$i0, node:$i1), (and (not node:$i0), node:$i1)>; - def xnor : PatFrag<(ops node:$i0, node:$i1), (not (xor node:$i0, node:$i1))>; - // These nodes use 'vnot' instead of 'not' to support vectors. --def vandn : PatFrag<(ops node:$i0, node:$i1), (and (vnot node:$i0), node:$i1)>; - def vxnor : PatFrag<(ops node:$i0, node:$i1), (vnot (xor node:$i0, node:$i1))>; - - // TODO - do we need a X86SchedWriteWidths::KMASK type? -@@ -2986,7 +2985,7 @@ defm KAND : avx512_mask_binop_all<0x41, "kand", and, SchedWriteVecLogic.XM - defm KOR : avx512_mask_binop_all<0x45, "kor", or, SchedWriteVecLogic.XMM, 1>; - defm KXNOR : avx512_mask_binop_all<0x46, "kxnor", vxnor, SchedWriteVecLogic.XMM, 1>; - defm KXOR : avx512_mask_binop_all<0x47, "kxor", xor, SchedWriteVecLogic.XMM, 1>; --defm KANDN : avx512_mask_binop_all<0x42, "kandn", vandn, SchedWriteVecLogic.XMM, 0>; -+defm KANDN : avx512_mask_binop_all<0x42, "kandn", X86andnp, SchedWriteVecLogic.XMM, 0>; - defm KADD : avx512_mask_binop_all<0x4A, "kadd", X86kadd, SchedWriteVecLogic.XMM, 1, HasDQI>; - - multiclass avx512_binop_pat; --defm : avx512_binop_pat; -+defm : avx512_binop_pat; - defm : avx512_binop_pat; - defm : avx512_binop_pat; - defm : avx512_binop_pat; -@@ -11570,7 +11569,7 @@ multiclass avx512_fixupimm_scalar opc, string OpcodeStr, - } - - multiclass avx512_fixupimm_packed_all { - let Predicates = [HasAVX512] in - defm Z : avx512_fixupimm_packed_sae<0x54, "vfixupimm", sched.ZMM, -@@ -11687,7 +11686,7 @@ multiclass AVX512_scalar_math_fp_patterns("V"#OpcPrefix#Zrr_Intkz) -+ (!cast("V"#OpcPrefix#Zrr_Intkz) - VK1WM:$mask, _.VT:$src1, - (_.VT (COPY_TO_REGCLASS _.FRC:$src2, VR128X)))>; - def : Pat<(MoveNode (_.VT VR128X:$src1), -diff --git a/test/CodeGen/X86/avx512-select.ll b/test/CodeGen/X86/avx512-select.ll -index 1ed7b408baf..64320d63eac 100644 ---- a/test/CodeGen/X86/avx512-select.ll -+++ b/test/CodeGen/X86/avx512-select.ll -@@ -595,3 +595,74 @@ define <16 x i64> @narrowExtractedVectorSelect_crash(<16 x i64> %arg, <16 x i16> - %tmp3 = zext <16 x i16> %tmp2 to <16 x i64> - ret <16 x i64> %tmp3 - } -+ -+; Regression test from https://github.com/JuliaLang/julia/issues/36955 -+define i8 @julia_issue36955(<8 x i1> %mask, <8 x double> %a) { -+; X86-AVX512F-LABEL: julia_issue36955: -+; X86-AVX512F: # %bb.0: -+; X86-AVX512F-NEXT: vpmovsxwq %xmm0, %zmm0 -+; X86-AVX512F-NEXT: vpsllq $63, %zmm0, %zmm0 -+; X86-AVX512F-NEXT: vptestmq %zmm0, %zmm0, %k0 -+; X86-AVX512F-NEXT: vpxor %xmm0, %xmm0, %xmm0 -+; X86-AVX512F-NEXT: vcmpnlepd %zmm0, %zmm1, %k1 -+; X86-AVX512F-NEXT: kandnw %k0, %k1, %k0 -+; X86-AVX512F-NEXT: kandw %k1, %k0, %k0 -+; X86-AVX512F-NEXT: knotw %k1, %k1 -+; X86-AVX512F-NEXT: korw %k1, %k0, %k0 -+; X86-AVX512F-NEXT: kmovw %k0, %eax -+; X86-AVX512F-NEXT: # kill: def $al killed $al killed $eax -+; X86-AVX512F-NEXT: vzeroupper -+; X86-AVX512F-NEXT: retl -+; -+; X64-AVX512F-LABEL: julia_issue36955: -+; X64-AVX512F: # %bb.0: -+; X64-AVX512F-NEXT: vpmovsxwq %xmm0, %zmm0 -+; X64-AVX512F-NEXT: vpsllq $63, %zmm0, %zmm0 -+; X64-AVX512F-NEXT: vptestmq %zmm0, %zmm0, %k0 -+; X64-AVX512F-NEXT: vpxor %xmm0, %xmm0, %xmm0 -+; X64-AVX512F-NEXT: vcmpnlepd %zmm0, %zmm1, %k1 -+; X64-AVX512F-NEXT: kandnw %k0, %k1, %k0 -+; X64-AVX512F-NEXT: kandw %k1, %k0, %k0 -+; X64-AVX512F-NEXT: knotw %k1, %k1 -+; X64-AVX512F-NEXT: korw %k1, %k0, %k0 -+; X64-AVX512F-NEXT: kmovw %k0, %eax -+; X64-AVX512F-NEXT: # kill: def $al killed $al killed $eax -+; X64-AVX512F-NEXT: vzeroupper -+; X64-AVX512F-NEXT: retq -+; -+; X86-AVX512BW-LABEL: julia_issue36955: -+; X86-AVX512BW: # %bb.0: -+; X86-AVX512BW-NEXT: vpsllw $15, %xmm0, %xmm0 -+; X86-AVX512BW-NEXT: vpmovw2m %zmm0, %k0 -+; X86-AVX512BW-NEXT: vpxor %xmm0, %xmm0, %xmm0 -+; X86-AVX512BW-NEXT: vcmpnlepd %zmm0, %zmm1, %k1 -+; X86-AVX512BW-NEXT: kandnw %k0, %k1, %k0 -+; X86-AVX512BW-NEXT: kandw %k1, %k0, %k0 -+; X86-AVX512BW-NEXT: knotw %k1, %k1 -+; X86-AVX512BW-NEXT: korw %k1, %k0, %k0 -+; X86-AVX512BW-NEXT: kmovd %k0, %eax -+; X86-AVX512BW-NEXT: # kill: def $al killed $al killed $eax -+; X86-AVX512BW-NEXT: vzeroupper -+; X86-AVX512BW-NEXT: retl -+; -+; X64-AVX512BW-LABEL: julia_issue36955: -+; X64-AVX512BW: # %bb.0: -+; X64-AVX512BW-NEXT: vpsllw $15, %xmm0, %xmm0 -+; X64-AVX512BW-NEXT: vpmovw2m %zmm0, %k0 -+; X64-AVX512BW-NEXT: vpxor %xmm0, %xmm0, %xmm0 -+; X64-AVX512BW-NEXT: vcmpnlepd %zmm0, %zmm1, %k1 -+; X64-AVX512BW-NEXT: kandnw %k0, %k1, %k0 -+; X64-AVX512BW-NEXT: kandw %k1, %k0, %k0 -+; X64-AVX512BW-NEXT: knotw %k1, %k1 -+; X64-AVX512BW-NEXT: korw %k1, %k0, %k0 -+; X64-AVX512BW-NEXT: kmovd %k0, %eax -+; X64-AVX512BW-NEXT: # kill: def $al killed $al killed $eax -+; X64-AVX512BW-NEXT: vzeroupper -+; X64-AVX512BW-NEXT: retq -+ %fcmp = fcmp ugt <8 x double> %a, zeroinitializer -+ %xor = xor <8 x i1> %fcmp, -+ %select1 = select <8 x i1> %fcmp, <8 x i1> zeroinitializer, <8 x i1> %mask -+ %select2 = select <8 x i1> %xor, <8 x i1> , <8 x i1> %select1 -+ %ret = bitcast <8 x i1> %select2 to i8 -+ ret i8 %ret -+} -diff --git a/test/CodeGen/X86/combine-bitselect.ll b/test/CodeGen/X86/combine-bitselect.ll -index 8cb6a4dca09..3c08a871c86 100644 ---- a/test/CodeGen/X86/combine-bitselect.ll -+++ b/test/CodeGen/X86/combine-bitselect.ll -@@ -616,13 +616,13 @@ define <4 x i1> @bitselect_v4i1_loop(<4 x i32> %a0, <4 x i32> %a1) { - ; AVX512F: # %bb.0: # %bb - ; AVX512F-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1 - ; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0 --; AVX512F-NEXT: vpbroadcastd {{.*#+}} xmm2 = [12,12,12,12] --; AVX512F-NEXT: vpcmpeqd %zmm2, %zmm1, %k1 -+; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k1 -+; AVX512F-NEXT: vpbroadcastd {{.*#+}} xmm0 = [12,12,12,12] - ; AVX512F-NEXT: vpbroadcastd {{.*#+}} xmm2 = [15,15,15,15] --; AVX512F-NEXT: vpcmpeqd %zmm2, %zmm1, %k2 --; AVX512F-NEXT: vptestnmd %zmm0, %zmm0, %k0 {%k2} --; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k1 {%k1} --; AVX512F-NEXT: korw %k0, %k1, %k1 -+; AVX512F-NEXT: vpcmpeqd %zmm2, %zmm1, %k0 -+; AVX512F-NEXT: vpcmpeqd %zmm0, %zmm1, %k2 {%k1} -+; AVX512F-NEXT: kandnw %k0, %k1, %k0 -+; AVX512F-NEXT: korw %k0, %k2, %k1 - ; AVX512F-NEXT: vpternlogd $255, %zmm0, %zmm0, %zmm0 {%k1} {z} - ; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0 - ; AVX512F-NEXT: vzeroupper -diff --git a/test/CodeGen/X86/vec_ssubo.ll b/test/CodeGen/X86/vec_ssubo.ll -index 515dc5c5aa2..dfb1e7c4dee 100644 ---- a/test/CodeGen/X86/vec_ssubo.ll -+++ b/test/CodeGen/X86/vec_ssubo.ll -@@ -1640,7 +1640,7 @@ define <4 x i32> @ssubo_v4i1(<4 x i1> %a0, <4 x i1> %a1, <4 x i1>* %p2) nounwind - ; AVX512-NEXT: vptestmd %xmm1, %xmm1, %k0 - ; AVX512-NEXT: vpslld $31, %xmm0, %xmm0 - ; AVX512-NEXT: vptestmd %xmm0, %xmm0, %k1 --; AVX512-NEXT: vptestnmd %xmm1, %xmm1, %k2 {%k1} -+; AVX512-NEXT: kandnw %k1, %k0, %k2 - ; AVX512-NEXT: kxorw %k0, %k1, %k0 - ; AVX512-NEXT: kxorw %k2, %k0, %k1 - ; AVX512-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0 -diff --git a/test/CodeGen/X86/vec_usubo.ll b/test/CodeGen/X86/vec_usubo.ll -index c5a7b19cf14..367c491d25a 100644 ---- a/test/CodeGen/X86/vec_usubo.ll -+++ b/test/CodeGen/X86/vec_usubo.ll -@@ -1244,10 +1244,10 @@ define <4 x i32> @usubo_v4i1(<4 x i1> %a0, <4 x i1> %a1, <4 x i1>* %p2) nounwind - ; AVX512: # %bb.0: - ; AVX512-NEXT: vpslld $31, %xmm0, %xmm0 - ; AVX512-NEXT: vptestmd %xmm0, %xmm0, %k0 --; AVX512-NEXT: vpslld $31, %xmm1, %xmm1 --; AVX512-NEXT: vptestmd %xmm1, %xmm1, %k1 -+; AVX512-NEXT: vpslld $31, %xmm1, %xmm0 -+; AVX512-NEXT: vptestmd %xmm0, %xmm0, %k1 - ; AVX512-NEXT: kxorw %k1, %k0, %k1 --; AVX512-NEXT: vptestnmd %xmm0, %xmm0, %k2 {%k1} -+; AVX512-NEXT: kandnw %k1, %k0, %k2 - ; AVX512-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0 - ; AVX512-NEXT: vmovdqa32 %xmm0, %xmm0 {%k2} {z} - ; AVX512-NEXT: kmovd %k1, %eax diff --git a/deps/patches/llvm-D57118-powerpc.patch b/deps/patches/llvm-D57118-powerpc.patch deleted file mode 100644 index 328fe205d1280..0000000000000 --- a/deps/patches/llvm-D57118-powerpc.patch +++ /dev/null @@ -1,30 +0,0 @@ -commit 812db527538f30ac77a19d755e24109a6db7e569 -Author: Keno Fischer -Date: Wed Jan 23 16:46:59 2019 -0500 - - [CMake][PowerPC] Recognize LLVM_NATIVE_TARGET="ppc64le" as PowerPC - - Summary: - This value is derived from the host triple, which on the machine - I'm currently using is `ppc64le-linux-redhat`. This change makes - LLVM compile. - - Reviewers: hfinkel - - Subscribers: nemanjai, mgorny, jsji, llvm-commits - - Differential Revision: https://reviews.llvm.org/D57118 - -diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake -index 900c35ee4f0..b9c9757a4f6 100644 ---- a/cmake/config-ix.cmake -+++ b/cmake/config-ix.cmake -@@ -386,6 +386,8 @@ elseif (LLVM_NATIVE_ARCH MATCHES "sparc") - set(LLVM_NATIVE_ARCH Sparc) - elseif (LLVM_NATIVE_ARCH MATCHES "powerpc") - set(LLVM_NATIVE_ARCH PowerPC) -+elseif (LLVM_NATIVE_ARCH MATCHES "ppc64le") -+ set(LLVM_NATIVE_ARCH PowerPC) - elseif (LLVM_NATIVE_ARCH MATCHES "aarch64") - set(LLVM_NATIVE_ARCH AArch64) - elseif (LLVM_NATIVE_ARCH MATCHES "arm64") diff --git a/deps/patches/llvm-exegesis-mingw.patch b/deps/patches/llvm-exegesis-mingw.patch deleted file mode 100644 index ff11f4da8231e..0000000000000 --- a/deps/patches/llvm-exegesis-mingw.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 9ba86352649a39b03adce98670714c4c8eb5341d Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Wed, 24 Jul 2019 21:19:20 -0400 -Subject: [PATCH] Fix build of llvm-exegis on mingw32 - ---- - llvm/tools/llvm-exegesis/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/llvm-exegesis/CMakeLists.txt b/tools/llvm-exegesis/CMakeLists.txt -index a59e1b74024..7a30e0ea98f 100644 ---- a/tools/llvm-exegesis/CMakeLists.txt -+++ b/tools/llvm-exegesis/CMakeLists.txt -@@ -4,7 +4,7 @@ set(LLVM_LINK_COMPONENTS - native - ) - --add_llvm_tool(llvm-exegesis -+add_llvm_tool(llvm-exegesis DISABLE_LLVM_LINK_LLVM_DYLIB - llvm-exegesis.cpp - ) - --- -2.22.0 diff --git a/deps/patches/llvm-symver-jlprefix.patch b/deps/patches/llvm-symver-jlprefix.patch deleted file mode 100644 index 59872380ad073..0000000000000 --- a/deps/patches/llvm-symver-jlprefix.patch +++ /dev/null @@ -1,18 +0,0 @@ -From f23277bb91a4925ba8763337137a3123a7600557 Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Tue, 16 Jan 2018 17:29:05 -0500 -Subject: [PATCH] add JL prefix to all LLVM version suffixes - ---- - tools/llvm-shlib/simple_version_script.map.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/llvm-shlib/simple_version_script.map.in b/tools/llvm-shlib/simple_version_script.map.in -index e9515fe7862..af082581627 100644 ---- a/tools/llvm-shlib/simple_version_script.map.in -+++ b/tools/llvm-shlib/simple_version_script.map.in -@@ -1 +1 @@ --LLVM_@LLVM_VERSION_MAJOR@.@LLVM_VERSION_MINOR@ { global: *; }; -+JL_LLVM_@LLVM_VERSION_MAJOR@.@LLVM_VERSION_MINOR@ { global: *; }; --- -2.15.1 diff --git a/deps/patches/llvm-test-plugin-mingw.patch b/deps/patches/llvm-test-plugin-mingw.patch deleted file mode 100644 index 14cf07166d861..0000000000000 --- a/deps/patches/llvm-test-plugin-mingw.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 9bd3774db73533c8df475639805ff1516aea274c Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Wed, 24 Jul 2019 21:45:33 -0400 -Subject: [PATCH] add missing components to TestPlugin - ---- - llvm/unittests/Passes/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/unittests/Passes/CMakeLists.txt b/unittests/Passes/CMakeLists.txt -index 3e83b527958..4b09f47c234 100644 ---- a/unittests/Passes/CMakeLists.txt -+++ b/unittests/Passes/CMakeLists.txt -@@ -14,7 +14,7 @@ add_llvm_unittest(PluginsTests - export_executable_symbols(PluginsTests) - target_link_libraries(PluginsTests PRIVATE LLVMTestingSupport) - --set(LLVM_LINK_COMPONENTS) -+set(LLVM_LINK_COMPONENTS Support Passes Core) - add_llvm_library(TestPlugin MODULE BUILDTREE_ONLY - TestPlugin.cpp - ) --- -2.22.0 diff --git a/deps/patches/llvm7-D50010-VNCoercion-ni.patch b/deps/patches/llvm7-D50010-VNCoercion-ni.patch deleted file mode 100644 index 729c4185128c9..0000000000000 --- a/deps/patches/llvm7-D50010-VNCoercion-ni.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp -index 948d9bd5baa..fbd5b9bb3be 100644 ---- a/lib/Transforms/Utils/VNCoercion.cpp -+++ b/lib/Transforms/Utils/VNCoercion.cpp -@@ -20,7 +20,8 @@ bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, - StoredVal->getType()->isStructTy() || StoredVal->getType()->isArrayTy()) - return false; - -- uint64_t StoreSize = DL.getTypeSizeInBits(StoredVal->getType()); -+ Type *StoredValTy = StoredVal->getType(); -+ uint64_t StoreSize = DL.getTypeSizeInBits(StoredValTy); - - // The store size must be byte-aligned to support future type casts. - if (llvm::alignTo(StoreSize, 8) != StoreSize) -@@ -30,10 +31,15 @@ bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, - if (StoreSize < DL.getTypeSizeInBits(LoadTy)) - return false; - -- // Don't coerce non-integral pointers to integers or vice versa. -- if (DL.isNonIntegralPointerType(StoredVal->getType()) != -- DL.isNonIntegralPointerType(LoadTy)) -+ bool StoredNI = DL.isNonIntegralPointerType(StoredValTy); -+ bool LoadNI = DL.isNonIntegralPointerType(LoadTy); -+ if (StoredNI != LoadNI) { -+ return false; -+ } else if (StoredNI && LoadNI && -+ cast(StoredValTy)->getAddressSpace() != -+ cast(LoadTy)->getAddressSpace()) { - return false; -+ } - - return true; - } -diff --git a/test/Transforms/GVN/non-integral-pointers.ll b/test/Transforms/GVN/non-integral-pointers.ll -index 9ae4132231d..5217fc1a06a 100644 ---- a/test/Transforms/GVN/non-integral-pointers.ll -+++ b/test/Transforms/GVN/non-integral-pointers.ll -@@ -1,6 +1,6 @@ - ; RUN: opt -gvn -S < %s | FileCheck %s - --target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" -+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4:5" - target triple = "x86_64-unknown-linux-gnu" - - define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) { -@@ -37,3 +37,21 @@ define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) { - alwaysTaken: - ret i64 42 - } -+ -+ define i8 addrspace(5)* @multini(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) { -+ ; CHECK-LABEL: @multini( -+ ; CHECK-NOT: inttoptr -+ ; CHECK-NOT: ptrtoint -+ ; CHECK-NOT: addrspacecast -+ entry: -+ store i8 addrspace(4)* %val, i8 addrspace(4)** %loc -+ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken -+ -+ neverTaken: -+ %loc.bc = bitcast i8 addrspace(4)** %loc to i8 addrspace(5)** -+ %differentas = load i8 addrspace(5)*, i8 addrspace(5)** %loc.bc -+ ret i8 addrspace(5)* %differentas -+ -+ alwaysTaken: -+ ret i8 addrspace(5)* null -+ } diff --git a/deps/patches/llvm7-windows-race.patch b/deps/patches/llvm7-windows-race.patch deleted file mode 100644 index b6ae6bae43ba4..0000000000000 --- a/deps/patches/llvm7-windows-race.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt -index f59402ac4b0..5de4c6febe7 100644 ---- a/tools/llvm-config/CMakeLists.txt -+++ b/tools/llvm-config/CMakeLists.txt -@@ -77,5 +77,10 @@ if(CMAKE_CROSSCOMPILING AND NOT LLVM_CONFIG_PATH) - add_custom_target(NativeLLVMConfig DEPENDS ${LLVM_CONFIG_PATH}) - add_dependencies(NativeLLVMConfig CONFIGURE_LLVM_NATIVE) - -+ # Add a dependency on the host tblgen, which uses the same working -+ # directory and with which we're otherwise racing to build some -+ # of the utility libraries. -+ add_dependencies(NativeLLVMConfig LLVM-tablegen-host) -+ - add_dependencies(llvm-config NativeLLVMConfig) - endif() diff --git a/deps/patches/llvm9-D71443-PPC-MC-redef-symbol.patch b/deps/patches/llvm9-D71443-PPC-MC-redef-symbol.patch deleted file mode 100644 index 904514a60f83f..0000000000000 --- a/deps/patches/llvm9-D71443-PPC-MC-redef-symbol.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 5cd52dbfa9c60cfd12676924bed97701ee9bc4ef Mon Sep 17 00:00:00 2001 -From: Fangrui Song -Date: Thu, 12 Dec 2019 16:18:57 -0800 -Subject: [PATCH] [MC][PowerPC] Fix a crash when redefining a symbol after .set - -Fix PR44284. This is probably not valid assembly but we should not crash. - -Reviewed By: luporl, #powerpc, steven.zhang - -Differential Revision: https://reviews.llvm.org/D71443 - -(cherry picked from commit f99eedeb72644671cd584f48e4c136d47f6b0020) ---- - llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 3 ++- - llvm/test/MC/PowerPC/ppc64-localentry-symbols.s | 5 +++++ - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp -index 90c3c8d20ed..71f926c265e 100644 ---- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp -+++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp -@@ -196,7 +196,8 @@ public: - - void finish() override { - for (auto *Sym : UpdateOther) -- copyLocalEntry(Sym, Sym->getVariableValue()); -+ if (Sym->isVariable()) -+ copyLocalEntry(Sym, Sym->getVariableValue()); - } - - private: -diff --git llvm/test/MC/PowerPC/ppc64-localentry-symbols.s llvm/test/MC/PowerPC/ppc64-localentry-symbols.s -index f1d5c5d0ab1..a663af57ad4 100644 ---- llvm/test/MC/PowerPC/ppc64-localentry-symbols.s -+++ llvm/test/MC/PowerPC/ppc64-localentry-symbols.s -@@ -32,3 +32,8 @@ func: - nop - nop - .localentry func, 8 -+ -+## PR44284 Don't crash if err is redefined after .set -+.set err, _err -+.globl err -+err: --- -2.26.0 - diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index 454cb0333443c..cda30e3403b32 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -42,7 +42,7 @@ The default version of LLVM is specified in `deps/Versions.make`. You can overri a file called `Make.user` in the top-level directory and adding a line to it such as: ``` -LLVM_VER = 6.0.1 +LLVM_VER = 12.0.0 ``` Besides the LLVM release numerals, you can also use `LLVM_VER = svn` to build against the latest diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index ce94cc66f0641..4d55d3d69a8de 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -23,13 +23,8 @@ Type *get_llvm_vectype(jl_datatype_t *dt) const assert(nfields > 0); if (nfields < 2) return nullptr; -#if JL_LLVM_VERSION >= 110000 static Type *T_vec64 = FixedVectorType::get(T_int32, 2); static Type *T_vec128 = FixedVectorType::get(T_int32, 4); -#else - static Type *T_vec64 = VectorType::get(T_int32, 2); - static Type *T_vec128 = VectorType::get(T_int32, 4); -#endif Type *lltype; // Short vector should be either 8 bytes or 16 bytes. // Note that there are only two distinct fundamental types for diff --git a/src/abi_ppc64le.cpp b/src/abi_ppc64le.cpp index dd6f927d9c301..1564b79ce2332 100644 --- a/src/abi_ppc64le.cpp +++ b/src/abi_ppc64le.cpp @@ -134,11 +134,7 @@ Type *preferred_llvm_type(jl_datatype_t *dt, bool isret) const override jl_datatype_t *vecty = (jl_datatype_t*)jl_field_type(ty0, 0); assert(jl_is_datatype(vecty) && vecty->name == jl_vecelement_typename); Type *ety = bitstype_to_llvm(jl_tparam0(vecty)); -#if JL_LLVM_VERSION >= 110000 Type *vty = FixedVectorType::get(ety, jl_datatype_nfields(ty0)); -#else - Type *vty = VectorType::get(ety, jl_datatype_nfields(ty0)); -#endif return ArrayType::get(vty, hfa); } } diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 5dbdf7000f5e7..db3f9f4b0e22e 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -47,9 +47,7 @@ #include #include #include -#if JL_LLVM_VERSION >= 100000 #include -#endif #include #include @@ -62,12 +60,6 @@ namespace llvm { extern Pass *createLowerSimdLoopPass(); } -#if JL_LLVM_VERSION < 100000 -static const TargetMachine::CodeGenFileType CGFT_ObjectFile = TargetMachine::CGFT_ObjectFile; -static const TargetMachine::CodeGenFileType CGFT_AssemblyFile = TargetMachine::CGFT_AssemblyFile; -#endif - - #include "julia.h" #include "julia_internal.h" #include "jitlayers.h" @@ -946,23 +938,14 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM) { TargetPassConfig *PassConfig = TM->createPassConfig(PM); PassConfig->setDisableVerify(false); PM.add(PassConfig); -#if JL_LLVM_VERSION >= 100000 MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(TM); PM.add(MMIWP); -#else - MachineModuleInfo *MMI = new MachineModuleInfo(TM); - PM.add(MMI); -#endif if (PassConfig->addISelPasses()) return NULL; PassConfig->addMachinePasses(); PassConfig->setInitialized(); -#if JL_LLVM_VERSION >= 100000 return &MMIWP->getMMI().getContext(); -#else - return &MMI->getContext(); -#endif } void jl_strip_llvm_debug(Module *m); @@ -1003,11 +986,7 @@ jl_value_t *jl_dump_llvm_asm(void *F, const char* asm_variant, const char *debug std::unique_ptr MAB(TM->getTarget().createMCAsmBackend( STI, MRI, TM->Options.MCOptions)); std::unique_ptr MCE; -#if JL_LLVM_VERSION >= 100000 auto FOut = std::make_unique(asmfile); -#else - auto FOut = llvm::make_unique(asmfile); -#endif std::unique_ptr S(TM->getTarget().createAsmStreamer( *Context, std::move(FOut), true, true, InstPrinter, diff --git a/src/ccall.cpp b/src/ccall.cpp index 66ab84c264f3a..c66e86867dc87 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1717,19 +1717,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) ctx.builder.CreateMemCpy( emit_inttoptr(ctx, destp, T_pint8), -#if JL_LLVM_VERSION >= 100000 MaybeAlign(1), -#else - 1, -#endif emit_inttoptr(ctx, emit_unbox(ctx, T_size, src, (jl_value_t*)jl_voidpointer_type), T_pint8), -#if JL_LLVM_VERSION >= 100000 MaybeAlign(0), -#else - 0, -#endif emit_unbox(ctx, T_size, n, (jl_value_t*)jl_ulong_type), false); JL_GC_POP(); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 58bfb958a917c..652b0a8791aae 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -628,11 +628,7 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ // We may need to insert padding first to get to the right offset if (al > MAX_ALIGN) { Type *AlignmentType; -#if JL_LLVM_VERSION >= 110000 AlignmentType = ArrayType::get(FixedVectorType::get(T_int8, al), 0); -#else - AlignmentType = ArrayType::get(VectorType::get(T_int8, al), 0); -#endif latypes.push_back(AlignmentType); al = MAX_ALIGN; } @@ -672,11 +668,7 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ } else if (isarray && !type_is_ghost(lasttype)) { if (isTuple && isvector && jl_special_vector_alignment(ntypes, jlasttype) != 0) -#if JL_LLVM_VERSION >= 110000 struct_decl = FixedVectorType::get(lasttype, ntypes); -#else - struct_decl = VectorType::get(lasttype, ntypes); -#endif else if (isTuple || !llvmcall) struct_decl = ArrayType::get(lasttype, ntypes); else @@ -1580,11 +1572,7 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va // for the load part (x.tbaa) and the store part (tbaa_stack). // since the tbaa lattice has to be a tree we have unfortunately // x.tbaa ∪ tbaa_stack = tbaa_root if x.tbaa != tbaa_stack -#if JL_LLVM_VERSION >= 100000 ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); -#else - ctx.builder.CreateMemCpy(dst, align, src, 0, sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); -#endif } static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src, @@ -1594,11 +1582,7 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va emit_memcpy_llvm(ctx, dst, tbaa_dst, src, tbaa_src, const_sz->getZExtValue(), align, is_volatile); return; } -#if JL_LLVM_VERSION >= 100000 ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); -#else - ctx.builder.CreateMemCpy(dst, align, src, 0, sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); -#endif } template @@ -2676,13 +2660,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con { if (AllocaInst *ai = dyn_cast(dest)) // TODO: make this a lifetime_end & dereferencable annotation? - ctx.builder.CreateAlignedStore(UndefValue::get(ai->getAllocatedType()), ai, -#if JL_LLVM_VERSION >= 110000 - ai->getAlign() -#else - ai->getAlignment() -#endif - ); + ctx.builder.CreateAlignedStore(UndefValue::get(ai->getAllocatedType()), ai, ai->getAlign()); if (jl_is_concrete_type(src.typ) || src.constant) { jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ; Type *store_ty = julia_type_to_llvm(ctx, typ); diff --git a/src/clangsa/GCChecker.cpp b/src/clangsa/GCChecker.cpp index 51b457b7acb88..b7cc89f210548 100644 --- a/src/clangsa/GCChecker.cpp +++ b/src/clangsa/GCChecker.cpp @@ -26,12 +26,7 @@ #define USED_FUNC #endif -#if LLVM_VERSION_MAJOR >= 10 using std::make_unique; -#else -using llvm::make_unique; -#define PathSensitiveBugReport BugReport -#endif namespace { using namespace clang; @@ -42,11 +37,7 @@ using namespace ento; static const Stmt *getStmtForDiagnostics(const ExplodedNode *N) { -#if LLVM_VERSION_MAJOR >= 10 return N->getStmtForDiagnostics(); -#else - return PathDiagnosticLocation::getStmt(N); -#endif } diff --git a/src/codegen.cpp b/src/codegen.cpp index 1a3460e44fbdd..519149970cac5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1718,13 +1718,9 @@ static void jl_init_function(Function *F) F->setHasUWTable(); // force NeedsWinEH #endif #ifdef JL_DISABLE_FPO -#if LLVM_VERSION_MAJOR >= 8 F->addFnAttr("frame-pointer", "all"); -#else - F->addFnAttr("no-frame-pointer-elim", "true"); -#endif #endif -#if JL_LLVM_VERSION >= 110000 && !defined(JL_ASAN_ENABLED) && !defined(_OS_WINDOWS_) +#if !defined(JL_ASAN_ENABLED) && !defined(_OS_WINDOWS_) // ASAN won't like us accessing undefined memory causing spurious issues, // and Windows has platform-specific handling which causes it to mishandle // this annotation. Other platforms should just ignore this if they don't @@ -3802,30 +3798,14 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va ssaslot->insertAfter(varslot); if (vi.isVolatile) { Value *unbox = ctx.builder.CreateAlignedLoad(ssaslot->getAllocatedType(), varslot, -#if JL_LLVM_VERSION >= 110000 varslot->getAlign(), -#else - varslot->getAlignment(), -#endif true); - ctx.builder.CreateAlignedStore(unbox, ssaslot, -#if JL_LLVM_VERSION >= 110000 - ssaslot->getAlign() -#else - ssaslot->getAlignment() -#endif - ); + ctx.builder.CreateAlignedStore(unbox, ssaslot, ssaslot->getAlign()); } else { const DataLayout &DL = jl_data_layout; uint64_t sz = DL.getTypeStoreSize(T); - emit_memcpy(ctx, ssaslot, tbaa_stack, vi.value, sz, -#if JL_LLVM_VERSION >= 110000 - ssaslot->getAlign().value() -#else - ssaslot->getAlignment() -#endif - ); + emit_memcpy(ctx, ssaslot, tbaa_stack, vi.value, sz, ssaslot->getAlign().value()); } Value *tindex = NULL; if (vi.pTIndex) @@ -3976,11 +3956,7 @@ static void emit_phinode_assign(jl_codectx_t &ctx, ssize_t idx, jl_value_t *r) Value *isboxed = ctx.builder.CreateICmpNE( ctx.builder.CreateAnd(Tindex_phi, ConstantInt::get(T_int8, 0x80)), ConstantInt::get(T_int8, 0)); -#if JL_LLVM_VERSION >= 100000 ctx.builder.CreateMemCpy(phi, MaybeAlign(min_align), dest, MaybeAlign(0), nbytes, false); -#else - ctx.builder.CreateMemCpy(phi, min_align, dest, 0, nbytes, false); -#endif ctx.builder.CreateLifetimeEnd(dest); Value *ptr = ctx.builder.CreateSelect(isboxed, maybe_bitcast(ctx, decay_derived(ctx, ptr_phi), T_pint8), @@ -4020,15 +3996,9 @@ static void emit_phinode_assign(jl_codectx_t &ctx, ssize_t idx, jl_value_t *r) // here it's moved into phi in the successor (from dest) dest = emit_static_alloca(ctx, vtype); Value *phi = emit_static_alloca(ctx, vtype); -#if JL_LLVM_VERSION >= 100000 ctx.builder.CreateMemCpy(phi, MaybeAlign(julia_alignment(phiType)), dest, MaybeAlign(0), jl_datatype_size(phiType), false); -#else - ctx.builder.CreateMemCpy(phi, julia_alignment(phiType), - dest, 0, - jl_datatype_size(phiType), false); -#endif ctx.builder.CreateLifetimeEnd(dest); slot = mark_julia_slot(phi, phiType, NULL, tbaa_stack); } diff --git a/src/codegen_shared.h b/src/codegen_shared.h index ee11870874688..f56854d2b4ca5 100644 --- a/src/codegen_shared.h +++ b/src/codegen_shared.h @@ -29,13 +29,8 @@ struct CountTrackedPointers { CountTrackedPointers(llvm::Type *T); }; -#if JL_LLVM_VERSION >= 110000 unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::IRBuilder<> &irbuilder); std::vector ExtractTrackedValues(llvm::Value *Src, llvm::Type *STy, bool isptr, llvm::IRBuilder<> &irbuilder, llvm::ArrayRef perm_offsets={}); -#else -unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::IRBuilder<> irbuilder); -std::vector ExtractTrackedValues(llvm::Value *Src, llvm::Type *STy, bool isptr, llvm::IRBuilder<> irbuilder, llvm::ArrayRef perm_offsets={}); -#endif static inline void llvm_dump(llvm::Value *v) { diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index b0243b2f3f4ff..95b562311b25b 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -236,15 +236,9 @@ class JuliaJITEventListener: public JITEventListener object::section_iterator EndSection = debugObj.section_end(); std::map loadedSections; for (const object::SectionRef &lSection: Object.sections()) { -#if JL_LLVM_VERSION >= 100000 auto sName = lSection.getName(); if (sName) loadedSections[*sName] = lSection; -#else - StringRef sName; - if (!lSection.getName(sName)) - loadedSections[sName] = lSection; -#endif } auto getLoadAddress = [&] (const StringRef &sName) -> uint64_t { auto search = loadedSections.find(sName); @@ -265,21 +259,12 @@ class JuliaJITEventListener: public JITEventListener istext = true; } else { -#if JL_LLVM_VERSION >= 100000 auto sName = section.getName(); if (!sName) continue; if (sName.get() != ".ARM.exidx") { continue; } -#else - StringRef sName; - if (section.getName(sName)) - continue; - if (sName != ".ARM.exidx") { - continue; - } -#endif } uint64_t loadaddr = L.getSectionLoadAddress(section); size_t seclen = section.getSize(); @@ -333,11 +318,7 @@ class JuliaJITEventListener: public JITEventListener auto Section = cantFail(sym_iter.getSection()); assert(Section != EndSection && Section->isText()); uint64_t SectionAddr = Section->getAddress(); -#if JL_LLVM_VERSION >= 100000 sName = cantFail(Section->getName()); -#else - Section->getName(sName); -#endif uint64_t SectionLoadAddr = getLoadAddress(sName); assert(SectionLoadAddr); if (SectionAddrCheck) // assert that all of the Sections are at the same location @@ -387,12 +368,7 @@ class JuliaJITEventListener: public JITEventListener if (Section == EndSection) continue; if (!Section->isText()) continue; uint64_t SectionAddr = Section->getAddress(); -#if JL_LLVM_VERSION >= 100000 StringRef secName = cantFail(Section->getName()); -#else - StringRef secName; - Section->getName(secName); -#endif uint64_t SectionLoadAddr = getLoadAddress(secName); Addr -= SectionAddr - SectionLoadAddr; StringRef sName = cantFail(sym_iter.getName()); @@ -622,13 +598,8 @@ static debug_link_info getDebuglink(const object::ObjectFile &Obj) JL_NOTSAFEPOI { debug_link_info info = {}; for (const object::SectionRef &Section: Obj.sections()) { -#if JL_LLVM_VERSION >= 100000 Expected sName = Section.getName(); if (sName && *sName == ".gnu_debuglink") -#else - StringRef sName; - if (!Section.getName(sName) && sName == ".gnu_debuglink") -#endif { auto found = Section.getContents(); if (found) { diff --git a/src/disasm.cpp b/src/disasm.cpp index 000f6916ec2bb..94dc91ee23905 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -763,11 +763,8 @@ static void jl_dump_asm_internal( SourceMgr SrcMgr; MCTargetOptions Options; - std::unique_ptr MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TheTriple.str()), TheTriple.str() -#if JL_LLVM_VERSION >= 100000 - , Options -#endif - )); + std::unique_ptr MAI( + TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TheTriple.str()), TheTriple.str(), Options)); assert(MAI && "Unable to create target asm info!"); std::unique_ptr MRI(TheTarget->createMCRegInfo(TheTriple.str())); @@ -878,11 +875,7 @@ static void jl_dump_asm_internal( std::string buf; dbgctx.emit_lineinfo(buf, di_lineIter->second); if (!buf.empty()) { -#if JL_LLVM_VERSION >= 110000 Streamer->emitRawText(buf); -#else - Streamer->EmitRawText(buf); -#endif } } } @@ -898,11 +891,7 @@ static void jl_dump_asm_internal( if (di_ctx) { std::string buf; DILineInfoSpecifier infoSpec( -#if JL_LLVM_VERSION >= 110000 DILineInfoSpecifier::FileLineInfoKind::RawValue, -#else - DILineInfoSpecifier::FileLineInfoKind::Default, -#endif DILineInfoSpecifier::FunctionNameKind::ShortName); DIInliningInfo dbg = di_ctx->getInliningInfoForAddress(makeAddress(Section, Index + Fptr + slide), infoSpec); if (dbg.getNumberOfFrames()) { @@ -912,11 +901,7 @@ static void jl_dump_asm_internal( dbgctx.emit_lineinfo(buf, di_lineIter->second); } if (!buf.empty()) { -#if JL_LLVM_VERSION >= 110000 Streamer->emitRawText(buf); -#else - Streamer->EmitRawText(buf); -#endif } nextLineAddr = (++di_lineIter)->first; } @@ -928,11 +913,7 @@ static void jl_dump_asm_internal( // stream << Index << ": "; MCSymbol *symbol = DisInfo.lookupSymbol(Fptr+Index); if (symbol) { -#if JL_LLVM_VERSION >= 110000 Streamer->emitLabel(symbol); -#else - Streamer->EmitLabel(symbol); -#endif } } @@ -940,9 +921,6 @@ static void jl_dump_asm_internal( MCDisassembler::DecodeStatus S; FuncMCView view = memoryObject.slice(Index); S = DisAsm->getInstruction(Inst, insSize, view, 0, -#if JL_LLVM_VERSION < 100000 - /*VStream*/ nulls(), -#endif /*CStream*/ pass != 0 ? Streamer->GetCommentOS() : nulls()); if (pass != 0 && Streamer->GetCommentOS().tell() > 0) Streamer->GetCommentOS() << '\n'; @@ -967,21 +945,13 @@ static void jl_dump_asm_internal( llvm::write_hex(buf, *(uint8_t*)(Fptr + Index + i), HexPrintStyle::PrefixLower, 2); } } -#if JL_LLVM_VERSION >= 110000 Streamer->emitRawText(StringRef(buf.str())); -#else - Streamer->EmitRawText(StringRef(buf.str())); -#endif } break; case MCDisassembler::SoftFail: if (pass != 0) { -#if JL_LLVM_VERSION >= 110000 Streamer->emitRawText(StringRef("potentially undefined instruction encoding:")); -#else - Streamer->EmitRawText(StringRef("potentially undefined instruction encoding:")); -#endif } // Fall through @@ -1014,11 +984,7 @@ static void jl_dump_asm_internal( } } } -#if JL_LLVM_VERSION >= 110000 Streamer->emitInstruction(Inst, *STI); -#else - Streamer->EmitInstruction(Inst, *STI); -#endif } break; } @@ -1032,11 +998,7 @@ static void jl_dump_asm_internal( std::string buf; dbgctx.emit_finish(buf); if (!buf.empty()) { -#if JL_LLVM_VERSION >= 110000 Streamer->emitRawText(buf); -#else - Streamer->EmitRawText(buf); -#endif } } } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index d21e84593b5a2..834034d367a9f 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -198,11 +198,7 @@ static Constant *julia_const_to_llvm(jl_codectx_t &ctx, const void *ptr, jl_data unsigned llvm_idx = isa(lt) ? convert_struct_offset(lt, offs) : i; while (fields.size() < llvm_idx) fields.push_back( -#if JL_LLVM_VERSION >= 110000 UndefValue::get(GetElementPtrInst::getTypeAtIndex(lt, fields.size()))); -#else - UndefValue::get(cast(lt)->getTypeAtIndex(fields.size()))); -#endif const uint8_t *ov = (const uint8_t*)ptr + offs; if (jl_is_uniontype(ft)) { // compute the same type layout as julia_struct_to_llvm diff --git a/src/jitlayers.h b/src/jitlayers.h index b517711185e45..e3cc9245932ac 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -144,11 +144,7 @@ typedef JITSymbol JL_SymbolInfo; using RTDyldObjHandleT = orc::VModuleKey; #endif -#if JL_LLVM_VERSION >= 100000 using CompilerResultT = Expected>; -#else -using CompilerResultT = std::unique_ptr; -#endif class JuliaOJIT { struct CompilerT : public orc::IRCompileLayer::IRCompiler { diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 3bb11988b730e..ec7060bd10a5e 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -24,9 +24,7 @@ #include #include -#if JL_LLVM_VERSION >= 100000 #include -#endif #include "codegen_shared.h" #include "julia.h" @@ -64,13 +62,8 @@ static bool hasObjref(Type *ty) { if (auto ptrty = dyn_cast(ty)) return ptrty->getAddressSpace() == AddressSpace::Tracked; -#if JL_LLVM_VERSION >= 110000 if (isa(ty) || isa(ty)) return hasObjref(GetElementPtrInst::getTypeAtIndex(ty, (uint64_t)0)); -#else - if (auto seqty = dyn_cast(ty)) - return hasObjref(seqty->getElementType()); -#endif if (auto structty = dyn_cast(ty)) { for (auto elty: structty->elements()) { if (hasObjref(elty)) { @@ -1289,11 +1282,7 @@ void Optimizer::splitOnStack(CallInst *orig_inst) val = newload; } // TODO: should we use `load->clone()`, or manually copy any other metadata? -#if JL_LLVM_VERSION >= 100000 newload->setAlignment(load->getAlign()); -#else - newload->setAlignment(load->getAlignment()); -#endif // since we're moving heap-to-stack, it is safe to downgrade the atomic level to NotAtomic newload->setOrdering(AtomicOrdering::NotAtomic); load->replaceAllUsesWith(val); @@ -1333,11 +1322,7 @@ void Optimizer::splitOnStack(CallInst *orig_inst) newstore = builder.CreateStore(store_val, slot_gep(slot, offset, store_ty, builder)); } // TODO: should we use `store->clone()`, or manually copy any other metadata? -#if JL_LLVM_VERSION >= 100000 newstore->setAlignment(store->getAlign()); -#else - newstore->setAlignment(store->getAlignment()); -#endif // since we're moving heap-to-stack, it is safe to downgrade the atomic level to NotAtomic newstore->setOrdering(AtomicOrdering::NotAtomic); store->eraseFromParent(); @@ -1383,11 +1368,7 @@ void Optimizer::splitOnStack(CallInst *orig_inst) auto sub_size = std::min(slot.offset + slot.size, offset + size) - std::max(offset, slot.offset); // TODO: alignment computation -#if JL_LLVM_VERSION >= 100000 builder.CreateMemSet(ptr8, val_arg, sub_size, MaybeAlign(0)); -#else - builder.CreateMemSet(ptr8, val_arg, sub_size, 0); -#endif } call->eraseFromParent(); return; diff --git a/src/llvm-api.cpp b/src/llvm-api.cpp index db8f6f94dc781..56ec131556f98 100644 --- a/src/llvm-api.cpp +++ b/src/llvm-api.cpp @@ -16,9 +16,6 @@ #include #include #include -#if JL_LLVM_VERSION < 110000 -#include -#endif #include #include #include diff --git a/src/llvm-gc-invariant-verifier.cpp b/src/llvm-gc-invariant-verifier.cpp index c1386efef8e72..1c584f3852e9e 100644 --- a/src/llvm-gc-invariant-verifier.cpp +++ b/src/llvm-gc-invariant-verifier.cpp @@ -19,9 +19,6 @@ #include #include #include -#if JL_LLVM_VERSION < 110000 -#include -#endif #include #include #include diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 99ff45cf61815..ef30966b4cc5a 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -16,9 +16,6 @@ #include #include #include -#if JL_LLVM_VERSION < 110000 -#include -#endif #include #include #include @@ -29,9 +26,7 @@ #include #include -#if JL_LLVM_VERSION >= 100000 #include -#endif #include "codegen_shared.h" #include "julia.h" @@ -427,11 +422,7 @@ void TrackCompositeType(Type *T, std::vector &Idxs, std::vector= 110000 Type *ElT = GetElementPtrInst::getTypeAtIndex(T, Idx); -#else - Type *ElT = cast(T)->getTypeAtIndex(Idx); -#endif TrackCompositeType(ElT, Idxs, Numberings); Idxs.pop_back(); } @@ -576,11 +567,7 @@ Value *LateLowerGCFrame::MaybeExtractScalar(State &S, std::pair ValE Type *FinalT = ExtractValueInst::getIndexedType(V->getType(), IdxsNotVec); bool IsVector = isa(FinalT); PointerType *T = cast( -#if JL_LLVM_VERSION >= 110000 GetElementPtrInst::getTypeAtIndex(FinalT, Idxs.back())); -#else - cast(FinalT)->getTypeAtIndex(Idxs.back())); -#endif if (T->getAddressSpace() != AddressSpace::Tracked) { // if V isn't tracked, get the shadow def auto Numbers = NumberAllBase(S, V); @@ -1670,11 +1657,7 @@ State LateLowerGCFrame::LocalScan(Function &F) { return S; } -#if JL_LLVM_VERSION >= 110000 static Value *ExtractScalar(Value *V, Type *VTy, bool isptr, ArrayRef Idxs, IRBuilder<> &irbuilder) { -#else -static Value *ExtractScalar(Value *V, Type *VTy, bool isptr, ArrayRef Idxs, IRBuilder<> irbuilder) { -#endif Type *T_int32 = Type::getInt32Ty(V->getContext()); if (isptr) { std::vector IdxList{Idxs.size() + 1}; @@ -1717,11 +1700,7 @@ static unsigned getFieldOffset(const DataLayout &DL, Type *STy, ArrayRef= 110000 std::vector ExtractTrackedValues(Value *Src, Type *STy, bool isptr, IRBuilder<> &irbuilder, ArrayRef perm_offsets) { -#else -std::vector ExtractTrackedValues(Value *Src, Type *STy, bool isptr, IRBuilder<> irbuilder, ArrayRef perm_offsets) { -#endif auto Tracked = TrackCompositeType(STy); std::vector Ptrs; unsigned perm_idx = 0; @@ -1754,11 +1733,7 @@ std::vector ExtractTrackedValues(Value *Src, Type *STy, bool isptr, IRBu return Ptrs; } -#if JL_LLVM_VERSION >= 110000 unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, IRBuilder<> &irbuilder) { -#else -unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, IRBuilder<> irbuilder) { -#endif auto Ptrs = ExtractTrackedValues(Src, STy, isptr, irbuilder); for (unsigned i = 0; i < Ptrs.size(); ++i) { Value *Elem = Ptrs[i]; @@ -2275,11 +2250,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) { // to remove write barrier because of it. // We pretty much only load using `T_size` so try our best to strip // as many cast as possible. -#if JL_LLVM_VERSION >= 100000 auto tag = CI->getArgOperand(2)->stripPointerCastsAndAliases(); -#else - auto tag = CI->getArgOperand(2)->stripPointerCasts(); -#endif if (auto C = dyn_cast(tag)) { if (C->getOpcode() == Instruction::IntToPtr) { tag = C->getOperand(0); @@ -2305,13 +2276,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) { auto tag_type = tag->getType(); if (tag_type->isPointerTy()) { auto &DL = CI->getModule()->getDataLayout(); -#if JL_LLVM_VERSION >= 110000 auto align = tag->getPointerAlignment(DL).value(); -#elif JL_LLVM_VERSION >= 100000 - auto align = tag->getPointerAlignment(DL).valueOrOne().value(); -#else - auto align = tag->getPointerAlignment(DL); -#endif if (align < 16) { // On 5 <= LLVM < 12, it is illegal to call this on // non-integral pointer. This relies on stripping the diff --git a/src/llvm-propagate-addrspaces.cpp b/src/llvm-propagate-addrspaces.cpp index 95182f144d6ec..6cfa66ddca6ff 100644 --- a/src/llvm-propagate-addrspaces.cpp +++ b/src/llvm-propagate-addrspaces.cpp @@ -16,9 +16,6 @@ #include #include #include -#if JL_LLVM_VERSION < 110000 -#include -#endif #include #include #include diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp index de5633b905762..ada10c8d5f1f9 100644 --- a/src/llvm-remove-addrspaces.cpp +++ b/src/llvm-remove-addrspaces.cpp @@ -92,14 +92,7 @@ class AddrspaceRemoveTypeRemapper : public ValueMapTypeRemapper { DstTy = ArrayType::get( remapType(Ty->getElementType()), Ty->getNumElements()); else if (auto Ty = dyn_cast(SrcTy)) - DstTy = VectorType::get(remapType(Ty->getElementType()), -#if JL_LLVM_VERSION >= 110000 - Ty -#else - Ty->getNumElements(), - Ty->isScalable() -#endif - ); + DstTy = VectorType::get(remapType(Ty->getElementType()), Ty); if (DstTy != SrcTy) LLVM_DEBUG( diff --git a/src/llvm-version.h b/src/llvm-version.h index 0b8a086e60b40..f59f7826c334d 100644 --- a/src/llvm-version.h +++ b/src/llvm-version.h @@ -9,11 +9,8 @@ #define JL_LLVM_VERSION (LLVM_VERSION_MAJOR * 10000 + LLVM_VERSION_MINOR * 100 \ + LLVM_VERSION_PATCH) -#if JL_LLVM_VERSION < 90000 - #error Only LLVM versions >= 9.0.0 are supported by Julia -#endif -#if JL_LLVM_VERSION < 100000 -#define Align(a) (a) +#if JL_LLVM_VERSION < 110000 + #error Only LLVM versions >= 11.0.0 are supported by Julia #endif #ifndef LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index 9bbd540fa233f..908b7889f3a01 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -1623,10 +1623,8 @@ get_llvm_target_noext(const TargetData &data) feature_strs.push_back(std::string("-") + fename_str); } } -#if JL_LLVM_VERSION >= 110000 if (test_nbit(features, Feature::v8_6a)) feature_strs.push_back("+v8.6a"); -#endif if (test_nbit(features, Feature::v8_5a)) feature_strs.push_back("+v8.5a"); if (test_nbit(features, Feature::v8_4a)) @@ -1760,13 +1758,7 @@ const std::pair &jl_get_llvm_disasm_target(void) auto max_feature = get_max_feature(); static const auto res = get_llvm_target_str(TargetData{host_cpu_name(), #ifdef _CPU_AARCH64_ -# if JL_LLVM_VERSION > 110000 - "+ecv," -# endif -# if JL_LLVM_VERSION > 100000 - "+tme," -# endif - "+am,+specrestrict,+predres,+lor,+perfmon,+spe,+tracev8.4", + "+ecv,+tme,+am,+specrestrict,+predres,+lor,+perfmon,+spe,+tracev8.4", #else "+dotprod", #endif From 961642f1140aad908f357e0242c3fa1c2fd15a68 Mon Sep 17 00:00:00 2001 From: Waldir Pimenta Date: Wed, 28 Apr 2021 15:33:01 +0100 Subject: [PATCH 279/439] mpfr.jl: don't add extra zero when pretty-printing BigFloats (#40513) * mpfr.jl: don't add extra zero when pretty-printing BigFloats * Cleanup MPFR tests - Make blank lines consistent: none around testset blocks, but present around standalone tests - Clarify name of testset: 'precision' --> 'setprecision' - Merge two redundant testsets on comparison operators --- base/mpfr.jl | 2 +- test/mpfr.jl | 30 +++++++++--------------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index cffad32e50ea0..40990df4c9c8f 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -982,7 +982,7 @@ function _prettify_bigfloat(s::String)::String neg = startswith(int, '-') neg == true && (int = lstrip(int, '-')) @assert length(int) == 1 - string(neg ? '-' : "", '0', '.', '0'^(-expo-1), int, frac) + string(neg ? '-' : "", '0', '.', '0'^(-expo-1), int, frac == "0" ? "" : frac) end else string(mantissa, 'e', exponent) diff --git a/test/mpfr.jl b/test/mpfr.jl index 86c7d345f49fd..a4fac9c93c79a 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -338,23 +338,6 @@ end @test *(a, b, c, d, f) == parse(BigFloat,"5.214588134765625e+04") @test *(a, b, c, d, f, g) == parse(BigFloat,"1.6295587921142578125e+03") end -@testset "< / > / <= / >=" begin - x = BigFloat(12) - y = BigFloat(42) - z = BigFloat(30) - @test y > x - @test y >= x - @test y > z - @test y >= z - @test x < y - @test x <= y - @test z < y - @test z <= y - @test y - x >= z - @test y - x <= z - @test !(x >= z) - @test !(y <= z) -end @testset "rounding modes" begin setprecision(4) do # default mode is round to nearest @@ -371,7 +354,6 @@ end end end end - @testset "copysign / sign" begin x = BigFloat(1) y = BigFloat(-1) @@ -473,10 +455,11 @@ end @test isnan(nextfloat(BigFloat(NaN), 1)) @test isnan(prevfloat(BigFloat(NaN), 1)) end + # sqrt DomainError @test_throws DomainError sqrt(BigFloat(-1)) -@testset "precision" begin +@testset "setprecision" begin old_precision = precision(BigFloat) x = BigFloat(0) @test precision(x) == old_precision @@ -512,7 +495,6 @@ end @test !isinteger(-BigFloat(Inf)) @test !isinteger(BigFloat(NaN)) end - @testset "comparisons" begin x = BigFloat(1) y = BigFloat(-1) @@ -521,9 +503,11 @@ end imi = BigFloat(-Inf) @test x > y @test x >= y + @test !(y >= x) @test x >= x @test y < x @test y <= x + @test !(x <= y) @test y <= y @test x < ipl @test x <= ipl @@ -675,14 +659,17 @@ end end setprecision(21) do @test string(parse(BigFloat, "0.1")) == "0.10000002" + @test string(parse(BigFloat, "0.5")) == "0.5" @test string(parse(BigFloat, "-9.9")) == "-9.9000015" end setprecision(40) do @test string(parse(BigFloat, "0.1")) == "0.10000000000002" + @test string(parse(BigFloat, "0.5")) == "0.5" @test string(parse(BigFloat, "-9.9")) == "-9.8999999999942" end setprecision(123) do @test string(parse(BigFloat, "0.1")) == "0.0999999999999999999999999999999999999953" + @test string(parse(BigFloat, "0.5")) == "0.5" @test string(parse(BigFloat, "-9.9")) == "-9.8999999999999999999999999999999999997" end end @@ -927,6 +914,7 @@ end @test i3+1 > f @test i3+1 >= f end + # issue #8318 @test convert(Int64,big(500_000_000_000_000.)) == 500_000_000_000_000 @@ -935,6 +923,7 @@ end @test MPFR.get_emin() == MPFR.get_emin_min() @test MPFR.get_emax() == MPFR.get_emax_max() end + # issue #10994: handle embedded NUL chars for string parsing @test_throws ArgumentError parse(BigFloat, "1\0") @@ -1025,7 +1014,6 @@ end @test to_string(big"-1.0") == "-1.0" end end - @testset "big(::Type)" begin for x in (2f0, pi, 7.8, big(ℯ)) @test big(typeof(x)) == typeof(big(x)) From 04705655a023221278beb329ed9f31724d0ccca9 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 28 Apr 2021 18:43:51 +0400 Subject: [PATCH 280/439] Fix reduced_index for Integer UnitRanges having eltypes other than Int (#39999) * reduced_index for BigInt UnitRanges * Add tests for Integer subtypes * use OneTo constructor instead of typeof Co-authored-by: Simeon Schaub Co-authored-by: Simeon Schaub --- base/reducedim.jl | 2 +- test/reducedim.jl | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index c473049dd5fa0..ff2b24db740ef 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -3,7 +3,7 @@ ## Functions to compute the reduced shape # for reductions that expand 0 dims to 1 -reduced_index(i::OneTo) = OneTo(1) +reduced_index(i::OneTo{T}) where {T} = OneTo(one(T)) reduced_index(i::Union{Slice, IdentityUnitRange}) = oftype(i, first(i):first(i)) reduced_index(i::AbstractUnitRange) = throw(ArgumentError( diff --git a/test/reducedim.jl b/test/reducedim.jl index cc07cfff1dad3..93287efc5eb1c 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -492,3 +492,16 @@ end @test @inferred(count(false:true, dims=:, init=0x0004)) === 0x0005 @test @inferred(count(isodd, reshape(1:9, 3, 3), dims=:, init=Int128(0))) === Int128(5) + +@testset "reduced_index for BigInt (issue #39995)" begin + for T in [Int8, Int16, Int32, Int64, Int128, BigInt] + r = T(1):T(2) + ax = axes(r, 1) + axred = Base.reduced_index(ax) + @test axred == Base.OneTo(1) + @test typeof(axred) === typeof(ax) + r_red = reduce(+, r, dims = 1) + @test eltype(r_red) == T + @test r_red == [3] + end +end From b692d9f444ba6e82f60623230b901fd622d9e5d6 Mon Sep 17 00:00:00 2001 From: Daniel Bruegmann Date: Wed, 28 Apr 2021 16:52:09 +0200 Subject: [PATCH 281/439] Make opnorm( 1x0 matrix ) zero (#40483) * Make opnorm( 1x0 matrix ) zero Fixes #40370. * more opnorm tests * remove convert on svdvals Co-authored-by: Daniel Karrasch --- stdlib/LinearAlgebra/src/generic.jl | 5 +++-- stdlib/LinearAlgebra/test/generic.jl | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index b74ac6cced810..427d7202d4b08 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -702,9 +702,10 @@ end function opnorm2(A::AbstractMatrix{T}) where T require_one_based_indexing(A) m,n = size(A) - if m == 1 || n == 1 return norm2(A) end Tnorm = typeof(float(real(zero(T)))) - (m == 0 || n == 0) ? zero(Tnorm) : convert(Tnorm, svdvals(A)[1]) + if m == 0 || n == 0 return zero(Tnorm) end + if m == 1 || n == 1 return norm2(A) end + return svdvals(A)[1] end function opnormInf(A::AbstractMatrix{T}) where T diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 0c1365b11679f..f3ef87da83052 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -209,6 +209,19 @@ end @test norm([2.4e-322, 4.4e-323], 3) ≈ 2.4e-322 @test_throws ArgumentError opnorm(Matrix{Float64}(undef,5,5),5) +# operator norm for zero-dimensional domain is zero (see #40370) +@testset "opnorm" begin + for m in (0, 1, 2) + @test @inferred(opnorm(fill(1,0,m))) == 0.0 + @test @inferred(opnorm(fill(1,m,0))) == 0.0 + end + for m in (1, 2) + @test @inferred(opnorm(fill(1im,1,m))) ≈ sqrt(m) + @test @inferred(opnorm(fill(1im,m,1))) ≈ sqrt(m) + end + @test @inferred(opnorm(fill(1,2,2))) ≈ 2 +end + @testset "generic norm for arrays of arrays" begin x = Vector{Int}[[1,2], [3,4]] @test @inferred(norm(x)) ≈ sqrt(30) From ebf6b167e2bc58a535a970153371057397835d23 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Wed, 28 Apr 2021 10:53:55 -0400 Subject: [PATCH 282/439] Make edit(f) return methods if multiple signatures available (#39481) Co-authored-by: Jameson Nash --- stdlib/InteractiveUtils/src/editless.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/stdlib/InteractiveUtils/src/editless.jl b/stdlib/InteractiveUtils/src/editless.jl index 4c18682d671b3..e9ff7cdd21101 100644 --- a/stdlib/InteractiveUtils/src/editless.jl +++ b/stdlib/InteractiveUtils/src/editless.jl @@ -222,9 +222,16 @@ method to edit. For modules, open the main source file. The module needs to be l To ensure that the file can be opened at the given line, you may need to call `define_editor` first. """ -edit(f) = edit(functionloc(f)...) -edit(f, @nospecialize t) = edit(functionloc(f,t)...) -edit(file, line::Integer) = error("could not find source file for function") +function edit(@nospecialize f) + ms = methods(f).ms + length(ms) == 1 && edit(functionloc(ms[1])...) + length(ms) > 1 && return ms + length(ms) == 0 && functionloc(f) # throws + nothing +end +edit(@nospecialize(f), idx::Integer) = edit(methods(f).ms[idx]) +edit(f, t) = (@nospecialize; edit(functionloc(f, t)...)) +edit(file::Nothing, line::Integer) = error("could not find source file for function") edit(m::Module) = edit(pathof(m)) # terminal pager From bbaca9d6331760cb8b1513f9417fb9d5689e0a29 Mon Sep 17 00:00:00 2001 From: Sanjiban Sengupta Date: Wed, 28 Apr 2021 22:06:08 +0530 Subject: [PATCH 283/439] more efficient array indexing with AbstractUnitRange (#39896) Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- base/array.jl | 6 +++++- test/abstractarray.jl | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index febbf4fb351cf..b1e67a91617f1 100644 --- a/base/array.jl +++ b/base/array.jl @@ -834,7 +834,7 @@ function getindex end @eval getindex(A::Array, i1::Int, i2::Int, I::Int...) = (@_inline_meta; arrayref($(Expr(:boundscheck)), A, i1, i2, I...)) # Faster contiguous indexing using copyto! for UnitRange and Colon -function getindex(A::Array, I::UnitRange{Int}) +function getindex(A::Array, I::AbstractUnitRange{<:Integer}) @_inline_meta @boundscheck checkbounds(A, I) lI = length(I) @@ -844,6 +844,10 @@ function getindex(A::Array, I::UnitRange{Int}) end return X end + +# getindex for carrying out logical indexing for AbstractUnitRange{Bool} as Bool <: Integer +getindex(a::Array, r::AbstractUnitRange{Bool}) = getindex(a, to_index(r)) + function getindex(A::Array, c::Colon) lI = length(A) X = similar(A, lI) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index b75869f3ed9d6..44e29e59ead69 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1293,6 +1293,25 @@ end @test_throws ArgumentError Int[t...; 3 4 5] end +@testset "issue #39896, modified getindex " begin + for arr = ([1:10;], reshape([1.0:16.0;],4,4), reshape(['a':'h';],2,2,2)) + for inds = (2:5, Base.OneTo(5), BigInt(3):BigInt(5), UInt(4):UInt(3)) + @test arr[inds] == arr[collect(inds)] + @test arr[inds] isa AbstractVector{eltype(arr)} + end + end + for arr = ([1], reshape([1.0],1,1), reshape(['a'],1,1,1)) + @test arr[true:true] == [arr[1]] + @test arr[true:true] isa AbstractVector{eltype(arr)} + @test arr[false:false] == [] + @test arr[false:false] isa AbstractVector{eltype(arr)} + end + for arr = ([1:10;], reshape([1.0:16.0;],4,4), reshape(['a':'h';],2,2,2)) + @test_throws BoundsError arr[true:true] + @test_throws BoundsError arr[false:false] + end +end + @testset "reduce(vcat, ...) inferrence #40277" begin x_vecs = ([5, ], [1.0, 2.0, 3.0]) @test @inferred(reduce(vcat, x_vecs)) == [5.0, 1.0, 2.0, 3.0] From e9b22ced35fe90642ed146146752041a92f0fe86 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 28 Apr 2021 13:04:36 -0400 Subject: [PATCH 284/439] doc: mentions of addenv seemed lacking (#40539) Co-authored-by: akaysh Co-authored-by: Sacha Verweij Co-authored-by: akaysh Co-authored-by: Sacha Verweij --- base/cmd.jl | 10 +++++-- doc/src/base/base.md | 1 + doc/src/manual/running-external-programs.md | 31 +++++++++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/base/cmd.jl b/base/cmd.jl index 809bc0f3c0a57..0d66cb932a04a 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -63,7 +63,7 @@ while changing the settings of the optional keyword arguments: array or tuple of `"var"=>val` pairs. In order to modify (rather than replace) the existing environment, initialize `env` with `copy(ENV)` and then set `env["var"]=val` as desired. To add to an environment block within a `Cmd` object without replacing all - elements, use `addenv()` which will return a `Cmd` object with the updated environment. + elements, use [`addenv()`](@ref) which will return a `Cmd` object with the updated environment. * `dir::AbstractString`: Specify a working directory for the command (instead of the current directory). @@ -236,9 +236,11 @@ Set environment variables to use when running the given `command`. `env` is eith dictionary mapping strings to strings, an array of strings of the form `"var=val"`, or zero or more `"var"=>val` pair arguments. In order to modify (rather than replace) the existing environment, create `env` through `copy(ENV)` and then setting `env["var"]=val` -as desired, or use `addenv`. +as desired, or use [`addenv`](@ref). The `dir` keyword argument can be used to specify a working directory for the command. + +See also [`Cmd`](@ref), [`addenv`](@ref), [`ENV`](@ref), [`pwd`](@ref). """ setenv(cmd::Cmd, env; dir="") = Cmd(cmd; env=byteenv(env), dir=dir) setenv(cmd::Cmd, env::Pair{<:AbstractString}...; dir="") = @@ -248,10 +250,12 @@ setenv(cmd::Cmd; dir="") = Cmd(cmd; dir=dir) """ addenv(command::Cmd, env...; inherit::Bool = true) -Merge new environment mappings into the given `Cmd` object, returning a new `Cmd` object. +Merge new environment mappings into the given [`Cmd`](@ref) object, returning a new `Cmd` object. Duplicate keys are replaced. If `command` does not contain any environment values set already, it inherits the current environment at time of `addenv()` call if `inherit` is `true`. +See also [`Cmd`](@ref), [`setenv`](@ref), [`ENV`](@ref). + !!! compat "Julia 1.6" This function requires Julia 1.6 or later. """ diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 3cb71ace680e6..d371f7aad9411 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -307,6 +307,7 @@ Base.ignorestatus Base.detach Base.Cmd Base.setenv +Base.addenv Base.withenv Base.pipeline(::Any, ::Any, ::Any, ::Any...) Base.pipeline(::Base.AbstractCmd) diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index 21dd435706082..16dc779318d51 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -376,11 +376,36 @@ saturated throughput. We strongly encourage you to try all these examples to see how they work. ## `Cmd` Objects -The syntax introduced above creates objects of type [`Cmd`](@ref). Such object may also be constructed directly: +The backtick syntax create an object of type [`Cmd`](@ref). Such object may also be constructed directly from +an existing `Cmd` or list of arguments: ```julia run(Cmd(`pwd`, dir="..")) +run(Cmd(["pwd"], detach=true, ignorestatus=true)) ``` -This way, they may be customized with the `dir` keyword to set the working directory, -`detach` keyword to run the command in a new process group, and `env` keyword to set environment variables. +This allows you to specify several aspects of the `Cmd`'s execution environment via keyword arguments. For +example, the `dir` keyword provides control over the `Cmd`'s working directory: + +```jldoctest +julia> run(Cmd(`pwd`, dir="/")); +/ +``` + +And the `env` keyword allows you to set execution environment variables: + +```jldoctest +julia> run(Cmd(`sh -c "echo foo \$HOWLONG"`, env=("HOWLONG" => "ever!",))); +foo ever! +``` + +See `[`Cmd`](@ref)` for additional keyword arguments. The [`setenv`](@ref) and [`addenv`](@ref) commands +provide another means for replacing or adding to the `Cmd` execution environment variables, respectively: + +```jldoctest +julia> run(setenv(`sh -c "echo foo \$HOWLONG"`, ("HOWLONG" => "ever!",))); +foo ever! + +julia> run(addenv(`sh -c "echo foo \$HOWLONG"`, "HOWLONG" => "ever!")); +foo ever! +``` From 3389940f945d0f942fe353e4dca6c1d4d18f26d1 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Thu, 29 Apr 2021 01:00:34 -0400 Subject: [PATCH 285/439] Add tests to make sure that `Base.project_names`, `Base.manifest_names`, `Base.preferences_names`, and `Artifacts.artifact_names` always have the same length (#40618) * Add tests to make sure that `Base.project_names`, `Base.manifest_names`, `Base.preferences_names`, and `Artifacts.artifact_names` always have the same length * Add a comment explaining why we have these tests --- stdlib/Artifacts/test/runtests.jl | 7 +++++++ test/loading.jl | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/stdlib/Artifacts/test/runtests.jl b/stdlib/Artifacts/test/runtests.jl index 36b5a0d3281ff..7527b548061ce 100644 --- a/stdlib/Artifacts/test/runtests.jl +++ b/stdlib/Artifacts/test/runtests.jl @@ -157,3 +157,10 @@ end end end end + +@testset "`Artifacts.artifact_names` and friends" begin + n = length(Artifacts.artifact_names) + @test length(Base.project_names) == n + @test length(Base.manifest_names) == n + @test length(Base.preferences_names) == n +end diff --git a/test/loading.jl b/test/loading.jl index 377087a63f558..cf9aa32952a66 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -718,3 +718,10 @@ import .Foo.Libdl; import Libdl end end end + +@testset "`Base.project_names` and friends" begin + # Some functions in Pkg assumes that these tuples have the same length + n = length(Base.project_names) + @test length(Base.manifest_names) == n + @test length(Base.preferences_names) == n +end From c556bb9e53779994c88587e8b24e698b7cf38527 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 29 Apr 2021 12:03:44 -0400 Subject: [PATCH 286/439] a bit of cleanup to init/loading (#40637) --- cli/loader_lib.c | 4 ++-- src/init.c | 2 +- src/jl_exported_funcs.inc | 7 ++++--- src/jlapi.c | 34 +++++++--------------------------- src/julia.expmap | 1 - src/julia.h | 7 ++----- src/julia_internal.h | 2 -- src/stackwalk.c | 5 +++++ src/task.c | 5 ----- 9 files changed, 21 insertions(+), 46 deletions(-) diff --git a/cli/loader_lib.c b/cli/loader_lib.c index b56a4893ea66f..2f596ac27202d 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -196,9 +196,9 @@ JL_DLLEXPORT int jl_load_repl(int argc, char * argv[]) { #endif // Load the repl entrypoint symbol and jump into it! - int (*entrypoint)(int, char **) = (int (*)(int, char **))lookup_symbol(libjulia_internal, "repl_entrypoint"); + int (*entrypoint)(int, char **) = (int (*)(int, char **))lookup_symbol(libjulia_internal, "jl_repl_entrypoint"); if (entrypoint == NULL) { - jl_loader_print_stderr("ERROR: Unable to find `repl_entrypoint()` within libjulia-internal!\n"); + jl_loader_print_stderr("ERROR: Unable to find `jl_repl_entrypoint()` within libjulia-internal!\n"); exit(1); } return entrypoint(argc, (char **)argv); diff --git a/src/init.c b/src/init.c index 05d7690cd47b0..7ed1a200eb2a5 100644 --- a/src/init.c +++ b/src/init.c @@ -628,7 +628,7 @@ static void restore_fp_env(void) } } -void _julia_init(JL_IMAGE_SEARCH rel) +JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) { jl_init_timing(); // Make sure we finalize the tls callback before starting any threads. diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 8a23a0f5e9b65..07f783d36439c 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -273,8 +273,8 @@ XX(jl_idtable_rehash) \ XX(jl_infer_thunk) \ XX(jl_init_restored_modules) \ - XX(jl_init__threading) \ - XX(jl_init_with_image__threading) \ + XX(jl_init) \ + XX(jl_init_with_image) \ XX(jl_install_sigint_handler) \ XX(jl_instantiate_type_in_env) \ XX(jl_instantiate_unionall) \ @@ -538,4 +538,5 @@ XX(jl_vexceptionf) \ XX(jl_vprintf) \ XX(jl_wakeup_thread) \ - XX(jl_yield) + XX(jl_yield) \ + XX(jl_print_backtrace) diff --git a/src/jlapi.c b/src/jlapi.c index d27f7e03d958c..a0ca896aa0ed0 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -500,8 +500,7 @@ static int exec_program(char *program) jl_load(jl_main_module, program); } JL_CATCH { - // TODO: It is possible for this output - // to be mangled due to `jlbacktrace` + // TODO: It is possible for this output to be mangled due to `jl_print_backtrace` // printing directly to STDERR_FILENO. int shown_err = 0; jl_printf(JL_STDERR, "error during bootstrap:\n"); @@ -520,32 +519,13 @@ static int exec_program(char *program) jl_static_show((JL_STREAM*)STDERR_FILENO, exc); jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); } - jlbacktrace(); // written to STDERR_FILENO + jl_print_backtrace(); // written to STDERR_FILENO jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); return 1; } return 0; } -#ifdef JL_GF_PROFILE -static void print_profile(void) -{ - size_t i; - void **table = jl_base_module->bindings.table; - for(i=1; i < jl_base_module->bindings.size; i+=2) { - if (table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)table[i]; - if (b->value != NULL && jl_is_function(b->value) && - jl_is_gf(b->value)) { - jl_printf(JL_STDERR, "%d\t%s\n", - jl_gf_mtable(b->value)->ncalls, - jl_gf_name(b->value)->name); - } - } - } -} -#endif - static NOINLINE int true_main(int argc, char *argv[]) { jl_set_ARGS(argc, argv); @@ -573,9 +553,9 @@ static NOINLINE int true_main(int argc, char *argv[]) } } - ios_puts("WARNING: Base._start not defined, falling back to economy mode repl.\n", ios_stdout); + jl_printf(JL_STDOUT, "WARNING: Base._start not defined, falling back to economy mode repl.\n"); if (!jl_errorexception_type) - ios_puts("WARNING: jl_errorexception_type not defined; any errors will be fatal.\n", ios_stdout); + jl_printf(JL_STDOUT, "WARNING: jl_errorexception_type not defined; any errors will be fatal.\n"); while (!ios_eof(ios_stdin)) { char *volatile line = NULL; @@ -597,7 +577,7 @@ static NOINLINE int true_main(int argc, char *argv[]) jl_printf(JL_STDOUT, "\n"); free(line); line = NULL; - uv_run(jl_global_event_loop(),UV_RUN_NOWAIT); + jl_process_events(); } JL_CATCH { if (line) { @@ -607,7 +587,7 @@ static NOINLINE int true_main(int argc, char *argv[]) jl_printf((JL_STREAM*)STDERR_FILENO, "\nparser error:\n"); jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception()); jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); - jlbacktrace(); // written to STDERR_FILENO + jl_print_backtrace(); // written to STDERR_FILENO } } return 0; @@ -665,7 +645,7 @@ static void rr_detach_teleport(void) { #endif } -JL_DLLEXPORT int repl_entrypoint(int argc, char *argv[]) +JL_DLLEXPORT int jl_repl_entrypoint(int argc, char *argv[]) { // no-op on Windows, note that the caller must have already converted // from `wchar_t` to `UTF-8` already if we're running on Windows. diff --git a/src/julia.expmap b/src/julia.expmap index d9d255cc8c547..5f03eccbfcad6 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -37,7 +37,6 @@ _IO_stdin_used; __ZN4llvm23createLowerSimdLoopPassEv; LLVMExtra*; - repl_entrypoint; /* freebsd */ environ; diff --git a/src/julia.h b/src/julia.h index 1e0d96af669c7..8ec461e77126b 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1639,10 +1639,6 @@ typedef enum { JL_IMAGE_JULIA_HOME = 1, //JL_IMAGE_LIBJULIA = 2, } JL_IMAGE_SEARCH; -// this helps turn threading compilation mismatches into linker errors -#define julia_init julia_init__threading -#define jl_init jl_init__threading -#define jl_init_with_image jl_init_with_image__threading JL_DLLEXPORT const char *jl_get_libdir(void); JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); @@ -1965,7 +1961,8 @@ JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT; -JL_DLLEXPORT void jlbacktrace(void) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jl_print_backtrace(void) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jlbacktrace(void) JL_NOTSAFEPOINT; // deprecated // Mainly for debugging, use `void*` so that no type cast is needed in C++. JL_DLLEXPORT void jl_(void *jl_value) JL_NOTSAFEPOINT; diff --git a/src/julia_internal.h b/src/julia_internal.h index 43617b17dbefe..d6170a9d56719 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -676,8 +676,6 @@ void jl_init_int32_int64_cache(void); void jl_teardown_codegen(void); -void _julia_init(JL_IMAGE_SEARCH rel); - void jl_set_base_ctx(char *__stk); extern ssize_t jl_tls_offset; diff --git a/src/stackwalk.c b/src/stackwalk.c index a00980fdf81ec..d117b7146fe77 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -774,6 +774,11 @@ JL_DLLEXPORT void jlbacktracet(jl_task_t *t) } } +JL_DLLEXPORT void jl_print_backtrace(void) JL_NOTSAFEPOINT +{ + jlbacktrace(); +} + #ifdef __cplusplus } #endif diff --git a/src/task.c b/src/task.c index 4d38d30f5cc56..54aaf5fdc530f 100644 --- a/src/task.c +++ b/src/task.c @@ -312,11 +312,6 @@ NOINLINE static void record_backtrace(jl_ptls_t ptls, int skip) JL_NOTSAFEPOINT ptls->bt_size = rec_backtrace(ptls->bt_data, JL_MAX_BT_SIZE, skip + 1); } -JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) -{ - _julia_init(rel); -} - JL_DLLEXPORT void jl_set_next_task(jl_task_t *task) JL_NOTSAFEPOINT { jl_get_ptls_states()->next_task = task; From e1f4f6541056fe75bfc0d3f8387a6dc5464d633e Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 29 Apr 2021 18:05:24 +0200 Subject: [PATCH 287/439] make sure sortperm on Vector{Float64} is precompiled (#40645) --- base/Base.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/Base.jl b/base/Base.jl index df304f6b87a67..1ffb747d982ae 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -426,6 +426,9 @@ for match = _methods(+, (Int, Int), -1, get_world_counter()) Core.svec(1, 2) == Core.svec(3, 4) any(t->t[1].line > 1, [(LineNumberNode(2,:none), :(1+1))]) + # Code loading uses this + sortperm(mtime.(readdir(".")), rev=true) + break # only actually need to do this once end From 37af9ed0ebc56186a389b4ae49a57333eca8e7c8 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 29 Apr 2021 18:27:52 +0200 Subject: [PATCH 288/439] add "see also" for `strip`, `lstrip` and `rstrip` docstrings (#40648) --- base/strings/util.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/strings/util.jl b/base/strings/util.jl index 11161ce49af09..9bc043513deed 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -239,6 +239,8 @@ The default behaviour is to remove leading whitespace and delimiters: see The optional `chars` argument specifies which characters to remove: it can be a single character, or a vector or set of characters. +See also [`strip`](@ref) and [`rstrip`](@ref). + # Examples ```jldoctest julia> a = lpad("March", 20) @@ -271,6 +273,8 @@ The default behaviour is to remove trailing whitespace and delimiters: see The optional `chars` argument specifies which characters to remove: it can be a single character, or a vector or set of characters. +See also [`strip`](@ref) and [`lstrip`](@ref). + # Examples ```jldoctest julia> a = rpad("March", 20) @@ -302,6 +306,8 @@ The default behaviour is to remove leading and trailing whitespace and delimiter The optional `chars` argument specifies which characters to remove: it can be a single character, vector or set of characters. +See also [`lstrip`](@ref) and [`rstrip`](@ref). + !!! compat "Julia 1.2" The method which accepts a predicate function requires Julia 1.2 or later. From 09d6a03234a1e8fe53d9380fa4bf7d9a01c7fa3d Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 29 Apr 2021 22:38:18 +0400 Subject: [PATCH 289/439] indexing arrays with abstractunitranges retains indices (#40660) --- base/array.jl | 4 ++-- test/offsetarray.jl | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/base/array.jl b/base/array.jl index b1e67a91617f1..6e5b9b148a043 100644 --- a/base/array.jl +++ b/base/array.jl @@ -838,9 +838,9 @@ function getindex(A::Array, I::AbstractUnitRange{<:Integer}) @_inline_meta @boundscheck checkbounds(A, I) lI = length(I) - X = similar(A, lI) + X = similar(A, axes(I)) if lI > 0 - unsafe_copyto!(X, 1, A, first(I), lI) + copyto!(X, firstindex(X), A, first(I), lI) end return X end diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 50fe2fcef4c1f..96a44c71e5483 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -776,3 +776,13 @@ end strY = String(take!(io)) @test strX == strY end + +@testset "vector indexing (issue #39896)" begin + a = collect(1:10) + r = Base.IdentityUnitRange(2:3) + b = a[r] + @test axes(b) == axes(r) + for i in r + @test b[i] == a[r[i]] + end +end From 7a0ee954c6784c4c423e7712ca2089207447956d Mon Sep 17 00:00:00 2001 From: Alex Hirzel Date: Thu, 29 Apr 2021 15:46:34 -0400 Subject: [PATCH 290/439] fix typo in "Rejecting cache file" message (#40662) --- base/loading.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index b2be6d2f75bc2..ca7ab7cb6b391 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1749,7 +1749,7 @@ function stale_cachefile(modpath::String, cachefile::String) # now check if this file is fresh relative to its source files if !skip_timecheck if !samefile(includes[1].filename, modpath) - @debug "Rejecting cache file $cachefile because it is for file $(includes[1].filename)) not file $modpath" + @debug "Rejecting cache file $cachefile because it is for file $(includes[1].filename) not file $modpath" return true # cache file was compiled from a different path end for (modkey, req_modkey) in requires From ca319b4a356f309a948df55f7e973540f62d2254 Mon Sep 17 00:00:00 2001 From: tuedo2 <47128027+tuedo2@users.noreply.github.com> Date: Fri, 30 Apr 2021 09:28:53 -0500 Subject: [PATCH 291/439] Added test for promotion of same-sized unsigned and signed integers (#39739) --- test/int.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/int.jl b/test/int.jl index f0e157711c808..52f554718645e 100644 --- a/test/int.jl +++ b/test/int.jl @@ -141,6 +141,10 @@ SItypes = Base.BitSigned_types R = sizeof(S) < sizeof(Int) ? Int : S @test promote(R(3), T(3)) === (sizeof(R) < sizeof(T) ? (T(3), T(3)) : (R(3), R(3))) end + + for i in 1:length(UItypes) + @test promote(UItypes[i](3), SItypes[i](3)) === (UItypes[i](3), UItypes[i](3)) + end end @testset "limiting conversions" begin for T in (Int8, Int16, Int32, Int64) From d7c6a9b4683635c426052d9db24019bc2bc366ef Mon Sep 17 00:00:00 2001 From: "Viktor G. Gumennyy" <20798349+sairus7@users.noreply.github.com> Date: Fri, 30 Apr 2021 17:33:38 +0300 Subject: [PATCH 292/439] `@lock` export from Base, closes #36441 (#39588) --- NEWS.md | 1 + base/exports.jl | 1 + base/lock.jl | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/NEWS.md b/NEWS.md index 089f81c272168..9e599898d452a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -85,6 +85,7 @@ Standard library changes @test isequal(complex(one(T)) / complex(T(Inf), T(-Inf)), complex(zero(T), zero(T))) broken=(T == Float64) ``` ([#39322]) +* `@lock` is now exported from Base ([#39588]). #### Package Manager diff --git a/base/exports.jl b/base/exports.jl index 9a6cdce86b38c..bfca26745e2ac 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -675,6 +675,7 @@ export istaskstarted, istaskfailed, lock, + @lock, notify, ReentrantLock, schedule, diff --git a/base/lock.jl b/base/lock.jl index b013a593cde84..07253211984fc 100644 --- a/base/lock.jl +++ b/base/lock.jl @@ -201,6 +201,22 @@ function trylock(f, l::AbstractLock) return false end +""" + @lock l expr + +Macro version of `lock(f, l::AbstractLock)` but with `expr` instead of `f` function. +Expands to: +```julia +lock(l) +try + expr +finally + unlock(l) +end +``` +This is similar to using [`lock`](@ref) with a `do` block, but avoids creating a closure +and thus can improve the performance. +""" macro lock(l, expr) quote temp = $(esc(l)) @@ -213,6 +229,13 @@ macro lock(l, expr) end end +""" + @lock_nofail l expr + +Equivalent to `@lock l expr` for cases in which we can guarantee that the function +will not throw any error. In this case, avoiding try-catch can improve the performance. +See [`@lock`](@ref). +""" macro lock_nofail(l, expr) quote temp = $(esc(l)) From eb111b291936baa6dc939941242f62ef55fbefa4 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 1 May 2021 23:51:38 +0530 Subject: [PATCH 293/439] [doc] minor change of filename in getting-started.md (#40674) --- doc/src/manual/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index 8b13385e9ede7..da8f3f985335f 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -61,7 +61,7 @@ bar The `--` delimiter can be used to separate command-line arguments intended for the script file from arguments intended for Julia: ``` -$ julia --color=yes -O -- foo.jl arg1 arg2.. +$ julia --color=yes -O -- script.jl arg1 arg2.. ``` See also [Scripting](@ref man-scripting) for more information on writing Julia scripts. From 2681a5128ba9f77d2f5fe1f38d92171251e726c3 Mon Sep 17 00:00:00 2001 From: Jack Dunn Date: Sat, 1 May 2021 14:41:04 -0400 Subject: [PATCH 294/439] Add compat to docstring for single-arg `isapprox` (#40659) Co-authored-by: Simeon Schaub --- base/floatfuncs.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 1b3a088524c8e..60134ee91919d 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -295,6 +295,9 @@ end Create a function that compares its argument to `x` using `≈`, i.e. a function equivalent to `y -> y ≈ x`. The keyword arguments supported here are the same as those in the 2-argument `isapprox`. + +!!! compat "Julia 1.5" + This method requires Julia 1.5 or later. """ isapprox(y; kwargs...) = x -> isapprox(x, y; kwargs...) From 8fdd1371f8b10bd8188ab3d2f2699bbbcbc8510f Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sun, 2 May 2021 22:59:28 +0000 Subject: [PATCH 295/439] [automated] Bump the Pkg stdlib from 879c21d9 to ad3d6396 (#40684) Co-authored-by: Dilum Aluthge --- .../Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 | 1 - .../Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 | 1 - .../Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 | 1 + .../Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 create mode 100644 deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 diff --git a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 deleted file mode 100644 index ac19c43317da9..0000000000000 --- a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -c529f61ceca38c5acf28e5ba57bd8b4d diff --git a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 b/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 deleted file mode 100644 index 3d042f16d8793..0000000000000 --- a/deps/checksums/Pkg-879c21d938d3d898539903bb3e381ef8cee21f1d.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -921e9dc6d422d90f722d6145182c0bccc2cf9be4653b1ed37084baf569a1f4d534fd78a50d3f0a9350ad5e7f0e49f1b3a32acb543749b8230a713688a8000bbf diff --git a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 new file mode 100644 index 0000000000000..c740cfe0adba5 --- /dev/null +++ b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 @@ -0,0 +1 @@ +430c0eb85897bebf5327cde9585b465b diff --git a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 new file mode 100644 index 0000000000000..3646aa055b000 --- /dev/null +++ b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 @@ -0,0 +1 @@ +9d9520b3acc9164cb52245a097a77a4d26110e535247135c9f7c474e11b8f0f9b8d5a4e47a8568b97ec7327e612acf99018a9e20683b6928b1c3a830b5873162 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 3f85f57b2a693..1ecbfce5e8de4 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 879c21d938d3d898539903bb3e381ef8cee21f1d +PKG_SHA1 = ad3d6396fb40b553e3a48bff2917610b67a971f4 From 2ceebfd9305c0e9accbd1b6496307887a9fe423b Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Mon, 3 May 2021 10:03:04 +0900 Subject: [PATCH 296/439] show sign for NaNs if required --- base/ryu/exp.jl | 33 ++----------------------- base/ryu/fixed.jl | 33 ++----------------------- base/ryu/shortest.jl | 45 +++++++++------------------------- base/ryu/utils.jl | 14 +++++++++++ stdlib/Printf/test/runtests.jl | 12 ++++----- 5 files changed, 36 insertions(+), 101 deletions(-) diff --git a/base/ryu/exp.jl b/base/ryu/exp.jl index ff20118d68011..58ae0fa97b712 100644 --- a/base/ryu/exp.jl +++ b/base/ryu/exp.jl @@ -4,19 +4,10 @@ function writeexp(buf, pos, v::T, @assert 0 < pos <= length(buf) startpos = pos x = Float64(v) - neg = signbit(x) + pos = append_sign(x, plus, space, buf, pos) + # special cases if x == 0 - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end buf[pos] = UInt8('0') pos += 1 if precision > 0 @@ -41,16 +32,6 @@ function writeexp(buf, pos, v::T, buf[pos + 2] = UInt8('N') return pos + 3 elseif !isfinite(x) - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end buf[pos] = UInt8('I') buf[pos + 1] = UInt8('n') buf[pos + 2] = UInt8('f') @@ -70,16 +51,6 @@ function writeexp(buf, pos, v::T, end nonzero = false precision += 1 - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end digits = 0 printedDigits = 0 availableDigits = 0 diff --git a/base/ryu/fixed.jl b/base/ryu/fixed.jl index 360b2ae5ac407..05259a9849d01 100644 --- a/base/ryu/fixed.jl +++ b/base/ryu/fixed.jl @@ -4,19 +4,10 @@ function writefixed(buf, pos, v::T, @assert 0 < pos <= length(buf) startpos = pos x = Float64(v) - neg = signbit(x) + pos = append_sign(x, plus, space, buf, pos) + # special cases if x == 0 - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end buf[pos] = UInt8('0') pos += 1 if precision > 0 @@ -40,16 +31,6 @@ function writefixed(buf, pos, v::T, buf[pos + 2] = UInt8('N') return pos + 3 elseif !isfinite(x) - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end buf[pos] = UInt8('I') buf[pos + 1] = UInt8('n') buf[pos + 2] = UInt8('f') @@ -68,16 +49,6 @@ function writefixed(buf, pos, v::T, m2 = (Int64(1) << 52) | mant end nonzero = false - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end if e2 >= -52 idx = e2 < 0 ? 0 : indexforexp(e2) p10bits = pow10bitsforindex(idx) diff --git a/base/ryu/shortest.jl b/base/ryu/shortest.jl index 1259ee5c69794..f95c09d235e6d 100644 --- a/base/ryu/shortest.jl +++ b/base/ryu/shortest.jl @@ -229,7 +229,6 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, precision=-1, expchar=UInt8('e'), padexp=false, decchar=UInt8('.'), typed=false, compact=false) where {T} @assert 0 < pos <= length(buf) - neg = signbit(x) # special cases if x == 0 if typed && x isa Float16 @@ -243,17 +242,7 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, buf[pos + 7] = UInt8('(') pos += 8 end - - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end + pos = append_sign(x, plus, space, buf, pos) buf[pos] = UInt8('0') pos += 1 if hash @@ -290,6 +279,7 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, end return pos elseif isnan(x) + pos = append_sign(x, plus, space, buf, pos) buf[pos] = UInt8('N') buf[pos + 1] = UInt8('a') buf[pos + 2] = UInt8('N') @@ -304,22 +294,20 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, end return pos + 3 + (typed && x isa Union{Float32, Float16} ? 2 : 0) elseif !isfinite(x) - if neg - buf[pos] = UInt8('-') - end - buf[pos + neg] = UInt8('I') - buf[pos + neg + 1] = UInt8('n') - buf[pos + neg + 2] = UInt8('f') + pos = append_sign(x, plus, space, buf, pos) + buf[pos] = UInt8('I') + buf[pos + 1] = UInt8('n') + buf[pos + 2] = UInt8('f') if typed if x isa Float32 - buf[pos + neg + 3] = UInt8('3') - buf[pos + neg + 4] = UInt8('2') + buf[pos + 3] = UInt8('3') + buf[pos + 4] = UInt8('2') elseif x isa Float16 - buf[pos + neg + 3] = UInt8('1') - buf[pos + neg + 4] = UInt8('6') + buf[pos + 3] = UInt8('1') + buf[pos + 4] = UInt8('6') end end - return pos + neg + 3 + (typed && x isa Union{Float32, Float16} ? 2 : 0) + return pos + 3 + (typed && x isa Union{Float32, Float16} ? 2 : 0) end output, nexp = reduce_shortest(x, compact ? 999_999 : nothing) @@ -335,16 +323,7 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, buf[pos + 7] = UInt8('(') pos += 8 end - if neg - buf[pos] = UInt8('-') - pos += 1 - elseif plus - buf[pos] = UInt8('+') - pos += 1 - elseif space - buf[pos] = UInt8(' ') - pos += 1 - end + pos = append_sign(x, plus, space, buf, pos) olength = decimallength(output) exp_form = true diff --git a/base/ryu/utils.jl b/base/ryu/utils.jl index 24e38a0a50241..352f8f19cb9be 100644 --- a/base/ryu/utils.jl +++ b/base/ryu/utils.jl @@ -195,6 +195,20 @@ Compute `(m * mul) >> j % 10^9` where `mul = mula + mulb<<64 + mulc<<128`, and ` return (v % UInt32) - UInt32(1000000000) * shifted end +@inline function append_sign(x, plus, space, buf, pos) + if signbit(x) && !isnan(x) # suppress minus sign for signaling NaNs + buf[pos] = UInt8('-') + pos += 1 + elseif plus + buf[pos] = UInt8('+') + pos += 1 + elseif space + buf[pos] = UInt8(' ') + pos += 1 + end + return pos +end + @inline function append_n_digits(olength, digits, buf, pos) i = 0 while digits >= 10000 diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index 5fd9d9fd2eef5..1dcd30d0971f1 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -110,9 +110,9 @@ end @test (Printf.@sprintf "%f" -Inf) == "-Inf" @test (Printf.@sprintf "%+f" -Inf) == "-Inf" @test (Printf.@sprintf "%f" NaN) == "NaN" - @test (Printf.@sprintf "%+f" NaN) == "NaN" - @test (Printf.@sprintf "% f" NaN) == "NaN" - @test (Printf.@sprintf "% #f" NaN) == "NaN" + @test (Printf.@sprintf "%+f" NaN) == "+NaN" + @test (Printf.@sprintf "% f" NaN) == " NaN" + @test (Printf.@sprintf "% #f" NaN) == " NaN" @test (Printf.@sprintf "%e" big"Inf") == "Inf" @test (Printf.@sprintf "%e" big"NaN") == "NaN" @@ -163,9 +163,9 @@ end @test (Printf.@sprintf "%e" -Inf) == "-Inf" @test (Printf.@sprintf "%+e" -Inf) == "-Inf" @test (Printf.@sprintf "%e" NaN) == "NaN" - @test (Printf.@sprintf "%+e" NaN) == "NaN" - @test (Printf.@sprintf "% e" NaN) == "NaN" - @test (Printf.@sprintf "% #e" NaN) == "NaN" + @test (Printf.@sprintf "%+e" NaN) == "+NaN" + @test (Printf.@sprintf "% e" NaN) == " NaN" + @test (Printf.@sprintf "% #e" NaN) == " NaN" @test (Printf.@sprintf "%e" big"Inf") == "Inf" @test (Printf.@sprintf "%e" big"NaN") == "NaN" From d22c3041a72e62ddc3b9e17e83a61b841a6d413b Mon Sep 17 00:00:00 2001 From: clement-f Date: Mon, 3 May 2021 04:52:20 +0200 Subject: [PATCH 297/439] Optimisation of getproperty for UmfpackLU object (avoid copying irrelevant information) (#40663) --- stdlib/SuiteSparse/src/umfpack.jl | 299 ++++++++++++++++++++++------- stdlib/SuiteSparse/test/umfpack.jl | 5 + 2 files changed, 231 insertions(+), 73 deletions(-) diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl index 4d6593a34aad9..e1e5df876c9a5 100644 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -428,61 +428,237 @@ for itype in UmfpackIndexTypes lnz, unz, n_row, n_col, nz_diag, lu.numeric) (lnz[], unz[], n_row[], n_col[], nz_diag[]) end - function umf_extract(lu::UmfpackLU{Float64,$itype}) - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - Lj = Vector{$itype}(undef, lnz) # L is returned in CSR (compressed sparse row) format - Lx = Vector{Float64}(undef, lnz) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - P = Vector{$itype}(undef, n_row) - Q = Vector{$itype}(undef, n_col) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_r,:libumfpack), $itype, - (Ptr{$itype},Ptr{$itype},Ptr{Float64}, - Ptr{$itype},Ptr{$itype},Ptr{Float64}, - Ptr{$itype},Ptr{$itype},Ptr{Cvoid}, - Ref{$itype},Ptr{Float64},Ptr{Cvoid}), - Lp,Lj,Lx, - Up,Ui,Ux, - P, Q, C_NULL, - 0, Rs, lu.numeric) - (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, increment!(Lp), increment!(Lj), Lx))), - SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), increment!(Ui), Ux), - increment!(P), increment!(Q), Rs) + function getproperty(lu::UmfpackLU{Float64, $itype}, d::Symbol) + if d === :L + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Lp = Vector{$itype}(undef, n_row + 1) + # L is returned in CSR (compressed sparse row) format + Lj = Vector{$itype}(undef, lnz) + Lx = Vector{Float64}(undef, lnz) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + Lp, Lj, Lx, + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, + increment!(Lp), increment!(Lj), Lx))) + elseif d === :U + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Up = Vector{$itype}(undef, n_col + 1) + Ui = Vector{$itype}(undef, unz) + Ux = Vector{Float64}(undef, unz) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, + Up, Ui, Ux, + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), + increment!(Ui), Ux) + elseif d === :p + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + P = Vector{$itype}(undef, n_row) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, + P, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return increment!(P) + elseif d === :q + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Q = Vector{$itype}(undef, n_col) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{$itype}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, + C_NULL, Q, C_NULL, + C_NULL, C_NULL, lu.numeric) + return increment!(Q) + elseif d === :Rs + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Rs = Vector{Float64}(undef, n_row) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, + C_NULL, Rs, lu.numeric) + return Rs + elseif d === :(:) + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Lp = Vector{$itype}(undef, n_row + 1) + # L is returned in CSR (compressed sparse row) format + Lj = Vector{$itype}(undef, lnz) + Lx = Vector{Float64}(undef, lnz) + Up = Vector{$itype}(undef, n_col + 1) + Ui = Vector{$itype}(undef, unz) + Ux = Vector{Float64}(undef, unz) + P = Vector{$itype}(undef, n_row) + Q = Vector{$itype}(undef, n_col) + Rs = Vector{Float64}(undef, n_row) + @isok ccall(($get_num_r, :libumfpack), $itype, + (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, + Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, + Ptr{$itype}, Ptr{$itype}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), + Lp, Lj, Lx, + Up, Ui, Ux, + P, Q, C_NULL, + C_NULL, Rs, lu.numeric) + return (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, + increment!(Lp), increment!(Lj), + Lx))), + SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), + increment!(Ui), Ux), + increment!(P), increment!(Q), Rs) + else + return getfield(lu, d) + end end - function umf_extract(lu::UmfpackLU{ComplexF64,$itype}) - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - Lj = Vector{$itype}(undef, lnz) # L is returned in CSR (compressed sparse row) format - Lx = Vector{Float64}(undef, lnz) - Lz = Vector{Float64}(undef, lnz) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - Uz = Vector{Float64}(undef, unz) - P = Vector{$itype}(undef, n_row) - Q = Vector{$itype}(undef, n_col) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_z,:libumfpack), $itype, - (Ptr{$itype},Ptr{$itype},Ptr{Float64},Ptr{Float64}, - Ptr{$itype},Ptr{$itype},Ptr{Float64},Ptr{Float64}, - Ptr{$itype},Ptr{$itype},Ptr{Cvoid}, Ptr{Cvoid}, - Ref{$itype},Ptr{Float64},Ptr{Cvoid}), - Lp,Lj,Lx,Lz, - Up,Ui,Ux,Uz, - P, Q, C_NULL, C_NULL, - 0, Rs, lu.numeric) - (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, increment!(Lp), increment!(Lj), complex.(Lx, Lz)))), - SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), increment!(Ui), complex.(Ux, Uz)), - increment!(P), increment!(Q), Rs) + function getproperty(lu::UmfpackLU{ComplexF64, $itype}, d::Symbol) + if d === :L + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Lp = Vector{$itype}(undef, n_row + 1) + # L is returned in CSR (compressed sparse row) format + Lj = Vector{$itype}(undef, lnz) + Lx = Vector{Float64}(undef, lnz) + Lz = Vector{Float64}(undef, lnz) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + Lp, Lj, Lx, Lz, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, + increment!(Lp), increment!(Lj), + complex.(Lx, Lz)))) + elseif d === :U + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Up = Vector{$itype}(undef, n_col + 1) + Ui = Vector{$itype}(undef, unz) + Ux = Vector{Float64}(undef, unz) + Uz = Vector{Float64}(undef, unz) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, C_NULL, + Up, Ui, Ux, Uz, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), + increment!(Ui), complex.(Ux, Uz)) + elseif d === :p + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + P = Vector{$itype}(undef, n_row) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, C_NULL, + P, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return increment!(P) + elseif d === :q + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Q = Vector{$itype}(undef, n_col) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, Q, C_NULL, C_NULL, + C_NULL, C_NULL, lu.numeric) + return increment!(Q) + elseif d === :Rs + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Rs = Vector{Float64}(undef, n_row) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, C_NULL, C_NULL, C_NULL, + C_NULL, Rs, lu.numeric) + return Rs + elseif d === :(:) + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) + Lp = Vector{$itype}(undef, n_row + 1) + # L is returned in CSR (compressed sparse row) format + Lj = Vector{$itype}(undef, lnz) + Lx = Vector{Float64}(undef, lnz) + Lz = Vector{Float64}(undef, lnz) + Up = Vector{$itype}(undef, n_col + 1) + Ui = Vector{$itype}(undef, unz) + Ux = Vector{Float64}(undef, unz) + Uz = Vector{Float64}(undef, unz) + P = Vector{$itype}(undef, n_row) + Q = Vector{$itype}(undef, n_col) + Rs = Vector{Float64}(undef, n_row) + @isok ccall(($get_num_z, :libumfpack), $itype, + (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, + Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, + Ptr{$itype}, Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), + Lp, Lj, Lx, Lz, + Up, Ui, Ux, Uz, + P, Q, C_NULL, C_NULL, + C_NULL, Rs, lu.numeric) + return (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, + increment!(Lp), increment!(Lj), + complex.(Lx, Lz)))), + SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), + increment!(Ui), complex.(Ux, Uz)), + increment!(P), increment!(Q), Rs) + else + return getfield(lu, d) + end end end end +# backward compatibility +umfpack_extract(lu::UmfpackLU) = getproperty(lu, :(:)) + function nnz(lu::UmfpackLU) lnz, unz, = umf_lunz(lu) return Int(lnz + unz) @@ -555,29 +731,6 @@ function _AqldivB_kernel!(X::StridedMatrix{Tb}, lu::UmfpackLU{Float64}, end end - -@inline function getproperty(lu::UmfpackLU, d::Symbol) - if d === :L || d === :U || d === :p || d === :q || d === :Rs || d === :(:) - # Guard the call to umf_extract behaind a branch to avoid infinite recursion - L, U, p, q, Rs = umf_extract(lu) - if d === :L - return L - elseif d === :U - return U - elseif d === :p - return p - elseif d === :q - return q - elseif d === :Rs - return Rs - elseif d === :(:) - return (L, U, p, q, Rs) - end - else - getfield(lu, d) - end -end - for Tv in (:Float64, :ComplexF64), Ti in UmfpackIndexTypes f = Symbol(umf_nm("free_symbolic", Tv, Ti)) @eval begin diff --git a/stdlib/SuiteSparse/test/umfpack.jl b/stdlib/SuiteSparse/test/umfpack.jl index a4f749f1ce58b..4dcf7007aa1c7 100644 --- a/stdlib/SuiteSparse/test/umfpack.jl +++ b/stdlib/SuiteSparse/test/umfpack.jl @@ -27,6 +27,11 @@ using SparseArrays: nnz, sparse, sprand, sprandn, SparseMatrixCSC @test nnz(lua) == 18 @test_throws ErrorException lua.Z L,U,p,q,Rs = lua.:(:) + @test L == lua.L + @test U == lua.U + @test p == lua.p + @test q == lua.q + @test Rs == lua.Rs @test (Diagonal(Rs) * A)[p,q] ≈ L * U det(lua) ≈ det(Array(A)) From b3b9aa0eb1a90765dd3d395073992c534254a23f Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 3 May 2021 12:46:57 +0400 Subject: [PATCH 298/439] ndims for AbstractArray{<:Any,N} (#40682) --- base/abstractarray.jl | 2 +- test/abstractarray.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index a5782b99e581c..2cbe4b501e718 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -234,7 +234,7 @@ julia> ndims(A) ``` """ ndims(::AbstractArray{T,N}) where {T,N} = N -ndims(::Type{<:AbstractArray{T,N}}) where {T,N} = N +ndims(::Type{<:AbstractArray{<:Any,N}}) where {N} = N """ length(collection) -> Integer diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 44e29e59ead69..6c5ed26a1c289 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -835,6 +835,11 @@ end @testset "ndims and friends" begin @test ndims(Diagonal(rand(1:5,5))) == 2 @test ndims(Diagonal{Float64}) == 2 + @test ndims(Diagonal) == 2 + @test ndims(Vector) == 1 + @test ndims(Matrix) == 2 + @test ndims(Array{<:Any, 0}) == 0 + @test_throws MethodError ndims(Array) end @testset "Issue #17811" begin From 140afc6479d4a7f8193a1cec992c5a6928f02fc4 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 3 May 2021 08:31:40 -0400 Subject: [PATCH 299/439] update all checksums and pcre rules to generate them (#40688) * update all checksums and pcre rules to generate them Co-authored-by: Jameson Nash --- deps/checksums/blastrampoline | 4 +- deps/checksums/clang | 2 + deps/checksums/suitesparse | 71 ++++++++++++++++------------------- deps/pcre.mk | 2 +- deps/suitesparse.mk | 14 ++++--- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index 1d371bee78d16..a9a564fc09042 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,5 +1,5 @@ -blastrampoline-5882fdf6395afb1ed01a8a10db94b7b3cbd39e16.tar.gz/md5/e0d62a761862e4331e39f3a863558b15 -blastrampoline-5882fdf6395afb1ed01a8a10db94b7b3cbd39e16.tar.gz/sha512/b0637d903183b42ad7fff0e7c6e2c9feda0082d31d6a86926586c56437fc91041b5fea2c4cd4f5b588e8f86e71fdbf4ac216fa6862a1df360faa77c8966e7b0e +blastrampoline-23de7a09bf354fe6f655c457bab5bf47fdd2486d.tar.gz/md5/0c8016a6e30bc2237184b816b613d11c +blastrampoline-23de7a09bf354fe6f655c457bab5bf47fdd2486d.tar.gz/sha512/7b7dbb101cf05ac833a8e5b09f1eec8eb99f0caafbe80075751a5f7e0bfe03a3b19d11d3507dadd13f503cfa9fc1a6cd53f3461af7d5afb39ca385a0ee26120b libblastrampoline.v3.0.4+0.aarch64-apple-darwin.tar.gz/md5/0ea485b558637933f039d8793b3aa6c6 libblastrampoline.v3.0.4+0.aarch64-apple-darwin.tar.gz/sha512/bc7d4edd90f0f01cbc23cdce38bf3fa550ce988790fc63d8c84951b884465cc4f2d591d91a119e5cf8ce6b3161da6e09dc3689d52b4e71175be0d21afba00319 libblastrampoline.v3.0.4+0.aarch64-linux-gnu.tar.gz/md5/a175724976338ad493b200194687f63a diff --git a/deps/checksums/clang b/deps/checksums/clang index 3e438a189a575..8d0505b5103d7 100644 --- a/deps/checksums/clang +++ b/deps/checksums/clang @@ -1,3 +1,5 @@ +clang-11.0.1.src.tar.xz/md5/b4cb0b74b1f3292a89c9720f3e1e2934 +clang-11.0.1.src.tar.xz/sha512/bb98ffb0a992c9907795f7bb7492196f7195fdb5e292e8a764a7a1a8cc078dcf60bebf26ed3db116f78b7022a600c996fd2645e5f6e5d24e4ed99392e1f08df3 Clang.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/55c50726cd43c1b49a222ec92ea05431 Clang.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/009b29068af7d8a008e34853faa3ce1e20817d3a7975fe4ca5657d1303e546410c903af345356fb94c88f8e95474895e68414a5a04096b2e9bdeed732780637e Clang.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/e5d8d1d5364dba4c5891c9a127ee358d diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 71603a22ccea5..7b4975e4ca709 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,41 +1,34 @@ SuiteSparse-5.8.1.tar.gz/md5/c414679bbc9432a3def01b31ad921140 SuiteSparse-5.8.1.tar.gz/sha512/3d986157acd39968216880c2de30c54d72e0addd7318a04948c1b842ad9c876bcde32f292504d4540a4baa998a368dfc0db000606a2d00f61760a92d5b8c1cb8 -SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/md5/57fa5164c7ee989ff95571037c0dfcc0 -SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/md5/57fa5164c7ee989ff95571037c0dfcc0 -SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/sha512/a12ac3ec77ac0b78595bc247a4fc37b9136e9a5095abf061b3fade60130b153d61b5a3c602be87c7334660b67f3539075975a9d4a1545d8ee5fd62c734941032 -SuiteSparse.v5.8.1+0.aarch64-apple-darwin.tar.gz/sha512/a12ac3ec77ac0b78595bc247a4fc37b9136e9a5095abf061b3fade60130b153d61b5a3c602be87c7334660b67f3539075975a9d4a1545d8ee5fd62c734941032 -SuiteSparse.v5.8.1+0.aarch64-linux-gnu.tar.gz/md5/a932269a0fb499d931867acc9505e49b -SuiteSparse.v5.8.1+0.aarch64-linux-gnu.tar.gz/sha512/2983c095533f7d8c2fa81779bf907e9024b1bfef58e934a4d524d767911a41f3006babc20530b3b23854d87adce02eb5e7e8a98d4ad3d853b03abc64cd8d5e6b -SuiteSparse.v5.8.1+0.aarch64-linux-musl.tar.gz/md5/ccc8c1b5378f208374c45ceb6c2b38a1 -SuiteSparse.v5.8.1+0.aarch64-linux-musl.tar.gz/sha512/eb357385de23ce864dc15892100372075aeb2ea2dcdc091a24d746d22278593391ff30cfb94b4c68ab66b03414f13b50614312f46b27f972b977541050b96630 -SuiteSparse.v5.8.1+0.armv6l-linux-gnueabihf.tar.gz/md5/ed3ea07e0996126bfac86e3abee78fb5 -SuiteSparse.v5.8.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/d9de5fb0c0627376d0145ef238a1910f8b0d2037180dcf32caf2bae32600521641abcf20d24d725326fa9bbb52581bb6a4bfaccad292de875cef54b3d721d733 -SuiteSparse.v5.8.1+0.armv6l-linux-musleabihf.tar.gz/md5/a71b0a47cbc98144f52229e10f4cd20d -SuiteSparse.v5.8.1+0.armv6l-linux-musleabihf.tar.gz/sha512/1c61f4ec94ea8adbd2aef50a6f42dd767325400579ff91019c7a5d2555fac5abf17a05201b22b1ff389ce795267daffbef2d961eb46125348ad64032133797b9 -SuiteSparse.v5.8.1+0.armv7l-linux-gnueabihf.tar.gz/md5/bd585f667a26df26db98ffab82d3e40f -SuiteSparse.v5.8.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/1a7b1d0fb7cc5c308a10384a8a8c48cb789ab40d31693722feb01d14ee2781cacc74f0d3082f2e7149805d303002e05e70ca7c9ce715fdc93cbfdc92b84ff03f -SuiteSparse.v5.8.1+0.armv7l-linux-musleabihf.tar.gz/md5/960379f40ad66b94004c7201a0a0bd13 -SuiteSparse.v5.8.1+0.armv7l-linux-musleabihf.tar.gz/sha512/99745a0f4422f9ecb86a6c246cf0a1e5f02151adb5f17b600515b7fa220cdb3e7d709f769270af1665d693955500e27e0662ea97069affe209c4a50e4381ec92 -SuiteSparse.v5.8.1+0.i686-linux-gnu.tar.gz/md5/55ad27f4ac55e6c759160742904958ae -SuiteSparse.v5.8.1+0.i686-linux-gnu.tar.gz/sha512/84b14edf20a9fa9be0fec034866bf469ae7b07924e28fee6d5c4fa5c70826b4ac68c0c7abd5496b76f342c93d1b85f2c2f601ede71c5fba484f6776aa0ad04ab -SuiteSparse.v5.8.1+0.i686-linux-musl.tar.gz/md5/db6ec8eb4aee46f158abe36e593d9c20 -SuiteSparse.v5.8.1+0.i686-linux-musl.tar.gz/sha512/9ecdd62891730f9b587a3f6debfc859c51bc1e6fc7a925339442f25c9c9be587e5df90572f87236fc79302dd2435990d6d054a494ff3498fb31d83b0be11d0f9 -SuiteSparse.v5.8.1+0.i686-w64-mingw32.tar.gz/md5/379dbd76bc5b33b2f00e25b93f15d7c1 -SuiteSparse.v5.8.1+0.i686-w64-mingw32.tar.gz/sha512/91b4a4b3d5fd710510bba2ffa7b19bdf2860fb4f6c1946dcb421e4143097e7b77ee3bc780ed89726152f2c5e72d4e897e5eaa152b1d97176ed9d0e4fb2cdb6c6 -SuiteSparse.v5.8.1+0.powerpc64le-linux-gnu.tar.gz/md5/13e5e383de77448d7fca6802a27e2fc9 -SuiteSparse.v5.8.1+0.powerpc64le-linux-gnu.tar.gz/sha512/412611fd82923e042001774cbc7951e8d6777843b308f6b25cf361c05b44d1dafc1639e7526b0871ec637f15ac8fcd247e9201ba0d75bfe0bf0900a9dace1001 -SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/md5/d266370cc574c8ca8b2b8a94d6b877f4 -SuiteSparse.v5.8.1+0.x86_64-apple-darwin.tar.gz/sha512/2377d662f91d01229e3c44ec1c5624b6361e823ff90d625acc3bab8f68ada1b3b7b67f4e56c8896f890e5780bd2fcb494b5a1f91c9c7803715eac2a2a4bb938f -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/md5/2545d16665a42f36fbbad9198a9668e5 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 -SuiteSparse.v5.8.1+0.x86_64-linux-gnu.tar.gz/sha512/66cf497a002b566a681531873da0b5dc3b4f79414068b7ae53845325afb2f56a55069ff5ba5f47de0eb961af4df18cf8495019150f163213d32aa5b12c511ce3 -SuiteSparse.v5.8.1+0.x86_64-linux-musl.tar.gz/md5/8a8ade173d751514e03a6987aee56ca1 -SuiteSparse.v5.8.1+0.x86_64-linux-musl.tar.gz/sha512/7393063fd2f88bf5dbe1378d6d34206bde446f1ed971d2dd334c3cca96075334f4f8ca69f7d406d532a631fd8a76d739df27dab7928e596a1d38ba9c96fbc9d6 -SuiteSparse.v5.8.1+0.x86_64-unknown-freebsd.tar.gz/md5/674bbae00649ff495aed5fb57de80966 -SuiteSparse.v5.8.1+0.x86_64-unknown-freebsd.tar.gz/sha512/4a1ee55b55149549cbe022b3354bb136b7bfbbbcef8254c2ec91aad8c921c689dbedd208003c8805c320e5d3319e9b36945c117eaac4a634f31e76ff3e579f3d -SuiteSparse.v5.8.1+0.x86_64-w64-mingw32.tar.gz/md5/f52e3758656acf8a4342f8a34584c266 -SuiteSparse.v5.8.1+0.x86_64-w64-mingw32.tar.gz/sha512/a9a335bae4b588147bf11b301d11e4d3663011c3f7bd449382b09bba3eeb108501ef1244477f11c408d463bc61c2eff613a182bcc56ff2acae630d84483bb724 +SuiteSparse.v5.8.1+2.aarch64-apple-darwin.tar.gz/md5/949a6cd6ac04e41f89cef401d7e5ca74 +SuiteSparse.v5.8.1+2.aarch64-apple-darwin.tar.gz/sha512/60612bd0bfeb1e00a452aea8024454110838eb20889be3f82fa6ee25884f791d7fd21c156aaca68e94561f084ab83b44f71c7740486d8233c5451ff267e85d9a +SuiteSparse.v5.8.1+2.aarch64-linux-gnu.tar.gz/md5/241344499b65b88a967fecae692e314c +SuiteSparse.v5.8.1+2.aarch64-linux-gnu.tar.gz/sha512/5ab6f4df36a56c2ebc880a10889071bbf0846d6231ffe750a1427108a5ae3c7e1dcd0e994dcd4264908a420cc6534b8f58912baaafd1cdc83d5c38f5f44fb217 +SuiteSparse.v5.8.1+2.aarch64-linux-musl.tar.gz/md5/d0cbfe923083718235a6ef878a36dd7d +SuiteSparse.v5.8.1+2.aarch64-linux-musl.tar.gz/sha512/e1e0b4c9408ae966c429a81c22089077f137cd44fdd6a8ee228122ac3dfe79dd163277657fcce69c916d071b46b82f6cc445b1b2a778691c2a7fc4178eaeae0c +SuiteSparse.v5.8.1+2.armv6l-linux-gnueabihf.tar.gz/md5/5c690a16f2a176e3d7369ef52aaf0dcc +SuiteSparse.v5.8.1+2.armv6l-linux-gnueabihf.tar.gz/sha512/ce018e09df64f63b728a6f3fd6b256859b1f6ff76750858192083b19acd25813512ae50755d5cfd716fa62dc17ef160bad1ed4c65a46268801df9504482e2c04 +SuiteSparse.v5.8.1+2.armv6l-linux-musleabihf.tar.gz/md5/4b51607d9d6c332b5c86adc9ab6887e6 +SuiteSparse.v5.8.1+2.armv6l-linux-musleabihf.tar.gz/sha512/9fac97308c3109d4a6c365393c8077f9717b2cdd3dd483e0a0aed82ed4e70cd321aeb18e3eaa764bdb1c3b24e378eb687eeb0c48b91e1d0de55a08301b50c6d6 +SuiteSparse.v5.8.1+2.armv7l-linux-gnueabihf.tar.gz/md5/f40fdd991ef0cf9d556d1ae2ae079cd1 +SuiteSparse.v5.8.1+2.armv7l-linux-gnueabihf.tar.gz/sha512/1d1b81b8f6f82d09f53bff5ade45d3183cb903fee0b279d69fbb7cfa737aeff72279d3e151d4094ed56dfa4b8affe1f4bda443c982c5fc8aa881c2ce9f88dafc +SuiteSparse.v5.8.1+2.armv7l-linux-musleabihf.tar.gz/md5/4a87fc57bc380220abc7422f9f428d6f +SuiteSparse.v5.8.1+2.armv7l-linux-musleabihf.tar.gz/sha512/47cab4afd3559f67dfe54c6bc2ce9ff3c0e69334c2df99e929ff4843c7f92b6fdf7b6001e61701040a1623fc97927001b7cd0f07074d4099cd03b2d4e184d4c1 +SuiteSparse.v5.8.1+2.i686-linux-gnu.tar.gz/md5/4d3826df74a9f0c64e4dffabb6de0c7d +SuiteSparse.v5.8.1+2.i686-linux-gnu.tar.gz/sha512/2a0a10e1ba273b308aa7d11b0ace54eaef300ff4c8ddbf8ff3a721766fa5b59a43184b73f80afe8205410fa4d295ed5b38973053dcdba278d8e03aa0f47903ed +SuiteSparse.v5.8.1+2.i686-linux-musl.tar.gz/md5/72543b4dd636e4ffadb7a24eff8b5f9e +SuiteSparse.v5.8.1+2.i686-linux-musl.tar.gz/sha512/216795d8af1c2012b692d1b6ec2a4b70012331bbe9619a502c43cf1530d3170c69eb2261d6bba973ab40173f0b9a05992f4c570ff35a25018c7bff936da607ff +SuiteSparse.v5.8.1+2.i686-w64-mingw32.tar.gz/md5/29141ae2b353d4477b9d8e9fad0b8242 +SuiteSparse.v5.8.1+2.i686-w64-mingw32.tar.gz/sha512/ac80a24f60cb89ec25fddd77371cf209e43c4223756d435eb6f1a931c840bf7f2b11762de889664b98b0e0bb9b35f747c6af2365d564a164d6d92bb69c7b5108 +SuiteSparse.v5.8.1+2.powerpc64le-linux-gnu.tar.gz/md5/a776cb5742b4d00c89c445bc07ac7c3d +SuiteSparse.v5.8.1+2.powerpc64le-linux-gnu.tar.gz/sha512/314a220782be70d8267cefe4efd84439e33516c576666d8edbfa02581f0a1ebd31af97618743d461acb63f447ddff4dc282445b96782f2a73ec72b911948e443 +SuiteSparse.v5.8.1+2.x86_64-apple-darwin.tar.gz/md5/8b94288d3ec650f85f7723fc53e0acfd +SuiteSparse.v5.8.1+2.x86_64-apple-darwin.tar.gz/sha512/7a790a3bf8b3ff4402aea6d8c06eaf5d997317c85a7f109850af4f6719388b4a0a96d540c55b6ca1c2a69732307a89780c3f7282b784ce9c5d65b2fd2169a20c +SuiteSparse.v5.8.1+2.x86_64-linux-gnu.tar.gz/md5/b78f13d88b69826d6cde30cf5e7dbdf1 +SuiteSparse.v5.8.1+2.x86_64-linux-gnu.tar.gz/sha512/0e624d5f0f5f69d9e60841c90a7205bb38e0916db83752bb837b42f956389b9dfb7aca55025cb071fedeaa2acde8f7c7ad567e264f43aa49b1e8797b8bc3b4cb +SuiteSparse.v5.8.1+2.x86_64-linux-musl.tar.gz/md5/f1e7760e7de7385617c42137c042f085 +SuiteSparse.v5.8.1+2.x86_64-linux-musl.tar.gz/sha512/a7098cce4bed90133e9625908373c7c695ff03ebebec556322652d1d5485c7f9ab3543122a8950d27f0d00d751f136aa640a403fd2f326e37538cea12c199ac1 +SuiteSparse.v5.8.1+2.x86_64-unknown-freebsd.tar.gz/md5/8ebdffa4e464038f5dfa00f63776a919 +SuiteSparse.v5.8.1+2.x86_64-unknown-freebsd.tar.gz/sha512/54a93637ff01d2606726d445e8f186517da8915ef6bde549f841cd11521031c4fc19d3a8254006683db6bee04e41b43aaad72bacdf3c826d0fd9eed16feb40ab +SuiteSparse.v5.8.1+2.x86_64-w64-mingw32.tar.gz/md5/d280f92f61ce045dcf434029b32b788c +SuiteSparse.v5.8.1+2.x86_64-w64-mingw32.tar.gz/sha512/a17bfa2562fc60f3832131d72d6055c7855b10a67cccea357de6bed51ed9a310da5ccae7ed31549f4628c1af73aebd26125073d49648d194827e6cad0e421626 diff --git a/deps/pcre.mk b/deps/pcre.mk index 2120f3c95bc3a..67185a7213c85 100644 --- a/deps/pcre.mk +++ b/deps/pcre.mk @@ -14,7 +14,7 @@ $(SRCCACHE)/pcre2-$(PCRE_VER)/source-extracted: $(SRCCACHE)/pcre2-$(PCRE_VER).ta cp $(SRCDIR)/patches/config.sub $(SRCCACHE)/pcre2-$(PCRE_VER)/config.sub echo 1 > $@ -checksum-pcre2: $(SRCCACHE)/pcre2-$(PCRE_VER).tar.bz2 +checksum-pcre: $(SRCCACHE)/pcre2-$(PCRE_VER).tar.bz2 $(JLCHECKSUM) $< $(SRCCACHE)/pcre2-$(PCRE_VER)/pcre2-sljit-apple-silicon-support.patch-applied: $(SRCCACHE)/pcre2-$(PCRE_VER)/source-extracted diff --git a/deps/suitesparse.mk b/deps/suitesparse.mk index 5be8589875dc4..8bc179ef76b00 100644 --- a/deps/suitesparse.mk +++ b/deps/suitesparse.mk @@ -73,17 +73,15 @@ $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-checked: $(BUILDDIR)/SuiteSpars done echo 1 > $@ +UNINSTALL_suitesparse := $(SUITESPARSE_VER) manual_suitesparse $(SUITESPARSE_LIBS) + $(build_prefix)/manifest/suitesparse: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled | $(build_prefix)/manifest $(build_shlibdir) for lib in $(SUITESPARSE_LIBS); do \ cp -a $(dir $<)lib/lib$${lib} $(build_shlibdir) || exit 1; \ done #cp -a $(dir $<)lib/* $(build_shlibdir) #cp -a $(dir $<)include/* $(build_includedir) - echo $(SUITESPARSE_VER) > $@ - -uninstall-suitesparse: - -rm $(build_prefix)/manifest/suitesparse - -rm $(addprefix $(build_shlibdir)/lib, $(SUITESPARSE_LIBS)) + echo $(UNINSTALL_suitesparse) > $@ clean-suitesparse: clean-suitesparse-wrapper uninstall-suitesparse -rm $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled @@ -150,3 +148,9 @@ install-suitesparse-wrapper: install-suitesparse # suitesparse depends on blastrampoline compile-suitesparse: | $(build_prefix)/manifest/blastrampoline endif + +define manual_suitesparse +uninstall-suitesparse: + -rm $(build_prefix)/manifest/suitesparse + -rm $(addprefix $(build_shlibdir)/lib,$3) +endef From ef45879b11a3459719ab007ab90c921136d389e2 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 3 May 2021 14:31:16 +0000 Subject: [PATCH 300/439] [automated] Bump the Pkg stdlib from ad3d6396 to 1a47f445 (#40687) Co-authored-by: Dilum Aluthge --- .../Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 | 1 + .../Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 | 1 + .../Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 | 1 - .../Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 create mode 100644 deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 diff --git a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 new file mode 100644 index 0000000000000..063360a77aea1 --- /dev/null +++ b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 @@ -0,0 +1 @@ +e5cb2763c4abd84522a0706584d2a733 diff --git a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 new file mode 100644 index 0000000000000..06705d8278f46 --- /dev/null +++ b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 @@ -0,0 +1 @@ +e3007f929abdbfa574b72dad24e0ab954fb7469bcfb0786545e109c1122bff65b1d41065c289ae18d8a50130ae09c0700101d4e83d1c023deb5c759eb4f2484d diff --git a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 deleted file mode 100644 index c740cfe0adba5..0000000000000 --- a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -430c0eb85897bebf5327cde9585b465b diff --git a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 b/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 deleted file mode 100644 index 3646aa055b000..0000000000000 --- a/deps/checksums/Pkg-ad3d6396fb40b553e3a48bff2917610b67a971f4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -9d9520b3acc9164cb52245a097a77a4d26110e535247135c9f7c474e11b8f0f9b8d5a4e47a8568b97ec7327e612acf99018a9e20683b6928b1c3a830b5873162 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 1ecbfce5e8de4..b0804498895f2 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = ad3d6396fb40b553e3a48bff2917610b67a971f4 +PKG_SHA1 = 1a47f445f92053edc83a9528ed849ca404b4a2af From 6c85c4c93f6bf0e2077abaa75c9d1f8acdc13dd2 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Tue, 4 May 2021 16:02:16 +0900 Subject: [PATCH 301/439] [doc]: fix typo in operators.jl (#40699) --- base/operators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/operators.jl b/base/operators.jl index bf4a8a98bddf6..b73d9705d071a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -202,7 +202,7 @@ largest values and `isgreater` defines a descending total order with `NaN` and !!! note Like `min`, `isgreater` orders containers (tuples, vectors, etc) - lexigraphically with `isless(y, x)` rather than recursively with itself: + lexicographically with `isless(y, x)` rather than recursively with itself: ```jldoctest julia> Base.isgreater(1, NaN) # 1 is greater than NaN From 3ed6c1b3c68bc7dac0e3ea565236833518fc34ab Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Tue, 4 May 2021 07:02:54 +0000 Subject: [PATCH 302/439] Update the Downloads stdlib from 6bb8306 to c0e5cbd (#40701) --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/Downloads.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/md5 delete mode 100644 deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/sha512 create mode 100644 deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/md5 create mode 100644 deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/sha512 diff --git a/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/md5 b/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/md5 deleted file mode 100644 index 58efffdca88d2..0000000000000 --- a/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -7e0ab65c9c6f9413a458ee77ad5e0b29 diff --git a/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/sha512 b/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/sha512 deleted file mode 100644 index c01000751dc6b..0000000000000 --- a/deps/checksums/Downloads-6bb83068bd796c4890baaeb39628ff79a4979374.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -b7961928dffd19fb4e5220da694260ae822e80b5ae39ad503f493dcd225f54bc50d4df1b2e833473a164dd42b89c710528d6c58c60f0997492f2551ae1eebaf4 diff --git a/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/md5 b/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/md5 new file mode 100644 index 0000000000000..3e5f8512f28d5 --- /dev/null +++ b/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/md5 @@ -0,0 +1 @@ +2f772706c50763c369486fa730fb6314 diff --git a/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/sha512 b/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/sha512 new file mode 100644 index 0000000000000..cae2e9b1fbbac --- /dev/null +++ b/deps/checksums/Downloads-c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71.tar.gz/sha512 @@ -0,0 +1 @@ +c18c87194f5c214c2a3caddc1e0b17924c3c1c7f6f1f711cd545af32736cedc612ee8056ad892d115042ba140d1c7cd8d1fbdd70203eb8995587e54842bb67a8 diff --git a/stdlib/Downloads.version b/stdlib/Downloads.version index 9dc2783a1389b..c11c56068a51a 100644 --- a/stdlib/Downloads.version +++ b/stdlib/Downloads.version @@ -1,2 +1,2 @@ DOWNLOADS_BRANCH = master -DOWNLOADS_SHA1 = 6bb83068bd796c4890baaeb39628ff79a4979374 +DOWNLOADS_SHA1 = c0e5cbdef011ea4b87c56efaf5e9b1d16500ce71 From 0fa39ecea380d9a97a1e4ff0f5d873caf39ff227 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Tue, 4 May 2021 09:05:11 +0200 Subject: [PATCH 303/439] Document UInt return type of objectid (#40669) --- base/reflection.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/reflection.jl b/base/reflection.jl index afe349573114a..f1ecab42ef9b7 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -293,7 +293,7 @@ macro locals() end """ - objectid(x) + objectid(x) -> UInt Get a hash value for `x` based on object identity. `objectid(x)==objectid(y)` if `x === y`. From ab04170ece55886d624c9836140693be2426cfa9 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Tue, 4 May 2021 12:53:13 +0530 Subject: [PATCH 304/439] protocol change from git to https in README.md (#40675) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f94447abbc1b..38566819e0d2e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ First, make sure you have all the [required dependencies](https://github.com/JuliaLang/julia/blob/master/doc/build/build.md#required-build-tools-and-external-libraries) installed. Then, acquire the source code by cloning the git repository: - git clone git://github.com/JuliaLang/julia.git + git clone https://github.com/JuliaLang/julia.git By default you will be building the latest unstable version of Julia. However, most users should use the most recent stable version From 24d9eab45632bdb3120c9e664503745eb58aa2d6 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Tue, 4 May 2021 15:11:20 +0200 Subject: [PATCH 305/439] Document UInt return type of hash(x) (#40707) --- base/hashing.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/hashing.jl b/base/hashing.jl index 580b27ab86ee0..c6319a9e070ea 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -3,7 +3,7 @@ ## hashing a single value ## """ - hash(x[, h::UInt]) + hash(x[, h::UInt]) -> UInt Compute an integer hash code such that `isequal(x,y)` implies `hash(x)==hash(y)`. The optional second argument `h` is a hash code to be mixed with the result. From 0f2ad74ef494ccb5b85457cbabbdfc3a8dd01907 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 4 May 2021 14:28:37 -0400 Subject: [PATCH 306/439] codegen: set ModFlag for `Debug Info Version` to Warning (#40653) This allows linking the resulting code against another bitcode library (such as libopencilk-abi.bc) that was built with a different version of llvm debug info. --- src/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 519149970cac5..ee5ec4dce0c10 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1689,7 +1689,7 @@ static void jl_setup_module(Module *m, const jl_cgparams_t *params = &jl_default m->addModuleFlag(llvm::Module::Warning, "Dwarf Version", dwarf_version); } if (!m->getModuleFlag("Debug Info Version")) - m->addModuleFlag(llvm::Module::Error, "Debug Info Version", + m->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); m->setDataLayout(jl_data_layout); m->setTargetTriple(jl_TargetMachine->getTargetTriple().str()); From 4c785179132d8064caf21821b48a2afa54583eaf Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Tue, 4 May 2021 20:52:28 +0200 Subject: [PATCH 307/439] Clean-up Bidiagonal code (#40706) --- stdlib/LinearAlgebra/src/bidiag.jl | 38 ------------------------------ 1 file changed, 38 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 69fbaa476de73..ff6598451509f 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -635,8 +635,6 @@ end const UpperOrUnitUpperTriangular = Union{UpperTriangular, UnitUpperTriangular} const LowerOrUnitLowerTriangular = Union{LowerTriangular, UnitLowerTriangular} -const AdjOrTransUpperOrUnitUpperTriangular = Union{Adjoint{<:Any, <:UpperOrUnitUpperTriangular}, Transpose{<:Any, <:UpperOrUnitUpperTriangular}} -const AdjOrTransLowerOrUnitLowerTriangular = Union{Adjoint{<:Any, <:LowerOrUnitLowerTriangular}, Transpose{<:Any, <:LowerOrUnitLowerTriangular}} function *(A::UpperOrUnitUpperTriangular, B::Bidiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) @@ -647,15 +645,6 @@ function *(A::UpperOrUnitUpperTriangular, B::Bidiagonal) end end -function *(A::AdjOrTransUpperOrUnitUpperTriangular, B::Bidiagonal) - TS = promote_op(matprod, eltype(A), eltype(B)) - if B.uplo == 'L' - A_mul_B_td!(LowerTriangular(zeros(TS, size(A)...)), A, B) - else - A_mul_B_td!(zeros(TS, size(A)...), A, B) - end -end - function *(A::LowerOrUnitLowerTriangular, B::Bidiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) if B.uplo == 'L' @@ -665,15 +654,6 @@ function *(A::LowerOrUnitLowerTriangular, B::Bidiagonal) end end -function *(A::AdjOrTransLowerOrUnitLowerTriangular, B::Bidiagonal) - TS = promote_op(matprod, eltype(A), eltype(B)) - if B.uplo == 'U' - A_mul_B_td!(UpperTriangular(zeros(TS, size(A)...)), A, B) - else - A_mul_B_td!(zeros(TS, size(A)...), A, B) - end -end - function *(A::Union{SymTridiagonal, Tridiagonal}, B::AbstractTriangular) TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_B_td!(zeros(TS, size(A)...), A, B) @@ -688,15 +668,6 @@ function *(A::Bidiagonal, B::UpperOrUnitUpperTriangular) end end -function *(A::Bidiagonal, B::AdjOrTransUpperOrUnitUpperTriangular) - TS = promote_op(matprod, eltype(A), eltype(B)) - if A.uplo == 'L' - A_mul_B_td!(LowerTriangular(zeros(TS, size(A)...)), A, B) - else - A_mul_B_td!(zeros(TS, size(A)...), A, B) - end -end - function *(A::Bidiagonal, B::LowerOrUnitLowerTriangular) TS = promote_op(matprod, eltype(A), eltype(B)) if A.uplo == 'L' @@ -706,15 +677,6 @@ function *(A::Bidiagonal, B::LowerOrUnitLowerTriangular) end end -function *(A::Bidiagonal, B::AdjOrTransLowerOrUnitLowerTriangular) - TS = promote_op(matprod, eltype(A), eltype(B)) - if A.uplo == 'U' - A_mul_B_td!(UpperTriangular(zeros(TS, size(A)...)), A, B) - else - A_mul_B_td!(zeros(TS, size(A)...), A, B) - end -end - function *(A::BiTri, B::Diagonal) TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_B_td!(similar(A, TS), A, B) From 44d484222005580432433b7889c4a56d25c0ea67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauchereau?= Date: Tue, 4 May 2021 20:52:56 +0200 Subject: [PATCH 308/439] Fix bug in schur for size zero matrices (#40693) --- stdlib/LinearAlgebra/src/lapack.jl | 8 ++++---- stdlib/LinearAlgebra/test/schur.jl | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 2019943b4e388..05e080e00450d 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -5963,9 +5963,9 @@ for (gees, gges, elty) in alphar = similar(A, $elty, n) alphai = similar(A, $elty, n) beta = similar(A, $elty, n) - ldvsl = jobvsl == 'V' ? n : 1 + ldvsl = jobvsl == 'V' ? max(1, n) : 1 vsl = similar(A, $elty, ldvsl, n) - ldvsr = jobvsr == 'V' ? n : 1 + ldvsr = jobvsr == 'V' ? max(1, n) : 1 vsr = similar(A, $elty, ldvsr, n) work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -6058,9 +6058,9 @@ for (gees, gges, elty, relty) in sdim = BlasInt(0) alpha = similar(A, $elty, n) beta = similar(A, $elty, n) - ldvsl = jobvsl == 'V' ? n : 1 + ldvsl = jobvsl == 'V' ? max(1, n) : 1 vsl = similar(A, $elty, ldvsl, n) - ldvsr = jobvsr == 'V' ? n : 1 + ldvsr = jobvsr == 'V' ? max(1, n) : 1 vsr = similar(A, $elty, ldvsr, n) work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) diff --git a/stdlib/LinearAlgebra/test/schur.jl b/stdlib/LinearAlgebra/test/schur.jl index 5d2589dd44afe..e8a4a619ae2c6 100644 --- a/stdlib/LinearAlgebra/test/schur.jl +++ b/stdlib/LinearAlgebra/test/schur.jl @@ -132,6 +132,17 @@ aimg = randn(n,n)/2 @test Z == A @test λ == zeros(0) end + @testset "0x0 $eltya matrices" begin + A = zeros(eltya, 0, 0) + B = zeros(eltya, 0, 0) + S = LinearAlgebra.schur(A, B) + @test S.S == A + @test S.T == A + @test S.Q == A + @test S.Z == A + @test S.alpha == zeros(0) + @test S.beta == zeros(0) + end end @testset "Generalized Schur convergence" begin From a2d85f6dc63439aea9f973bacb55006596fdb2b8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 4 May 2021 11:53:40 -0700 Subject: [PATCH 309/439] Replace llvm::sys::fs::F_None with llvm::sys::fs::OF_None (#40666) The former is deprecated. OF_None has been available in LLVM since 2018-06. --- src/codegen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index ee5ec4dce0c10..bc60798220d52 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8092,12 +8092,12 @@ extern "C" void jl_dump_llvm_mfunction(void *v) extern void jl_write_bitcode_func(void *F, char *fname) { std::error_code EC; - raw_fd_ostream OS(fname, EC, sys::fs::F_None); + raw_fd_ostream OS(fname, EC, sys::fs::OF_None); llvm::WriteBitcodeToFile(*((llvm::Function*)F)->getParent(), OS); } extern void jl_write_bitcode_module(void *M, char *fname) { std::error_code EC; - raw_fd_ostream OS(fname, EC, sys::fs::F_None); + raw_fd_ostream OS(fname, EC, sys::fs::OF_None); llvm::WriteBitcodeToFile(*(llvm::Module*)M, OS); } From f2eb0fa44fd69ef73ac4b4867f86b2a48c74aa6f Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 4 May 2021 14:55:45 -0400 Subject: [PATCH 310/439] Delete CITATION.bib (#40711) The list is growing and is perhaps best managed on the website. --- CITATION.bib | 75 ---------------------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 CITATION.bib diff --git a/CITATION.bib b/CITATION.bib deleted file mode 100644 index af8cffe7aa524..0000000000000 --- a/CITATION.bib +++ /dev/null @@ -1,75 +0,0 @@ -% This article is the definitive citation for Julia. -@article{Julia-2017, - title={Julia: A fresh approach to numerical computing}, - author={Bezanson, Jeff and Edelman, Alan and Karpinski, Stefan and Shah, Viral B}, - journal={SIAM {R}eview}, - volume={59}, - number={1}, - pages={65--98}, - year={2017}, - publisher={SIAM}, - doi={10.1137/141000671} -} - -% The following citations are about specific aspects of Julia. - -@article{Julia-2019-a, - author = {Bezanson, Jeff and Chen, Jiahao and Chung, Benjamin and Karpinski, Stefan and Shah, Viral B. and Vitek, Jan and Zoubritzky, Lionel}, - title = {Julia: Dynamism and Performance Reconciled by Design}, - journal = {Proc. ACM Program. Lang.}, - issue_date = {November 2018}, - volume = {2}, - number = {OOPSLA}, - month = oct, - year = {2018}, - issn = {2475-1421}, - pages = {120:1--120:23}, - articleno = {120}, - numpages = {23}, - url = {https://doi.acm.org/10.1145/3276490}, - doi = {10.1145/3276490}, - acmid = {3276490}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {dynamic languages, just-in-time compilation, multiple dispatch}, -} - -@article{Julia-2019-b, - author = {Zappa Nardelli, Francesco and Belyakova, Julia and Pelenitsyn, Artem and Chung, Benjamin and Bezanson, Jeff and Vitek, Jan}, - title = {Julia Subtyping: A Rational Reconstruction}, - journal = {Proc. ACM Program. Lang.}, - issue_date = {November 2018}, - volume = {2}, - number = {OOPSLA}, - month = oct, - year = {2018}, - issn = {2475-1421}, - pages = {113:1--113:27}, - articleno = {113}, - numpages = {27}, - url = {https://doi.acm.org/10.1145/3276483}, - doi = {10.1145/3276483}, - acmid = {3276483}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Multiple Dispatch, Subtyping}, -} - -@inproceedings{Julia-2014, - author = {Bezanson, Jeff and Chen, Jiahao and Karpinski, Stefan and Shah, Viral and Edelman, Alan}, - title = {Array Operators Using Multiple Dispatch: A Design Methodology for Array Implementations in Dynamic Languages}, - booktitle = {Proceedings of ACM SIGPLAN International Workshop on Libraries, Languages, and Compilers for Array Programming}, - series = {ARRAY'14}, - year = {2014}, - isbn = {978-1-4503-2937-8}, - location = {Edinburgh, United Kingdom}, - pages = {56:56--56:61}, - articleno = {56}, - numpages = {6}, - url = {https://doi.acm.org/10.1145/2627373.2627383}, - doi = {10.1145/2627373.2627383}, - acmid = {2627383}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Julia, array indexing, dynamic dispatch, multiple dispatch, static analysis, type inference}, -} From fd2061b77b7897d4336e3f1ac0822421a617c508 Mon Sep 17 00:00:00 2001 From: Ben Peachey Higdon Date: Tue, 4 May 2021 15:08:52 -0400 Subject: [PATCH 311/439] doc: fix typos in calling-c-and-fortran-code.md (#40692) --- doc/src/manual/calling-c-and-fortran-code.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 2bd99ea836686..312e668afbd3f 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -157,7 +157,7 @@ This is why we don't use the `Cstring` type here: as the array is uninitialized, NUL bytes. Converting to a `Cstring` as part of the [`ccall`](@ref) checks for contained NUL bytes and could therefore throw a conversion error. -Deferencing `pointer(hostname)` with `unsafe_string` is an unsafe operation as it requires access to +Dereferencing `pointer(hostname)` with `unsafe_string` is an unsafe operation as it requires access to the memory allocated for `hostname` that may have been in the meanwhile garbage collected. The macro [`GC.@preserve`](@ref) prevents this from happening and therefore accessing an invalid memory location. @@ -657,7 +657,7 @@ For translating a C argument list to Julia: * `Ref{Any}` * argument list must be a valid Julia object (or `C_NULL`) * cannot be used for an output parameter, unless the user is able to - manage to separate arrange for the object to be GC-preserved + separately arrange for the object to be GC-preserved * `T*` * `Ref{T}`, where `T` is the Julia type corresponding to `T` From ff213c1f597fc2fb930a47de1ba751b137b647ba Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Wed, 5 May 2021 05:17:51 +0900 Subject: [PATCH 312/439] fix consistency of trimtrailingzeros (Ryu) (#40685) * fix consistency of trimtrailingzeros (Ryu) --- base/ryu/exp.jl | 2 +- base/ryu/fixed.jl | 5 +---- test/ryu.jl | 11 +++++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/base/ryu/exp.jl b/base/ryu/exp.jl index 58ae0fa97b712..30291212d014d 100644 --- a/base/ryu/exp.jl +++ b/base/ryu/exp.jl @@ -10,7 +10,7 @@ function writeexp(buf, pos, v::T, if x == 0 buf[pos] = UInt8('0') pos += 1 - if precision > 0 + if precision > 0 && !trimtrailingzeros buf[pos] = decchar pos += 1 for _ = 1:precision diff --git a/base/ryu/fixed.jl b/base/ryu/fixed.jl index 05259a9849d01..5c780aa7acbf8 100644 --- a/base/ryu/fixed.jl +++ b/base/ryu/fixed.jl @@ -10,12 +10,9 @@ function writefixed(buf, pos, v::T, if x == 0 buf[pos] = UInt8('0') pos += 1 - if precision > 0 + if precision > 0 && !trimtrailingzeros buf[pos] = decchar pos += 1 - if trimtrailingzeros - precision = 1 - end for _ = 1:precision buf[pos] = UInt8('0') pos += 1 diff --git a/test/ryu.jl b/test/ryu.jl index 9970942575e0a..d8d3c17752f63 100644 --- a/test/ryu.jl +++ b/test/ryu.jl @@ -544,6 +544,11 @@ end # Float16 @test Ryu.writefixed(7.018232e-82, 6) == "0.000000" end + @testset "Consistency of trimtrailingzeros" begin + @test Ryu.writefixed(0.0, 1, false, false, false, UInt8('.'), true) == "0" + @test Ryu.writefixed(1.0, 1, false, false, false, UInt8('.'), true) == "1" + @test Ryu.writefixed(2.0, 1, false, false, false, UInt8('.'), true) == "2" + end end # fixed @testset "Ryu.writeexp" begin @@ -736,6 +741,12 @@ end @test Ryu.writeexp(1e+83, 1) == "1.0e+83" end +@testset "Consistency of trimtrailingzeros" begin + @test Ryu.writeexp(0.0, 1, false, false, false, UInt8('e'), UInt8('.'), true) == "0e+00" + @test Ryu.writeexp(1.0, 1, false, false, false, UInt8('e'), UInt8('.'), true) == "1e+00" + @test Ryu.writeexp(2.0, 1, false, false, false, UInt8('e'), UInt8('.'), true) == "2e+00" +end + end # exp @testset "compact" begin From c33877f417ce486ad864efbb2a5e4973c6a27e17 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Mon, 3 May 2021 15:20:37 +0900 Subject: [PATCH 313/439] make Printf's general format C11 compliant --- stdlib/Printf/src/Printf.jl | 23 +++++++++++++++++++++-- stdlib/Printf/test/runtests.jl | 8 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index f77fa89aa1fe5..b40ce3406f212 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -421,9 +421,28 @@ const __BIG_FLOAT_MAX__ = 8192 elseif T == Val{'f'} || T == Val{'F'} newpos = Ryu.writefixed(buf, pos, x, prec, plus, space, hash, UInt8('.')) elseif T == Val{'g'} || T == Val{'G'} + # C11-compliant general format prec = prec == 0 ? 1 : prec - x = round(x, sigdigits=prec) - newpos = Ryu.writeshortest(buf, pos, x, plus, space, hash, prec, T == Val{'g'} ? UInt8('e') : UInt8('E'), true, UInt8('.')) + # format the value in scientific notation and parse the exponent part + exp = let p = Ryu.writeexp(buf, pos, x, prec) + b1, b2, b3, b4 = buf[p-4], buf[p-3], buf[p-2], buf[p-1] + Z = UInt8('0') + if b1 == UInt8('e') + # two-digit exponent + sign = b2 == UInt8('+') ? 1 : -1 + exp = 10 * (b3 - Z) + (b4 - Z) + else + # three-digit exponent + sign = b1 == UInt8('+') ? 1 : -1 + exp = 100 * (b2 - Z) + 10 * (b3 - Z) + (b4 - Z) + end + flipsign(exp, sign) + end + if -4 ≤ exp < prec + newpos = Ryu.writefixed(buf, pos, x, prec - (exp + 1), plus, space, hash, UInt8('.'), !hash) + else + newpos = Ryu.writeexp(buf, pos, x, prec - 1, plus, space, hash, T == Val{'g'} ? UInt8('e') : UInt8('E'), UInt8('.'), !hash) + end elseif T == Val{'a'} || T == Val{'A'} x, neg = x < 0 || x === -Base.zero(x) ? (-x, true) : (x, false) newpos = pos diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index 1dcd30d0971f1..212a74da2b4c6 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -449,6 +449,14 @@ end @test Printf.@sprintf("%e", 1) == "1.000000e+00" @test Printf.@sprintf("%g", 1) == "1" + # issue #39748 + @test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983" + @test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983" + @test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302" + @test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308" + @test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308" + @test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308" + # escaped '%' @test_throws ArgumentError @sprintf("%s%%%s", "a") @test @sprintf("%s%%%s", "a", "b") == "a%b" From 6f7d07d0f0eaa454f31e62c38e7c20dda5949c25 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Tue, 4 May 2021 23:42:36 +0200 Subject: [PATCH 314/439] Remove eltype check in adjtrans (#40567) Co-authored-by: Andy Ferris Co-authored-by: Andy Ferris --- stdlib/LinearAlgebra/src/adjtrans.jl | 32 ++------------------------- stdlib/LinearAlgebra/test/adjtrans.jl | 16 +++++++------- 2 files changed, 10 insertions(+), 38 deletions(-) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 494429a4fca2d..dac216f0f072a 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -34,10 +34,6 @@ julia> adjoint(A) """ struct Adjoint{T,S} <: AbstractMatrix{T} parent::S - function Adjoint{T,S}(A::S) where {T,S} - checkeltype_adjoint(T, eltype(A)) - new(A) - end end """ Transpose @@ -65,30 +61,6 @@ julia> transpose(A) """ struct Transpose{T,S} <: AbstractMatrix{T} parent::S - function Transpose{T,S}(A::S) where {T,S} - checkeltype_transpose(T, eltype(A)) - new(A) - end -end - -function checkeltype_adjoint(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype,ParentEltype} - Expected = Base.promote_op(adjoint, ParentEltype) - ResultEltype === Expected || error(string( - "Element type mismatch. Tried to create an `Adjoint{", ResultEltype, "}` ", - "from an object with eltype `", ParentEltype, "`, but the element type of ", - "the adjoint of an object with eltype `", ParentEltype, "` must be ", - "`", Expected, "`.")) - return nothing -end - -function checkeltype_transpose(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype, ParentEltype} - Expected = Base.promote_op(transpose, ParentEltype) - ResultEltype === Expected || error(string( - "Element type mismatch. Tried to create a `Transpose{", ResultEltype, "}` ", - "from an object with eltype `", ParentEltype, "`, but the element type of ", - "the transpose of an object with eltype `", ParentEltype, "` must be ", - "`", Expected, "`.")) - return nothing end # basic outer constructors @@ -203,8 +175,8 @@ axes(v::AdjOrTransAbsVec) = (Base.OneTo(1), axes(v.parent)...) axes(A::AdjOrTransAbsMat) = reverse(axes(A.parent)) IndexStyle(::Type{<:AdjOrTransAbsVec}) = IndexLinear() IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian() -@propagate_inbounds getindex(v::AdjOrTransAbsVec, i::Int) = wrapperop(v)(v.parent[i-1+first(axes(v.parent)[1])]) -@propagate_inbounds getindex(A::AdjOrTransAbsMat, i::Int, j::Int) = wrapperop(A)(A.parent[j, i]) +@propagate_inbounds getindex(v::AdjOrTransAbsVec{T}, i::Int) where {T} = wrapperop(v)(v.parent[i-1+first(axes(v.parent)[1])])::T +@propagate_inbounds getindex(A::AdjOrTransAbsMat{T}, i::Int, j::Int) where {T} = wrapperop(A)(A.parent[j, i])::T @propagate_inbounds setindex!(v::AdjOrTransAbsVec, x, i::Int) = (setindex!(v.parent, wrapperop(v)(x), i-1+first(axes(v.parent)[1])); v) @propagate_inbounds setindex!(A::AdjOrTransAbsMat, x, i::Int, j::Int) = (setindex!(A.parent, wrapperop(A)(x), j, i); A) # AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 083c8dfa5cb29..f0f0461c23862 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -7,15 +7,15 @@ using Test, LinearAlgebra, SparseArrays @testset "Adjoint and Transpose inner constructor basics" begin intvec, intmat = [1, 2], [1 2; 3 4] # Adjoint/Transpose eltype must match the type of the Adjoint/Transpose of the input eltype - @test_throws ErrorException Adjoint{Float64,Vector{Int}}(intvec) - @test_throws ErrorException Adjoint{Float64,Matrix{Int}}(intmat) - @test_throws ErrorException Transpose{Float64,Vector{Int}}(intvec) - @test_throws ErrorException Transpose{Float64,Matrix{Int}}(intmat) + @test_throws TypeError Adjoint{Float64,Vector{Int}}(intvec)[1,1] + @test_throws TypeError Adjoint{Float64,Matrix{Int}}(intmat)[1,1] + @test_throws TypeError Transpose{Float64,Vector{Int}}(intvec)[1,1] + @test_throws TypeError Transpose{Float64,Matrix{Int}}(intmat)[1,1] # Adjoint/Transpose wrapped array type must match the input array type - @test_throws MethodError Adjoint{Int,Vector{Float64}}(intvec) - @test_throws MethodError Adjoint{Int,Matrix{Float64}}(intmat) - @test_throws MethodError Transpose{Int,Vector{Float64}}(intvec) - @test_throws MethodError Transpose{Int,Matrix{Float64}}(intmat) + @test_throws TypeError Adjoint{Int,Vector{Float64}}(intvec)[1,1] + @test_throws TypeError Adjoint{Int,Matrix{Float64}}(intmat)[1,1] + @test_throws TypeError Transpose{Int,Vector{Float64}}(intvec)[1,1] + @test_throws TypeError Transpose{Int,Matrix{Float64}}(intmat)[1,1] # Adjoint/Transpose inner constructor basic functionality, concrete scalar eltype @test (Adjoint{Int,Vector{Int}}(intvec)::Adjoint{Int,Vector{Int}}).parent === intvec @test (Adjoint{Int,Matrix{Int}}(intmat)::Adjoint{Int,Matrix{Int}}).parent === intmat From f806df603489cfca558f6284d52a38f523b81881 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 4 May 2021 22:20:48 -0400 Subject: [PATCH 315/439] Meta.parse doc string: clarify that indices are not chars (#40714) --- base/meta.jl | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/base/meta.jl b/base/meta.jl index af170707874af..d4847dc476247 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -203,21 +203,32 @@ end """ parse(str, start; greedy=true, raise=true, depwarn=true) -Parse the expression string and return an expression (which could later be passed to eval -for execution). `start` is the index of the first character to start parsing. If `greedy` is -`true` (default), `parse` will try to consume as much input as it can; otherwise, it will -stop as soon as it has parsed a valid expression. Incomplete but otherwise syntactically -valid expressions will return `Expr(:incomplete, "(error message)")`. If `raise` is `true` -(default), syntax errors other than incomplete expressions will raise an error. If `raise` -is `false`, `parse` will return an expression that will raise an error upon evaluation. If -`depwarn` is `false`, deprecation warnings will be suppressed. +Parse the expression string and return an expression (which could later be +passed to eval for execution). `start` is the code unit index into `str` of the +first character to start parsing at (as with all string indexing, these are not +character indices). If `greedy` is `true` (default), `parse` will try to consume +as much input as it can; otherwise, it will stop as soon as it has parsed a +valid expression. Incomplete but otherwise syntactically valid expressions will +return `Expr(:incomplete, "(error message)")`. If `raise` is `true` (default), +syntax errors other than incomplete expressions will raise an error. If `raise` +is `false`, `parse` will return an expression that will raise an error upon +evaluation. If `depwarn` is `false`, deprecation warnings will be suppressed. ```jldoctest -julia> Meta.parse("x = 3, y = 5", 7) -(:(y = 5), 13) +julia> Meta.parse("(α, β) = 3, 5", 1) # start of string +(:((α, β) = (3, 5)), 16) -julia> Meta.parse("x = 3, y = 5", 5) -(:((3, y) = 5), 13) +julia> Meta.parse("(α, β) = 3, 5", 1, greedy=false) +(:((α, β)), 9) + +julia> Meta.parse("(α, β) = 3, 5", 16) # end of string +(nothing, 16) + +julia> Meta.parse("(α, β) = 3, 5", 11) # index of 3 +(:((3, 5)), 16) + +julia> Meta.parse("(α, β) = 3, 5", 11, greedy=false) +(3, 13) ``` """ function parse(str::AbstractString, pos::Integer; greedy::Bool=true, raise::Bool=true, From 9f665c19e076ab37cbca2d0cc99283b82e99c26f Mon Sep 17 00:00:00 2001 From: Suavesito Date: Thu, 6 May 2021 02:32:26 -0500 Subject: [PATCH 316/439] Remove duplicated line in `NEWS.md` file (#40725) There was a duplicated line about the `@invoke` macro. --- NEWS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 9e599898d452a..2e63729ee09cb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,7 +42,6 @@ New library functions * Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]). * `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`. * New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971]) -* New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}; kwargs...)` ([#38438]) * Two arguments method `lock(f, lck)` now accepts a `Channel` as the second argument. ([#39312]) * New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438]) From 15b5143c3fcfa85bda144b4c5e392b1c87a046cc Mon Sep 17 00:00:00 2001 From: Elias Jarlebring Date: Thu, 6 May 2021 11:34:47 +0200 Subject: [PATCH 317/439] Efficiency improvement of exp(::StridedMatrix) with UniformScaling and mul! (#40668) Co-authored-by: Daniel Karrasch --- stdlib/LinearAlgebra/src/dense.jl | 42 +++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 27fa515e70a02..94926805bb387 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -617,7 +617,6 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat end ilo, ihi, scale = LAPACK.gebal!('B', A) # modifies A nA = opnorm(A, 1) - Inn = Matrix{T}(I, n, n) ## For sufficiently small nA, use lower order Padé-Approximations if (nA <= 2.1) if nA > 0.95 @@ -634,17 +633,21 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat C = T[120.,60.,12.,1.] end A2 = A * A - P = copy(Inn) - U = C[2] * P - V = C[1] * P - for k in 1:(div(size(C, 1), 2) - 1) + # Compute U and V: Even/odd terms in Padé numerator & denom + # Expansion of k=1 in for loop + P = A2 + U = C[2]*I + C[4]*P + V = C[1]*I + C[3]*P + for k in 2:(div(size(C, 1), 2) - 1) k2 = 2 * k P *= A2 - U += C[k2 + 2] * P - V += C[k2 + 1] * P + mul!(U, C[k2 + 2], P, true, true) # U += C[k2+2]*P + mul!(V, C[k2 + 1], P, true, true) # V += C[k2+1]*P end + U = A * U X = V + U + # Padé approximant: (V-U)\(V+U) LAPACK.gesv!(V-U, X) else s = log2(nA/5.4) # power of 2 later reversed by squaring @@ -660,10 +663,27 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat A2 = A * A A4 = A2 * A2 A6 = A2 * A4 - U = A * (A6 * (CC[14].*A6 .+ CC[12].*A4 .+ CC[10].*A2) .+ - CC[8].*A6 .+ CC[6].*A4 .+ CC[4].*A2 .+ CC[2].*Inn) - V = A6 * (CC[13].*A6 .+ CC[11].*A4 .+ CC[9].*A2) .+ - CC[7].*A6 .+ CC[5].*A4 .+ CC[3].*A2 .+ CC[1].*Inn + Ut = CC[4]*A2 + Ut[diagind(Ut)] .+= CC[2] + # Allocation economical version of: + #U = A * (A6 * (CC[14].*A6 .+ CC[12].*A4 .+ CC[10].*A2) .+ + # CC[8].*A6 .+ CC[6].*A4 .+ Ut) + U = mul!(CC[8].*A6 .+ CC[6].*A4 .+ Ut, + A6, + CC[14].*A6 .+ CC[12].*A4 .+ CC[10].*A2, + true, true) + U = A*U + + # Allocation economical version of: Vt = CC[3]*A2 (recycle Ut) + Vt = mul!(Ut, CC[3], A2, true, false) + Vt[diagind(Vt)] .+= CC[1] + # Allocation economical version of: + #V = A6 * (CC[13].*A6 .+ CC[11].*A4 .+ CC[9].*A2) .+ + # CC[7].*A6 .+ CC[5].*A4 .+ Vt + V = mul!(CC[7].*A6 .+ CC[5].*A4 .+ Vt, + A6, + CC[13].*A6 .+ CC[11].*A4 .+ CC[9].*A2, + true, true) X = V + U LAPACK.gesv!(V-U, X) From fbe28e4779f3d2b8683b5e721d7aa312ec656ac2 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Thu, 6 May 2021 09:38:00 -0400 Subject: [PATCH 318/439] Add some bounds checks for `Diagonal([1])` (#40728) --- stdlib/LinearAlgebra/src/diagonal.jl | 69 +++++++++++++++++---------- stdlib/LinearAlgebra/test/diagonal.jl | 4 +- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 7bdcfb7d930e6..204ff56e0c443 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -14,46 +14,55 @@ Diagonal(v::AbstractVector{T}) where {T} = Diagonal{T,typeof(v)}(v) Diagonal{T}(v::AbstractVector) where {T} = Diagonal(convert(AbstractVector{T}, v)::AbstractVector{T}) """ - Diagonal(A::AbstractMatrix) + Diagonal(V::AbstractVector) -Construct a matrix from the diagonal of `A`. +Construct a matrix with `V` as its diagonal. + +See also [`diag`](@ref), [`diagm`](@ref). # Examples ```jldoctest -julia> A = [1 2 3; 4 5 6; 7 8 9] -3×3 Matrix{Int64}: - 1 2 3 - 4 5 6 - 7 8 9 - -julia> Diagonal(A) -3×3 Diagonal{Int64, Vector{Int64}}: - 1 ⋅ ⋅ - ⋅ 5 ⋅ - ⋅ ⋅ 9 +julia> Diagonal([1, 10, 100]) +3×3 Diagonal{$Int, Vector{$Int}}: + 1 ⋅ ⋅ + ⋅ 10 ⋅ + ⋅ ⋅ 100 + +julia> diagm([7, 13]) +2×2 Matrix{$Int}: + 7 0 + 0 13 ``` """ -Diagonal(A::AbstractMatrix) = Diagonal(diag(A)) +Diagonal(V::AbstractVector) """ - Diagonal(V::AbstractVector) + Diagonal(A::AbstractMatrix) -Construct a matrix with `V` as its diagonal. +Construct a matrix from the diagonal of `A`. # Examples ```jldoctest -julia> V = [1, 2] -2-element Vector{Int64}: - 1 - 2 - -julia> Diagonal(V) -2×2 Diagonal{Int64, Vector{Int64}}: - 1 ⋅ - ⋅ 2 +julia> A = permutedims(reshape(1:15, 5, 3)) +3×5 Matrix{Int64}: + 1 2 3 4 5 + 6 7 8 9 10 + 11 12 13 14 15 + +julia> Diagonal(A) +3×3 Diagonal{$Int, Vector{$Int}}: + 1 ⋅ ⋅ + ⋅ 7 ⋅ + ⋅ ⋅ 13 + +julia> diag(A, 2) +3-element Vector{$Int}: + 3 + 9 + 15 ``` """ -Diagonal(V::AbstractVector) +Diagonal(A::AbstractMatrix) = Diagonal(diag(A)) Diagonal(D::Diagonal) = D Diagonal{T}(D::Diagonal{T}) where {T} = D @@ -211,12 +220,20 @@ end function rmul!(A::AbstractMatrix, D::Diagonal) require_one_based_indexing(A) + nA, nD = size(A, 2), length(D.diag) + if nA != nD + throw(DimensionMismatch("second dimension of A, $nA, does not match the first of D, $nD")) + end A .= A .* permutedims(D.diag) return A end function lmul!(D::Diagonal, B::AbstractVecOrMat) require_one_based_indexing(B) + nB, nD = size(B, 1), length(D.diag) + if nB != nD + throw(DimensionMismatch("second dimension of D, $nD, does not match the first of B, $nB")) + end B .= D.diag .* B return B end diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 564cccab9e6ba..b6b52c0a0770c 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -679,13 +679,15 @@ end @test yt*D*y == (yt*D)*y == (yt*A)*y end -@testset "Multiplication of single element Diagonal (#36746)" begin +@testset "Multiplication of single element Diagonal (#36746, #40726)" begin @test_throws DimensionMismatch Diagonal(randn(1)) * randn(5) @test_throws DimensionMismatch Diagonal(randn(1)) * Diagonal(randn(3, 3)) A = [1 0; 0 2] v = [3, 4] @test Diagonal(A) * v == A * v @test Diagonal(A) * Diagonal(A) == A * A + @test_throws DimensionMismatch [1 0;0 1] * Diagonal([2 3]) # Issue #40726 + @test_throws DimensionMismatch lmul!(Diagonal([1]), [1,2,3]) # nearby end @testset "Triangular division by Diagonal #27989" begin From 6726ae89f08e45780f64cfdafd87700d5fc6c4ca Mon Sep 17 00:00:00 2001 From: Elias Jarlebring Date: Fri, 7 May 2021 13:59:33 +0200 Subject: [PATCH 319/439] Five arg mul! for UniformScaling and improvement in exp! (#40731) Co-authored-by: Daniel Karrasch --- stdlib/LinearAlgebra/src/dense.jl | 9 ++++----- stdlib/LinearAlgebra/src/uniformscaling.jl | 18 ++++++++++++++++++ stdlib/LinearAlgebra/test/uniformscaling.jl | 11 +++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 94926805bb387..e0fd0a6d532bc 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -636,8 +636,8 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat # Compute U and V: Even/odd terms in Padé numerator & denom # Expansion of k=1 in for loop P = A2 - U = C[2]*I + C[4]*P - V = C[1]*I + C[3]*P + U = mul!(C[4]*P, true, C[2]*I, true, true) #U = C[2]*I + C[4]*P + V = mul!(C[3]*P, true, C[1]*I, true, true) #V = C[1]*I + C[3]*P for k in 2:(div(size(C, 1), 2) - 1) k2 = 2 * k P *= A2 @@ -663,8 +663,7 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat A2 = A * A A4 = A2 * A2 A6 = A2 * A4 - Ut = CC[4]*A2 - Ut[diagind(Ut)] .+= CC[2] + Ut = mul!(CC[4]*A2, true,CC[2]*I, true, true); # Ut = CC[4]*A2+CC[2]*I # Allocation economical version of: #U = A * (A6 * (CC[14].*A6 .+ CC[12].*A4 .+ CC[10].*A2) .+ # CC[8].*A6 .+ CC[6].*A4 .+ Ut) @@ -676,7 +675,7 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat # Allocation economical version of: Vt = CC[3]*A2 (recycle Ut) Vt = mul!(Ut, CC[3], A2, true, false) - Vt[diagind(Vt)] .+= CC[1] + mul!(Vt, true, CC[1]*I, true, true); # Vt += CC[1]*I # Allocation economical version of: #V = A6 * (CC[13].*A6 .+ CC[11].*A4 .+ CC[9].*A2) .+ # CC[7].*A6 .+ CC[5].*A4 .+ Vt diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 1b2e3010ff27d..44ad5d98e99a4 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -284,6 +284,24 @@ end mul!(C, A, J.λ, alpha, beta) @inline mul!(C::AbstractVecOrMat, J::UniformScaling, B::AbstractVecOrMat, alpha::Number, beta::Number) = mul!(C, J.λ, B, alpha, beta) + +function mul!(out::AbstractMatrix{T}, a::Number, B::UniformScaling, α::Number, β::Number) where {T} + checksquare(out) + if iszero(β) # zero contribution of the out matrix + fill!(out, zero(T)) + elseif !isone(β) + rmul!(out, β) + end + s = convert(T, a*B.λ*α) + if !iszero(s) + @inbounds for i in diagind(out) + out[i] += s + end + end + return out +end +@inline mul!(out::AbstractMatrix, A::UniformScaling, b::Number, α::Number, β::Number)= + mul!(out, A.λ, UniformScaling(b), α, β) rmul!(A::AbstractMatrix, J::UniformScaling) = rmul!(A, J.λ) lmul!(J::UniformScaling, B::AbstractVecOrMat) = lmul!(J.λ, B) rdiv!(A::AbstractMatrix, J::UniformScaling) = rdiv!(A, J.λ) diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 33b2ba7032734..b7b2e5c81cf88 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -454,6 +454,17 @@ end target = J * A * alpha + C * beta @test mul!(copy(C), J, A, alpha, beta) ≈ target @test mul!(copy(C), A, J, alpha, beta) ≈ target + + a = randn() + C = randn(3, 3) + target_5mul = a*alpha*J + beta*C + @test mul!(copy(C), a, J, alpha, beta) ≈ target_5mul + @test mul!(copy(C), J, a, alpha, beta) ≈ target_5mul + target_5mul = beta*C # alpha = 0 + @test mul!(copy(C), a, J, 0, beta) ≈ target_5mul + target_5mul = a*alpha*Matrix(J, 3, 3) # beta = 0 + @test mul!(copy(C), a, J, alpha, 0) ≈ target_5mul + end @testset "Construct Diagonal from UniformScaling" begin From ddeba0ba8aa452cb2064eb2d03bea47fe6b0ebbe Mon Sep 17 00:00:00 2001 From: Pablo Zubieta <8410335+pabloferz@users.noreply.github.com> Date: Sat, 8 May 2021 02:02:42 -0500 Subject: [PATCH 320/439] Make istriu, istril, and pinv more gpu friendly (#39756) * Make istriu,istril, and pinv more gpu friendly --- stdlib/LinearAlgebra/src/dense.jl | 30 ++++++++++---------------- stdlib/LinearAlgebra/src/generic.jl | 20 ++++++++++------- stdlib/LinearAlgebra/src/triangular.jl | 16 ++------------ 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index e0fd0a6d532bc..ff789a9fd11b2 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -1428,31 +1428,23 @@ function pinv(A::AbstractMatrix{T}; atol::Real = 0.0, rtol::Real = (eps(real(flo m, n = size(A) Tout = typeof(zero(T)/sqrt(one(T) + one(T))) if m == 0 || n == 0 - return Matrix{Tout}(undef, n, m) + return similar(A, Tout, (n, m)) end - if istril(A) - if istriu(A) - maxabsA = maximum(abs.(diag(A))) - tol = max(rtol*maxabsA, atol) - B = zeros(Tout, n, m) - for i = 1:min(m, n) - if abs(A[i,i]) > tol - Aii = inv(A[i,i]) - if isfinite(Aii) - B[i,i] = Aii - end - end - end - return B - end + if isdiag(A) + ind = diagind(A) + dA = view(A, ind) + maxabsA = maximum(abs, dA) + tol = max(rtol * maxabsA, atol) + B = fill!(similar(A, Tout, (n, m)), 0) + B[ind] .= (x -> abs(x) > tol ? pinv(x) : zero(x)).(dA) + return B end SVD = svd(A, full = false) tol = max(rtol*maximum(SVD.S), atol) Stype = eltype(SVD.S) - Sinv = zeros(Stype, length(SVD.S)) + Sinv = fill!(similar(A, Stype, length(SVD.S)), 0) index = SVD.S .> tol - Sinv[index] = one(Stype) ./ SVD.S[index] - Sinv[findall(.!isfinite.(Sinv))] .= zero(Stype) + Sinv[index] .= pinv.(view(SVD.S, index)) return SVD.Vt' * (Diagonal(Sinv) * SVD.U') end function pinv(x::Number) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 427d7202d4b08..ec8e9df654c46 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1292,15 +1292,17 @@ false """ function istriu(A::AbstractMatrix, k::Integer = 0) require_one_based_indexing(A) + return _istriu(A, k) +end +istriu(x::Number) = true + +@inline function _istriu(A::AbstractMatrix, k) m, n = size(A) for j in 1:min(n, m + k - 1) - for i in max(1, j - k + 1):m - iszero(A[i, j]) || return false - end + all(iszero, view(A, max(1, j - k + 1):m, j)) || return false end return true end -istriu(x::Number) = true """ istril(A::AbstractMatrix, k::Integer = 0) -> Bool @@ -1334,15 +1336,17 @@ false """ function istril(A::AbstractMatrix, k::Integer = 0) require_one_based_indexing(A) + return _istril(A, k) +end +istril(x::Number) = true + +@inline function _istril(A::AbstractMatrix, k) m, n = size(A) for j in max(1, k + 2):n - for i in 1:min(j - k - 1, m) - iszero(A[i, j]) || return false - end + all(iszero, view(A, 1:min(j - k - 1, m), j)) || return false end return true end -istril(x::Number) = true """ isbanded(A::AbstractMatrix, kl::Integer, ku::Integer) -> Bool diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index 1752d29a9ec65..c141f6469e359 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -285,23 +285,11 @@ end function istril(A::Union{LowerTriangular,UnitLowerTriangular}, k::Integer=0) k >= 0 && return true - m, n = size(A) - for j in max(1, k + 2):n - for i in 1:min(j - k - 1, m) - iszero(A[i, j]) || return false - end - end - return true + return _istril(A, k) end function istriu(A::Union{UpperTriangular,UnitUpperTriangular}, k::Integer=0) k <= 0 && return true - m, n = size(A) - for j in 1:min(n, m + k - 1) - for i in max(1, j - k + 1):m - iszero(A[i, j]) || return false - end - end - return true + return _istriu(A, k) end istril(A::Adjoint) = istriu(A.parent) istril(A::Transpose) = istriu(A.parent) From ccf7824354e770dfe15ca2c884891fc8f7bb492e Mon Sep 17 00:00:00 2001 From: Moritz Schauer Date: Sat, 8 May 2021 17:19:25 +0200 Subject: [PATCH 321/439] Docs: What are `min` and `max` actually comparing? (#40713) --- base/operators.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index b73d9705d071a..303fc915e978c 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -480,7 +480,7 @@ cmp(x::Integer, y::Integer) = ifelse(isless(x, y), -1, ifelse(isless(y, x), 1, 0 """ max(x, y, ...) -Return the maximum of the arguments. See also the [`maximum`](@ref) function +Return the maximum of the arguments (with respect to [`isless`](@ref)). See also the [`maximum`](@ref) function to take the maximum element from a collection. # Examples @@ -494,7 +494,7 @@ max(x, y) = ifelse(isless(y, x), x, y) """ min(x, y, ...) -Return the minimum of the arguments. See also the [`minimum`](@ref) function +Return the minimum of the arguments (with respect to [`isless`](@ref)). See also the [`minimum`](@ref) function to take the minimum element from a collection. # Examples From 87d4e3ffeec26849107a015984795b8a695ac315 Mon Sep 17 00:00:00 2001 From: Spencer Russell Date: Sat, 8 May 2021 17:20:26 -0400 Subject: [PATCH 322/439] updates documentation for `Test.finish` (#25481) * updates documentation for `Test.finish` remind custom testset implementers to add themselves to their parent's results when they `finish` * wording tweak to `Test.finish` docstring --- stdlib/Test/src/Test.jl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 596aedb2d9aa7..e40793968e7d9 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -816,9 +816,20 @@ function record end finish(ts::AbstractTestSet) Do any final processing necessary for the given testset. This is called by the -`@testset` infrastructure after a test block executes. One common use for this -function is to record the testset to the parent's results list, using -`get_testset`. +`@testset` infrastructure after a test block executes. + +Custom `AbstractTestSet` subtypes should call `record` on their parent (if there +is one) to add themselves to the tree of test results. This might be implemented +as: + +```julia +if get_testset_depth() != 0 + # Attach this test set to the parent test set + parent_ts = get_testset() + record(parent_ts, self) + return self +end +``` """ function finish end From 27d39316da8b041b68111e7623c5a80f014c7404 Mon Sep 17 00:00:00 2001 From: Mustafa M Date: Sat, 8 May 2021 17:20:56 -0400 Subject: [PATCH 323/439] Fix windows resource FILEVERSION (#40752) --- cli/Makefile | 2 +- contrib/windows/julia.rc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/Makefile b/cli/Makefile index b998462db9a32..c38b9972a243b 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -70,7 +70,7 @@ $(BUILDDIR)/julia_res.o: $(JULIAHOME)/contrib/windows/julia.rc $(JULIAHOME)/VERS JLVER=`cat $(JULIAHOME)/VERSION` && \ JLVERi=`echo $$JLVER | perl -nle \ '/^(\d+)\.?(\d*)\.?(\d*)/ && \ - print int $$1,",",int $$2,",0,",int $$3'` && \ + print int $$1,",",int $$2,",",int $$3,",0"'` && \ $(CROSS_COMPILE)windres $< -O coff -o $@ -DJLVER=$$JLVERi -DJLVER_STR=\\\"$$JLVER\\\" EXE_OBJS += $(BUILDDIR)/julia_res.o EXE_DOBJS += $(BUILDDIR)/julia_res.o diff --git a/contrib/windows/julia.rc b/contrib/windows/julia.rc index 759b4f1b3023a..9a82ee1083ad6 100644 --- a/contrib/windows/julia.rc +++ b/contrib/windows/julia.rc @@ -1,13 +1,13 @@ #include #include -1 VERSIONINFO +VS_VERSION_INFO VERSIONINFO FILEVERSION JLVER PRODUCTVERSION JLVER /* -FILEFLAGSMASK VS_FF_PRERELEASE -FILEFLAGS VS_FF_PRERELEASE +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS VER_PRIVATEBUILD */ -FILEOS VOS_DOS_WINDOWS32 +FILEOS VOS__WINDOWS32 FILETYPE VFT_APP BEGIN BLOCK "StringFileInfo" From 00f4194c0f63dc79a28972c335b9bd91f35daa76 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sun, 9 May 2021 11:46:17 +0900 Subject: [PATCH 324/439] do not trim trailing zeros of integral part --- base/ryu/Ryu.jl | 2 +- base/ryu/fixed.jl | 5 ++++- test/ryu.jl | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/base/ryu/Ryu.jl b/base/ryu/Ryu.jl index 1d260fe9b3696..81d1c41f4c19f 100644 --- a/base/ryu/Ryu.jl +++ b/base/ryu/Ryu.jl @@ -64,7 +64,7 @@ Various options for the output format include: * `hash`: whether the decimal point should be written, even if no additional digits are needed for precision * `precision`: minimum number of significant digits to be included in the decimal string; extra `'0'` characters will be added for padding if necessary * `decchar`: decimal point character to be used - * `trimtrailingzeros`: whether trailing zeros should be removed + * `trimtrailingzeros`: whether trailing zeros of fractional part should be removed """ function writefixed(x::T, precision::Integer, diff --git a/base/ryu/fixed.jl b/base/ryu/fixed.jl index 5c780aa7acbf8..e0085f5c66dab 100644 --- a/base/ryu/fixed.jl +++ b/base/ryu/fixed.jl @@ -69,9 +69,11 @@ function writefixed(buf, pos, v::T, buf[pos] = UInt8('0') pos += 1 end + hasfractional = false if precision > 0 || hash buf[pos] = decchar pos += 1 + hasfractional = true end if e2 < 0 idx = div(-e2, 16) @@ -139,6 +141,7 @@ function writefixed(buf, pos, v::T, if dotPos > 1 buf[dotPos] = UInt8('0') buf[dotPos + 1] = decchar + hasfractional = true end buf[pos] = UInt8('0') pos += 1 @@ -167,7 +170,7 @@ function writefixed(buf, pos, v::T, pos += 1 end end - if trimtrailingzeros + if trimtrailingzeros && hasfractional while buf[pos - 1] == UInt8('0') pos -= 1 end diff --git a/test/ryu.jl b/test/ryu.jl index d8d3c17752f63..d5a8df24bd03b 100644 --- a/test/ryu.jl +++ b/test/ryu.jl @@ -544,10 +544,14 @@ end # Float16 @test Ryu.writefixed(7.018232e-82, 6) == "0.000000" end - @testset "Consistency of trimtrailingzeros" begin + @testset "Trimming of trailing zeros" begin @test Ryu.writefixed(0.0, 1, false, false, false, UInt8('.'), true) == "0" @test Ryu.writefixed(1.0, 1, false, false, false, UInt8('.'), true) == "1" @test Ryu.writefixed(2.0, 1, false, false, false, UInt8('.'), true) == "2" + + @show Ryu.writefixed(1.25e+5, 0, false, false, false, UInt8('.'), true) == "125000" + @show Ryu.writefixed(1.25e+5, 1, false, false, false, UInt8('.'), true) == "125000" + @show Ryu.writefixed(1.25e+5, 2, false, false, false, UInt8('.'), true) == "125000" end end # fixed From 9bceffd4c38d28f26580cf4fedfd48e1ec723655 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 11 May 2021 00:33:56 +0900 Subject: [PATCH 325/439] REPL: improve `getfield` type completion (#40624) fix #40247 --- stdlib/REPL/src/REPLCompletions.jl | 32 ++++++---- stdlib/REPL/test/replcompletions.jl | 90 +++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 5412f6f157ada..5d857dbe10407 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -387,14 +387,24 @@ get_value(sym::QuoteNode, fn) = isdefined(fn, sym.value) ? (getfield(fn, sym.val get_value(sym::GlobalRef, fn) = get_value(sym.name, sym.mod) get_value(sym, fn) = (sym, true) -# Return the value of a getfield call expression -function get_value_getfield(ex::Expr, fn) - # Example :((top(getfield))(Base,:max)) - val, found = get_value_getfield(ex.args[2],fn) #Look up Base in Main and returns the module - (found && length(ex.args) >= 3) || return (nothing, false) - return get_value_getfield(ex.args[3], val) #Look up max in Base and returns the function if found. +# Return the type of a getfield call expression +function get_type_getfield(ex::Expr, fn::Module) + length(ex.args) == 3 || return Any, false # should never happen, but just for safety + obj, x = ex.args[2:3] + objt, found = get_type(obj, fn) + objt isa DataType || return Any, false + found || return Any, false + if x isa QuoteNode + fld = x.value + elseif isexpr(x, :quote) || isexpr(x, :inert) + fld = x.args[1] + else + fld = nothing # we don't know how to get the value of variable `x` here + end + fld isa Symbol || return Any, false + hasfield(objt, fld) || return Any, false + return fieldtype(objt, fld), true end -get_value_getfield(sym, fn) = get_value(sym, fn) # Determines the return type with Base.return_types of a function call using the type information of the arguments. function get_type_call(expr::Expr) @@ -424,7 +434,7 @@ function get_type_call(expr::Expr) return (return_type, true) end -# Returns the return type. example: get_type(:(Base.strip("", ' ')), Main) returns (String, true) +# Returns the return type. example: get_type(:(Base.strip("", ' ')), Main) returns (SubString{String}, true) function try_get_type(sym::Expr, fn::Module) val, found = get_value(sym, fn) found && return Core.Typeof(val), found @@ -432,10 +442,8 @@ function try_get_type(sym::Expr, fn::Module) # getfield call is special cased as the evaluation of getfield provides good type information, # is inexpensive and it is also performed in the complete_symbol function. a1 = sym.args[1] - if isa(a1,GlobalRef) && isconst(a1.mod,a1.name) && isdefined(a1.mod,a1.name) && - eval(a1) === Core.getfield - val, found = get_value_getfield(sym, Main) - return found ? Core.Typeof(val) : Any, found + if a1 === :getfield || a1 === GlobalRef(Core, :getfield) + return get_type_getfield(sym, fn) end return get_type_call(sym) elseif sym.head === :thunk diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 97eee61579142..545e81a27968d 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -97,10 +97,11 @@ function map_completion_text(completions) return map(completion_text, c), r, res end -test_complete(s) = map_completion_text(@inferred(completions(s,lastindex(s)))) -test_scomplete(s) = map_completion_text(@inferred(shell_completions(s,lastindex(s)))) -test_bslashcomplete(s) = map_completion_text(@inferred(bslash_completions(s,lastindex(s)))[2]) -test_complete_context(s) = map_completion_text(@inferred(completions(s,lastindex(s),Main.CompletionFoo))) +test_complete(s) = map_completion_text(@inferred(completions(s, lastindex(s)))) +test_scomplete(s) = map_completion_text(@inferred(shell_completions(s, lastindex(s)))) +test_bslashcomplete(s) = map_completion_text(@inferred(bslash_completions(s, lastindex(s)))[2]) +test_complete_context(s, m) = map_completion_text(@inferred(completions(s,lastindex(s), m))) +test_complete_foo(s) = test_complete_context(s, Main.CompletionFoo) module M32377 end test_complete_32377(s) = map_completion_text(completions(s,lastindex(s), M32377)) @@ -297,7 +298,7 @@ end # test latex symbol completion in getindex expressions (#24705) let s = "tuple[\\alpha" - c, r, res = test_complete_context(s) + c, r, res = test_complete_foo(s) @test c[1] == "α" @test r == 7:12 @test length(c) == 1 @@ -987,13 +988,13 @@ end # No CompletionFoo.CompletionFoo let s = "" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test !("CompletionFoo" in c) end # Can see `rand()` after `using Random` let s = "r" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "rand" in c @test r == 1:1 @test s[r] == "r" @@ -1001,7 +1002,7 @@ end # Can see `Test.AbstractTestSet` after `import Test` let s = "Test.A" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "AbstractTestSet" in c @test r == 6:6 @test s[r] == "A" @@ -1009,21 +1010,21 @@ end # Can complete relative import let s = "import ..M" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test_broken "Main" in c @test r == 10:10 @test s[r] == "M" end let s = "" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "bar" in c @test r === 1:0 @test s[r] == "" end let s = "f" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "foo" in c @test r == 1:1 @test s[r] == "f" @@ -1031,7 +1032,7 @@ let s = "f" end let s = "@f" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "@foobar" in c @test r == 1:2 @test s[r] == "@f" @@ -1039,48 +1040,48 @@ let s = "@f" end let s = "type_test.x" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "xx" in c @test r == 11:11 @test s[r] == "x" end let s = "bar.no_val_available" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test length(c)==0 end let s = "type_test.xx.y" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "yy" in c @test r == 14:14 @test s[r] == "y" end let s = ":(function foo(::Int) end).args[1].args[2]." - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test c == Any[] end let s = "log(log.(x)," - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test !isempty(c) end let s = "Base.return_types(getin" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test "getindex" in c @test r == 19:23 @test s[r] == "getin" end let s = "using Test, Random" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test !("RandomDevice" in c) end let s = "test(1,1, " - c, r, res = test_complete_context(s) + c, r, res = test_complete_foo(s) @test !res @test c[1] == string(first(methods(Main.CompletionFoo.test, Tuple{Int, Int}))) @test length(c) == 3 @@ -1089,7 +1090,7 @@ let s = "test(1,1, " end let s = "test.(1,1, " - c, r, res = test_complete_context(s) + c, r, res = test_complete_foo(s) @test !res @test length(c) == 4 @test r == 1:4 @@ -1097,7 +1098,7 @@ let s = "test.(1,1, " end let s = "prevind(\"θ\",1," - c, r, res = test_complete_context(s) + c, r, res = test_complete_foo(s) @test c[1] == string(first(methods(prevind, Tuple{String, Int}))) @test r == 1:7 @test s[r] == "prevind" @@ -1105,12 +1106,12 @@ end # Issue #32840 let s = "typeof(+)." - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test length(c) == length(fieldnames(DataType)) end let s = "test_dict[\"ab" - c, r = test_complete_context(s) + c, r = test_complete_foo(s) @test c == Any["\"abc\"", "\"abcd\""] end @@ -1120,3 +1121,44 @@ let (test_complete("Main.@noexist."); @test true) (test_complete("@Main.noexist."); @test true) end + +@testset "https://github.com/JuliaLang/julia/issues/40247" begin + # getfield type completion can work for complicated expression + + let + m = Module() + @eval m begin + struct Rs + rs::Vector{Regex} + end + var = nothing + function foo() + global var = 1 + return Rs([r"foo"]) + end + end + + c, r = test_complete_context("foo().rs[1].", m) + @test m.var ≠ 1 # getfield type completion should never execute `foo()` + @test length(c) == fieldcount(Regex) + end + + let + m = Module() + @eval m begin + struct R + r::Regex + end + var = nothing + function foo() + global var = 1 + return R(r"foo") + end + end + + c, r = test_complete_context("foo().r.", m) + # the current implementation of `REPL.REPLCompletions.completions(::String, ::Int, ::Module)` + # cuts off "foo().r." to `.r.`, and the getfield type completion doesn't work for this simpler case + @test_broken length(c) == fieldcount(Regex) + end +end From e4f79b7167312dab649218b53b84c0829ea0c103 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 10 May 2021 11:38:48 -0400 Subject: [PATCH 326/439] [CLI] ensure error on not finding symbol (#40748) This sanity check was attempted in #38994, but dlsym is often also okay with finding the trampoline, so we want to also check that it does not use that to resolve the trampoline ad infinitum. --- cli/jl_exports.h | 14 ++++++++++---- cli/loader_lib.c | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cli/jl_exports.h b/cli/jl_exports.h index 0d467a6528b75..35d2767726865 100644 --- a/cli/jl_exports.h +++ b/cli/jl_exports.h @@ -10,13 +10,19 @@ JL_EXPORTED_DATA_POINTERS(XX) #undef XX -// Define symbol data as `$type) $(name);` +// Define symbol data as `$(type) $(name);` #define XX(name, type) JL_DLLEXPORT type name; JL_EXPORTED_DATA_SYMBOLS(XX) #undef XX -// Define holder locations for function addresses as `const void * $(name)_addr` -#define XX(name) JL_HIDDEN const void * name##_addr; +// Declare list of exported functions (sans type) +#define XX(name) JL_DLLEXPORT void name(void); +typedef void (anonfunc)(void); +JL_EXPORTED_FUNCS(XX) +#undef XX + +// Define holder locations for function addresses as `const void * $(name)_addr = & $(name);` +#define XX(name) JL_HIDDEN anonfunc * name##_addr = (anonfunc*)&name; JL_EXPORTED_FUNCS(XX) #undef XX @@ -29,7 +35,7 @@ static const char *const jl_exported_func_names[] = { #undef XX #define XX(name) &name##_addr, -static const void ** jl_exported_func_addrs[] = { +static anonfunc **const jl_exported_func_addrs[] = { JL_EXPORTED_FUNCS(XX) NULL }; diff --git a/cli/loader_lib.c b/cli/loader_lib.c index 2f596ac27202d..f7858d9bc909f 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -161,7 +161,7 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { // Once we have libjulia-internal loaded, re-export its symbols: for (unsigned int symbol_idx=0; jl_exported_func_names[symbol_idx] != NULL; ++symbol_idx) { void *addr = lookup_symbol(libjulia_internal, jl_exported_func_names[symbol_idx]); - if (addr == NULL) { + if (addr == NULL || addr == *jl_exported_func_addrs[symbol_idx]) { jl_loader_print_stderr3("ERROR: Unable to load ", jl_exported_func_names[symbol_idx], " from libjulia-internal"); exit(1); } From 67186f43f73392bf1390eeacea929e81d29bdb05 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Mon, 10 May 2021 18:18:10 -0400 Subject: [PATCH 327/439] show(::String): elide long strings (close #40724) (#40736) --- NEWS.md | 1 + base/strings/io.jl | 48 +++++++++++++++++++++++++++++++++++++++++ test/show.jl | 54 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2e63729ee09cb..07db69fecf7db 100644 --- a/NEWS.md +++ b/NEWS.md @@ -55,6 +55,7 @@ New library features Standard library changes ------------------------ +* Long strings are now elided using the syntax `"head" ⋯ 12345 bytes ⋯ "tail"` when displayed in the REPL ([#40736]). * `count` and `findall` now accept an `AbstractChar` argument to search for a character in a string ([#38675]). * `range` now supports the `range(start, stop)` and `range(start, stop, length)` methods ([#39228]). * `range` now supports `start` as an optional keyword argument ([#38041]). diff --git a/base/strings/io.jl b/base/strings/io.jl index 3977f137510e3..0f877275ed759 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -190,6 +190,54 @@ print(io::IO, s::AbstractString) = for c in s; print(io, c); end write(io::IO, s::AbstractString) = (len = 0; for c in s; len += Int(write(io, c))::Int; end; len) show(io::IO, s::AbstractString) = print_quoted(io, s) +# show elided string if more than `limit` characters +function show( + io :: IO, + mime :: MIME"text/plain", + str :: AbstractString; + limit :: Union{Int, Nothing} = nothing, +) + # compute limit in default case + if limit === nothing + get(io, :limit, false) || return show(io, str) + limit = max(20, displaysize(io)[2]) + # one line in collection, seven otherwise + get(io, :typeinfo, nothing) === nothing && (limit *= 7) + end + + # early out for short strings + len = ncodeunits(str) + len ≤ limit - 2 && # quote chars + return show(io, str) + + # these don't depend on string data + units = codeunit(str) == UInt8 ? "bytes" : "code units" + skip_text(skip) = " ⋯ $skip $units ⋯ " + short = length(skip_text("")) + 4 # quote chars + chars = max(limit, short + 1) - short # at least 1 digit + + # figure out how many characters to print in elided case + chars -= d = ndigits(len - chars) # first adjustment + chars += d - ndigits(len - chars) # second if needed + chars = max(0, chars) + + # find head & tail, avoiding O(length(str)) computation + head = nextind(str, 0, 1 + (chars + 1) ÷ 2) + tail = prevind(str, len + 1, chars ÷ 2) + + # threshold: min chars skipped to make elision worthwhile + t = short + ndigits(len - chars) - 1 + n = tail - head # skipped code units + if 4t ≤ n || t ≤ n && t ≤ length(str, head, tail-1) + skip = skip_text(n) + show(io, SubString(str, 1:prevind(str, head))) + print(io, skip) # TODO: bold styled + show(io, SubString(str, tail)) + else + show(io, str) + end +end + # optimized methods to avoid iterating over chars write(io::IO, s::Union{String,SubString{String}}) = GC.@preserve s Int(unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))))::Int diff --git a/test/show.jl b/test/show.jl index 2c8a6fd67bd4a..2dde201b06dfb 100644 --- a/test/show.jl +++ b/test/show.jl @@ -808,13 +808,20 @@ Base.methodloc_callback[] = nothing # test that no spurious visual lines are added when one element spans multiple lines v = fill!(Array{Any}(undef, 9), 0) v[1] = "look I'm wide! --- " ^ 9 - @test replstr(v) == "9-element Vector{Any}:\n \"look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- \"\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0" - @test replstr([fill(0, 9) v]) == "9×2 Matrix{Any}:\n 0 … \"look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- \"\n 0 0\n 0 0\n 0 0\n 0 0\n 0 … 0\n 0 0\n 0 0\n 0 0" + r = replstr(v) + @test startswith(r, "9-element Vector{Any}:\n \"look I'm wide! ---") + @test endswith(r, "look I'm wide! --- \"\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0") + # test vertical/diagonal ellipsis v = fill!(Array{Any}(undef, 50), 0) v[1] = "look I'm wide! --- " ^ 9 - @test replstr(v) == "50-element Vector{Any}:\n \"look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- \"\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n ⋮\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0" - @test replstr([fill(0, 50) v]) == "50×2 Matrix{Any}:\n 0 … \"look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- look I'm wide! --- \"\n 0 0\n 0 0\n 0 0\n 0 0\n 0 … 0\n 0 0\n 0 0\n 0 0\n 0 0\n ⋮ ⋱ \n 0 0\n 0 0\n 0 0\n 0 0\n 0 … 0\n 0 0\n 0 0\n 0 0\n 0 0" + r = replstr(v) + @test startswith(r, "50-element Vector{Any}:\n \"look I'm wide! ---") + @test endswith(r, "look I'm wide! --- \"\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n ⋮\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0\n 0") + + r = replstr([fill(0, 50) v]) + @test startswith(r, "50×2 Matrix{Any}:\n 0 … \"look I'm wide! ---") + @test endswith(r, "look I'm wide! --- \"\n 0 0\n 0 0\n 0 0\n 0 0\n 0 … 0\n 0 0\n 0 0\n 0 0\n 0 0\n ⋮ ⋱ \n 0 0\n 0 0\n 0 0\n 0 0\n 0 … 0\n 0 0\n 0 0\n 0 0\n 0 0") # issue #34659 @test replstr(Int32[]) == "Int32[]" @@ -825,6 +832,45 @@ Base.methodloc_callback[] = nothing @test replstr([zeros(3,0),zeros(2,0)]) == "2-element Vector{Matrix{Float64}}:\n 3×0 Matrix{Float64}\n 2×0 Matrix{Float64}" end +# string show with elision +@testset "string show with elision" begin + @testset "elision logic" begin + strs = ["A", "∀", "∀A", "A∀", "😃"] + for limit = 0:100, len = 0:100, str in strs + str = str^len + str = str[1:nextind(str, 0, len)] + out = sprint() do io + show(io, MIME"text/plain"(), str; limit) + end + lower = length("\"\" ⋯ $(ncodeunits(str)) bytes ⋯ \"\"") + limit = max(limit, lower) + if length(str) + 2 ≤ limit + @test eval(Meta.parse(out)) == str + else + @test limit-!isascii(str) <= length(out) <= limit + re = r"(\"[^\"]*\") ⋯ (\d+) bytes ⋯ (\"[^\"]*\")" + m = match(re, out) + head = eval(Meta.parse(m.captures[1])) + tail = eval(Meta.parse(m.captures[3])) + skip = parse(Int, m.captures[2]) + @test startswith(str, head) + @test endswith(str, tail) + @test ncodeunits(str) == + ncodeunits(head) + skip + ncodeunits(tail) + end + end + end + + @testset "default elision limit" begin + r = replstr("x"^1000) + @test length(r) == 7*80 + @test r == repr("x"^271) * " ⋯ 459 bytes ⋯ " * repr("x"^270) + r = replstr(["x"^1000]) + @test length(r) < 120 + @test r == "1-element Vector{String}:\n " * repr("x"^31) * " ⋯ 939 bytes ⋯ " * repr("x"^30) + end +end + # Issue 14121 @test_repr "(A'x)'" From 50fa83c71bbf47425378e3a72a413161c6fb4adc Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 11 May 2021 00:47:42 -0700 Subject: [PATCH 328/439] Add logabsdet method for UmfpackLU (#40716) Co-authored-by: Daniel Karrasch --- stdlib/SuiteSparse/src/umfpack.jl | 39 +++++++++++++++++++++++++++++- stdlib/SuiteSparse/test/umfpack.jl | 6 ++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl index e1e5df876c9a5..61cb2a035a5b9 100644 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -6,7 +6,7 @@ export UmfpackLU import Base: (\), getproperty, show, size using LinearAlgebra -import LinearAlgebra: Factorization, det, lu, lu!, ldiv! +import LinearAlgebra: Factorization, checksquare, det, logabsdet, lu, lu!, ldiv! using SparseArrays using SparseArrays: getcolptr @@ -279,6 +279,26 @@ function deserialize(s::AbstractSerializer, t::Type{UmfpackLU{Tv,Ti}}) where {Tv return obj end +# compute the sign/parity of a permutation +function _signperm(p) + n = length(p) + result = 0 + todo = trues(n) + while any(todo) + k = findfirst(todo) + todo[k] = false + result += 1 # increment element count + j = p[k] + while j != k + result += 1 # increment element count + todo[j] = false + j = p[j] + end + result += 1 # increment cycle count + end + return ifelse(isodd(result), -1, 1) +end + ## Wrappers for UMFPACK functions # generate the name of the C function according to the value and integer types @@ -406,6 +426,23 @@ for itype in UmfpackIndexTypes mx, mz, C_NULL, lu.numeric, umf_info) complex(mx[], mz[]) end + function logabsdet(F::UmfpackLU{T, $itype}) where {T<:Union{Float64,ComplexF64}} # return log(abs(det)) and sign(det) + n = checksquare(F) + issuccess(F) || return log(zero(real(T))), zero(T) + U = F.U + Rs = F.Rs + p = F.p + q = F.q + s = _signperm(p)*_signperm(q)*one(real(T)) + P = one(T) + abs_det = zero(real(T)) + @inbounds for i in 1:n + dg_ii = U[i, i] / Rs[i] + P *= sign(dg_ii) + abs_det += log(abs(dg_ii)) + end + return abs_det, s * P + end function umf_lunz(lu::UmfpackLU{Float64,$itype}) lnz = Ref{$itype}() unz = Ref{$itype}() diff --git a/stdlib/SuiteSparse/test/umfpack.jl b/stdlib/SuiteSparse/test/umfpack.jl index 4dcf7007aa1c7..ba8e2f54b975b 100644 --- a/stdlib/SuiteSparse/test/umfpack.jl +++ b/stdlib/SuiteSparse/test/umfpack.jl @@ -34,7 +34,11 @@ using SparseArrays: nnz, sparse, sprand, sprandn, SparseMatrixCSC @test Rs == lua.Rs @test (Diagonal(Rs) * A)[p,q] ≈ L * U - det(lua) ≈ det(Array(A)) + @test det(lua) ≈ det(Array(A)) + logdet_lua, sign_lua = logabsdet(lua) + logdet_A, sign_A = logabsdet(Array(A)) + @test logdet_lua ≈ logdet_A + @test sign_lua ≈ sign_A b = [8., 45., -3., 3., 19.] x = lua\b From 0105fe42fed1ba200ee39f92aa59efe1b1e2d72e Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Tue, 11 May 2021 21:09:50 +1200 Subject: [PATCH 329/439] Fix inference of max_values(::Union) (#40785) --- base/abstractset.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/abstractset.jl b/base/abstractset.jl index 697a1ca275aae..442bbcb4bff48 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -83,7 +83,11 @@ end max_values(::Type) = typemax(Int) max_values(T::Union{map(X -> Type{X}, BitIntegerSmall_types)...}) = 1 << (8*sizeof(T)) # saturated addition to prevent overflow with typemax(Int) -max_values(T::Union) = max(max_values(T.a), max_values(T.b), max_values(T.a) + max_values(T.b)) +function max_values(T::Union) + a = max_values(T.a)::Int + b = max_values(T.b)::Int + return max(a, b, a + b) +end max_values(::Type{Bool}) = 2 max_values(::Type{Nothing}) = 1 From ad20f0a42372be7137e3777d24004a7067db3cbd Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 11 May 2021 14:21:05 +0200 Subject: [PATCH 330/439] REPL: Skip comments when assessing for missing packages, fixes #40776 (#40784) --- stdlib/REPL/src/REPL.jl | 1 + stdlib/REPL/test/repl.jl | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 0c5a6c6267cff..e777655806afa 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -191,6 +191,7 @@ function modules_to_be_loaded(ast, mods = Symbol[]) end return mods end +modules_to_be_loaded(::Nothing) = Symbol[] # comments are parsed as nothing """ start_repl_backend(repl_channel::Channel, response_channel::Channel) diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 677d184f99eab..9b72b8db7b1c5 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -1298,27 +1298,32 @@ end @testset "Install missing packages via hooks" begin @testset "Parse AST for packages" begin - mods = REPL.modules_to_be_loaded(Meta.parse("using Foo")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("using Foo")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("import Foo")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("import Foo")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("using Foo, Bar")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("using Foo, Bar")) @test mods == [:Foo, :Bar] - mods = REPL.modules_to_be_loaded(Meta.parse("import Foo, Bar")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("import Foo, Bar")) @test mods == [:Foo, :Bar] - mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo end")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("if false using Foo end")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("if false if false using Foo end end")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("if false if false using Foo end end")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo, Bar end")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("if false using Foo, Bar end")) @test mods == [:Foo, :Bar] - mods = REPL.modules_to_be_loaded(Meta.parse("if false using Foo: bar end")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("if false using Foo: bar end")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("import Foo.bar as baz")) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("import Foo.bar as baz")) @test mods == [:Foo] - mods = REPL.modules_to_be_loaded(Meta.parse("using .Foo")) - @test mods == [] + mods = REPL.modules_to_be_loaded(Base.parse_input_line("using .Foo")) + @test isempty(mods) + + mods = REPL.modules_to_be_loaded(Base.parse_input_line("# comment")) + @test isempty(mods) + mods = REPL.modules_to_be_loaded(Base.parse_input_line("Foo")) + @test isempty(mods) end end From 6cebd28e66689828db5f98b5fa5a36b250779f18 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 11 May 2021 09:04:14 -0500 Subject: [PATCH 331/439] `@something`: a short-circuiting `something` (#40729) * Create `@something` * Create `@coalesce` * Correction to `something`/`coalesce` docstring --- NEWS.md | 1 + base/exports.jl | 2 ++ base/missing.jl | 37 +++++++++++++++++++++++++++++++++++-- base/some.jl | 44 ++++++++++++++++++++++++++++++++++++++++++-- doc/src/base/base.md | 2 ++ test/missing.jl | 10 ++++++++++ test/some.jl | 10 ++++++++++ 7 files changed, 102 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 07db69fecf7db..eafec374d5a0e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -45,6 +45,7 @@ New library functions * Two arguments method `lock(f, lck)` now accepts a `Channel` as the second argument. ([#39312]) * New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438]) +* New macros `@something` and `@coalesce` which are short-circuiting versions of `something` and `coalesce`, respectively ([#40729]) New library features -------------------- diff --git a/base/exports.jl b/base/exports.jl index bfca26745e2ac..125e38930640d 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -699,9 +699,11 @@ export # missing values coalesce, + @coalesce, ismissing, missing, skipmissing, + @something, something, isnothing, nonmissingtype, diff --git a/base/missing.jl b/base/missing.jl index 87a63eb6327dc..1c15786a86a51 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -401,12 +401,12 @@ function filter(f, itr::SkipMissing{<:AbstractArray}) end """ - coalesce(x, y...) + coalesce(x...) Return the first value in the arguments which is not equal to [`missing`](@ref), if any. Otherwise return `missing`. -See also [`skipmissing`](@ref), [`something`](@ref). +See also [`skipmissing`](@ref), [`something`](@ref), [`@coalesce`](@ref). # Examples @@ -428,3 +428,36 @@ function coalesce end coalesce() = missing coalesce(x::Missing, y...) = coalesce(y...) coalesce(x::Any, y...) = x + + +""" + @coalesce(x...) + +Short-circuiting version of [`coalesce`](@ref). + +# Examples +```jldoctest +julia> f(x) = (println("f(\$x)"); missing); + +julia> a = 1; + +julia> a = @coalesce a f(2) f(3) error("`a` is still missing") +1 + +julia> b = missing; + +julia> b = @coalesce b f(2) f(3) error("`b` is still missing") +f(2) +f(3) +ERROR: `b` is still missing +[...] +``` +""" +macro coalesce(args...) + expr = :(missing) + for arg in reverse(args) + expr = :((val = $arg) !== missing ? val : $expr) + end + return esc(:(let val; $expr; end)) +end + diff --git a/base/some.jl b/base/some.jl index 30fc36d32e13f..f762f7f9aa4d1 100644 --- a/base/some.jl +++ b/base/some.jl @@ -71,13 +71,13 @@ isnothing(x) = x === nothing """ - something(x, y...) + something(x...) Return the first value in the arguments which is not equal to [`nothing`](@ref), if any. Otherwise throw an error. Arguments of type [`Some`](@ref) are unwrapped. -See also [`coalesce`](@ref), [`skipmissing`](@ref). +See also [`coalesce`](@ref), [`skipmissing`](@ref), [`@something`](@ref). # Examples ```jldoctest @@ -100,3 +100,43 @@ something() = throw(ArgumentError("No value arguments present")) something(x::Nothing, y...) = something(y...) something(x::Some, y...) = x.value something(x::Any, y...) = x + + +""" + @something(x...) + +Short-circuiting version of [`something`](@ref). + +# Examples +```jldoctest +julia> f(x) = (println("f(\$x)"); nothing); + +julia> a = 1; + +julia> a = @something a f(2) f(3) error("Unable to find default for `a`") +1 + +julia> b = nothing; + +julia> b = @something b f(2) f(3) error("Unable to find default for `b`") +f(2) +f(3) +ERROR: Unable to find default for `b` +[...] + +julia> b = @something b f(2) f(3) Some(nothing) +f(2) +f(3) + +julia> b === nothing +true +``` +""" +macro something(args...) + expr = :(nothing) + for arg in reverse(args) + expr = :((val = $arg) !== nothing ? val : $expr) + end + return esc(:(something(let val; $expr; end))) +end + diff --git a/doc/src/base/base.md b/doc/src/base/base.md index d371f7aad9411..7d1160dac918b 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -229,6 +229,7 @@ Base.isnothing Base.notnothing Base.Some Base.something +Base.@something Base.Enums.Enum Base.Enums.@enum Core.Expr @@ -287,6 +288,7 @@ Base.@deprecate Base.Missing Base.missing Base.coalesce +Base.@coalesce Base.ismissing Base.skipmissing Base.nonmissingtype diff --git a/test/missing.jl b/test/missing.jl index 0610377a7e67a..e1042f76fc7a7 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -575,6 +575,16 @@ end @test coalesce(missing, nothing) === nothing end +@testset "@coalesce" begin + @test @coalesce() === missing + @test @coalesce(1) === 1 + @test @coalesce(nothing) === nothing + @test @coalesce(missing) === missing + + @test @coalesce(1, error("failed")) === 1 + @test_throws ErrorException @coalesce(missing, error("failed")) +end + mutable struct Obj; x; end @testset "weak references" begin @noinline function mk_wr(r, wr) diff --git a/test/some.jl b/test/some.jl index 224eb8600814c..b2111c8b86085 100644 --- a/test/some.jl +++ b/test/some.jl @@ -79,6 +79,16 @@ @test something(missing, nothing, missing) === missing end +@testset "@something" begin + @test_throws ArgumentError @something() + @test_throws ArgumentError @something(nothing) + @test @something(1) === 1 + @test @something(Some(nothing)) === nothing + + @test @something(1, error("failed")) === 1 + @test_throws ErrorException @something(nothing, error("failed")) +end + # issue #26927 a = [missing, nothing, Some(nothing), Some(missing)] @test a isa Vector{Union{Missing, Nothing, Some}} From d6c092d6d73be9b41b5b8fef30d882fdb63a8d20 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Tue, 11 May 2021 22:39:26 +0200 Subject: [PATCH 332/439] Add a few tests for generic LinearAlgebra (#40794) --- stdlib/LinearAlgebra/test/generic.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index f3ef87da83052..92baaa6363b4f 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -142,6 +142,10 @@ end @testset "Scaling with 5-argument mul!" begin @test mul!(copy(a), 5., a, 10, 100) == a*150 @test mul!(copy(a), a, 5., 10, 100) == a*150 + @test mul!(vec(copy(a)), 5., a, 10, 100) == vec(a*150) + @test mul!(vec(copy(a)), a, 5., 10, 100) == vec(a*150) + @test_throws DimensionMismatch mul!([vec(copy(a)); 0], 5., a, 10, 100) + @test_throws DimensionMismatch mul!([vec(copy(a)); 0], a, 5., 10, 100) @test mul!(copy(a), Diagonal([1.; 2.]), a, 10, 100) == 10a.*[1; 2] .+ 100a @test mul!(copy(a), Diagonal([1; 2]), a, 10, 100) == 10a.*[1; 2] .+ 100a @test mul!(copy(a), a, Diagonal(1.:an), 10, 100) == 10a.*Vector(1:an)' .+ 100a @@ -189,6 +193,7 @@ end @test det(a) == a @test norm(a) == abs(a) @test norm(a, 0) == 1 + @test norm(0, 0) == 0 end @test !issymmetric(NaN16) @@ -241,12 +246,14 @@ end rotate!(x, y, c, s) @test x ≈ c*x2 + s*y2 @test y ≈ -conj(s)*x2 + c*y2 + @test_throws DimensionMismatch rotate!([x; x], y, c, s) x3 = copy(x) y3 = copy(y) reflect!(x, y, c, s) @test x ≈ c*x3 + s*y3 @test y ≈ conj(s)*x3 - c*y3 + @test_throws DimensionMismatch reflect!([x; x], y, c, s) end @testset "LinearAlgebra.axp(b)y! for element type without commutative multiplication" begin @@ -270,6 +277,7 @@ end ry = [2 8] @test LinearAlgebra.axpy!(α, x, rx, y, ry) == [1 1 1 1; 11 1 1 26] end + @testset "norm and normalize!" begin vr = [3.0, 4.0] for Tr in (Float32, Float64) From c3a31804a88beb4b05c8fd4b0981e76d14058311 Mon Sep 17 00:00:00 2001 From: Glen Hertz Date: Thu, 13 May 2021 05:12:56 -0400 Subject: [PATCH 333/439] [doc] update documentation for join (#40806) --- base/strings/io.jl | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 0f877275ed759..8b6bc21723ced 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -301,15 +301,12 @@ IOBuffer(s::SubString{String}) = IOBuffer(view(unsafe_wrap(Vector{UInt8}, s.stri # join is implemented using IO """ - join([io::IO,] strings [, delim [, last]]) + join([io::IO,] iterator [, delim [, last]]) -Join an array of `strings` into a single string, inserting the given delimiter (if any) between -adjacent strings. If `last` is given, it will be used instead of `delim` between the last -two strings. If `io` is given, the result is written to `io` rather than returned -as a `String`. - -`strings` can be any iterable over elements `x` which are convertible to strings -via `print(io::IOBuffer, x)`. `strings` will be printed to `io`. +Join any `iterator` into a single string, inserting the given delimiter (if any) between +adjacent items. If `last` is given, it will be used instead of `delim` between the last +two items. Each item of `iterator` is converted to a string via `print(io::IOBuffer, x)`. +If `io` is given, the result is written to `io` rather than returned as a `String`. # Examples ```jldoctest @@ -320,15 +317,15 @@ julia> join([1,2,3,4,5]) "12345" ``` """ -function join(io::IO, strings, delim, last) +function join(io::IO, iterator, delim, last) first = true local prev - for str in strings + for item in iterator if @isdefined prev first ? (first = false) : print(io, delim) print(io, prev) end - prev = str + prev = item end if @isdefined prev first || print(io, last) @@ -336,19 +333,19 @@ function join(io::IO, strings, delim, last) end nothing end -function join(io::IO, strings, delim="") +function join(io::IO, iterator, delim="") # Specialization of the above code when delim==last, # which lets us emit (compile) less code first = true - for str in strings + for item in iterator first ? (first = false) : print(io, delim) - print(io, str) + print(io, item) end end -join(strings) = sprint(join, strings) -join(strings, delim) = sprint(join, strings, delim) -join(strings, delim, last) = sprint(join, strings, delim, last) +join(iterator) = sprint(join, iterator) +join(iterator, delim) = sprint(join, iterator, delim) +join(iterator, delim, last) = sprint(join, iterator, delim, last) ## string escaping & unescaping ## From c8c7820de035a4657a74a595b844f6040741c0ea Mon Sep 17 00:00:00 2001 From: Daan Huybrechs Date: Thu, 13 May 2021 14:49:17 +0200 Subject: [PATCH 334/439] fix typo in manual, section on interfaces (#40811) fixes #40805 Co-authored-by: Fredrik Ekre --- doc/src/manual/interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index a6539c457c6fc..264639bc6d28c 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -371,7 +371,7 @@ julia> A[1:2,:] 2.0 5.0 8.0 ``` -In this example it is accomplished by defining `Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims)` +In this example it is accomplished by defining `Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where T` to create the appropriate wrapped array. (Note that while `similar` supports 1- and 2-argument forms, in most case you only need to specialize the 3-argument form.) For this to work it's important that `SparseArray` is mutable (supports `setindex!`). Defining `similar`, `getindex` and From 58e44a0ab74998e3064223b6a85460994b7aa6d2 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Thu, 13 May 2021 08:54:25 -0400 Subject: [PATCH 335/439] Improve docstring for `digits` (#40761) * docstring for digits * ... and for nearby functions * a few more, including count_zeros --- base/int.jl | 6 ++++++ base/intfuncs.jl | 52 +++++++++++++++++++++++++++++++++--------------- base/math.jl | 2 +- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/base/int.jl b/base/int.jl index 85482f12a5c07..c6b50c3a646bc 100644 --- a/base/int.jl +++ b/base/int.jl @@ -390,6 +390,9 @@ Number of ones in the binary representation of `x`. ```jldoctest julia> count_ones(7) 3 + +julia> count_ones(Int32(-1)) +32 ``` """ count_ones(x::BitInteger) = (ctpop_int(x) % Int)::Int @@ -429,6 +432,9 @@ Number of zeros in the binary representation of `x`. ```jldoctest julia> count_zeros(Int32(2 ^ 16 - 1)) 16 + +julia> count_zeros(-1) +0 ``` """ count_zeros(x::Integer) = count_ones(~x) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 7070aa9d13579..d3ab6f2842386 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -387,6 +387,8 @@ _prevpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -_prevpow2(unsigned(-x)) : Test whether `n` is an integer power of two. +See also [`count_ones`](@ref), [`prevpow`](@ref), [`nextpow`](@ref). + # Examples ```jldoctest julia> ispow2(4) @@ -418,6 +420,8 @@ ispow2(x::Integer) = x > 0 && count_ones(x) == 1 The smallest `a^n` not less than `x`, where `n` is a non-negative integer. `a` must be greater than 1, and `x` must be greater than 0. +See also [`prevpow`](@ref). + # Examples ```jldoctest julia> nextpow(2, 7) @@ -432,8 +436,6 @@ julia> nextpow(5, 20) julia> nextpow(4, 16) 16 ``` - -See also [`prevpow`](@ref). """ function nextpow(a::Real, x::Real) x <= 0 && throw(DomainError(x, "`x` must be positive.")) @@ -455,6 +457,8 @@ end The largest `a^n` not greater than `x`, where `n` is a non-negative integer. `a` must be greater than 1, and `x` must not be less than 1. +See also [`nextpow`](@ref), [`isqrt`](@ref). + # Examples ```jldoctest julia> prevpow(2, 7) @@ -469,7 +473,6 @@ julia> prevpow(5, 20) julia> prevpow(4, 16) 16 ``` -See also [`nextpow`](@ref). """ function prevpow(a::Real, x::Real) x < 1 && throw(DomainError(x, "`x` must be ≥ 1.")) @@ -611,6 +614,8 @@ Compute the number of digits in integer `n` written in base `base` (`base` must not be in `[-1, 0, 1]`), optionally padded with zeros to a specified size (the result will never be less than `pad`). +See also [`digits`](@ref), [`count_ones`](@ref). + # Examples ```jldoctest julia> ndigits(12345) @@ -624,6 +629,9 @@ julia> string(1022, base=16) julia> ndigits(123, pad=5) 5 + +julia> ndigits(-123) +3 ``` """ ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, base)) @@ -748,12 +756,15 @@ split_sign(n::Unsigned) = n, false Convert an integer `n` to a string in the given `base`, optionally specifying a number of digits to pad to. +See also [`digits`](@ref), [`bitstring`](@ref), [`count_zeros`](@ref). + +# Examples ```jldoctest julia> string(5, base = 13, pad = 4) "0005" -julia> string(13, base = 5, pad = 4) -"0023" +julia> string(-13, base = 5, pad = 4) +"-0023" ``` """ function string(n::Integer; base::Integer = 10, pad::Integer = 1) @@ -782,10 +793,12 @@ string(b::Bool) = b ? "true" : "false" A string giving the literal bit representation of a number. +See also [`count_ones`](@ref), [`count_zeros`](@ref), [`digits`](@ref). + # Examples ```jldoctest -julia> bitstring(4) -"0000000000000000000000000000000000000000000000000000000000000100" +julia> bitstring(Int32(4)) +"00000000000000000000000000000100" julia> bitstring(2.2) "0100000000000001100110011001100110011001100110011001100110011010" @@ -806,9 +819,12 @@ Return an array with element type `T` (default `Int`) of the digits of `n` in th base, optionally padded with zeros to a specified size. More significant digits are at higher indices, such that `n == sum(digits[k]*base^(k-1) for k=1:length(digits))`. +See also [`ndigits`](@ref), [`digits!`](@ref), +and for base 2 also [`bitstring`](@ref), [`count_ones`](@ref). + # Examples ```jldoctest -julia> digits(10, base = 10) +julia> digits(10) 2-element Vector{Int64}: 0 1 @@ -820,14 +836,18 @@ julia> digits(10, base = 2) 0 1 -julia> digits(10, base = 2, pad = 6) -6-element Vector{Int64}: - 0 - 1 - 0 - 1 - 0 - 0 +julia> digits(-256, base = 10, pad = 5) +5-element Vector{Int64}: + -6 + -5 + -2 + 0 + 0 + +julia> n = rand(-999:999); + +julia> n == evalpoly(13, digits(n, base = 13)) +true ``` """ digits(n::Integer; base::Integer = 10, pad::Integer = 1) = diff --git a/base/math.jl b/base/math.jl index c08c25d05f112..003d4e0c8f831 100644 --- a/base/math.jl +++ b/base/math.jl @@ -495,7 +495,7 @@ log(x::Number) Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. -See also: [`exp2`](@ref), [`ldexp`](@ref). +See also: [`exp2`](@ref), [`ldexp`](@ref), [`ispow2`](@ref). # Examples ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" From feba24fd5db8a7b682f87ba8d7767533478af4ac Mon Sep 17 00:00:00 2001 From: Alex Wadell Date: Thu, 13 May 2021 09:50:10 -0400 Subject: [PATCH 336/439] [Test stdlib] detailed test failure printing of type comparisons with <: and >:, fixes #39243 (#40798) --- stdlib/Test/src/Test.jl | 6 ++++++ stdlib/Test/test/runtests.jl | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index e40793968e7d9..d303b6a7c69aa 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -516,6 +516,12 @@ function get_test_result(ex, source) first(string(ex.args[1])) != '.' && !is_splat(ex.args[2]) && !is_splat(ex.args[3]) && (ex.args[1] === :(==) || Base.operator_precedence(ex.args[1]) == comparison_prec) ex = Expr(:comparison, ex.args[2], ex.args[1], ex.args[3]) + + # Mark <: and >: as :comparison expressions + elseif isa(ex, Expr) && length(ex.args) == 2 && + !is_splat(ex.args[1]) && !is_splat(ex.args[2]) && + Base.operator_precedence(ex.head) == comparison_prec + ex = Expr(:comparison, ex.args[1], ex.head, ex.args[2]) end if isa(ex, Expr) && ex.head === :comparison # pass all terms of the comparison to `eval_comparison`, as an Expr diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 1b99fcf4a66e2..22bc815e0019b 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -146,6 +146,8 @@ let fails = @testset NoThrowTestSet begin @test endswith(str1, str2) # 21 - Fail - contains @test contains(str1, str2) + # 22 - Fail - Type Comparison + @test typeof(1) <: typeof("julia") end for fail in fails @test fail isa Test.Fail @@ -255,6 +257,11 @@ let fails = @testset NoThrowTestSet begin @test occursin("Expression: contains(str1, str2)", str) @test occursin("Evaluated: contains(\"Hello\", \"World\")", str) end + + let str = sprint(show, fails[22]) + @test occursin("Expression: typeof(1) <: typeof(\"julia\")", str) + @test occursin("Evaluated: $(typeof(1)) <: $(typeof("julia"))", str) + end end let errors = @testset NoThrowTestSet begin From 296f77c31cac73cac7e4aa8c3533e65ca7ed1382 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 13 May 2021 11:17:32 -0400 Subject: [PATCH 337/439] [Make] make clangsa work with out of tree builds --- test/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 9ca65ffa9d7c7..3d16f88a741b8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -35,8 +35,11 @@ embedding: gcext: @$(MAKE) -C $(SRCDIR)/$@ check $(GCEXT_ARGS) +clangsa: + @$(MAKE) -C $(SRCDIR)/$@ + clean: @$(MAKE) -C embedding $@ $(EMBEDDING_ARGS) @$(MAKE) -C gcext $@ $(GCEXT_ARGS) -.PHONY: $(TESTS) $(addprefix revise-, $(TESTS)) embedding gcext clean +.PHONY: $(TESTS) $(addprefix revise-, $(TESTS)) embedding gcext clangsa clean From 853a936331c40b1fff6f6b6edf078a5aac2cca97 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 14 May 2021 01:14:25 +0900 Subject: [PATCH 338/439] inference: fix missing `LimitedAccuracy` handling in `conditional_changes` (#40744) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following JET analysis told me that we missed to handle `LimitedAccuracy` in `conditional_changes` and limited conditional constraints weren't propagated: ```julia julia> using JET, Test julia> report_call() do @testset "foo" begin; true; end end ┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:1262 Test.finish(ts) │┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:1007 Test.print_test_results(ts) ││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:941 #self#(ts, 0) │││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:961 Test.get_alignment(ts, 0) ││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:1034 Test.map(#36, Base.getproperty(ts, :results)) │││││┌ @ abstractarray.jl:2362 Base.collect_similar(A, Base.Generator(f, A)) ││││││┌ @ array.jl:638 Base._collect(cont, itr, Base.IteratorEltype(itr), Base.IteratorSize(itr)) │││││││┌ @ array.jl:723 Base.iterate(itr) ││││││││┌ @ generator.jl:47 Base.getproperty(g, :f)(Base.getindex(y, 1)) │││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Test/src/Test.jl:1034 Test.get_alignment(t, Test.+(Core.getfield(#self#, :depth), 1)) │││││││││││││┌ @ array.jl:728 Base.collect_to_with_first!(Base._similar_for(c, Base.typeof(v1), itr, isz), v1, itr, st) ││││││││││││││┌ @ array.jl:734 Base.collect_to!(dest, itr, Base.+(i1, 1), st) │││││││││││││││┌ @ /Users/aviatesk/julia/julia/base/array.jl:764 Base.collect_to!(new, itr, Base.+(i, 1), st) ││││││││││││││││┌ @ /Users/aviatesk/julia/julia/base/array.jl:758 Base.indexed_iterate(y, 2, _8) │││││││││││││││││┌ @ tuple.jl:94 Base.iterate(I, state) ││││││││││││││││││ no matching method found for call signature (Tuple{typeof(iterate), Nothing, Int64}): Base.iterate(I::Nothing, state::Int64) │││││││││││││││││└─────────────── ││││││││││││││││┌ @ /Users/aviatesk/julia/julia/base/array.jl:758 Base.indexed_iterate(y, 1) │││││││││││││││││┌ @ tuple.jl:89 Base.iterate(I) ││││││││││││││││││ no matching method found for call signature (Tuple{typeof(iterate), Nothing}): Base.iterate(I::Nothing) │││││││││││││││││└─────────────── Union{Test.FallbackTestSet, Test.DefaultTestSet} ``` After this PR: ```julia julia> report_call() do @testset "foo" begin; true; end end No errors ! Union{Test.FallbackTestSet, Test.DefaultTestSet} ``` --- base/compiler/abstractinterpretation.jl | 7 ++++++- base/compiler/typelattice.jl | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 9b7434c0a5a45..5ea1d761f1b26 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1846,7 +1846,12 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) end function conditional_changes(changes::VarTable, @nospecialize(typ), var::Slot) - if typ ⊑ (changes[slot_id(var)]::VarState).typ + oldtyp = (changes[slot_id(var)]::VarState).typ + # approximate test for `typ ∩ oldtyp` being better than `oldtyp` + # since we probably formed these types with `typesubstract`, the comparison is likely simple + if ignorelimited(typ) ⊑ ignorelimited(oldtyp) + # typ is better unlimited, but we may still need to compute the tmeet with the limit "causes" since we ignored those in the comparison + oldtyp isa LimitedAccuracy && (typ = tmerge(typ, LimitedAccuracy(Bottom, oldtyp.causes))) return StateUpdate(var, VarState(typ, false), changes, true) end return changes diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 0f3dd7b4a84ed..a4064a7fa3ca6 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -91,7 +91,7 @@ struct StateUpdate end # Represent that the type estimate has been approximated, due to "causes" -# (only used in abstractinterpret, doesn't appear in optimize) +# (only used in abstract interpretion, doesn't appear in optimization) # N.B. in the lattice, this is epsilon smaller than `typ` (except Union{}) struct LimitedAccuracy typ From 55c32b5d9767fd897b008ccc8b753ef77ad42233 Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Thu, 13 May 2021 17:22:54 +0100 Subject: [PATCH 339/439] Make issparse handle nested wrappers (#34308) --- NEWS.md | 2 +- stdlib/SparseArrays/src/abstractsparse.jl | 22 ++++++++++++---------- stdlib/SparseArrays/test/sparse.jl | 6 ++++++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/NEWS.md b/NEWS.md index eafec374d5a0e..d93e4d2d5f968 100644 --- a/NEWS.md +++ b/NEWS.md @@ -117,7 +117,7 @@ Standard library changes * new `sizehint!(::SparseMatrixCSC, ::Integer)` method ([#30676]). * `cholesky()` now fully preserves the user-specified permutation. ([#40560]) - +* `issparse` now applies consistently to all wrapper arrays, including nested, by checking `issparse` on the wrapped parent array ([#37644]). #### Dates diff --git a/stdlib/SparseArrays/src/abstractsparse.jl b/stdlib/SparseArrays/src/abstractsparse.jl index 3ea70f48b4a7e..86d6c4b3da56d 100644 --- a/stdlib/SparseArrays/src/abstractsparse.jl +++ b/stdlib/SparseArrays/src/abstractsparse.jl @@ -50,17 +50,19 @@ julia> issparse(Array(sv)) false ``` """ -issparse(A::AbstractArray) = false +function issparse(A::AbstractArray) + # Handle wrapper arrays: sparse if it is wrapping a sparse array. + # This gets compiled away during specialization. + p = parent(A) + if p === A + # have reached top of wrapping without finding a sparse array, assume it is not. + return false + else + return issparse(p) + end +end +issparse(A::DenseArray) = false issparse(S::AbstractSparseArray) = true -issparse(S::LinearAlgebra.Adjoint{<:Any,<:AbstractSparseArray}) = true -issparse(S::LinearAlgebra.Transpose{<:Any,<:AbstractSparseArray}) = true - -issparse(S::LinearAlgebra.Symmetric{<:Any,<:AbstractSparseMatrix}) = true -issparse(S::LinearAlgebra.Hermitian{<:Any,<:AbstractSparseMatrix}) = true -issparse(S::LinearAlgebra.LowerTriangular{<:Any,<:AbstractSparseMatrix}) = true -issparse(S::LinearAlgebra.UnitLowerTriangular{<:Any,<:AbstractSparseMatrix}) = true -issparse(S::LinearAlgebra.UpperTriangular{<:Any,<:AbstractSparseMatrix}) = true -issparse(S::LinearAlgebra.UnitUpperTriangular{<:Any,<:AbstractSparseMatrix}) = true indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = Ti diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index f2754ba5ade81..4c6ca81127129 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2165,6 +2165,12 @@ end @test issparse(LinearAlgebra.UnitLowerTriangular(Array(m))) == false @test issparse(UpperTriangular(Array(m))) == false @test issparse(LinearAlgebra.UnitUpperTriangular(Array(m))) == false + @test issparse(Base.ReshapedArray(m, (20, 5), ())) + @test issparse(@view m[1:3, :]) + + # greater nesting + @test issparse(Symmetric(UpperTriangular(m))) + @test issparse(Symmetric(UpperTriangular(Array(m)))) == false end @testset "issparse for sparse vectors #34253" begin From 2688a06535909f2272bb41a4c4c29d835eb525d6 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 14 May 2021 01:28:37 +0900 Subject: [PATCH 340/439] inference: minor refactor for compiler/reflection code (#40745) --- base/compiler/abstractinterpretation.jl | 5 +---- base/compiler/typeinfer.jl | 3 +-- base/compiler/typelattice.jl | 13 +++++-------- base/reflection.jl | 6 +++--- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 5ea1d761f1b26..3a72f9c8a6a80 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -284,9 +284,6 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), return CallMeta(rettype, info) end -widenwrappedconditional(@nospecialize(typ)) = widenconditional(typ) -widenwrappedconditional(typ::LimitedAccuracy) = LimitedAccuracy(widenconditional(typ.typ), typ.causes) - function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype), edges::Vector{MethodInstance}, @@ -1128,7 +1125,7 @@ function abstract_invoke(interp::AbstractInterpreter, argtypes::Vector{Any}, sv: end method, valid_worlds = result update_valid_age!(sv, valid_worlds) - (ti, env) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector + (ti, env::SimpleVector) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector rt, edge = typeinf_edge(interp, method, ti, env, sv) edge !== nothing && add_backedge!(edge::MethodInstance, sv) return CallMeta(rt, InvokeCallInfo(MethodMatch(ti, env, method, argtype <: method.sig))) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index a20ef946723a7..9087020ac6304 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -428,8 +428,7 @@ function finish(me::InferenceState, interp::AbstractInterpreter) # prepare to run optimization passes on fulltree s_edges = me.stmt_edges[1] if s_edges === nothing - s_edges = [] - me.stmt_edges[1] = s_edges + s_edges = me.stmt_edges[1] = [] end for edges in me.stmt_edges edges === nothing && continue diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index a4064a7fa3ca6..07a15aeb30a4b 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -313,6 +313,9 @@ function widenconditional(typ::AnyConditional) end widenconditional(t::LimitedAccuracy) = error("unhandled LimitedAccuracy") +widenwrappedconditional(@nospecialize(typ)) = widenconditional(typ) +widenwrappedconditional(typ::LimitedAccuracy) = LimitedAccuracy(widenconditional(typ.typ), typ.causes) + ignorelimited(@nospecialize typ) = typ ignorelimited(typ::LimitedAccuracy) = typ.typ @@ -329,10 +332,7 @@ function stupdate!(state::Nothing, changes::StateUpdate) if isa(newtype, VarState) newtypetyp = ignorelimited(newtype.typ) if isa(newtypetyp, Conditional) && slot_id(newtypetyp.var) == changeid - newtypetyp = widenconditional(newtypetyp) - if newtype.typ isa LimitedAccuracy - newtypetyp = LimitedAccuracy(newtypetyp, newtype.typ.causes) - end + newtypetyp = widenwrappedconditional(newtype.typ) newst[i] = VarState(newtypetyp, newtype.undef) end end @@ -360,10 +360,7 @@ function stupdate!(state::VarTable, changes::StateUpdate) if !changes.conditional && isa(newtype, VarState) newtypetyp = ignorelimited(newtype.typ) if isa(newtypetyp, Conditional) && slot_id(newtypetyp.var) == changeid - newtypetyp = widenconditional(newtypetyp) - if newtype.typ isa LimitedAccuracy - newtypetyp = LimitedAccuracy(newtypetyp, newtype.typ.causes) - end + newtypetyp = widenwrappedconditional(newtype.typ) newtype = VarState(newtypetyp, newtype.undef) end end diff --git a/base/reflection.jl b/base/reflection.jl index f1ecab42ef9b7..8fe04defe1d3f 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -862,7 +862,7 @@ function code_lowered(@nospecialize(f), @nospecialize(t=Tuple); generated::Bool= throw(ArgumentError("'debuginfo' must be either :source or :none")) end return map(method_instances(f, t)) do m - if generated && isgenerated(m) + if generated && hasgenerator(m) if may_invoke_generator(m) return ccall(:jl_code_for_staged, Any, (Any,), m)::CodeInfo else @@ -877,8 +877,8 @@ function code_lowered(@nospecialize(f), @nospecialize(t=Tuple); generated::Bool= end end -isgenerated(m::Method) = isdefined(m, :generator) -isgenerated(m::Core.MethodInstance) = isgenerated(m.def) +hasgenerator(m::Method) = isdefined(m, :generator) +hasgenerator(m::Core.MethodInstance) = hasgenerator(m.def::Method) # low-level method lookup functions used by the compiler From 5d84bc01e52dc2c1efa775c2211495612da5d293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Thu, 13 May 2021 17:29:27 +0100 Subject: [PATCH 341/439] [CompilerSupportLibraries] Bump to v0.4.3 (#40807) There is one notable change in this version: now _all_ compiler libraries are the latest available, instead of only libstdc++. So for example for libgfortran5 we get libraries from GCC 10.2 at the moment. --- deps/checksums/compilersupportlibraries | 184 +++++++++--------- deps/checksums/csl | 0 .../CompilerSupportLibraries_jll/Project.toml | 2 +- 3 files changed, 93 insertions(+), 93 deletions(-) delete mode 100644 deps/checksums/csl diff --git a/deps/checksums/compilersupportlibraries b/deps/checksums/compilersupportlibraries index 87a5d98c832f4..deacc52a102a3 100644 --- a/deps/checksums/compilersupportlibraries +++ b/deps/checksums/compilersupportlibraries @@ -1,92 +1,92 @@ -CompilerSupportLibraries.v0.4.2+1.aarch64-apple-darwin-libgfortran5.tar.gz/md5/da6b125a14c8afc701510ef495ec48a4 -CompilerSupportLibraries.v0.4.2+1.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/607fe8dd0e18301c4ae39b3dc4a53a3f5e262ef5e1dca85c57bf621bba0458839abb4dc8a35468ba4f30e199a2430c79f74836649ee1de33d5017e33266ed531 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran3.tar.gz/md5/d99a6e58fa807d660d6c05ce9ed0302c -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/b2d23ed345f42a3f6704cc075b86bf9d0cd0e471b538337ddb6c696ac1f25fcb809f52a01beab807e44e5bb57a4b2c790931bb251d29795e74046a69149f3eba -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran4.tar.gz/md5/92d99e83e51b7d74a7c757897af218ac -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/1e0caa6ac57def1ea2fb15cdee2617227e9610ec285254c2882064fc876b35a1ec07ffaad469ad75e86141dfa45ffee63d130183f2b7ace331ff96917641d68f -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran5.tar.gz/md5/d850abc973fc99cc9d814e2a9d634b62 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/1150fec9b23e7d33963e3f48837fcbe3bc57ce75defb8820d40fe841a96b92bb2ae2f8bfd68a236bf2644e827d97770a3f82cfa847a2eee393fbca20ac7eb1e0 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran3.tar.gz/md5/4a46df38821119323610dc3a3de89991 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran3.tar.gz/sha512/4e6879736bd642fefe7b15e53130ecfad0555d06a7bc65c8f9f2b406853945b0683986e04da110b2bf936beb0ecc686ac7bc85248d121e2ebf8925973c62583f -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran4.tar.gz/md5/e2426e6e1bb801b49805f44f890b6769 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran4.tar.gz/sha512/b7cb4adf76d34543c468f42a84f421db7a3ddfa9ad6b677705b010e7cd14d44a454b6e91e2f748b8d7d862b32be17732d88c2c15d3d4c43be12f9a798cf17d63 -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran5.tar.gz/md5/89f6ca21d2208dfaa7137511dd5a3a4a -CompilerSupportLibraries.v0.4.2+1.aarch64-linux-musl-libgfortran5.tar.gz/sha512/7a4f861ffb066b1644ba18d86f744f6b9d546a35e89d4ee31d3515e164df313c17fc7894dbcd36fa29541cb85a0063cd405da84d5c00401c4047407568a746f2 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/3c6aa40c3103cf4421ce31da6436731a -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/d6df143490d601023fbd81b9eee671f22857d3a8da34cf4ddef7d81a75c65c5a28b8be957f0ecfa78da5ddc119b419a9a313fdb9f76ad15ceffd07d29d03f17e -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/0e61fe0790e4bef56def41808370285c -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/3a4b3d7e4f0fde8c5ca82145d0b5b534c852b9db3fa3414f5eafa8969636ecbe46623fc7047ef1832de4314c188513b6014ca22dabef39f94773e4e8525e9133 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/fd4de3c2926f16ba1ad522b6fbbd82aa -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/f4557719615d12034ca66c55521366c34f555bf69da87263c12e137f2778a17861cf980c3c2c51bbb07cc7873a04aa14b4fc0b3452ddd7d84efbe51d74f68ff6 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/abe8c779a1ee2eaf15a5f0e1a3435b88 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/50b9531bed2a137f06d1b8a08ce24404bd2e9c0438eeec1e6805dc1dfeb47e26193f6bd32e125e17a1f5390c44da08c75414029aac6b723b68d57ffee8f2d7e6 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/295ff16df4d4f1d95e4b34a7c15ea3aa -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/036a985fd449f37cd9c7e9977d13c176b039276b0a23867084582970d85aa6692fc33a7512b2ff77add180ca7ecca7fa99dfcd251fb57972967cfd7c1dac0c35 -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/cd4c4db7896d087bdccf17db917d654f -CompilerSupportLibraries.v0.4.2+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/eba18b632136f95dc17c07d9fdf926251cdc17d963993516e439ad6a65187f976a28c0fa53e2a6aad7158e817f6b262b6786d8a483a0a575aa8efc3019dfe1fe -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/53cf17a61872002baf4978f6ff2cf799 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/ed13268cdfce6c37c55637cdf534092ce9b0309e4f998627a65e37238c17c1c6fb031e74f10865b5355172a1624debf1cec1b6c6487ae1c9a6f29e06b98194e4 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/88cfbbae6d8d694e1174aad15e06fd9f -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/f4cd5d4e46cbcc28fab7ad853c03b3bc1c71bcb2cb7e295f183311e1bc4c3790ba8cb8cc50c3ba8751ffde92e7d23d66a119b62cf110ae3ee2f59c162dc09de8 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/a97498d00965c13d69ae9b0ef6af6e92 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/fa6b0a05b507ffbb67f2b247512b38523f9454c12755a26b18f80d5868e3a09f139943dde08e1c658fc6ad63986713281cc523ab677fffe1d48c0af9121c8cf0 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/9b7f2c17daff254f4492ed6c94af2de7 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/e42789807f2a17783fcfdfe08c80939f233db696ec03c6fe2f73ed113257bc2977cac84c5b731c6e4f18c52bafe0b85348a99720dd2815e5697903ab4f16d968 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/5df4ba6a775a231d3067dc5126222b9b -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/a89af0d35943e79b7588ca4794384680939182d413997dfe5642a672efb13622560a5c36a0eeafee1dbab3eebfa69a5dadaa2e93370bc14a9767f9b4abb0584f -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/342270a5bb44984aea91e857ce7b4379 -CompilerSupportLibraries.v0.4.2+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/14a60f0173bb10215463fd9a88f310bcd0a9c5d411fd72d5aa3ff0bf6c6ecc9590e0e51471088d907e0f22291920cff570f2b2da5e64f790ff1d1ff4824ae935 -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran3.tar.gz/md5/6f71074bfbaea42e65b8d54a03485f7d -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran3.tar.gz/sha512/33dd5656ca6bc78c2c151e593c3fc63b2962d4776f0f3bd18de988931dc386caa3e3c248ca913fcb249d938423fc32a7f7364ab21b936674a772b264f8c4eee7 -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran4.tar.gz/md5/a0d6b7c929cad48710f431458e9fd906 -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran4.tar.gz/sha512/0ac88f8f9158822f41761cd59e406d9d978d6b6e6858dc7e3b57484200dca5b2f8cca7dd2521e0ea1ebf3f781b04f31848fc124a96eea0e7f37f59d03732bade -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran5.tar.gz/md5/980fac5e2db2401e5a83d3e09bdcf90b -CompilerSupportLibraries.v0.4.2+1.i686-linux-gnu-libgfortran5.tar.gz/sha512/b7ffa357ac8deb9c1458526473e1878e9668ad7ae0ce984b0fa3c42acddda126cb7c1e0d3a1bf84e845f94daa9432d8fe989d51617ce9fb8e66e13e59022e27a -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran3.tar.gz/md5/4076ddcfa6c2f23c301666e26f36174a -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran3.tar.gz/sha512/18cdb52d8e99bfd7f81700dee3c7a1752d4cc097ee00c640cd378fe6621c32b4bad9da81e159432079525c54370518feacf74e9338ee32af4bc04908b7664585 -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran4.tar.gz/md5/df0d1c7c9cae6416d4eb55af9af2dd1f -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran4.tar.gz/sha512/6cf9bb0318270448074abc4edb0a373ea4ab17a4e363006f70477e4a9e3f847608344fa23ed9205adafa0c754daccd5d4c4b7628322351727900f12835b7e619 -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran5.tar.gz/md5/6451c7b007ee4914fa96e152132dd6e5 -CompilerSupportLibraries.v0.4.2+1.i686-linux-musl-libgfortran5.tar.gz/sha512/ce15a66f47704cc1a7e002b89c74580a2cf6e7ed391ac0bcb56e6a913c6abdfd1f2e61721fe25c871fd7543a3a466f030647c8867786c53f39fdc14c17f398a5 -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran3.tar.gz/md5/0db39343cff6f5a3e62535f914937c8e -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran3.tar.gz/sha512/5499161fb358af90fe0287226ef1e11a72b64d412f5c89e38da2c367270bef520d0ea0622c37088a4a729093a5b6601a808f54dfdc6f64b6f24c3c1e05f81297 -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran4.tar.gz/md5/4ce35cb3838e32862d21a528b3850279 -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran4.tar.gz/sha512/601b569aa569dc68f7e4a4509ae233bd88b461da373e127b459768f6c22100b7cb5905c0025a3d32919854ac02b9d3073952bc1d68a1dd1b973978682cb70c52 -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran5.tar.gz/md5/e8d6ff85569ce872142e55d6fff97309 -CompilerSupportLibraries.v0.4.2+1.i686-w64-mingw32-libgfortran5.tar.gz/sha512/894c4fc5e57bcd59958b536566ba04b27204fe31c854e7d8f82fd7b59eda84792d86379e1f994f6574c8120bf85c6608f69083c660180064ba1148928914e6ae -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/b9ba022254d0945179b89fe214897312 -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/e141b870f3fd2bb69a2a5227aad3987a32caaa2280e3d59e70e3a1498a0e71eb30f454aaa1c2a5df0d72f18876ec8a336494707d04fa817eec3a8dc8f5dedf9f -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/352054f4b9be20ae4e7bb8f41e3ea547 -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/7fab7e059ff57e1c76a919cf52dd6849850d918f8859208658f6b85bbbcef04567a576b4d824264d0743895391e1bb3a33c385cc196bb98081699a6b0c5e3420 -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/c28cf8dddf0208fdb7bf981f3539413a -CompilerSupportLibraries.v0.4.2+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/dbf6ffbbab2569dee117ed8d249c510fba31d0738dea173e7fa146f56a0a8602112467cbac3f83aef1743737aa63bc2f2ab40b9393dbe0a2efbe6a031c152a97 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran3.tar.gz/md5/3a3b0b2d283ed9bc502c58c07a9c7ad3 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/072e743b89a8609d0651b9d1ed2880d7a804bd1c6a13e5ac3d23e0212e721adceb764678a22af715e5f35a74434bdfdbb87c9370c282f3f8193a0bd354a03d91 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran4.tar.gz/md5/1531545b7c2234be3e6c24a9e3dc7fd5 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/51c3892be0adbea098daf66ee3afff6da2172f65af63cce24bf968c8e237409b0ad3a3ca89abce5c4b27ec96d89f347b45f4fb26f50d84e23835da3963ab1d86 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran5.tar.gz/md5/3529a60ccc713a9a825fad7d2f3d07e8 -CompilerSupportLibraries.v0.4.2+1.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/6e5fae2d39569634d7b9d583d6a8d785e5689a65e30adb0ecded87a3235586dc4fe210e76153e26e9ef2a583183834a312e84991134949000516a2accb3dee4c -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran3.tar.gz/md5/ea74cd089e94203a6ef33754388c786a -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/30a72e2a50ff152ceb4e9764c60bcc5113845a918eb69a08b8a70e54e9df6b7923f697f39c2e576c553108dfff2cc14a27078c698cc325fc69736ebd67d403ab -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran4.tar.gz/md5/68075a244cb9f2c055a4b7b2ec6fab27 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/b49c77dfd2bf54587023eadc8cb64e2600fa826c99fb49c74325f1a631b2edf845870715bbd7a8bd4fe94233c78df632f9a8e433650c9a168c8fbc4894b6532a -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran5.tar.gz/md5/b2751b7c72c0ba52d8a252e2d1f01dd1 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/454fc2ab7bb604e2a424507ff35f213414f286382963e0dd29443c0bf21772a9a5923bd81c77317977ca0cec826ee46408b079aedad8ade87db3f35353125c20 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran3.tar.gz/md5/e691c3d13d5cd7265bbc830a28adaf14 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran3.tar.gz/sha512/62d5e3928bcc00e2741705403d39c96236b7e578b63256f67b5e36d9a60c960007c18c499e33487559e1b677b01445af0541a1ac6236bc724809aa757eb55f61 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran4.tar.gz/md5/0a1a41e1591bcb654a60fee50c041236 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran4.tar.gz/sha512/ef4ce20e72418e72293b5a6836b90dac4a8975c50db4204eef6e6c6660588a8c5769998462f758232c54ba4067ca4d0a1172bee3460f92cb41bb75a75d76f96d -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran5.tar.gz/md5/2ceecbfa72398c12532403fbf731f108 -CompilerSupportLibraries.v0.4.2+1.x86_64-linux-musl-libgfortran5.tar.gz/sha512/ff15be3083eb86159cbc5df969305e7990fa2f22f86f73a090db6ff25ab1671288ac37d8b54ae95acaca0f281dfda48de702c87cd0126114626a954f7b0516a2 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/49dcf29be7810799c2d36e1f89e97ca7 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/daf2fc70f8bace0b83b0317ada7444b6ef6188105fee403f76ddb043f2aee4c1f4bc04787d6a920abd583eaf32a078dcf680cae09e6f751b43a64567af4e7672 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/b446db483a6aa734c0dffe1f7f1f5c65 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/d707d5af3c5407ae47d1d55745259855ba899dfbebf71e528fcade4830fbdbf0e8d215c41c745594b9db3dc1bc846e46222571dcf8eea8639a6037510e3bef06 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/2ae1eac30f638c88eef1fc6621740069 -CompilerSupportLibraries.v0.4.2+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/c6585232b6adadc5b78c870f516a3ed1381b421fa58735b74e096afc69b6d08a169bd06662eeac70f63a52ea6b9f1f94d96aa86eee8b026419a59a231317637b -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/1cffa4d37629e62c17ae78f88b3ba3ed -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/164aff25e92fab85a4df4ae43b0dcc628e4e8ff0afe59721a98ab9dfff01edbaf93370d8c3079f4c9cbbb3ffdd9050f85a53cd336f9947f19cf4a3b3ff8b4394 -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/0511722afd53392fcafe72932b7d1bc9 -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/4edc52b6e15f19896019e0227b3c95c73b50cc16544c70d7506e05b1a20ba2a694ae8cfb460df453d062939bef3b09693d209922247a585c48043f269c40e8d7 -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/42fe08fa435e5e0bc71bd3135fa23d6e -CompilerSupportLibraries.v0.4.2+1.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/051c20c7f6c7c6f22fb467786b031c43c53ff17d67a87d82e2f0c01c7623a1787afa3bc46eb347cc2eecee199953976b6f7119f371ba8d05d1a8d4e11161cdae +CompilerSupportLibraries.v0.4.3+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/36348c1087386681380589f7fdbd383a +CompilerSupportLibraries.v0.4.3+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/e3dd3c93a855a85f02190659fdc9f41e96332b74577c67a149f78c35ebc2bb193bb4c156104d4bf24ca278f5b8621e944807a554153721bb5d0f22b8e9069fc1 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/b9d432c6639d30f1c63e9a234c1f10b7 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/f208fb24fb34e82a60fc37ae3acfca6a1cac7201b8b8daf29c3ac98e607d9eb94a51fe92c54fde287359a7398b4646e8df98bf359f7acd1eacf25b1b5ea16456 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/37ccf8848bdee5445d002b889e54bca5 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/0b29ef79bf8b238d9778d72f0e404145536933d9f9185f2cc1e917b3ec7cb8cfaa33ff664837e9e8e6ec28a3612ebd9cb226c0938954594849b4267514b27be3 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/bde8da82e00ed6375716bbcba6b04c3b +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/7d50d91d4b6430154ae037fe54eb8b321e57c4ef1f7740ce0633416d8e39e133d3049a36481fba8ea689fdbf8ee8750c99578f7ef287736476bd39e5b05793e9 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/b58108feab2a1d546fc2c3184233da69 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/4079e9a5548426863bf610a1287f4e0c41fb701af95be66db12a805686cc89b6d3baf9ab203dd6ac7429bff8d1352bcd80dde7adf22bfae20688fd8a17dfe457 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/00ab7379109240a211f492dbae4d31c8 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/d2d5e7165566fcaf38f97fedd78cb7c6df475a01dec262643c79a0d310ebde4b64f670ad92104ae5e7bb8b1004d211c8f7d2bd4df05b87ddd188db62b11325c4 +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/ee7881127866d50c9d1fc76ef0ac50be +CompilerSupportLibraries.v0.4.3+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/8f622cbac6777cf14d98a6cfcea38d42296f9f93b7202eee501c9fcf02f112ca2833dc9c034beb0b79aacc85bef9d57a26ee672716ca50b8353e3d17da298ecb +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/fe4c403eedb9dca880961501834bdc8f +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/de829db62f7e28b425ac04d883db62e45f346e2e115d364a6f9ace29681a73422109bab7239014b51e6174cbd6141902ee65868a5cd2c6836d2db43b07c7ec3f +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/670dbd3088ccb46830d80edd4c64143e +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/43a419548597d2624c68504c405da1104007b80f49189dddef5f2abb0a7cbe404af80172d69d7b8b2dea516fa4bf429a73068de2959266f1bc796868ac926682 +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/00a9ea852c32c503e405389cb322827b +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/741c34b253f4c785b1092333d9060aea71b73879bed96da0f964dda1d1367032f133abde335cc7917c2e04c8cae4c3e110a249518d5305d8a4752cdea7d3aada +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/7b4528e842d27c849b6bc0443255f974 +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/8dc362faaded886ca1bf7c48f43847cdc4f6685e29b0468809d254ff44121061c49d962a33e37acde9ab00b258636a77213ded1f8570ad2543dfb0097f3a7cc7 +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/a8d66ecf146c17a5af2f7a6c4c75dc9c +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/4fc7590050d18a3cff6cad29bdaed3ae1aad72a7bed3e69a14b726309cdd5631ba903998ae042a488c815f9668567cbbb2e779eb44c13fca1aee47f93bbaaad0 +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/4405f621357e9bc3178ceb24337385b6 +CompilerSupportLibraries.v0.4.3+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/0c8eeda7d94c551e90cefc6ef5c41fa1d79776abd87f1e739e17b8507ae966c0a6aed10bf466f37c34e29e38fe5bd25d542829e25269adf971c0e8a9d640dfb0 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/2a37fb150af0438cbe768e8c479ff893 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/d0f577f4bfa76c349f188e4573644a82a749f9e5c3293246de0347fda866c9a1610fe9f3383ef54ac1bcee774f2a557aa1c67cbfe76580313cd5f9a231df05fd +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/f7bc21abc374654421385f27d653f3e6 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/fe55de45a99817cbd7a4ac69b87744acd9804d159b9b9144ce24d401742c87b9621a388614da32dac00f6b5e78037cef88d37c2b14308b6c94f951aacb176e94 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/022cb4d36156bf257fc57a50124cdfcd +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/f12af33831b91fff66e5ab2964aa4fe520e3063e148a794d9840ed4f526e6741555350e5d6dffe7857c733d2f405e1db81949d1e24a42425c521b1dd71539ec3 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/b99d07c03c91c9d2186999bc924eb4d3 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/6ded3253561e5fa0c93712a2a86efbc5b1bbdca26f2170876e855400978674910c43dba6dfe992537ce90db66e40b618a7fdc3753abae67940ac46175bbbf9b7 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/c1d701eee76fd974ece928cb3e1a85f2 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/ad338863ddbe47ec579636dc6ce155b47b701b9d47c8f0bca93918af18e8df6da6ddf65a2e2042fb79b335d1df07549addb2e794cf1e8f41d6fb518259a6dcd9 +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/0fa43aa26c3f5a717945659ad00ad96a +CompilerSupportLibraries.v0.4.3+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/387a676e4e79a5f783c3797dab0ab4a9ba3b469b66d008bbe3262751e94316b0f7ae6987db212f763be47e9cb5202b1a6740b3f419818b30c2f1251bf0b305fa +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran3.tar.gz/md5/e8360ca87e6f9d7e512d20fd0669ea70 +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/6441bfbd93ae4edad1cc1e7d8adedeff85bc7749bf68b802f4316117e81938fdec35620264627fca367ff2182b503dd97235f7871dc79e70cdb0b86712d570e8 +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran4.tar.gz/md5/088a85ce5999f373ead5f43e7bece97a +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/c3d75384c93afabb2eff3f84a13df8b7ecf535e8f786c5fcea78ee1902fb052854acbfdf9fda5d558ca19f285883836e6827acdb042a9d50ca65d5d0823e44e5 +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran5.tar.gz/md5/97ddfc865ec5218c7d2d092f65de71b1 +CompilerSupportLibraries.v0.4.3+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/2328f3fd706078125badd6294159d860b2349203b85d77f2ecae914f3a41a99951021ab1124a40c358ea82352f6778a87f8094b039679356965fc4c8bb48beb4 +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran3.tar.gz/md5/479a7a80865c38795cc4454dacebead6 +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran3.tar.gz/sha512/cb4c79f6e5e9129b3d99f3f0ac17f395d696b9f354df966faebc27f6ea120a8592548a59e5f7a7ad124583d23c93d621f00069a4af07a4b41a4a1f474bded4e0 +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran4.tar.gz/md5/03e4d7d3189be081e4b56cdfcd439b5f +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran4.tar.gz/sha512/6c3f3b9fcad535a5e071853540b4b8689cde976a375b9406c93734e37d412f86069c8133ef85898efedd3b8fab0477d51f9ae681dabb00a66ec3f213e042bf82 +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran5.tar.gz/md5/6b20e61bf6eef2bd8587d93bcbdf8ac2 +CompilerSupportLibraries.v0.4.3+0.i686-linux-musl-libgfortran5.tar.gz/sha512/2f7b0c63773f7c5e8bad43041ec30e727dffb665f4371c7ec5619648644c9ecc085674a15f0df20e5399d25d84bc8e49ce0cd29a5a438e7a828000395e0928eb +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/185a1f5582eede2e71bc6664294fe368 +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/cc54dc1e1fe10374fd62d7e3a6159024dbb9638b90014e9cf6168ed63ee1b64f7a52f8c851315a340e5327513dfe939b3b04035631cdb251ec2232f8ba381d8a +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/ec4d496e9c5f3e806d78c30bb92f4324 +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/4917f4755c3ccf223491d75baf729677d51abae00a66f7a66439b45169283aa86070bb314ae9256525de4b422b7213de9d087d0dba9a821caa71ec346f1138ed +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/4080d550f9a31d084c59195a98b6ed7b +CompilerSupportLibraries.v0.4.3+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/6048b61a476905469e46c4e15a7067f0f39451c7374e981212cc9d2a66bdcbd7f0503d9eef731bfbe10b174d76937d7fa349f079a652587fecdfb2c6d59a1a1e +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/30bd967c069fbc73dc653f2ac9d55b6c +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/e16e77c72e3dd3399240bfcd72123da4540016eb91f10bd6015f0e6e58b397677b685c143527f5827423e7abb15abf5e461e3b74fccdb07dfdece2f0cb361912 +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/073a8be233fae3c6b453684de7e51ea7 +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/3fda4c515131c75181c662fa4d5fd538a0c8e257673edca7f94c46509c641d4720c130cffa37512bea0a215b6a9952735acbe359fb38e8e341822545021d88dc +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/4853c451821303959723f541434a7d1c +CompilerSupportLibraries.v0.4.3+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/539a6b7626883d54b7661db6fcad1b7390ce37ab406a88065b8c24786353725f8cd972cbc29d07e71c9fefcb126239c8a63583626a0b8298c04b34de47bb9248 +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/889855efa0450aa975166803fa775686 +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/8162aebac8f13264cebdbc8359f4823f25cd28c76812df8687b5801b6e133206b514cbad5d5ff0d6fbb584eecd82038049c5a965637b43a5d12f77ad386addc8 +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/ed9f7aee0565904a8cbd5cc26df37a9d +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/e93bd2a9e4e2c358f46f756f15d9765ef5aef44e5ee2adbfb23e971f380052f4ad5e4569fc5932b6250a40e204253e70966a6554c30c0251f1d5406babdac837 +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/6757ed75b520bfd1f6edf55f01f7d1af +CompilerSupportLibraries.v0.4.3+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/5f50c9df89ebd5a8b2c6a97e99b8340b0e63e4f689e3062a32474fdd6dd33f160647ae1a2ba96a30abac1bfbbd730be9824dcf4b05a4c327c0ad60c9b96f889f +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/954ffb60eb3cba5d7d02d3cf31fc3c75 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/199738c5e226565230368e38183de6af66ac1decc880cb28e072aeba097b8c060a6ee51d755072d66fe955a6621d183f28de364f7d57f372c8ad7585e30cded9 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/02c5342c240220803dea5edaa6aa03c0 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/c752b742d7aa39b7ac2297c8f4bae066c6c8217cb717cb7f913aa045b402350325e8ac96b0656404e39a891c825c57e18e5dc9325a954c7e64d98ece776293cd +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/5b2ca9ee08026e2ab9d24d18bb631ede +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/f98aed5aec767e1145b4f19515c99927e30790f577494e6d439c7f1a24f7e8e2acb977945f616abeceb614776e329f1a1f852edc1ade9de78a0c94f619046e40 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/6e5a0d8521b560e79cb5d5caffa4c675 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/7079605d315f45ebbd2a517b2aad38b226b574ee3f892a20efe02b8336654c84139a810820734456fcf6bb5bcc8fdd9408e783d1dfa2aa25168ec3e9b3e57785 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/dde75524ca38581b671d21c7ccc12c6d +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/ae229ccbb704da44f911704ee0700fe3e01730c9a5e7519dbf41c9e1aaf6d3f594678055845430e9c9d9b3ea974d1437fe2d84ae89f2886512c4569b9659a5dd +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/1d13546f090e9e068540d5ca42f193f2 +CompilerSupportLibraries.v0.4.3+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/cd8a4a83a2f09f9b18baa719b0ed13e9eefbee765bce326854e29ca76075e18401b9052d70b13461f16b08219707237aba7e7857aec28d417bd5dddf4eea9dda +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/6987269d8385d6b5716f075ab51ad5a9 +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/0b5efa2c22c9be737a1396d10779fbbb91acd8662a6d419ba76d98b380b5c9cef977ac2d60e27c844d3c5f083fe4b59a6419675d09b8bd3e5b2fefc74ac09e0e +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/d430f7c46b66121833622ed58694368f +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/fc3c7bbf2c3730b68780950e4055491639d8874dc4b8509898722a4e7a06341cc43dbd7ed371e89f2a0cd11b515b0901a803f93349039b2c21aff6e453bca669 +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/557985cb8720a3995482e13c319678fc +CompilerSupportLibraries.v0.4.3+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/4d2b6b4431456e8067fd09b092617887277b4da3dc6e030d8091e7a9331c5fa73483f72626f6f06b3a749804b8060fc6ec8e592ecf87a3b1fcef96f5fc267c7d +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/aa27b022d98f489fb21c6d9a05b913a0 +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/13d0f7e243674034b1d41a7020db58df6932a9a3d9a9ba450e1b673f5e56ff984ab68af8a3bf5a14590bfa43661a20d88a781d67009e3af9f60c15bf32e56196 +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/7b381af909065da2da0e8eb035fffb47 +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/c35170eea5174360ebe795ccb79fe4d6c9dca288d8f751e731dcaaf26866172372b5919393a965e18ba1aa553b6f420ca8d8db32b8d38aebd226906e18b7a4d9 +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/8b4d1ee5add108fc05879fd0102cf34b +CompilerSupportLibraries.v0.4.3+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/23c7bd53523d8380491b97cd57083956b55273b8d6aebef2e1b5c80ce8593cfe3eab5ff50b6a417b974996673fdfb810ed2fc28798bba42ce59cfe6284b1ef8f diff --git a/deps/checksums/csl b/deps/checksums/csl deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/stdlib/CompilerSupportLibraries_jll/Project.toml b/stdlib/CompilerSupportLibraries_jll/Project.toml index 86a66afc17ed0..95366df955720 100644 --- a/stdlib/CompilerSupportLibraries_jll/Project.toml +++ b/stdlib/CompilerSupportLibraries_jll/Project.toml @@ -1,6 +1,6 @@ name = "CompilerSupportLibraries_jll" uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.4.2+1" +version = "0.4.3+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 7c63647e0c81e41cb4370d226eeaa930c23baa31 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 13 May 2021 21:16:22 +0200 Subject: [PATCH 342/439] Enable pasted lines to switch to pkg, shell and help repl modes (#40604) * allow pasted lines to switch to pkg, shell and help modes --- stdlib/REPL/src/REPL.jl | 101 ++++++++++++++++++++++++++++++--------- stdlib/REPL/test/repl.jl | 26 ++++++++++ 2 files changed, 104 insertions(+), 23 deletions(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index e777655806afa..e74834e0bd2c3 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -76,6 +76,9 @@ end answer_color(::AbstractREPL) = "" const JULIA_PROMPT = "julia> " +const PKG_PROMPT = "pkg> " +const SHELL_PROMPT = "shell> " +const HELP_PROMPT = "help?> " mutable struct REPLBackend "channel for AST" @@ -935,7 +938,7 @@ function setup_interface( on_enter = return_callback) # Setup help mode - help_mode = Prompt("help?> ", + help_mode = Prompt(HELP_PROMPT, prompt_prefix = hascolor ? repl.help_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", @@ -947,7 +950,7 @@ function setup_interface( # Set up shell mode - shell_mode = Prompt("shell> "; + shell_mode = Prompt(SHELL_PROMPT; prompt_prefix = hascolor ? repl.shell_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", @@ -1001,6 +1004,12 @@ function setup_interface( search_prompt, skeymap = LineEdit.setup_search_keymap(hp) search_prompt.complete = LatexCompletions() + jl_prompt_len = length(JULIA_PROMPT) + pkg_prompt_len = length(PKG_PROMPT) + shell_prompt_len = length(SHELL_PROMPT) + help_prompt_len = length(HELP_PROMPT) + pkg_prompt_regex = r"^(?:\(.+\) )?pkg>" + # Canonicalize user keymap input if isa(extra_repl_keymap, Dict) extra_repl_keymap = AnyDict[extra_repl_keymap] @@ -1053,12 +1062,15 @@ function setup_interface( oldpos = firstindex(input) firstline = true isprompt_paste = false - jl_prompt_len = 7 # "julia> " + curr_prompt_len = 0 + pasting_help = false + while oldpos <= lastindex(input) # loop until all lines have been executed if JL_PROMPT_PASTE[] - # Check if the next statement starts with "julia> ", in that case - # skip it. But first skip whitespace - while input[oldpos] in ('\n', ' ', '\t') + # Check if the next statement starts with a prompt i.e. "julia> ", in that case + # skip it. But first skip whitespace unless pasting in a docstring which may have + # indented prompt examples that we don't want to execute + while input[oldpos] in (pasting_help ? ('\n') : ('\n', ' ', '\t')) oldpos = nextind(input, oldpos) oldpos >= sizeof(input) && return end @@ -1066,7 +1078,32 @@ function setup_interface( if (firstline || isprompt_paste) && startswith(SubString(input, oldpos), JULIA_PROMPT) isprompt_paste = true oldpos += jl_prompt_len - # If we are prompt pasting and current statement does not begin with julia> , skip to next line + curr_prompt_len = jl_prompt_len + transition(s, julia_prompt) + pasting_help = false + # Check if input line starts with "pkg> " or "(...) pkg> ", remove it if we are in prompt paste mode and switch mode + elseif (firstline || isprompt_paste) && startswith(SubString(input, oldpos), pkg_prompt_regex) + detected_pkg_prompt = match(pkg_prompt_regex, SubString(input, oldpos)).match + isprompt_paste = true + curr_prompt_len = length(detected_pkg_prompt) + oldpos += curr_prompt_len + Base.active_repl.interface.modes[1].keymap_dict[']'](s, o...) + pasting_help = false + # Check if input line starts with "shell> ", remove it if we are in prompt paste mode and switch mode + elseif (firstline || isprompt_paste) && startswith(SubString(input, oldpos), SHELL_PROMPT) + isprompt_paste = true + oldpos += shell_prompt_len + curr_prompt_len = shell_prompt_len + transition(s, shell_mode) + pasting_help = false + # Check if input line starts with "help?> ", remove it if we are in prompt paste mode and switch mode + elseif (firstline || isprompt_paste) && startswith(SubString(input, oldpos), HELP_PROMPT) + isprompt_paste = true + oldpos += help_prompt_len + curr_prompt_len = help_prompt_len + transition(s, help_mode) + pasting_help = true + # If we are prompt pasting and current statement does not begin with a mode prefix, skip to next line elseif isprompt_paste while input[oldpos] != '\n' oldpos = nextind(input, oldpos) @@ -1075,29 +1112,47 @@ function setup_interface( continue end end - ast, pos = Meta.parse(input, oldpos, raise=false, depwarn=false) - if (isa(ast, Expr) && (ast.head === :error || ast.head === :incomplete)) || - (pos > ncodeunits(input) && !endswith(input, '\n')) - # remaining text is incomplete (an error, or parser ran to the end but didn't stop with a newline): - # Insert all the remaining text as one line (might be empty) - tail = input[oldpos:end] - if !firstline - # strip leading whitespace, but only if it was the result of executing something - # (avoids modifying the user's current leading wip line) - tail = lstrip(tail) + if s.current_mode == julia_prompt + ast, pos = Meta.parse(input, oldpos, raise=false, depwarn=false) + if (isa(ast, Expr) && (ast.head === :error || ast.head === :incomplete)) || + (pos > ncodeunits(input) && !endswith(input, '\n')) + # remaining text is incomplete (an error, or parser ran to the end but didn't stop with a newline): + # Insert all the remaining text as one line (might be empty) + tail = input[oldpos:end] + if !firstline + # strip leading whitespace, but only if it was the result of executing something + # (avoids modifying the user's current leading wip line) + tail = lstrip(tail) + end + if isprompt_paste # remove indentation spaces corresponding to the prompt + tail = replace(tail, r"^"m * ' '^curr_prompt_len => "") + end + LineEdit.replace_line(s, tail, true) + LineEdit.refresh_line(s) + break end - if isprompt_paste # remove indentation spaces corresponding to the prompt - tail = replace(tail, r"^"m * ' '^jl_prompt_len => "") + elseif s.current_mode == shell_mode # handle multiline shell commands + lines = split(input[oldpos:end], '\n') + pos = oldpos + sizeof(lines[1]) + 1 + if length(lines) > 1 + for line in lines[2:end] + # to be recognized as a multiline shell command, the lines must be indented to the + # same prompt position + if !startswith(line, ' '^curr_prompt_len) + break + end + pos += sizeof(line) + 1 + end end - LineEdit.replace_line(s, tail, true) - LineEdit.refresh_line(s) - break + else + nl_pos = findfirst('\n', input[oldpos:end]) + pos = isnothing(nl_pos) ? oldpos : oldpos + nl_pos end # get the line and strip leading and trailing whitespace line = strip(input[oldpos:prevind(input, pos)]) if !isempty(line) if isprompt_paste # remove indentation spaces corresponding to the prompt - line = replace(line, r"^"m * ' '^jl_prompt_len => "") + line = replace(line, r"^"m * ' '^curr_prompt_len => "") end # put the line on the screen and history LineEdit.replace_line(s, line) diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 9b72b8db7b1c5..34011569659af 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -750,6 +750,32 @@ fake_repl() do stdin_write, stdout_read, repl readuntil(stdout_read, "begin") @test readuntil(stdout_read, "end", keep=true) == "\n\r\e[7C α=1\n\r\e[7C β=2\n\r\e[7Cend" + # Test switching repl modes + sendrepl2("""\e[200~ + julia> A = 1 + 1 + + shell> echo foo + foo + + shell> echo foo + foo + foo foo + + help?> Int + Dummy docstring + + Some text + + julia> error("If this error throws, the paste handler has failed to ignore this docstring example") + + julia> B = 2 + 2\e[201~ + """) + wait(c) + @test Main.A == 1 + @test Main.B == 2 + # Close repl write(stdin_write, '\x04') Base.wait(repltask) From 2f400e098ec395c4507849f0e1d8489761590da9 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Thu, 13 May 2021 22:28:22 +0000 Subject: [PATCH 343/439] [automated] Bump the Pkg stdlib from 1a47f445 to edfe2943 (#40817) Co-authored-by: Dilum Aluthge --- .../Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 | 1 - .../Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 | 1 - .../Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 | 1 + .../Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 create mode 100644 deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 diff --git a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 deleted file mode 100644 index 063360a77aea1..0000000000000 --- a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e5cb2763c4abd84522a0706584d2a733 diff --git a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 b/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 deleted file mode 100644 index 06705d8278f46..0000000000000 --- a/deps/checksums/Pkg-1a47f445f92053edc83a9528ed849ca404b4a2af.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e3007f929abdbfa574b72dad24e0ab954fb7469bcfb0786545e109c1122bff65b1d41065c289ae18d8a50130ae09c0700101d4e83d1c023deb5c759eb4f2484d diff --git a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 new file mode 100644 index 0000000000000..c704b9f08d0b1 --- /dev/null +++ b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 @@ -0,0 +1 @@ +65ec1044bb9815844f239b7e2b3d2e7a diff --git a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 new file mode 100644 index 0000000000000..bfa5cd447f375 --- /dev/null +++ b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 @@ -0,0 +1 @@ +65209c1461075cc58098650abdef5814295490693f4cf11fda957e7f1304d99fc76e7ab38a9a5c041503c7acdeb512ff405fb804b589536d3fcc24fd8379b48e diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index b0804498895f2..1c8f4efa425b8 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 1a47f445f92053edc83a9528ed849ca404b4a2af +PKG_SHA1 = edfe2943a7867ea6b1292877a94131ac2a29b848 From a0241b9226f549acfc15ed0a1430c37385d60a8f Mon Sep 17 00:00:00 2001 From: bramtayl Date: Thu, 13 May 2021 19:27:21 -0400 Subject: [PATCH 344/439] missing at-static test (#40818) --- test/osutils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/osutils.jl b/test/osutils.jl index c9e3b9d91a377..5f597292c5cc9 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -44,6 +44,7 @@ end @test (@static if false 1 elseif false 2 else 3 end) === 3 @test (@static if false 1 elseif false 2 elseif true && false 3 else 4 end) === 4 @test (@static if false 1 elseif false 2 elseif true && false 3 end) === nothing + @test_throws ArgumentError("invalid @static macro") @macroexpand @static 1 end if Sys.iswindows() From be6887fa9ffa3d08315c93f1551c41b44dd3d720 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 14 May 2021 05:46:23 +0200 Subject: [PATCH 345/439] Handle pastes for other repl modes that don't end in newlines (#40819) --- stdlib/REPL/src/REPL.jl | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index e74834e0bd2c3..2289bc65b368e 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1008,7 +1008,7 @@ function setup_interface( pkg_prompt_len = length(PKG_PROMPT) shell_prompt_len = length(SHELL_PROMPT) help_prompt_len = length(HELP_PROMPT) - pkg_prompt_regex = r"^(?:\(.+\) )?pkg>" + pkg_prompt_regex = r"^(?:\(.+\) )?pkg> " # Canonicalize user keymap input if isa(extra_repl_keymap, Dict) @@ -1085,7 +1085,7 @@ function setup_interface( elseif (firstline || isprompt_paste) && startswith(SubString(input, oldpos), pkg_prompt_regex) detected_pkg_prompt = match(pkg_prompt_regex, SubString(input, oldpos)).match isprompt_paste = true - curr_prompt_len = length(detected_pkg_prompt) + curr_prompt_len = sizeof(detected_pkg_prompt) oldpos += curr_prompt_len Base.active_repl.interface.modes[1].keymap_dict[']'](s, o...) pasting_help = false @@ -1112,25 +1112,18 @@ function setup_interface( continue end end + dump_tail = false + nl_pos = findfirst('\n', input[oldpos:end]) if s.current_mode == julia_prompt ast, pos = Meta.parse(input, oldpos, raise=false, depwarn=false) if (isa(ast, Expr) && (ast.head === :error || ast.head === :incomplete)) || (pos > ncodeunits(input) && !endswith(input, '\n')) # remaining text is incomplete (an error, or parser ran to the end but didn't stop with a newline): # Insert all the remaining text as one line (might be empty) - tail = input[oldpos:end] - if !firstline - # strip leading whitespace, but only if it was the result of executing something - # (avoids modifying the user's current leading wip line) - tail = lstrip(tail) - end - if isprompt_paste # remove indentation spaces corresponding to the prompt - tail = replace(tail, r"^"m * ' '^curr_prompt_len => "") - end - LineEdit.replace_line(s, tail, true) - LineEdit.refresh_line(s) - break + dump_tail = true end + elseif isnothing(nl_pos) # no newline at end, so just dump the tail into the prompt and don't execute + dump_tail = true elseif s.current_mode == shell_mode # handle multiline shell commands lines = split(input[oldpos:end], '\n') pos = oldpos + sizeof(lines[1]) + 1 @@ -1145,8 +1138,21 @@ function setup_interface( end end else - nl_pos = findfirst('\n', input[oldpos:end]) - pos = isnothing(nl_pos) ? oldpos : oldpos + nl_pos + pos = oldpos + nl_pos + end + if dump_tail + tail = input[oldpos:end] + if !firstline + # strip leading whitespace, but only if it was the result of executing something + # (avoids modifying the user's current leading wip line) + tail = lstrip(tail) + end + if isprompt_paste # remove indentation spaces corresponding to the prompt + tail = replace(tail, r"^"m * ' '^curr_prompt_len => "") + end + LineEdit.replace_line(s, tail, true) + LineEdit.refresh_line(s) + break end # get the line and strip leading and trailing whitespace line = strip(input[oldpos:prevind(input, pos)]) From d425ca85ccadc6eef3c5d991f9fea897864a0184 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 14 May 2021 11:51:39 +0200 Subject: [PATCH 346/439] move SuiteSparse to an external repository (#40770) --- .../md5 | 1 + .../sha512 | 1 + stdlib/.gitignore | 2 + stdlib/Makefile | 4 +- stdlib/SuiteSparse.version | 2 + stdlib/SuiteSparse/Project.toml | 19 - stdlib/SuiteSparse/docs/src/index.md | 34 - stdlib/SuiteSparse/src/SuiteSparse.jl | 31 - stdlib/SuiteSparse/src/cholmod.jl | 2026 ----------------- stdlib/SuiteSparse/src/cholmod_h.jl | 80 - stdlib/SuiteSparse/src/deprecated.jl | 1 - stdlib/SuiteSparse/src/spqr.jl | 416 ---- stdlib/SuiteSparse/src/umfpack.jl | 833 ------- stdlib/SuiteSparse/src/umfpack_h.jl | 43 - stdlib/SuiteSparse/test/cholmod.jl | 945 -------- stdlib/SuiteSparse/test/runtests.jl | 30 - stdlib/SuiteSparse/test/spqr.jl | 136 -- stdlib/SuiteSparse/test/threads.jl | 22 - stdlib/SuiteSparse/test/umfpack.jl | 249 -- 19 files changed, 9 insertions(+), 4866 deletions(-) create mode 100644 deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 create mode 100644 deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 create mode 100644 stdlib/SuiteSparse.version delete mode 100644 stdlib/SuiteSparse/Project.toml delete mode 100644 stdlib/SuiteSparse/docs/src/index.md delete mode 100644 stdlib/SuiteSparse/src/SuiteSparse.jl delete mode 100644 stdlib/SuiteSparse/src/cholmod.jl delete mode 100644 stdlib/SuiteSparse/src/cholmod_h.jl delete mode 100644 stdlib/SuiteSparse/src/deprecated.jl delete mode 100644 stdlib/SuiteSparse/src/spqr.jl delete mode 100644 stdlib/SuiteSparse/src/umfpack.jl delete mode 100644 stdlib/SuiteSparse/src/umfpack_h.jl delete mode 100644 stdlib/SuiteSparse/test/cholmod.jl delete mode 100644 stdlib/SuiteSparse/test/runtests.jl delete mode 100644 stdlib/SuiteSparse/test/spqr.jl delete mode 100644 stdlib/SuiteSparse/test/threads.jl delete mode 100644 stdlib/SuiteSparse/test/umfpack.jl diff --git a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 new file mode 100644 index 0000000000000..f7c002884f412 --- /dev/null +++ b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 @@ -0,0 +1 @@ +80b2f04e722a97261755e6d0a7ab83e5 diff --git a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 new file mode 100644 index 0000000000000..fd802a1117072 --- /dev/null +++ b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 @@ -0,0 +1 @@ +8547896fc8a1296f5efe1a9a05b7f7ebd5905d8e8a3d444b94e64e672565869eb540d7fba28ad6d6634e2a6b1220b7c1c67c61a5b0735de7ad37157bd841d1b9 diff --git a/stdlib/.gitignore b/stdlib/.gitignore index 59354288f912c..891eda58c689d 100644 --- a/stdlib/.gitignore +++ b/stdlib/.gitignore @@ -13,5 +13,7 @@ /Tar /NetworkOptions-* /NetworkOptions +/SuiteSparse-* +/SuiteSparse /*_jll/StdlibArtifacts.toml /*/Manifest.toml diff --git a/stdlib/Makefile b/stdlib/Makefile index 8ef2330f5a5ad..8dfa1e2f40fc3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -44,7 +44,7 @@ STDLIBS = Artifacts Base64 CRC32c Dates DelimitedFiles Distributed FileWatching SharedArrays Sockets SparseArrays SuiteSparse Test TOML Unicode UUIDs \ $(JLL_NAMES) -STDLIBS_EXT = Pkg Statistics LibCURL Downloads ArgTools Tar NetworkOptions +STDLIBS_EXT = Pkg Statistics LibCURL Downloads ArgTools Tar NetworkOptions SuiteSparse PKG_GIT_URL := git://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 STATISTICS_GIT_URL := git://github.com/JuliaLang/Statistics.jl.git @@ -59,6 +59,8 @@ TAR_GIT_URL := git://github.com/JuliaIO/Tar.jl.git TAR_TAR_URL = https://api.github.com/repos/JuliaIO/Tar.jl/tarball/$1 NETWORKOPTIONS_GIT_URL := git://github.com/JuliaLang/NetworkOptions.jl.git NETWORKOPTIONS_TAR_URL = https://api.github.com/repos/JuliaLang/NetworkOptions.jl/tarball/$1 +SUITESPARSE_GIT_URL := git://github.com/JuliaLang/SuiteSparse.jl.git +SUITESPARSE_TAR_URL = https://api.github.com/repos/JuliaLang/SuiteSparse.jl/tarball/$1 $(foreach module, $(STDLIBS_EXT), $(eval $(call stdlib-external,$(module),$(shell echo $(module) | tr a-z A-Z)))) diff --git a/stdlib/SuiteSparse.version b/stdlib/SuiteSparse.version new file mode 100644 index 0000000000000..1283d47e9ea52 --- /dev/null +++ b/stdlib/SuiteSparse.version @@ -0,0 +1,2 @@ +SUITESPARSE_BRANCH = master +SUITESPARSE_SHA1 = 9cfdbbd33d2d52b83b2459f670162244cc95460c diff --git a/stdlib/SuiteSparse/Project.toml b/stdlib/SuiteSparse/Project.toml deleted file mode 100644 index 0312b1625f7e3..0000000000000 --- a/stdlib/SuiteSparse/Project.toml +++ /dev/null @@ -1,19 +0,0 @@ -name = "SuiteSparse" -uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" - -[deps] -Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" -SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -SuiteSparse_jll = "bea87d4a-7f5b-5778-9afe-8cc45184846c" - -[extras] -DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Test", "Printf", "Random", "DelimitedFiles", "Serialization"] diff --git a/stdlib/SuiteSparse/docs/src/index.md b/stdlib/SuiteSparse/docs/src/index.md deleted file mode 100644 index e8654caf943b4..0000000000000 --- a/stdlib/SuiteSparse/docs/src/index.md +++ /dev/null @@ -1,34 +0,0 @@ -# Sparse Linear Algebra - -```@meta -DocTestSetup = :(using LinearAlgebra, SparseArrays, SuiteSparse) -``` - -Sparse matrix solvers call functions from [SuiteSparse](http://suitesparse.com). The following factorizations are available: - -| Type | Description | -|:--------------------------------- |:--------------------------------------------- | -| `SuiteSparse.CHOLMOD.Factor` | Cholesky factorization | -| `SuiteSparse.UMFPACK.UmfpackLU` | LU factorization | -| `SuiteSparse.SPQR.QRSparse` | QR factorization | - -Other solvers such as [Pardiso.jl](https://github.com/JuliaSparse/Pardiso.jl/) are as external packages. [Arpack.jl](https://julialinearalgebra.github.io/Arpack.jl/stable/) provides `eigs` and `svds` for iterative solution of eigensystems and singular value decompositions. - -These factorizations are described in the [`Linear Algebra`](@ref man-linalg) section of the manual: -1. [`cholesky`](@ref) -2. [`ldlt`](@ref) -3. [`lu`](@ref) -4. [`qr`](@ref) - -```@docs -SuiteSparse.CHOLMOD.lowrankupdate -SuiteSparse.CHOLMOD.lowrankupdate! -SuiteSparse.CHOLMOD.lowrankdowndate -SuiteSparse.CHOLMOD.lowrankdowndate! -SuiteSparse.CHOLMOD.lowrankupdowndate! -``` - - -```@meta -DocTestSetup = nothing -``` diff --git a/stdlib/SuiteSparse/src/SuiteSparse.jl b/stdlib/SuiteSparse/src/SuiteSparse.jl deleted file mode 100644 index e07e6aaea1c5a..0000000000000 --- a/stdlib/SuiteSparse/src/SuiteSparse.jl +++ /dev/null @@ -1,31 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module SuiteSparse - -import Base: \ -import LinearAlgebra: ldiv!, rdiv! - -## Functions to switch to 0-based indexing to call external sparse solvers - -# Convert from 1-based to 0-based indices -function decrement!(A::AbstractArray{T}) where T<:Integer - for i in eachindex(A); A[i] -= oneunit(T) end - A -end -decrement(A::AbstractArray{<:Integer}) = decrement!(copy(A)) - -# Convert from 0-based to 1-based indices -function increment!(A::AbstractArray{T}) where T<:Integer - for i in eachindex(A); A[i] += oneunit(T) end - A -end -increment(A::AbstractArray{<:Integer}) = increment!(copy(A)) - -if Base.USE_GPL_LIBS - include("umfpack.jl") - include("cholmod.jl") - include("spqr.jl") - include("deprecated.jl") -end - -end # module SuiteSparse diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl deleted file mode 100644 index 8bc3b9747f53b..0000000000000 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ /dev/null @@ -1,2026 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# Theoretically CHOLMOD supports both Int32 and Int64 indices on 64-bit. -# However experience suggests that using both in the same session causes memory -# leaks, so we restrict indices to be SuiteSparse_long (see cholmod_h.jl). -# Ref: https://github.com/JuliaLang/julia/issues/12664 - -# Additionally, only Float64/ComplexF64 are supported in practice. -# Ref: https://github.com/JuliaLang/julia/issues/25986 - -module CHOLMOD - -import Base: (*), convert, copy, eltype, getindex, getproperty, show, size, - IndexStyle, IndexLinear, IndexCartesian, adjoint, axes -using Base: require_one_based_indexing - -using LinearAlgebra -import LinearAlgebra: (\), - cholesky, cholesky!, det, diag, ishermitian, isposdef, - issuccess, issymmetric, ldlt, ldlt!, logdet - -using SparseArrays -using SparseArrays: getcolptr -import Libdl - -export - Dense, - Factor, - Sparse - -import SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, indtype, sparse, spzeros, nnz - -import ..increment, ..increment!, ..decrement, ..decrement! - -######### -# Setup # -######### - -include("cholmod_h.jl") - -const CHOLMOD_MIN_VERSION = v"2.1.1" - -## macro to generate the name of the C function according to the integer type -macro cholmod_name(nm) - string("cholmod_l_", nm) -end - -# Set a `common` field, execute some code and then safely reset the field to -# its initial value -macro cholmod_param(kwarg, code) - @assert kwarg.head == :(=) - param = kwarg.args[1] - value = kwarg.args[2] - - common_param = # Read `common.param` - Expr(:., :(common[Threads.threadid()]), QuoteNode(param)) - - return quote - default_value = $common_param - try - $common_param = $(esc(value)) - $(esc(code)) - finally - $common_param = default_value - end - end -end - -# Julia copy of the cholmod_method_struct -# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L655 -# Keep this synchronized with `jl_cholmod_method_offsets` in -# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c -struct Method - lnz::Cdouble - fl::Cdouble - prune_dense::Cdouble - prune_dense2::Cdouble - nd_oksep::Cdouble - other_1::NTuple{4,Cdouble} - nd_small::Csize_t - other_2::NTuple{4,Csize_t} - aggressive::Cint - order_for_lu::Cint - nd_compress::Cint - nd_camd::Cint - nd_components::Cint - ordering::Cint - other_3::NTuple{4,Csize_t} -end - -# Julia copy of the cholmod_common_struct -# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L414 -# Keep this synchronized with `jl_cholmod_method_offsets` in -# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c -mutable struct Common - dbound::Cdouble - grow0::Cdouble - grow1::Cdouble - grow2::Csize_t - maxrank::Csize_t - supernodal_switch::Cdouble - supernodal::Cint - final_asis::Cint - final_super::Cint - final_ll::Cint - final_pack::Cint - final_monotonic::Cint - final_resymbol::Cint - zrelax::NTuple{3,Cdouble} - nrelax::NTuple{3,Csize_t} - prefer_zomplex::Cint - prefer_upper::Cint - quick_return_if_not_posdef::Cint - prefer_binary::Cint - print::Cint - precise::Cint - try_catch::Cint - error_handler::Ptr{Nothing} - nmethods::Cint - current::Cint - selected::Cint - method::NTuple{10,Method} - postorder::Cint - default_nesdis::Cint - metis_memory::Cdouble - metis_dswitch::Cdouble - metis_nswitch::Csize_t - nrow::Csize_t - mark::SuiteSparse_long - iworksize::Csize_t - xworksize::Csize_t - Flag::Ptr{Nothing} - Head::Ptr{Nothing} - Xwork::Ptr{Nothing} - Iwork::Ptr{Nothing} - itype::Cint - dtype::Cint - no_workspace_reallocate::Cint - status::Cint - fl::Cdouble - lnz::Cdouble - anz::Cdouble - modfl::Cdouble - malloc_count::Csize_t - memory_usage::Csize_t - memory_inuse::Csize_t - nrealloc_col::Cdouble - nrealloc_factor::Cdouble - ndbounds_hit::Cdouble - rowfacfl::Cdouble - aatfl::Cdouble - called_nd::Cint - blas_ok::Cint - SPQR_grain::Cdouble - SPQR_small::Cdouble - SPQR_shrink::Cint - SPQR_nthreads::Cint - SPQR_flopcount::Cdouble - SPQR_analyze_time::Cdouble - SPQR_factorize_time::Cdouble - SPQR_solve_time::Cdouble - SPQR_flopcount_bound::Cdouble - SPQR_tol_used::Cdouble - SPQR_norm_E_fro::Cdouble - SPQR_istat::NTuple{10,SuiteSparse_long} - useGPU::Cint - maxGpuMemBytes::Csize_t - maxGpuMemFraction::Cdouble - gpuMemorySize::Csize_t - gpuKernelTime::Cdouble - gpuFlops::SuiteSparse_long - gpuNumKernelLaunches::Cint - cublasHandle::Ptr{Nothing} - gpuStream::NTuple{8,Ptr{Nothing}} - cublasEventPotrf::NTuple{3,Ptr{Nothing}} - updateCKernelsComplete::Ptr{Nothing} - updateCBuffersFree::NTuple{8,Ptr{Nothing}} - dev_mempool::Ptr{Nothing} - dev_mempool_size::Csize_t - host_pinned_mempool::Ptr{Nothing} - host_pinned_mempool_size::Csize_t - devBuffSize::Csize_t - ibuffer::Cint - syrkStart::Cdouble - cholmod_cpu_gemm_time::Cdouble - cholmod_cpu_syrk_time::Cdouble - cholmod_cpu_trsm_time::Cdouble - cholmod_cpu_potrf_time::Cdouble - cholmod_gpu_gemm_time::Cdouble - cholmod_gpu_syrk_time::Cdouble - cholmod_gpu_trsm_time::Cdouble - cholmod_gpu_potrf_time::Cdouble - cholmod_assemble_time::Cdouble - cholmod_assemble_time2::Cdouble - cholmod_cpu_gemm_calls::Csize_t - cholmod_cpu_syrk_calls::Csize_t - cholmod_cpu_trsm_calls::Csize_t - cholmod_cpu_potrf_calls::Csize_t - cholmod_gpu_gemm_calls::Csize_t - cholmod_gpu_syrk_calls::Csize_t - cholmod_gpu_trsm_calls::Csize_t - cholmod_gpu_potrf_calls::Csize_t - - function Common() - common = new() - ccall((@cholmod_name("start"), :libcholmod), - Cint, (Ptr{Common},), common) - finalizer(common) do common - ccall((@cholmod_name("finish"), :libcholmod), - Cint, (Ptr{Common},), common) == TRUE - end - end -end - -Base.unsafe_convert(::Type{Ptr{Common}},c::Common) = - reinterpret(Ptr{Common}, pointer_from_objref(c)) - -const common = Vector{Common}() - -function defaults!(common) - ccall((@cholmod_name("defaults"), :libcholmod), - Cint, (Ptr{Common},), common) - return common -end - -const build_version_array = Vector{Cint}(undef, 3) -ccall((:jl_cholmod_version, :libsuitesparse_wrapper), Cint, (Ptr{Cint},), build_version_array) -const build_version = VersionNumber(build_version_array...) - -function __init__() - try - ### Check if the linked library is compatible with the Julia code - if Libdl.dlsym_e(Libdl.dlopen("libcholmod"), :cholmod_version) != C_NULL - current_version_array = Vector{Cint}(undef, 3) - ccall((:cholmod_version, :libcholmod), Cint, (Ptr{Cint},), current_version_array) - current_version = VersionNumber(current_version_array...) - else # CHOLMOD < 2.1.1 does not include cholmod_version() - current_version = v"0.0.0" - end - - - if current_version < CHOLMOD_MIN_VERSION - @warn """ - CHOLMOD version incompatibility - - Julia was compiled with CHOLMOD version $build_version. It is - currently linked with a version older than - $(CHOLMOD_MIN_VERSION). This might cause Julia to - terminate when working with sparse matrix factorizations, - e.g. solving systems of equations with \\. - - It is recommended that you use Julia with a recent version - of CHOLMOD, or download the generic binaries - from www.julialang.org, which ship with the correct - versions of all dependencies. - """ - elseif build_version != current_version - @warn """ - CHOLMOD version incompatibility - - Julia was compiled with CHOLMOD version $build_version. It is - currently linked with version $current_version. - This might cause Julia to terminate when working with - sparse matrix factorizations, e.g. solving systems of - equations with \\. - - It is recommended that you use Julia with the same major - version of CHOLMOD as the one used during the build, or - download the generic binaries from www.julialang.org, - which ship with the correct versions of all dependencies. - """ - end - - intsize = Int(ccall((:jl_cholmod_sizeof_long,:libsuitesparse_wrapper),Csize_t,())) - if intsize != 4length(IndexTypes) - @error """ - CHOLMOD integer size incompatibility - - Julia was compiled with a version of CHOLMOD that - supported $(32length(IndexTypes)) bit integers. It is - currently linked with version that supports $(8intsize) - integers. This might cause Julia to terminate when - working with sparse matrix factorizations, e.g. solving - systems of equations with \\. - - This problem can be fixed by modifying the Julia build - configuration or by downloading the OS X or generic - Linux binary from www.julialang.org, which include - the correct versions of all dependencies. - """ - end - - ### Initiate CHOLMOD - ### common controls the type of factorization and keeps pointers - ### to temporary memory. We need to manage a copy for each thread. - nt = Threads.nthreads() - resize!(common, nt) - errorhandler = @cfunction(error_handler, Cvoid, (Cint, Cstring, Cint, Cstring)) - for i in 1:nt - common[i] = Common() - common[i].print = 0 # no printing from CHOLMOD by default - common[i].error_handler = errorhandler - end - - # Register gc tracked allocator if CHOLMOD is new enough - if current_version >= v"3.0.0" - cnfg = cglobal((:SuiteSparse_config, :libsuitesparseconfig), Ptr{Cvoid}) - unsafe_store!(cnfg, cglobal(:jl_malloc, Ptr{Cvoid}), 1) - unsafe_store!(cnfg, cglobal(:jl_calloc, Ptr{Cvoid}), 2) - unsafe_store!(cnfg, cglobal(:jl_realloc, Ptr{Cvoid}), 3) - unsafe_store!(cnfg, cglobal(:jl_free, Ptr{Cvoid}), 4) - end - - catch ex - @error "Error during initialization of module CHOLMOD" exception=ex,catch_backtrace() - end -end - -#################### -# Type definitions # -#################### - -abstract type SuiteSparseStruct end - -# The three core data types for CHOLMOD: Dense, Sparse and Factor. -# CHOLMOD manages the memory, so the Julia versions only wrap a -# pointer to a struct. Therefore finalizers should be registered each -# time a pointer is returned from CHOLMOD. - -# Dense -struct C_Dense{T<:VTypes} <: SuiteSparseStruct - nrow::Csize_t - ncol::Csize_t - nzmax::Csize_t - d::Csize_t - x::Ptr{T} - z::Ptr{Cvoid} - xtype::Cint - dtype::Cint -end - -mutable struct Dense{Tv<:VTypes} <: DenseMatrix{Tv} - ptr::Ptr{C_Dense{Tv}} - function Dense{Tv}(ptr::Ptr{C_Dense{Tv}}) where Tv<:VTypes - if ptr == C_NULL - throw(ArgumentError("dense matrix construction failed for " * - "unknown reasons. Please submit a bug report.")) - end - s = unsafe_load(ptr) - if s.xtype != xtyp(Tv) - free!(ptr) - throw(CHOLMODException("xtype=$(s.xtype) not supported")) - elseif s.dtype != dtyp(Tv) - free!(ptr) - throw(CHOLMODException("dtype=$(s.dtype) not supported")) - end - A = new(ptr) - finalizer(free!, A) - return A - end -end -Dense(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes} = Dense{Tv}(p) - -# Sparse -# allow Cvoid pointer for reading matrices of unknown type from files as in -# cholmod_read_sparse -struct C_Sparse{Tv<:Union{Cvoid, VTypes}} <: SuiteSparseStruct - nrow::Csize_t - ncol::Csize_t - nzmax::Csize_t - p::Ptr{SuiteSparse_long} - i::Ptr{SuiteSparse_long} - nz::Ptr{SuiteSparse_long} - x::Ptr{Tv} - z::Ptr{Cvoid} - stype::Cint - itype::Cint - xtype::Cint - dtype::Cint - sorted::Cint - packed::Cint -end - -mutable struct Sparse{Tv<:VTypes} <: AbstractSparseMatrix{Tv,SuiteSparse_long} - ptr::Ptr{C_Sparse{Tv}} - function Sparse{Tv}(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes - if ptr == C_NULL - throw(ArgumentError("sparse matrix construction failed for " * - "unknown reasons. Please submit a bug report.")) - end - s = unsafe_load(ptr) - if s.itype != ityp(SuiteSparse_long) - free!(ptr) - throw(CHOLMODException("itype=$(s.itype) not supported")) - elseif s.xtype != xtyp(Tv) - free!(ptr) - throw(CHOLMODException("xtype=$(s.xtype) not supported")) - elseif s.dtype != dtyp(Tv) - free!(ptr) - throw(CHOLMODException("dtype=$(s.dtype) not supported")) - end - A = new(ptr) - finalizer(free!, A) - return A - end -end -Sparse(p::Ptr{C_Sparse{Tv}}) where {Tv<:VTypes} = Sparse{Tv}(p) - -# Useful when reading in files, but not type stable -function Sparse(p::Ptr{C_Sparse{Cvoid}}) - if p == C_NULL - throw(ArgumentError("sparse matrix construction failed for " * - "unknown reasons. Please submit a bug report.")) - end - s = unsafe_load(p) - Tv = s.xtype == REAL ? Float64 : ComplexF64 - Sparse(convert(Ptr{C_Sparse{Tv}}, p)) -end - -Base.unsafe_convert(::Type{Ptr{Tv}}, A::Sparse{Tv}) where {Tv} = getfield(A, :ptr) - -# Factor -# Cvoid is used for pattern-only factors -struct C_Factor{Tv<:VTypes} <: SuiteSparseStruct - n::Csize_t - minor::Csize_t - Perm::Ptr{SuiteSparse_long} - ColCount::Ptr{SuiteSparse_long} - @static if build_version >= v"2.1.0" - IPerm::Ptr{SuiteSparse_long} # this pointer was added in version 2.1.0 - end - nzmax::Csize_t - p::Ptr{SuiteSparse_long} - i::Ptr{SuiteSparse_long} - x::Ptr{Tv} - z::Ptr{Cvoid} - nz::Ptr{SuiteSparse_long} - next::Ptr{SuiteSparse_long} - prev::Ptr{SuiteSparse_long} - nsuper::Csize_t - ssize::Csize_t - xsize::Csize_t - maxcsize::Csize_t - maxesize::Csize_t - super::Ptr{SuiteSparse_long} - pi::Ptr{SuiteSparse_long} - px::Ptr{SuiteSparse_long} - s::Ptr{SuiteSparse_long} - ordering::Cint - is_ll::Cint - is_super::Cint - is_monotonic::Cint - itype::Cint - xtype::Cint - dtype::Cint -end - -mutable struct Factor{Tv<:VTypes} <: Factorization{Tv} - ptr::Ptr{C_Factor{Tv}} - function Factor{Tv}(ptr::Ptr{C_Factor{Tv}}, register_finalizer = true) where Tv - if ptr == C_NULL - throw(ArgumentError("factorization construction failed for " * - "unknown reasons. Please submit a bug report.")) - end - s = unsafe_load(ptr) - if s.itype != ityp(SuiteSparse_long) - free!(ptr) - throw(CHOLMODException("itype=$(s.itype) not supported")) - elseif s.xtype != xtyp(Tv) && s.xtype != PATTERN - free!(ptr) - throw(CHOLMODException("xtype=$(s.xtype) not supported")) - elseif s.dtype != dtyp(Tv) - free!(ptr) - throw(CHOLMODException("dtype=$(s.dtype) not supported")) - end - F = new(ptr) - if register_finalizer - finalizer(free!, F) - end - return F - end -end -Factor(ptr::Ptr{C_Factor{Tv}}) where {Tv<:VTypes} = Factor{Tv}(ptr) -Factor(x::Factor) = x - -Base.adjoint(F::Factor) = Adjoint(F) -Base.transpose(F::Factor) = Transpose(F) - -# All pointer loads should be checked to make sure that SuiteSparse is not called with -# a C_NULL pointer which could cause a segfault. Pointers are set to null -# when serialized so this can happen when multiple processes are in use. -function Base.unsafe_convert(::Type{Ptr{T}}, x::Union{Dense,Sparse,Factor}) where T<:SuiteSparseStruct - xp = getfield(x, :ptr) - if xp == C_NULL - throw(ArgumentError("pointer to the $T object is null. This can " * - "happen if the object has been serialized.")) - else - return xp - end -end -Base.pointer(x::Dense{Tv}) where {Tv} = Base.unsafe_convert(Ptr{C_Dense{Tv}}, x) -Base.pointer(x::Sparse{Tv}) where {Tv} = Base.unsafe_convert(Ptr{C_Sparse{Tv}}, x) -Base.pointer(x::Factor{Tv}) where {Tv} = Base.unsafe_convert(Ptr{C_Factor{Tv}}, x) - -# FactorComponent, for encoding particular factors from a factorization -mutable struct FactorComponent{Tv,S} <: AbstractMatrix{Tv} - F::Factor{Tv} - - function FactorComponent{Tv,S}(F::Factor{Tv}) where {Tv,S} - s = unsafe_load(pointer(F)) - if s.is_ll != 0 - if !(S === :L || S === :U || S === :PtL || S === :UP) - throw(CHOLMODException(string(S, " not supported for sparse ", - "LLt matrices; try :L, :U, :PtL, or :UP"))) - end - elseif !(S === :L || S === :U || S === :PtL || S === :UP || - S === :D || S === :LD || S === :DU || S === :PtLD || S === :DUP) - throw(CHOLMODException(string(S, " not supported for sparse LDLt ", - "matrices; try :L, :U, :PtL, :UP, :D, :LD, :DU, :PtLD, or :DUP"))) - end - new(F) - end -end -function FactorComponent(F::Factor{Tv}, sym::Symbol) where Tv - FactorComponent{Tv,sym}(F) -end - -Factor(FC::FactorComponent) = Factor(FC.F) - -################# -# Thin wrappers # -################# - -# Dense wrappers - -### cholmod_core_h ### -function allocate_dense(m::Integer, n::Integer, d::Integer, ::Type{Tv}) where {Tv<:VTypes} - Dense(ccall((@cholmod_name("allocate_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, d, xtyp(Tv), common[Threads.threadid()])) -end - -function free!(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes} - ccall((@cholmod_name("free_dense"), :libcholmod), Cint, - (Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}), - p, common[Threads.threadid()]) == TRUE -end -function zeros(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes - Dense(ccall((@cholmod_name("zeros"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, xtyp(Tv), common[Threads.threadid()])) -end -zeros(m::Integer, n::Integer) = zeros(m, n, Float64) - -function ones(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes - Dense(ccall((@cholmod_name("ones"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, xtyp(Tv), common[Threads.threadid()])) -end -ones(m::Integer, n::Integer) = ones(m, n, Float64) - -function eye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes - Dense(ccall((@cholmod_name("eye"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, xtyp(Tv), common[Threads.threadid()])) -end -eye(m::Integer, n::Integer) = eye(m, n, Float64) -eye(n::Integer) = eye(n, n, Float64) - -function copy(A::Dense{Tv}) where Tv<:VTypes - Dense(ccall((@cholmod_name("copy_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Ptr{C_Dense{Tv}}, Ptr{Common}), - A, common[Threads.threadid()])) -end - -function sort!(S::Sparse{Tv}) where Tv<:VTypes - ccall((@cholmod_name("sort"), :libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - S, common[Threads.threadid()]) - return S -end - -### cholmod_matrixops.h ### -function norm_dense(D::Dense{Tv}, p::Integer) where Tv<:VTypes - s = unsafe_load(pointer(D)) - if p == 2 - if s.ncol > 1 - throw(ArgumentError("2 norm only supported when matrix has one column")) - end - elseif p != 0 && p != 1 - throw(ArgumentError("second argument must be either 0 (Inf norm), 1, or 2")) - end - ccall((@cholmod_name("norm_dense"), :libcholmod), Cdouble, - (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), - D, p, common[Threads.threadid()]) -end - -### cholmod_check.h ### -function check_dense(A::Dense{Tv}) where Tv<:VTypes - ccall((@cholmod_name("check_dense"), :libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Ptr{Common}), - pointer(A), common[Threads.threadid()]) != 0 -end - -# Non-Dense wrappers -### cholmod_core.h ### -function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer, - sorted::Bool, packed::Bool, stype::Integer, ::Type{Tv}) where {Tv<:VTypes} - Sparse(ccall((@cholmod_name("allocate_sparse"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, - Cint, Cint, Cint, Ptr{Common}), - nrow, ncol, nzmax, sorted, - packed, stype, xtyp(Tv), common[Threads.threadid()])) -end - -function free!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes - ccall((@cholmod_name("free_sparse"), :libcholmod), Cint, - (Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}), - ptr, common[Threads.threadid()]) == TRUE -end - -function free!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes - # Warning! Important that finalizer doesn't modify the global Common struct. - ccall((@cholmod_name("free_factor"), :libcholmod), Cint, - (Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}), - ptr, common[Threads.threadid()]) == TRUE -end - -function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes - Sparse(ccall((@cholmod_name("aat"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{Common}), - A, fset, length(fset), mode, common[Threads.threadid()])) -end - -function sparse_to_dense(A::Sparse{Tv}) where Tv<:VTypes - Dense(ccall((@cholmod_name("sparse_to_dense"),:libcholmod), - Ptr{C_Dense{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - A, common[Threads.threadid()])) -end -function dense_to_sparse(D::Dense{Tv}, ::Type{SuiteSparse_long}) where Tv<:VTypes - Sparse(ccall((@cholmod_name("dense_to_sparse"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), - D, true, common[Threads.threadid()])) -end - -function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes - ss = unsafe_load(pointer(F)) - ss.xtype == PATTERN && throw(CHOLMODException("only numeric factors are supported")) - Sparse(ccall((@cholmod_name("factor_to_sparse"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{Common}), - F, common[Threads.threadid()])) -end - -function change_factor!(F::Factor{Tv}, to_ll::Bool, to_super::Bool, to_packed::Bool, - to_monotonic::Bool) where Tv<:VTypes - ccall((@cholmod_name("change_factor"),:libcholmod), Cint, - (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}), - xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) == TRUE -end - -function check_sparse(A::Sparse{Tv}) where Tv<:VTypes - ccall((@cholmod_name("check_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - A, common[Threads.threadid()]) != 0 -end - -function check_factor(F::Factor{Tv}) where Tv<:VTypes - ccall((@cholmod_name("check_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{Common}), - F, common[Threads.threadid()]) != 0 -end - -function nnz(A::Sparse{Tv}) where Tv<:VTypes - ccall((@cholmod_name("nnz"),:libcholmod), Int, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - A, common[Threads.threadid()]) -end - -function speye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes - Sparse(ccall((@cholmod_name("speye"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, xtyp(Tv), common[Threads.threadid()])) -end - -function spzeros(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) where Tv<:VTypes - Sparse(ccall((@cholmod_name("spzeros"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), - m, n, nzmax, xtyp(Tv), common[Threads.threadid()])) -end - -function transpose_(A::Sparse{Tv}, values::Integer) where Tv<:VTypes - Sparse(ccall((@cholmod_name("transpose"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), - A, values, common[Threads.threadid()])) -end - -function copy(F::Factor{Tv}) where Tv<:VTypes - Factor(ccall((@cholmod_name("copy_factor"),:libcholmod), - Ptr{C_Factor{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{Common}), - F, common[Threads.threadid()])) -end -function copy(A::Sparse{Tv}) where Tv<:VTypes - Sparse(ccall((@cholmod_name("copy_sparse"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - A, common[Threads.threadid()])) -end -function copy(A::Sparse{Tv}, stype::Integer, mode::Integer) where Tv<:VRealTypes - Sparse(ccall((@cholmod_name("copy"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{Common}), - A, stype, mode, common[Threads.threadid()])) -end - -### cholmod_check.h ### -function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes - isascii(name) || error("non-ASCII name: $name") - @cholmod_param print = 3 begin - ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), - A, name, common[Threads.threadid()]) - end - nothing -end -function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes - @cholmod_param print = 3 begin - ccall((@cholmod_name("print_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), - F, name, common[Threads.threadid()]) - end - nothing -end - -### cholmod_matrixops.h ### -function ssmult(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, - values::Bool, sorted::Bool) where Tv<:VRealTypes - lA = unsafe_load(pointer(A)) - lB = unsafe_load(pointer(B)) - if lA.ncol != lB.nrow - throw(DimensionMismatch("inner matrix dimensions do not fit")) - end - Sparse(ccall((@cholmod_name("ssmult"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Cint, - Cint, Ptr{Common}), - A, B, stype, values, - sorted, common[Threads.threadid()])) -end - -function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes - if norm != 0 && norm != 1 - throw(ArgumentError("norm argument must be either 0 or 1")) - end - ccall((@cholmod_name("norm_sparse"), :libcholmod), Cdouble, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), - A, norm, common[Threads.threadid()]) -end - -function horzcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes - Sparse(ccall((@cholmod_name("horzcat"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), - A, B, values, common[Threads.threadid()])) -end - -function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealTypes - sS = unsafe_load(pointer(S)) - sA = unsafe_load(pointer(A)) - if sS.ncol != 1 && sS.nrow != 1 - throw(DimensionMismatch("first argument must be a vector")) - end - if scale == SCALAR && sS.nrow != 1 - throw(DimensionMismatch("scaling argument must have length one")) - elseif scale == ROW && sS.nrow*sS.ncol != sA.nrow - throw(DimensionMismatch("scaling vector has length $(sS.nrow*sS.ncol), " * - "but matrix has $(sA.nrow) rows.")) - elseif scale == COL && sS.nrow*sS.ncol != sA.ncol - throw(DimensionMismatch("scaling vector has length $(sS.nrow*sS.ncol), " * - "but matrix has $(sA.ncol) columns")) - elseif scale == SYM - if sA.nrow != sA.ncol - throw(DimensionMismatch("matrix must be square")) - elseif sS.nrow*sS.ncol != sA.nrow - throw(DimensionMismatch("scaling vector has length $(sS.nrow*sS.ncol), " * - "but matrix has $(sA.ncol) columns and rows")) - end - end - - sA = unsafe_load(pointer(A)) - ccall((@cholmod_name("scale"),:libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}), - S, scale, A, common[Threads.threadid()]) - A -end - -function sdmult!(A::Sparse{Tv}, transpose::Bool, - α::Number, β::Number, X::Dense{Tv}, Y::Dense{Tv}) where Tv<:VTypes - m, n = size(A) - nc = transpose ? m : n - nr = transpose ? n : m - if nc != size(X, 1) - throw(DimensionMismatch("incompatible dimensions, $nc and $(size(X,1))")) - end - ccall((@cholmod_name("sdmult"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Cint, - Ref{ComplexF64}, Ref{ComplexF64}, - Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), - A, transpose, α, β, X, Y, common[Threads.threadid()]) - Y -end - -function vertcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes - Sparse(ccall((@cholmod_name("vertcat"), :libcholmod), - Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), - A, B, values, common[Threads.threadid()])) -end - -function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes - xmatched = Ref{SuiteSparse_long}() - pmatched = Ref{SuiteSparse_long}() - nzoffdiag = Ref{SuiteSparse_long}() - nzdiag = Ref{SuiteSparse_long}() - rv = ccall((@cholmod_name("symmetry"), :libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{Common}), - A, option, xmatched, pmatched, - nzoffdiag, nzdiag, common[Threads.threadid()]) - rv, xmatched[], pmatched[], nzoffdiag[], nzdiag[] -end - -# cholmod_cholesky.h -# For analyze, analyze_p, and factorize_p!, the Common argument must be -# supplied in order to control if the factorization is LLt or LDLt -function analyze(A::Sparse{Tv}) where Tv<:VTypes - Factor(ccall((@cholmod_name("analyze"),:libcholmod), - Ptr{C_Factor{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{Common}), - A, common[Threads.threadid()])) -end -function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}) where Tv<:VTypes - length(perm) != size(A,1) && throw(BoundsError()) - Factor(ccall((@cholmod_name("analyze_p"),:libcholmod), - Ptr{C_Factor{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Csize_t, Ptr{Common}), - A, perm, C_NULL, 0, common[Threads.threadid()])) -end -function factorize!(A::Sparse{Tv}, F::Factor{Tv}) where Tv<:VTypes - ccall((@cholmod_name("factorize"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), - A, F, common[Threads.threadid()]) - F -end -function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}) where Tv<:VTypes - # note that β is passed as a complex number (double beta[2]), - # but the CHOLMOD manual says that only beta[0] (real part) is used - ccall((@cholmod_name("factorize_p"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t, - Ptr{C_Factor{Tv}}, Ptr{Common}), - A, β, C_NULL, 0, F, common[Threads.threadid()]) - F -end - -function solve(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) where Tv<:VTypes - if size(F,1) != size(B,1) - throw(DimensionMismatch("LHS and RHS should have the same number of rows. " * - "LHS has $(size(F,1)) rows, but RHS has $(size(B,1)) rows.")) - end - if !issuccess(F) - s = unsafe_load(pointer(F)) - if s.is_ll == 1 - throw(LinearAlgebra.PosDefException(s.minor)) - else - throw(LinearAlgebra.ZeroPivotException(s.minor)) - end - end - Dense(ccall((@cholmod_name("solve"),:libcholmod), Ptr{C_Dense{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), - sys, F, B, common[Threads.threadid()])) -end - -function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes - if size(F,1) != size(B,1) - throw(DimensionMismatch("LHS and RHS should have the same number of rows. " * - "LHS has $(size(F,1)) rows, but RHS has $(size(B,1)) rows.")) - end - Sparse(ccall((@cholmod_name("spsolve"),:libcholmod), - Ptr{C_Sparse{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Sparse{Tv}}, Ptr{Common}), - sys, F, B, common[Threads.threadid()])) -end - -# Autodetects the types -function read_sparse(file::Libc.FILE, ::Type{SuiteSparse_long}) - Sparse(ccall((@cholmod_name("read_sparse"), :libcholmod), - Ptr{C_Sparse{Cvoid}}, - (Ptr{Cvoid}, Ptr{Common}), - file.ptr, common[Threads.threadid()])) -end - -function read_sparse(file::IO, T) - cfile = Libc.FILE(file) - try return read_sparse(cfile, T) - finally close(cfile) - end -end - -function get_perm(F::Factor) - s = unsafe_load(pointer(F)) - p = unsafe_wrap(Array, s.Perm, s.n, own = false) - p .+ 1 -end -get_perm(FC::FactorComponent) = get_perm(Factor(FC)) - -######################### -# High level interfaces # -######################### - -# Conversion/construction -function Dense{T}(A::StridedVecOrMat) where T<:VTypes - d = allocate_dense(size(A, 1), size(A, 2), stride(A, 2), T) - GC.@preserve d begin - s = unsafe_load(pointer(d)) - for (i, c) in enumerate(eachindex(A)) - unsafe_store!(s.x, A[c], i) - end - end - d -end -function Dense{T}(A::Union{Adjoint{<:Any, <:StridedVecOrMat}, Transpose{<:Any, <:StridedVecOrMat}}) where T<:VTypes - d = allocate_dense(size(A, 1), size(A, 2), size(A, 1), T) - GC.@preserve d begin - s = unsafe_load(pointer(d)) - for (i, c) in enumerate(eachindex(A)) - unsafe_store!(s.x, A[c], i) - end - end - d -end -function Dense(A::Union{StridedVecOrMat, Adjoint{<:Any, <:StridedVecOrMat}, Transpose{<:Any, <:StridedVecOrMat}}) - T = promote_type(eltype(A), Float64) - return Dense{T}(A) -end -Dense(A::Sparse) = sparse_to_dense(A) - -# This constructior assumes zero based colptr and rowval -function Sparse(m::Integer, n::Integer, - colptr0::Vector{SuiteSparse_long}, rowval0::Vector{SuiteSparse_long}, - nzval::Vector{Tv}, stype) where Tv<:VTypes - # checks - ## length of input - if length(colptr0) <= n - throw(ArgumentError("length of colptr0 must be at least n + 1 = $(n + 1) but was $(length(colptr0))")) - end - if colptr0[n + 1] > length(rowval0) - throw(ArgumentError("length of rowval0 is $(length(rowval0)) but value of colptr0 requires length to be at least $(colptr0[n + 1])")) - end - if colptr0[n + 1] > length(nzval) - throw(ArgumentError("length of nzval is $(length(nzval)) but value of colptr0 requires length to be at least $(colptr0[n + 1])")) - end - ## columns are sorted - iss = true - for i = 2:length(colptr0) - if !issorted(view(rowval0, colptr0[i - 1] + 1:colptr0[i])) - iss = false - break - end - end - - o = allocate_sparse(m, n, colptr0[n + 1], iss, true, stype, Tv) - s = unsafe_load(pointer(o)) - - unsafe_copyto!(s.p, pointer(colptr0), n + 1) - unsafe_copyto!(s.i, pointer(rowval0), colptr0[n + 1]) - unsafe_copyto!(s.x, pointer(nzval) , colptr0[n + 1]) - - check_sparse(o) - - return o -end - -function Sparse(m::Integer, n::Integer, - colptr0::Vector{SuiteSparse_long}, - rowval0::Vector{SuiteSparse_long}, - nzval::Vector{<:VTypes}) - o = Sparse(m, n, colptr0, rowval0, nzval, 0) - - # sort indices - sort!(o) - - # check if array is symmetric and change stype if it is - if ishermitian(o) - change_stype!(o, -1) - end - o -end - -function Sparse{Tv}(A::SparseMatrixCSC, stype::Integer) where Tv<:VTypes - ## Check length of input. This should never fail but see #20024 - if length(getcolptr(A)) <= size(A, 2) - throw(ArgumentError("length of colptr must be at least size(A,2) + 1 = $(size(A, 2) + 1) but was $(length(getcolptr(A)))")) - end - if nnz(A) > length(rowvals(A)) - throw(ArgumentError("length of rowval is $(length(rowvals(A))) but value of colptr requires length to be at least $(nnz(A))")) - end - if nnz(A) > length(nonzeros(A)) - throw(ArgumentError("length of nzval is $(length(nonzeros(A))) but value of colptr requires length to be at least $(nnz(A))")) - end - - o = allocate_sparse(size(A, 1), size(A, 2), nnz(A), true, true, stype, Tv) - s = unsafe_load(pointer(o)) - for i = 1:(size(A, 2) + 1) - unsafe_store!(s.p, getcolptr(A)[i] - 1, i) - end - for i = 1:nnz(A) - unsafe_store!(s.i, rowvals(A)[i] - 1, i) - end - if Tv <: Complex && stype != 0 - # Need to remove any non real elements in the diagonal because, in contrast to - # BLAS/LAPACK these are not ignored by CHOLMOD. If even tiny imaginary parts are - # present CHOLMOD will fail with a non-positive definite/zero pivot error. - for j = 1:size(A, 2) - for ip = getcolptr(A)[j]:getcolptr(A)[j + 1] - 1 - v = nonzeros(A)[ip] - unsafe_store!(s.x, rowvals(A)[ip] == j ? Complex(real(v)) : v, ip) - end - end - elseif Tv == eltype(nonzeros(A)) - unsafe_copyto!(s.x, pointer(nonzeros(A)), nnz(A)) - else - for i = 1:nnz(A) - unsafe_store!(s.x, nonzeros(A)[i], i) - end - end - - check_sparse(o) - - return o -end - -# handle promotion -function Sparse(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) where {Tv} - T = promote_type(Tv, Float64) - return Sparse{T}(A, stype) -end - -# convert SparseVectors into CHOLMOD Sparse types through a mx1 CSC matrix -Sparse(A::SparseVector) = Sparse(SparseMatrixCSC(A)) -function Sparse(A::SparseMatrixCSC) - o = Sparse(A, 0) - # check if array is symmetric and change stype if it is - if ishermitian(o) - change_stype!(o, -1) - end - o -end - -Sparse(A::Symmetric{Tv, SparseMatrixCSC{Tv,Ti}}) where {Tv<:Real, Ti} = - Sparse(A.data, A.uplo == 'L' ? -1 : 1) -Sparse(A::Hermitian{Tv,SparseMatrixCSC{Tv,Ti}}) where {Tv, Ti} = - Sparse(A.data, A.uplo == 'L' ? -1 : 1) - -Sparse(A::Dense) = dense_to_sparse(A, SuiteSparse_long) -Sparse(L::Factor) = factor_to_sparse!(copy(L)) -function Sparse(filename::String) - open(filename) do f - return read_sparse(f, SuiteSparse_long) - end -end - -## conversion back to base Julia types -function Matrix{T}(D::Dense{T}) where T - s = unsafe_load(pointer(D)) - a = Matrix{T}(undef, s.nrow, s.ncol) - copyto!(a, D) -end - -Base.copyto!(dest::Base.PermutedDimsArrays.PermutedDimsArray, src::Dense) = _copy!(dest, src) # ambig -Base.copyto!(dest::Dense{T}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) -Base.copyto!(dest::AbstractArray{T}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) -Base.copyto!(dest::AbstractArray{T,2}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) -Base.copyto!(dest::AbstractArray, D::Dense) = _copy!(dest, D) - -function _copy!(dest::AbstractArray, D::Dense) - require_one_based_indexing(dest) - s = unsafe_load(pointer(D)) - n = s.nrow*s.ncol - n <= length(dest) || throw(BoundsError(dest, n)) - if s.d == s.nrow && isa(dest, Array) - unsafe_copyto!(pointer(dest), s.x, s.d*s.ncol) - else - k = 0 - for j = 1:s.ncol - for i = 1:s.nrow - dest[k+=1] = unsafe_load(s.x, i + (j - 1)*s.d) - end - end - end - dest -end -Matrix(D::Dense{T}) where {T} = Matrix{T}(D) -function Vector{T}(D::Dense{T}) where T - if size(D, 2) > 1 - throw(DimensionMismatch("input must be a vector but had $(size(D, 2)) columns")) - end - copyto!(Vector{T}(undef, size(D, 1)), D) -end -Vector(D::Dense{T}) where {T} = Vector{T}(D) - -function _extract_args(s) - return (s.nrow, s.ncol, increment(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false)), - increment(unsafe_wrap(Array, s.i, (s.nzmax,), own = false)), - copy(unsafe_wrap(Array, s.x, (s.nzmax,), own = false))) -end - -# Trim extra elements in rowval and nzval left around sometimes by CHOLMOD rutines -function _trim_nz_builder!(m, n, colptr, rowval, nzval) - l = colptr[end] - 1 - resize!(rowval, l) - resize!(nzval, l) - SparseMatrixCSC(m, n, colptr, rowval, nzval) -end - -function SparseMatrixCSC{Tv,SuiteSparse_long}(A::Sparse{Tv}) where Tv - s = unsafe_load(pointer(A)) - if s.stype != 0 - throw(ArgumentError("matrix has stype != 0. Convert to matrix " * - "with stype == 0 before converting to SparseMatrixCSC")) - end - args = _extract_args(s) - s.sorted == 0 && _sort_buffers!(args...); - return _trim_nz_builder!(args...) -end - -function Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A::Sparse{Float64}) - s = unsafe_load(pointer(A)) - issymmetric(A) || throw(ArgumentError("matrix is not symmetric")) - args = _extract_args(s) - s.sorted == 0 && _sort_buffers!(args...) - Symmetric(_trim_nz_builder!(args...), s.stype > 0 ? :U : :L) -end -convert(T::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}}, A::Sparse{Float64}) = T(A) - -function Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}(A::Sparse{Tv}) where Tv<:VTypes - s = unsafe_load(pointer(A)) - ishermitian(A) || throw(ArgumentError("matrix is not Hermitian")) - args = _extract_args(s) - s.sorted == 0 && _sort_buffers!(args...) - Hermitian(_trim_nz_builder!(args...), s.stype > 0 ? :U : :L) -end -convert(T::Type{Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}}, A::Sparse{Tv}) where {Tv<:VTypes} = T(A) - -function sparse(A::Sparse{Float64}) # Notice! Cannot be type stable because of stype - s = unsafe_load(pointer(A)) - if s.stype == 0 - return SparseMatrixCSC{Float64,SuiteSparse_long}(A) - end - Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A) -end -function sparse(A::Sparse{ComplexF64}) # Notice! Cannot be type stable because of stype - s = unsafe_load(pointer(A)) - if s.stype == 0 - return SparseMatrixCSC{ComplexF64,SuiteSparse_long}(A) - end - Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,SuiteSparse_long}}(A) -end -function sparse(F::Factor) - s = unsafe_load(pointer(F)) - if s.is_ll != 0 - L = Sparse(F) - A = sparse(L*L') - else - LD = sparse(F.LD) - L, d = getLd!(LD) - A = (L * Diagonal(d)) * L' - end - # no need to sort buffers here, as A isa SparseMatrixCSC - # and it is taken care in sparse - p = get_perm(F) - if p != [1:s.n;] - pinv = Vector{Int}(undef, length(p)) - for k = 1:length(p) - pinv[p[k]] = k - end - A = A[pinv,pinv] - end - A -end - -sparse(D::Dense) = sparse(Sparse(D)) - -function sparse(FC::FactorComponent{Tv,:L}) where Tv - F = Factor(FC) - s = unsafe_load(pointer(F)) - if s.is_ll == 0 - throw(CHOLMODException("sparse: supported only for :LD on LDLt factorizations")) - end - sparse(Sparse(F)) -end -sparse(FC::FactorComponent{Tv,:LD}) where {Tv} = sparse(Sparse(Factor(FC))) - -# Calculate the offset into the stype field of the cholmod_sparse_struct and -# change the value -let offset = fieldoffset(C_Sparse{Float64}, findfirst(name -> name === :stype, fieldnames(C_Sparse{Float64}))::Int) - global change_stype! - function change_stype!(A::Sparse, i::Integer) - unsafe_store!(convert(Ptr{Cint}, pointer(A)), i, div(offset, 4) + 1) - return A - end -end - -free!(A::Dense) = free!(pointer(A)) -free!(A::Sparse) = free!(pointer(A)) -free!(F::Factor) = free!(pointer(F)) - -eltype(::Type{Dense{T}}) where {T<:VTypes} = T -eltype(::Type{Factor{T}}) where {T<:VTypes} = T -eltype(::Type{Sparse{T}}) where {T<:VTypes} = T - -nnz(F::Factor) = nnz(Sparse(F)) - -function show(io::IO, F::Factor) - println(io, typeof(F)) - showfactor(io, F) -end - -function show(io::IO, FC::FactorComponent) - println(io, typeof(FC)) - showfactor(io, Factor(FC)) -end - -function showfactor(io::IO, F::Factor) - s = unsafe_load(pointer(F)) - print(io, """ - type: $(s.is_ll!=0 ? "LLt" : "LDLt") - method: $(s.is_super!=0 ? "supernodal" : "simplicial") - maxnnz: $(Int(s.nzmax)) - nnz: $(nnz(F)) - success: $(s.minor == size(F, 1)) - """) -end - -# getindex not defined for these, so don't use the normal array printer -show(io::IO, ::MIME"text/plain", FC::FactorComponent) = show(io, FC) -show(io::IO, ::MIME"text/plain", F::Factor) = show(io, F) - -isvalid(A::Dense) = check_dense(A) -isvalid(A::Sparse) = check_sparse(A) -isvalid(A::Factor) = check_factor(A) - -function size(A::Union{Dense,Sparse}) - s = unsafe_load(pointer(A)) - return (Int(s.nrow), Int(s.ncol)) -end -function size(F::Factor, i::Integer) - if i < 1 - throw(ArgumentError("dimension must be positive")) - end - s = unsafe_load(pointer(F)) - if i <= 2 - return Int(s.n) - end - return 1 -end -size(F::Factor) = (size(F, 1), size(F, 2)) -axes(A::Union{Dense,Sparse,Factor}) = map(Base.OneTo, size(A)) - -IndexStyle(::Dense) = IndexLinear() - -size(FC::FactorComponent, i::Integer) = size(FC.F, i) -size(FC::FactorComponent) = size(FC.F) - -adjoint(FC::FactorComponent{Tv,:L}) where {Tv} = FactorComponent{Tv,:U}(FC.F) -adjoint(FC::FactorComponent{Tv,:U}) where {Tv} = FactorComponent{Tv,:L}(FC.F) -adjoint(FC::FactorComponent{Tv,:PtL}) where {Tv} = FactorComponent{Tv,:UP}(FC.F) -adjoint(FC::FactorComponent{Tv,:UP}) where {Tv} = FactorComponent{Tv,:PtL}(FC.F) -adjoint(FC::FactorComponent{Tv,:D}) where {Tv} = FC -adjoint(FC::FactorComponent{Tv,:LD}) where {Tv} = FactorComponent{Tv,:DU}(FC.F) -adjoint(FC::FactorComponent{Tv,:DU}) where {Tv} = FactorComponent{Tv,:LD}(FC.F) -adjoint(FC::FactorComponent{Tv,:PtLD}) where {Tv} = FactorComponent{Tv,:DUP}(FC.F) -adjoint(FC::FactorComponent{Tv,:DUP}) where {Tv} = FactorComponent{Tv,:PtLD}(FC.F) - -function getindex(A::Dense, i::Integer) - s = unsafe_load(pointer(A)) - 0 < i <= s.nrow*s.ncol || throw(BoundsError()) - unsafe_load(s.x, i) -end - -IndexStyle(::Sparse) = IndexCartesian() -function getindex(A::Sparse{T}, i0::Integer, i1::Integer) where T - s = unsafe_load(pointer(A)) - !(1 <= i0 <= s.nrow && 1 <= i1 <= s.ncol) && throw(BoundsError()) - s.stype < 0 && i0 < i1 && return conj(A[i1,i0]) - s.stype > 0 && i0 > i1 && return conj(A[i1,i0]) - - r1 = Int(unsafe_load(s.p, i1) + 1) - r2 = Int(unsafe_load(s.p, i1 + 1)) - (r1 > r2) && return zero(T) - r1 = Int(searchsortedfirst(unsafe_wrap(Array, s.i, (s.nzmax,), own = false), - i0 - 1, r1, r2, Base.Order.Forward)) - ((r1 > r2) || (unsafe_load(s.i, r1) + 1 != i0)) ? zero(T) : unsafe_load(s.x, r1) -end - -@inline function getproperty(F::Factor, sym::Symbol) - if sym === :p - return get_perm(F) - elseif sym === :ptr - return getfield(F, :ptr) - else - return FactorComponent(F, sym) - end -end - -function getLd!(S::SparseMatrixCSC) - d = Vector{eltype(S)}(undef, size(S, 1)) - fill!(d, 0) - col = 1 - for k = 1:nnz(S) - while k >= getcolptr(S)[col+1] - col += 1 - end - if rowvals(S)[k] == col - d[col] = nonzeros(S)[k] - nonzeros(S)[k] = 1 - end - end - S, d -end - -## Multiplication -(*)(A::Sparse, B::Sparse) = ssmult(A, B, 0, true, true) -(*)(A::Sparse, B::Dense) = sdmult!(A, false, 1., 0., B, zeros(size(A, 1), size(B, 2))) -(*)(A::Sparse, B::VecOrMat) = (*)(A, Dense(B)) - -function *(A::Sparse{Tv}, adjB::Adjoint{Tv,Sparse{Tv}}) where Tv<:VRealTypes - B = adjB.parent - if A !== B - aa1 = transpose_(B, 2) - ## result of ssmult will have stype==0, contain numerical values and be sorted - return ssmult(A, aa1, 0, true, true) - end - - ## The A*A' case is handled by cholmod_aat. This routine requires - ## A->stype == 0 (storage of upper and lower parts). If necessary - ## the matrix A is first converted to stype == 0 - s = unsafe_load(pointer(A)) - fset = s.ncol == 0 ? SuiteSparse_long[] : SuiteSparse_long[0:s.ncol-1;] - if s.stype != 0 - aa1 = copy(A, 0, 1) - return aat(aa1, fset, 1) - else - return aat(A, fset, 1) - end -end - -function *(adjA::Adjoint{<:Any,<:Sparse}, B::Sparse) - A = adjA.parent - aa1 = transpose_(A, 2) - if A === B - return *(aa1, adjoint(aa1)) - end - ## result of ssmult will have stype==0, contain numerical values and be sorted - return ssmult(aa1, B, 0, true, true) -end - -*(adjA::Adjoint{<:Any,<:Sparse}, B::Dense) = - (A = adjA.parent; sdmult!(A, true, 1., 0., B, zeros(size(A, 2), size(B, 2)))) -*(adjA::Adjoint{<:Any,<:Sparse}, B::VecOrMat) = - (A = adjA.parent; *(adjoint(A), Dense(B))) - - -## Factorization methods - -## Compute that symbolic factorization only -function symbolic(A::Sparse{<:VTypes}; - perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing, - postorder::Bool=isnothing(perm)||isempty(perm), userperm_only::Bool=true) - - sA = unsafe_load(pointer(A)) - sA.stype == 0 && throw(ArgumentError("sparse matrix is not symmetric/Hermitian")) - - @cholmod_param postorder = postorder begin - if perm === nothing || isempty(perm) # TODO: deprecate empty perm - return analyze(A) - else # user permutation provided - if userperm_only # use perm even if it is worse than AMD - @cholmod_param nmethods = 1 begin - return analyze_p(A, SuiteSparse_long[p-1 for p in perm]) - end - else - return analyze_p(A, SuiteSparse_long[p-1 for p in perm]) - end - end - end -end - -function cholesky!(F::Factor{Tv}, A::Sparse{Tv}; - shift::Real=0.0, check::Bool = true) where Tv - # Compute the numerical factorization - @cholmod_param final_ll = true begin - factorize_p!(A, shift, F) - end - - check && (issuccess(F) || throw(LinearAlgebra.PosDefException(1))) - return F -end - -""" - cholesky!(F::CHOLMOD.Factor, A::SparseMatrixCSC; shift = 0.0, check = true) -> CHOLMOD.Factor - -Compute the Cholesky (``LL'``) factorization of `A`, reusing the symbolic -factorization `F`. `A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@ref)/ -[`Hermitian`](@ref) view of a `SparseMatrixCSC`. Note that even if `A` doesn't -have the type tag, it must still be symmetric or Hermitian. - -See also [`cholesky`](@ref). - -!!! note - This method uses the CHOLMOD library from SuiteSparse, which only supports - doubles or complex doubles. Input matrices not of those element types will - be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` - as appropriate. -""" -cholesky!(F::Factor, A::Union{SparseMatrixCSC{T}, - SparseMatrixCSC{Complex{T}}, - Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, - Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, - Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - shift = 0.0, check::Bool = true) where {T<:Real} = - cholesky!(F, Sparse(A); shift = shift, check = check) - -function cholesky(A::Sparse; shift::Real=0.0, check::Bool = true, - perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - - # Compute the symbolic factorization - F = symbolic(A; perm = perm) - - # Compute the numerical factorization - cholesky!(F, A; shift = shift, check = check) - - return F -end - -""" - cholesky(A::SparseMatrixCSC; shift = 0.0, check = true, perm = nothing) -> CHOLMOD.Factor - -Compute the Cholesky factorization of a sparse positive definite matrix `A`. -`A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@ref)/[`Hermitian`](@ref) -view of a `SparseMatrixCSC`. Note that even if `A` doesn't -have the type tag, it must still be symmetric or Hermitian. -If `perm` is not given, a fill-reducing permutation is used. -`F = cholesky(A)` is most frequently used to solve systems of equations with `F\\b`, -but also the methods [`diag`](@ref), [`det`](@ref), and -[`logdet`](@ref) are defined for `F`. -You can also extract individual factors from `F`, using `F.L`. -However, since pivoting is on by default, the factorization is internally -represented as `A == P'*L*L'*P` with a permutation matrix `P`; -using just `L` without accounting for `P` will give incorrect answers. -To include the effects of permutation, -it's typically preferable to extract "combined" factors like `PtL = F.PtL` -(the equivalent of `P'*L`) and `LtP = F.UP` (the equivalent of `L'*P`). - -When `check = true`, an error is thrown if the decomposition fails. -When `check = false`, responsibility for checking the decomposition's -validity (via [`issuccess`](@ref)) lies with the user. - -Setting the optional `shift` keyword argument computes the factorization of -`A+shift*I` instead of `A`. If the `perm` argument is provided, -it should be a permutation of `1:size(A,1)` giving the ordering to use -(instead of CHOLMOD's default AMD ordering). - -# Examples - -In the following example, the fill-reducing permutation used is `[3, 2, 1]`. -If `perm` is set to `1:3` to enforce no permutation, the number of nonzero -elements in the factor is 6. -```jldoctest -julia> A = [2 1 1; 1 2 0; 1 0 2] -3×3 Matrix{Int64}: - 2 1 1 - 1 2 0 - 1 0 2 - -julia> C = cholesky(sparse(A)) -SuiteSparse.CHOLMOD.Factor{Float64} -type: LLt -method: simplicial -maxnnz: 5 -nnz: 5 -success: true - -julia> C.p -3-element Vector{Int64}: - 3 - 2 - 1 - -julia> L = sparse(C.L); - -julia> Matrix(L) -3×3 Matrix{Float64}: - 1.41421 0.0 0.0 - 0.0 1.41421 0.0 - 0.707107 0.707107 1.0 - -julia> L * L' ≈ A[C.p, C.p] -true - -julia> P = sparse(1:3, C.p, ones(3)) -3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries: - ⋅ ⋅ 1.0 - ⋅ 1.0 ⋅ - 1.0 ⋅ ⋅ - -julia> P' * L * L' * P ≈ A -true - -julia> C = cholesky(sparse(A), perm=1:3) -SuiteSparse.CHOLMOD.Factor{Float64} -type: LLt -method: simplicial -maxnnz: 6 -nnz: 6 -success: true - -julia> L = sparse(C.L); - -julia> Matrix(L) -3×3 Matrix{Float64}: - 1.41421 0.0 0.0 - 0.707107 1.22474 0.0 - 0.707107 -0.408248 1.1547 - -julia> L * L' ≈ A -true -``` - -!!! note - This method uses the CHOLMOD library from SuiteSparse, which only supports - doubles or complex doubles. Input matrices not of those element types will - be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` - as appropriate. - - Many other functions from CHOLMOD are wrapped but not exported from the - `Base.SparseArrays.CHOLMOD` module. -""" -cholesky(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, - Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, - Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, - Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - kws...) where {T<:Real} = cholesky(Sparse(A); kws...) - - -function ldlt!(F::Factor{Tv}, A::Sparse{Tv}; - shift::Real=0.0, check::Bool = true) where Tv - # Makes it an LDLt - change_factor!(F, false, false, true, false) - - # Compute the numerical factorization - factorize_p!(A, shift, F) - - check && (issuccess(F) || throw(LinearAlgebra.ZeroPivotException(1))) - return F -end - -""" - ldlt!(F::CHOLMOD.Factor, A::SparseMatrixCSC; shift = 0.0, check = true) -> CHOLMOD.Factor - -Compute the ``LDL'`` factorization of `A`, reusing the symbolic factorization `F`. -`A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@ref)/[`Hermitian`](@ref) -view of a `SparseMatrixCSC`. Note that even if `A` doesn't -have the type tag, it must still be symmetric or Hermitian. - -See also [`ldlt`](@ref). - -!!! note - This method uses the CHOLMOD library from SuiteSparse, which only supports - doubles or complex doubles. Input matrices not of those element types will - be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` - as appropriate. -""" -ldlt!(F::Factor, A::Union{SparseMatrixCSC{T}, - SparseMatrixCSC{Complex{T}}, - Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, - Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, - Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - shift = 0.0, check::Bool = true) where {T<:Real} = - ldlt!(F, Sparse(A), shift = shift, check = check) - -function ldlt(A::Sparse; shift::Real=0.0, check::Bool = true, - perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - - # Makes it an LDLt - @cholmod_param final_ll = false begin - # Really make sure it's an LDLt by avoiding supernodal factorization - @cholmod_param supernodal = 0 begin - # Compute the symbolic factorization - F = symbolic(A; perm = perm) - - # Compute the numerical factorization - ldlt!(F, A; shift = shift, check = check) - - return F - end - end -end - -""" - ldlt(A::SparseMatrixCSC; shift = 0.0, check = true, perm=nothing) -> CHOLMOD.Factor - -Compute the ``LDL'`` factorization of a sparse matrix `A`. -`A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@ref)/[`Hermitian`](@ref) -view of a `SparseMatrixCSC`. Note that even if `A` doesn't -have the type tag, it must still be symmetric or Hermitian. -A fill-reducing permutation is used. `F = ldlt(A)` is most frequently -used to solve systems of equations `A*x = b` with `F\\b`. The returned -factorization object `F` also supports the methods [`diag`](@ref), -[`det`](@ref), [`logdet`](@ref), and [`inv`](@ref). -You can extract individual factors from `F` using `F.L`. -However, since pivoting is on by default, the factorization is internally -represented as `A == P'*L*D*L'*P` with a permutation matrix `P`; -using just `L` without accounting for `P` will give incorrect answers. -To include the effects of permutation, it is typically preferable to extract -"combined" factors like `PtL = F.PtL` (the equivalent of -`P'*L`) and `LtP = F.UP` (the equivalent of `L'*P`). -The complete list of supported factors is `:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP`. - -When `check = true`, an error is thrown if the decomposition fails. -When `check = false`, responsibility for checking the decomposition's -validity (via [`issuccess`](@ref)) lies with the user. - -Setting the optional `shift` keyword argument computes the factorization of -`A+shift*I` instead of `A`. If the `perm` argument is provided, -it should be a permutation of `1:size(A,1)` giving the ordering to use -(instead of CHOLMOD's default AMD ordering). - -!!! note - This method uses the CHOLMOD library from SuiteSparse, which only supports - doubles or complex doubles. Input matrices not of those element types will - be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` - as appropriate. - - Many other functions from CHOLMOD are wrapped but not exported from the - `Base.SparseArrays.CHOLMOD` module. -""" -ldlt(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}, - Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, - Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, - Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - kws...) where {T<:Real} = ldlt(Sparse(A); kws...) - -## Rank updates - -""" - lowrankupdowndate!(F::CHOLMOD.Factor, C::Sparse, update::Cint) - -Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A ± C*C'`. - -If sparsity preserving factorization is used, i.e. `L*L' == P*A*P'` then the new -factor will be `L*L' == P*A*P' + C'*C` - -`update`: `Cint(1)` for `A + CC'`, `Cint(0)` for `A - CC'` -""" -function lowrankupdowndate!(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) where Tv<:VTypes - lF = unsafe_load(pointer(F)) - lC = unsafe_load(pointer(C)) - if lF.n != lC.nrow - throw(DimensionMismatch("matrix dimensions do not fit")) - end - ccall((@cholmod_name("updown"), :libcholmod), Cint, - (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), - update, C, F, common[Threads.threadid()]) - F -end - -#Helper functions for rank updates -lowrank_reorder(V::AbstractArray,p) = Sparse(sparse(V[p,:])) -lowrank_reorder(V::AbstractSparseArray,p) = Sparse(V[p,:]) - -""" - lowrankupdate!(F::CHOLMOD.Factor, C::AbstractArray) - -Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A + C*C'`. - -`LLt` factorizations are converted to `LDLt`. - -See also [`lowrankupdate`](@ref), [`lowrankdowndate`](@ref), [`lowrankdowndate!`](@ref). -""" -function lowrankupdate!(F::Factor{Tv}, V::AbstractArray{Tv}) where Tv<:VTypes - #Reorder and copy V to account for permutation - C = lowrank_reorder(V, get_perm(F)) - lowrankupdowndate!(F, C, Cint(1)) -end - -""" - lowrankdowndate!(F::CHOLMOD.Factor, C::AbstractArray) - -Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A - C*C'`. - -`LLt` factorizations are converted to `LDLt`. - -See also [`lowrankdowndate`](@ref), [`lowrankupdate`](@ref), [`lowrankupdate!`](@ref). -""" -function lowrankdowndate!(F::Factor{Tv}, V::AbstractArray{Tv}) where Tv<:VTypes - #Reorder and copy V to account for permutation - C = lowrank_reorder(V, get_perm(F)) - lowrankupdowndate!(F, C, Cint(0)) -end - -""" - lowrankupdate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor - -Get an `LDLt` Factorization of `A + C*C'` given an `LDLt` or `LLt` factorization `F` of `A`. - -The returned factor is always an `LDLt` factorization. - -See also [`lowrankupdate!`](@ref), [`lowrankdowndate`](@ref), [`lowrankdowndate!`](@ref). -""" -lowrankupdate(F::Factor{Tv}, V::AbstractArray{Tv}) where {Tv<:VTypes} = - lowrankupdate!(copy(F), V) - -""" - lowrankupdate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor - -Get an `LDLt` Factorization of `A + C*C'` given an `LDLt` or `LLt` factorization `F` of `A`. - -The returned factor is always an `LDLt` factorization. - -See also [`lowrankdowndate!`](@ref), [`lowrankupdate`](@ref), [`lowrankupdate!`](@ref). -""" -lowrankdowndate(F::Factor{Tv}, V::AbstractArray{Tv}) where {Tv<:VTypes} = - lowrankdowndate!(copy(F), V) - -## Solvers - -for (T, f) in ((:Dense, :solve), (:Sparse, :spsolve)) - @eval begin - # Solve Lx = b and L'x=b where A = L*L' - function (\)(L::FactorComponent{T,:L}, B::$T) where T - ($f)(CHOLMOD_L, Factor(L), B) - end - function (\)(L::FactorComponent{T,:U}, B::$T) where T - ($f)(CHOLMOD_Lt, Factor(L), B) - end - # Solve PLx = b and L'P'x=b where A = P*L*L'*P' - function (\)(L::FactorComponent{T,:PtL}, B::$T) where T - F = Factor(L) - ($f)(CHOLMOD_L, F, ($f)(CHOLMOD_P, F, B)) # Confusingly, CHOLMOD_P solves P'x = b - end - function (\)(L::FactorComponent{T,:UP}, B::$T) where T - F = Factor(L) - ($f)(CHOLMOD_Pt, F, ($f)(CHOLMOD_Lt, F, B)) - end - # Solve various equations for A = L*D*L' and A = P*L*D*L'*P' - function (\)(L::FactorComponent{T,:D}, B::$T) where T - ($f)(CHOLMOD_D, Factor(L), B) - end - function (\)(L::FactorComponent{T,:LD}, B::$T) where T - ($f)(CHOLMOD_LD, Factor(L), B) - end - function (\)(L::FactorComponent{T,:DU}, B::$T) where T - ($f)(CHOLMOD_DLt, Factor(L), B) - end - function (\)(L::FactorComponent{T,:PtLD}, B::$T) where T - F = Factor(L) - ($f)(CHOLMOD_LD, F, ($f)(CHOLMOD_P, F, B)) - end - function (\)(L::FactorComponent{T,:DUP}, B::$T) where T - F = Factor(L) - ($f)(CHOLMOD_Pt, F, ($f)(CHOLMOD_DLt, F, B)) - end - end -end - -SparseVecOrMat{Tv,Ti} = Union{SparseVector{Tv,Ti}, SparseMatrixCSC{Tv,Ti}} - -function (\)(L::FactorComponent, b::Vector) - reshape(Matrix(L\Dense(b)), length(b)) -end -function (\)(L::FactorComponent, B::Matrix) - Matrix(L\Dense(B)) -end -function (\)(L::FactorComponent, B::SparseVecOrMat) - sparse(L\Sparse(B,0)) -end -(\)(L::FactorComponent, B::Adjoint{<:Any,<:SparseMatrixCSC}) = L \ copy(B) -(\)(L::FactorComponent, B::Transpose{<:Any,<:SparseMatrixCSC}) = L \ copy(B) - -\(adjL::Adjoint{<:Any,<:FactorComponent}, B::Union{VecOrMat,SparseVecOrMat}) = (L = adjL.parent; adjoint(L)\B) - -(\)(L::Factor{T}, B::Dense{T}) where {T<:VTypes} = solve(CHOLMOD_A, L, B) -# Explicit typevars are necessary to avoid ambiguities with defs in linalg/factorizations.jl -# Likewise the two following explicit Vector and Matrix defs (rather than a single VecOrMat) -(\)(L::Factor{T}, B::Vector{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) -(\)(L::Factor{T}, B::Matrix{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) -(\)(L::Factor{T}, B::Adjoint{<:Any, <:Matrix{Complex{T}}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) -(\)(L::Factor{T}, B::Transpose{<:Any, <:Matrix{Complex{T}}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) - -(\)(L::Factor{T}, b::StridedVector) where {T<:VTypes} = Vector(L\Dense{T}(b)) -(\)(L::Factor{T}, B::StridedMatrix) where {T<:VTypes} = Matrix(L\Dense{T}(B)) -(\)(L::Factor{T}, B::Adjoint{<:Any, <:StridedMatrix}) where {T<:VTypes} = Matrix(L\Dense{T}(B)) -(\)(L::Factor{T}, B::Transpose{<:Any, <:StridedMatrix}) where {T<:VTypes} = Matrix(L\Dense{T}(B)) - -(\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B) -# When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric. -(\)(L::Factor, B::SparseMatrixCSC) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0))) -(\)(L::Factor, B::Adjoint{<:Any,<:SparseMatrixCSC}) = L \ copy(B) -(\)(L::Factor, B::Transpose{<:Any,<:SparseMatrixCSC}) = L \ copy(B) -(\)(L::Factor, B::SparseVector) = sparse(spsolve(CHOLMOD_A, L, Sparse(B))) - -\(adjL::Adjoint{<:Any,<:Factor}, B::Dense) = (L = adjL.parent; solve(CHOLMOD_A, L, B)) -\(adjL::Adjoint{<:Any,<:Factor}, B::Sparse) = (L = adjL.parent; spsolve(CHOLMOD_A, L, B)) -\(adjL::Adjoint{<:Any,<:Factor}, B::SparseVecOrMat) = (L = adjL.parent; \(adjoint(L), Sparse(B))) - -function \(adjL::Adjoint{<:Any,<:Factor}, b::StridedVector) - L = adjL.parent - return Vector(solve(CHOLMOD_A, L, Dense(b))) -end -function \(adjL::Adjoint{<:Any,<:Factor}, B::StridedMatrix) - L = adjL.parent - return Matrix(solve(CHOLMOD_A, L, Dense(B))) -end - -const RealHermSymComplexHermF64SSL = Union{ - Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, - Hermitian{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, - Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,SuiteSparse_long}}} -const StridedVecOrMatInclAdjAndTrans = Union{StridedVecOrMat, Adjoint{<:Any, <:StridedVecOrMat}, Transpose{<:Any, <:StridedVecOrMat}} -function \(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMatInclAdjAndTrans) - F = cholesky(A; check = false) - if issuccess(F) - return \(F, B) - else - ldlt!(F, A; check = false) - if issuccess(F) - return \(F, B) - else - return \(lu(SparseMatrixCSC{eltype(A), SuiteSparse_long}(A)), B) - end - end -end -function \(adjA::Adjoint{<:Any,<:RealHermSymComplexHermF64SSL}, B::StridedVecOrMatInclAdjAndTrans) - A = adjA.parent - F = cholesky(A; check = false) - if issuccess(F) - return \(adjoint(F), B) - else - ldlt!(F, A; check = false) - if issuccess(F) - return \(adjoint(F), B) - else - return \(adjoint(lu(SparseMatrixCSC{eltype(A), SuiteSparse_long}(A))), B) - end - end -end - -## Other convenience methods -function diag(F::Factor{Tv}) where Tv - f = unsafe_load(pointer(F)) - fsuper = f.super - fpi = f.pi - res = Base.zeros(Tv, Int(f.n)) - xv = f.x - if f.is_super!=0 - px = f.px - pos = 1 - for i in 1:f.nsuper - base = unsafe_load(px, i) + 1 - res[pos] = unsafe_load(xv, base) - pos += 1 - for j in 1:unsafe_load(fsuper, i + 1) - unsafe_load(fsuper, i) - 1 - res[pos] = unsafe_load(xv, base + j*(unsafe_load(fpi, i + 1) - - unsafe_load(fpi, i) + 1)) - pos += 1 - end - end - else - c0 = f.p - r0 = f.i - xv = f.x - for j in 1:f.n - jj = unsafe_load(c0, j) + 1 - @assert(unsafe_load(r0, jj) == j - 1) - res[j] = unsafe_load(xv, jj) - end - end - res -end - -function logdet(F::Factor{Tv}) where Tv<:VTypes - f = unsafe_load(pointer(F)) - res = zero(Tv) - for d in diag(F); res += log(abs(d)) end - f.is_ll != 0 ? 2res : res -end - -det(L::Factor) = exp(logdet(L)) - -function issuccess(F::Factor) - s = unsafe_load(pointer(F)) - return s.minor == size(F, 1) -end - -function isposdef(F::Factor) - if issuccess(F) - s = unsafe_load(pointer(F)) - if s.is_ll == 1 - return true - else - # try conversion to LLt - change_factor!(F, true, s.is_super, true, s.is_monotonic) - b = issuccess(F) - # convert back - change_factor!(F, false, s.is_super, true, s.is_monotonic) - return b - end - else - return false - end -end - -function ishermitian(A::Sparse{Float64}) - s = unsafe_load(pointer(A)) - if s.stype != 0 - return true - else - i = symmetry(A, 1)[1] - if i < 0 - throw(CHOLMODException("negative value returned from CHOLMOD's symmetry function. This - is either because the indices are not sorted or because of a memory error")) - end - return i == MM_SYMMETRIC || i == MM_SYMMETRIC_POSDIAG - end -end -function ishermitian(A::Sparse{ComplexF64}) - s = unsafe_load(pointer(A)) - if s.stype != 0 - return true - else - i = symmetry(A, 1)[1] - if i < 0 - throw(CHOLMODException("negative value returned from CHOLMOD's symmetry function. This - is either because the indices are not sorted or because of a memory error")) - end - return i == MM_HERMITIAN || i == MM_HERMITIAN_POSDIAG - end -end - -(*)(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, - B::SparseVecOrMat{Float64,Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) -(*)(A::Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,Ti}}, - B::SparseVecOrMat{ComplexF64,Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) -(*)(A::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}, - B::SparseVecOrMat{Float64,Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) - -(*)(A::SparseVecOrMat{Float64,Ti}, - B::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) -(*)(A::SparseVecOrMat{ComplexF64,Ti}, - B::Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) -(*)(A::SparseVecOrMat{Float64,Ti}, - B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) - -# Sort all the indices in each column for the construction of a CSC sparse matrix -function _sort_buffers!(m, n, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv}) where {Ti <: Integer, Tv} - index = Base.zeros(Ti, m) - row = Base.zeros(Ti, m) - val = Base.zeros(Tv, m) - - perm = Base.Perm(Base.ord(isless, identity, false, Base.Order.Forward), row) - - @inbounds for i = 1:n - nzr = colptr[i]:colptr[i+1]-1 - numrows = length(nzr) - if numrows <= 1 - continue - elseif numrows == 2 - f = first(nzr) - s = f+1 - if rowval[f] > rowval[s] - rowval[f], rowval[s] = rowval[s], rowval[f] - nzval[f], nzval[s] = nzval[s], nzval[f] - end - continue - end - resize!(row, numrows) - resize!(index, numrows) - - jj = 1 - @simd for j = nzr - row[jj] = rowval[j] - val[jj] = nzval[j] - jj += 1 - end - - if numrows <= 16 - alg = Base.Sort.InsertionSort - else - alg = Base.Sort.QuickSort - end - - # Reset permutation - index .= 1:numrows - - Base.sort!(index, alg, perm) - - jj = 1 - @simd for j = nzr - rowval[j] = row[index[jj]] - nzval[j] = val[index[jj]] - jj += 1 - end - end -end - - -end #module diff --git a/stdlib/SuiteSparse/src/cholmod_h.jl b/stdlib/SuiteSparse/src/cholmod_h.jl deleted file mode 100644 index 0528b736ba9e7..0000000000000 --- a/stdlib/SuiteSparse/src/cholmod_h.jl +++ /dev/null @@ -1,80 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -## CHOLMOD -const TRUE = Int32(1) -const FALSE = Int32(0) - -## itype defines the types of integer used: -const INT = Int32(0) # all integer arrays are int -const INTLONG = Int32(1) # most are int, some are SuiteSparse_long -const LONG = Int32(2) # all integer arrays are SuiteSparse_long - -## dtype defines what the numerical type is (double or float): -const DOUBLE = Int32(0) # all numerical values are double -const SINGLE = Int32(1) # all numerical values are float -dtyp(::Type{Float32}) = SINGLE -dtyp(::Type{Float64}) = DOUBLE -dtyp(::Type{ComplexF32}) = SINGLE -dtyp(::Type{ComplexF64}) = DOUBLE - -## xtype defines the kind of numerical values used: -const PATTERN = Int32(0) # pattern only, no numerical values -const REAL = Int32(1) # a real matrix -const COMPLEX = Int32(2) # a complex matrix (ANSI C99 compatible) -const ZOMPLEX = Int32(3) # a complex matrix (MATLAB compatible) -xtyp(::Type{Float32}) = REAL -xtyp(::Type{Float64}) = REAL -xtyp(::Type{ComplexF32}) = COMPLEX -xtyp(::Type{ComplexF64}) = COMPLEX - -## Scaling modes, selected by the scale input parameter: -const SCALAR = Int32(0) # A = s*A -const ROW = Int32(1) # A = diag(s)*A -const COL = Int32(2) # A = A*diag(s) -const SYM = Int32(3) # A = diag(s)*A*diag(s) - -## Types of systems to solve -const CHOLMOD_A = Int32(0) # solve Ax=b -const CHOLMOD_LDLt = Int32(1) # solve LDL'x=b -const CHOLMOD_LD = Int32(2) # solve LDx=b -const CHOLMOD_DLt = Int32(3) # solve DL'x=b -const CHOLMOD_L = Int32(4) # solve Lx=b -const CHOLMOD_Lt = Int32(5) # solve L'x=b -const CHOLMOD_D = Int32(6) # solve Dx=b -const CHOLMOD_P = Int32(7) # permute x=Px -const CHOLMOD_Pt = Int32(8) # permute x=P'x - -# Symmetry types -const EMPTY =-1 -const MM_RECTANGULAR = 1 -const MM_UNSYMMETRIC = 2 -const MM_SYMMETRIC = 3 -const MM_HERMITIAN = 4 -const MM_SKEW_SYMMETRIC = 5 -const MM_SYMMETRIC_POSDIAG = 6 -const MM_HERMITIAN_POSDIAG = 7 - -# check the size of SuiteSparse_long -if Int(ccall((:jl_cholmod_sizeof_long, :libsuitesparse_wrapper),Csize_t,())) == 4 - const SuiteSparse_long = Int32 - const IndexTypes = (:Int32,) - const ITypes = Union{Int32} -else - const SuiteSparse_long = Int64 - const IndexTypes = (:Int32, :Int64) - const ITypes = Union{Int32, Int64} -end -ityp(::Type{SuiteSparse_long}) = LONG - - -const VTypes = Union{ComplexF64, Float64} -const VRealTypes = Union{Float64} - -struct CHOLMODException <: Exception - msg::String -end - -function error_handler(status::Cint, file::Cstring, line::Cint, message::Cstring)::Cvoid - status < 0 && throw(CHOLMODException(unsafe_string(message))) - nothing -end diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl deleted file mode 100644 index ee28d60dc4406..0000000000000 --- a/stdlib/SuiteSparse/src/deprecated.jl +++ /dev/null @@ -1 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl deleted file mode 100644 index 0cb0d470fc897..0000000000000 --- a/stdlib/SuiteSparse/src/spqr.jl +++ /dev/null @@ -1,416 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module SPQR - -import Base: \ -using Base: require_one_based_indexing -using LinearAlgebra - -# ordering options */ -const ORDERING_FIXED = Int32(0) -const ORDERING_NATURAL = Int32(1) -const ORDERING_COLAMD = Int32(2) -const ORDERING_GIVEN = Int32(3) # only used for C/C++ interface -const ORDERING_CHOLMOD = Int32(4) # CHOLMOD best-effort (COLAMD, METIS,...) -const ORDERING_AMD = Int32(5) # AMD(A'*A) -const ORDERING_METIS = Int32(6) # metis(A'*A) -const ORDERING_DEFAULT = Int32(7) # SuiteSparseQR default ordering -const ORDERING_BEST = Int32(8) # try COLAMD, AMD, and METIS; pick best -const ORDERING_BESTAMD = Int32(9) # try COLAMD and AMD; pick best# -const ORDERINGS = [ORDERING_FIXED, ORDERING_NATURAL, ORDERING_COLAMD, ORDERING_CHOLMOD, - ORDERING_AMD, ORDERING_METIS, ORDERING_DEFAULT, ORDERING_BEST, - ORDERING_BESTAMD] - -# Let [m n] = size of the matrix after pruning singletons. The default -# ordering strategy is to use COLAMD if m <= 2*n. Otherwise, AMD(A'A) is -# tried. If there is a high fill-in with AMD then try METIS(A'A) and take -# the best of AMD and METIS. METIS is not tried if it isn't installed. - -using SparseArrays -using SparseArrays: getcolptr -using ..SuiteSparse.CHOLMOD -using ..SuiteSparse.CHOLMOD: change_stype!, free! - -function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, - A::Sparse{Tv}, - Bsparse::Union{Sparse{Tv} , Ptr{Cvoid}} = C_NULL, - Bdense::Union{Dense{Tv} , Ptr{Cvoid}} = C_NULL, - Zsparse::Union{Ref{Ptr{CHOLMOD.C_Sparse{Tv}}} , Ptr{Cvoid}} = C_NULL, - Zdense::Union{Ref{Ptr{CHOLMOD.C_Dense{Tv}}} , Ptr{Cvoid}} = C_NULL, - R::Union{Ref{Ptr{CHOLMOD.C_Sparse{Tv}}} , Ptr{Cvoid}} = C_NULL, - E::Union{Ref{Ptr{CHOLMOD.SuiteSparse_long}} , Ptr{Cvoid}} = C_NULL, - H::Union{Ref{Ptr{CHOLMOD.C_Sparse{Tv}}} , Ptr{Cvoid}} = C_NULL, - HPinv::Union{Ref{Ptr{CHOLMOD.SuiteSparse_long}}, Ptr{Cvoid}} = C_NULL, - HTau::Union{Ref{Ptr{CHOLMOD.C_Dense{Tv}}} , Ptr{Cvoid}} = C_NULL) where {Tv<:CHOLMOD.VTypes} - - ordering ∈ ORDERINGS || error("unknown ordering $ordering") - - AA = unsafe_load(pointer(A)) - m, n = AA.nrow, AA.ncol - rnk = ccall((:SuiteSparseQR_C, :libspqr), CHOLMOD.SuiteSparse_long, - (Cint, Cdouble, CHOLMOD.SuiteSparse_long, Cint, - Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Dense{Tv}}, - Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, - Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, - Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{CHOLMOD.Common}), - ordering, # all, except 3:given treated as 0:fixed - tol, # columns with 2-norm <= tol treated as 0 - econ, # e = max(min(m,econ),rank(A)) - getCTX, # 0: Z=C (e-by-k), 1: Z=C', 2: Z=X (e-by-k) - A, # m-by-n sparse matrix to factorize - Bsparse, # sparse m-by-k B - Bdense, # dense m-by-k B - # /* outputs: */ - Zsparse, # sparse Z - Zdense, # dense Z - R, # e-by-n sparse matrix */ - E, # size n column perm, NULL if identity */ - H, # m-by-nh Householder vectors - HPinv, # size m row permutation - HTau, # 1-by-nh Householder coefficients - CHOLMOD.common[Threads.threadid()]) # /* workspace and parameters */ - - if rnk < 0 - error("Sparse QR factorization failed") - end - - e = E[] - if e == C_NULL - _E = Vector{CHOLMOD.SuiteSparse_long}() - else - _E = Vector{CHOLMOD.SuiteSparse_long}(undef, n) - for i in 1:n - @inbounds _E[i] = unsafe_load(e, i) + 1 - end - # Free memory allocated by SPQR. This call will make sure that the - # correct deallocator function is called and that the memory count in - # the common struct is updated - ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), - n, sizeof(CHOLMOD.SuiteSparse_long), e, CHOLMOD.common[Threads.threadid()]) - end - hpinv = HPinv[] - if hpinv == C_NULL - _HPinv = Vector{CHOLMOD.SuiteSparse_long}() - else - _HPinv = Vector{CHOLMOD.SuiteSparse_long}(undef, m) - for i in 1:m - @inbounds _HPinv[i] = unsafe_load(hpinv, i) + 1 - end - # Free memory allocated by SPQR. This call will make sure that the - # correct deallocator function is called and that the memory count in - # the common struct is updated - ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), - m, sizeof(CHOLMOD.SuiteSparse_long), hpinv, CHOLMOD.common[Threads.threadid()]) - end - - return rnk, _E, _HPinv -end - -# Struct for storing sparse QR from SPQR such that -# A[invperm(rpivinv), cpiv] = (I - factors[:,1]*τ[1]*factors[:,1]')*...*(I - factors[:,k]*τ[k]*factors[:,k]')*R -# with k = size(factors, 2). -struct QRSparse{Tv,Ti} <: LinearAlgebra.Factorization{Tv} - factors::SparseMatrixCSC{Tv,Ti} - τ::Vector{Tv} - R::SparseMatrixCSC{Tv,Ti} - cpiv::Vector{Ti} - rpivinv::Vector{Ti} -end - -Base.size(F::QRSparse) = (size(F.factors, 1), size(F.R, 2)) -function Base.size(F::QRSparse, i::Integer) - if i == 1 - return size(F.factors, 1) - elseif i == 2 - return size(F.R, 2) - elseif i > 2 - return 1 - else - throw(ArgumentError("second argument must be positive")) - end -end -Base.axes(F::QRSparse) = map(Base.OneTo, size(F)) - -struct QRSparseQ{Tv<:CHOLMOD.VTypes,Ti<:Integer} <: LinearAlgebra.AbstractQ{Tv} - factors::SparseMatrixCSC{Tv,Ti} - τ::Vector{Tv} - n::Int # Number of columns in original matrix -end - -Base.size(Q::QRSparseQ) = (size(Q.factors, 1), size(Q.factors, 1)) -Base.axes(Q::QRSparseQ) = map(Base.OneTo, size(Q)) - -Matrix{T}(Q::QRSparseQ) where {T} = lmul!(Q, Matrix{T}(I, size(Q, 1), min(size(Q, 1), Q.n))) - -# From SPQR manual p. 6 -_default_tol(A::SparseMatrixCSC) = - 20*sum(size(A))*eps(real(eltype(A)))*maximum(norm(view(A, :, i)) for i in 1:size(A, 2)) - -""" - qr(A::SparseMatrixCSC; tol=_default_tol(A), ordering=ORDERING_DEFAULT) -> QRSparse - -Compute the `QR` factorization of a sparse matrix `A`. Fill-reducing row and column permutations -are used such that `F.R = F.Q'*A[F.prow,F.pcol]`. The main application of this type is to -solve least squares or underdetermined problems with [`\\`](@ref). The function calls the C library SPQR. - -!!! note - `qr(A::SparseMatrixCSC)` uses the SPQR library that is part of SuiteSparse. - As this library only supports sparse matrices with [`Float64`](@ref) or - `ComplexF64` elements, as of Julia v1.4 `qr` converts `A` into a copy that is - of type `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` as appropriate. - -# Examples -```jldoctest -julia> A = sparse([1,2,3,4], [1,1,2,2], [1.0,1.0,1.0,1.0]) -4×2 SparseMatrixCSC{Float64, Int64} with 4 stored entries: - 1.0 ⋅ - 1.0 ⋅ - ⋅ 1.0 - ⋅ 1.0 - -julia> qr(A) -SuiteSparse.SPQR.QRSparse{Float64, Int64} -Q factor: -4×4 SuiteSparse.SPQR.QRSparseQ{Float64, Int64}: - -0.707107 0.0 0.0 -0.707107 - 0.0 -0.707107 -0.707107 0.0 - 0.0 -0.707107 0.707107 0.0 - -0.707107 0.0 0.0 0.707107 -R factor: -2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries: - -1.41421 ⋅ - ⋅ -1.41421 -Row permutation: -4-element Vector{Int64}: - 1 - 3 - 4 - 2 -Column permutation: -2-element Vector{Int64}: - 1 - 2 -``` -""" -function LinearAlgebra.qr(A::SparseMatrixCSC{Tv}; tol=_default_tol(A), ordering=ORDERING_DEFAULT) where {Tv <: CHOLMOD.VTypes} - R = Ref{Ptr{CHOLMOD.C_Sparse{Tv}}}() - E = Ref{Ptr{CHOLMOD.SuiteSparse_long}}() - H = Ref{Ptr{CHOLMOD.C_Sparse{Tv}}}() - HPinv = Ref{Ptr{CHOLMOD.SuiteSparse_long}}() - HTau = Ref{Ptr{CHOLMOD.C_Dense{Tv}}}(C_NULL) - - # SPQR doesn't accept symmetric matrices so we explicitly set the stype - r, p, hpinv = _qr!(ordering, tol, 0, 0, Sparse(A, 0), - C_NULL, C_NULL, C_NULL, C_NULL, - R, E, H, HPinv, HTau) - - R_ = SparseMatrixCSC(Sparse(R[])) - return QRSparse(SparseMatrixCSC(Sparse(H[])), - vec(Array(CHOLMOD.Dense(HTau[]))), - SparseMatrixCSC(min(size(A)...), - size(R_, 2), - getcolptr(R_), - rowvals(R_), - nonzeros(R_)), - p, hpinv) -end -LinearAlgebra.qr(A::SparseMatrixCSC{<:Union{Float16,Float32}}; tol=_default_tol(A)) = - qr(convert(SparseMatrixCSC{Float64}, A); tol=tol) -LinearAlgebra.qr(A::SparseMatrixCSC{<:Union{ComplexF16,ComplexF32}}; tol=_default_tol(A)) = - qr(convert(SparseMatrixCSC{ComplexF64}, A); tol=tol) -LinearAlgebra.qr(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}; - tol=_default_tol(A)) where {T<:AbstractFloat} = - throw(ArgumentError(string("matrix type ", typeof(A), "not supported. ", - "Try qr(convert(SparseMatrixCSC{Float64/ComplexF64, Int}, A)) for ", - "sparse floating point QR using SPQR or qr(Array(A)) for generic ", - "dense QR."))) -LinearAlgebra.qr(A::SparseMatrixCSC; tol=_default_tol(A)) = qr(float(A); tol=tol) - -function LinearAlgebra.lmul!(Q::QRSparseQ, A::StridedVecOrMat) - if size(A, 1) != size(Q, 1) - throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) - end - for l in size(Q.factors, 2):-1:1 - τl = -Q.τ[l] - h = view(Q.factors, :, l) - for j in 1:size(A, 2) - a = view(A, :, j) - LinearAlgebra.axpy!(τl*dot(h, a), h, a) - end - end - return A -end - -function LinearAlgebra.rmul!(A::StridedMatrix, Q::QRSparseQ) - if size(A, 2) != size(Q, 1) - throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) - end - tmp = similar(A, size(A, 1)) - for l in 1:size(Q.factors, 2) - τl = -Q.τ[l] - h = view(Q.factors, :, l) - LinearAlgebra.mul!(tmp, A, h) - LinearAlgebra.lowrankupdate!(A, tmp, h, τl) - end - return A -end - -function LinearAlgebra.lmul!(adjQ::Adjoint{<:Any,<:QRSparseQ}, A::StridedVecOrMat) - Q = adjQ.parent - if size(A, 1) != size(Q, 1) - throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) - end - for l in 1:size(Q.factors, 2) - τl = -Q.τ[l] - h = view(Q.factors, :, l) - for j in 1:size(A, 2) - a = view(A, :, j) - LinearAlgebra.axpy!(τl'*dot(h, a), h, a) - end - end - return A -end - -function LinearAlgebra.rmul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRSparseQ}) - Q = adjQ.parent - if size(A, 2) != size(Q, 1) - throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) - end - tmp = similar(A, size(A, 1)) - for l in size(Q.factors, 2):-1:1 - τl = -Q.τ[l] - h = view(Q.factors, :, l) - LinearAlgebra.mul!(tmp, A, h) - LinearAlgebra.lowrankupdate!(A, tmp, h, τl') - end - return A -end - -@inline function Base.getproperty(F::QRSparse, d::Symbol) - if d === :Q - return QRSparseQ(F.factors, F.τ, size(F, 2)) - elseif d === :prow - return invperm(F.rpivinv) - elseif d === :pcol - return F.cpiv - else - getfield(F, d) - end -end - -function Base.propertynames(F::QRSparse, private::Bool=false) - public = (:R, :Q, :prow, :pcol) - private ? ((public ∪ fieldnames(typeof(F)))...,) : public -end - -function Base.show(io::IO, mime::MIME{Symbol("text/plain")}, F::QRSparse) - summary(io, F); println(io) - println(io, "Q factor:") - show(io, mime, F.Q) - println(io, "\nR factor:") - show(io, mime, F.R) - println(io, "\nRow permutation:") - show(io, mime, F.prow) - println(io, "\nColumn permutation:") - show(io, mime, F.pcol) -end - -# With a real lhs and complex rhs with the same precision, we can reinterpret -# the complex rhs as a real rhs with twice the number of columns -# -# This definition is similar to the definition in factorization.jl except that -# here we have to use \ instead of ldiv! because of limitations in SPQR - -## Two helper methods -_ret_size(F::QRSparse, b::AbstractVector) = (size(F, 2),) -_ret_size(F::QRSparse, B::AbstractMatrix) = (size(F, 2), size(B, 2)) - -LinearAlgebra.rank(F::QRSparse) = reduce(max, view(rowvals(F.R), 1:nnz(F.R)), init = eltype(rowvals(F.R))(0)) -LinearAlgebra.rank(S::SparseMatrixCSC) = rank(qr(S)) - -function (\)(F::QRSparse{T}, B::VecOrMat{Complex{T}}) where T<:LinearAlgebra.BlasReal -# |z1|z3| reinterpret |x1|x2|x3|x4| transpose |x1|y1| reshape |x1|y1|x3|y3| -# |z2|z4| -> |y1|y2|y3|y4| -> |x2|y2| -> |x2|y2|x4|y4| -# |x3|y3| -# |x4|y4| - require_one_based_indexing(F, B) - c2r = reshape(copy(transpose(reinterpret(T, reshape(B, (1, length(B)))))), size(B, 1), 2*size(B, 2)) - x = F\c2r - -# |z1|z3| reinterpret |x1|x2|x3|x4| transpose |x1|y1| reshape |x1|y1|x3|y3| -# |z2|z4| <- |y1|y2|y3|y4| <- |x2|y2| <- |x2|y2|x4|y4| -# |x3|y3| -# |x4|y4| - return collect(reshape(reinterpret(Complex{T}, copy(transpose(reshape(x, (length(x) >> 1), 2)))), _ret_size(F, B))) -end - -function _ldiv_basic(F::QRSparse, B::StridedVecOrMat) - if size(F, 1) != size(B, 1) - throw(DimensionMismatch("size(F) = $(size(F)) but size(B) = $(size(B))")) - end - - # The rank of F equal might be reduced - rnk = rank(F) - - # allocate an array for the return value large enough to hold B and X - # For overdetermined problem, B is larger than X and vice versa - X = similar(B, ntuple(i -> i == 1 ? max(size(F, 2), size(B, 1)) : size(B, 2), Val(ndims(B)))) - - # Fill will zeros. These will eventually become the zeros in the basic solution - # fill!(X, 0) - # Apply left permutation to the solution and store in X - for j in 1:size(B, 2) - for i in 1:length(F.rpivinv) - @inbounds X[F.rpivinv[i], j] = B[i, j] - end - end - - # Make a view into X corresponding to the size of B - X0 = view(X, 1:size(B, 1), :) - - # Apply Q' to B - LinearAlgebra.lmul!(adjoint(F.Q), X0) - - # Zero out to get basic solution - X[rnk + 1:end, :] .= 0 - - # Solve R*X = B - LinearAlgebra.ldiv!(UpperTriangular(F.R[Base.OneTo(rnk), Base.OneTo(rnk)]), - view(X0, Base.OneTo(rnk), :)) - - # Apply right permutation and extract solution from X - # NB: cpiv == [] if SPQR was called with ORDERING_FIXED - if length(F.cpiv) == 0 - return getindex(X, ntuple(i -> i == 1 ? (1:size(F,2)) : :, Val(ndims(B)))...) - end - return getindex(X, ntuple(i -> i == 1 ? invperm(F.cpiv) : :, Val(ndims(B)))...) -end - -(\)(F::QRSparse{T}, B::StridedVecOrMat{T}) where {T} = _ldiv_basic(F, B) -""" - (\\)(F::QRSparse, B::StridedVecOrMat) - -Solve the least squares problem ``\\min\\|Ax - b\\|^2`` or the linear system of equations -``Ax=b`` when `F` is the sparse QR factorization of ``A``. A basic solution is returned -when the problem is underdetermined. - -# Examples -```jldoctest -julia> A = sparse([1,2,4], [1,1,1], [1.0,1.0,1.0], 4, 2) -4×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries: - 1.0 ⋅ - 1.0 ⋅ - ⋅ ⋅ - 1.0 ⋅ - -julia> qr(A)\\fill(1.0, 4) -2-element Vector{Float64}: - 1.0 - 0.0 -``` -""" -(\)(F::QRSparse, B::StridedVecOrMat) = F\convert(AbstractArray{eltype(F)}, B) - -end # module diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl deleted file mode 100644 index 61cb2a035a5b9..0000000000000 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ /dev/null @@ -1,833 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module UMFPACK - -export UmfpackLU - -import Base: (\), getproperty, show, size -using LinearAlgebra -import LinearAlgebra: Factorization, checksquare, det, logabsdet, lu, lu!, ldiv! - -using SparseArrays -using SparseArrays: getcolptr -import SparseArrays: nnz - -import Serialization: AbstractSerializer, deserialize - -import ..increment, ..increment!, ..decrement, ..decrement! - -include("umfpack_h.jl") -struct MatrixIllConditionedException <: Exception - msg::String -end - -function umferror(status::Integer) - if status==UMFPACK_OK - return - elseif status==UMFPACK_WARNING_singular_matrix - throw(LinearAlgebra.SingularException(0)) - elseif status==UMFPACK_WARNING_determinant_underflow - throw(MatrixIllConditionedException("the determinant is nonzero but underflowed")) - elseif status==UMFPACK_WARNING_determinant_overflow - throw(MatrixIllConditionedException("the determinant overflowed")) - elseif status==UMFPACK_ERROR_out_of_memory - throw(OutOfMemoryError()) - elseif status==UMFPACK_ERROR_invalid_Numeric_object - throw(ArgumentError("invalid UMFPack numeric object")) - elseif status==UMFPACK_ERROR_invalid_Symbolic_object - throw(ArgumentError("invalid UMFPack symbolic object")) - elseif status==UMFPACK_ERROR_argument_missing - throw(ArgumentError("a required argument to UMFPack is missing")) - elseif status==UMFPACK_ERROR_n_nonpositive - throw(ArgumentError("the number of rows or columns of the matrix must be greater than zero")) - elseif status==UMFPACK_ERROR_invalid_matrix - throw(ArgumentError("invalid matrix")) - elseif status==UMFPACK_ERROR_different_pattern - throw(ArgumentError("pattern of the matrix changed")) - elseif status==UMFPACK_ERROR_invalid_system - throw(ArgumentError("invalid sys argument provided to UMFPack solver")) - elseif status==UMFPACK_ERROR_invalid_permutation - throw(ArgumentError("invalid permutation")) - elseif status==UMFPACK_ERROR_file_IO - throw(ErrorException("error saving / loading UMFPack decomposition")) - elseif status==UMFPACK_ERROR_ordering_failed - throw(ErrorException("the ordering method failed")) - elseif status==UMFPACK_ERROR_internal_error - throw(ErrorException("an internal error has occurred, of unknown cause")) - else - throw(ErrorException("unknown UMFPack error code: $status")) - end -end - -macro isok(A) - :(umferror($(esc(A)))) -end - -# check the size of SuiteSparse_long -if Int(ccall((:jl_cholmod_sizeof_long,:libsuitesparse_wrapper),Csize_t,())) == 4 - const UmfpackIndexTypes = (:Int32,) - const UMFITypes = Int32 -else - const UmfpackIndexTypes = (:Int32, :Int64) - const UMFITypes = Union{Int32, Int64} -end - -const UMFVTypes = Union{Float64,ComplexF64} - -## UMFPACK - -# the control and info arrays -const umf_ctrl = Vector{Float64}(undef, UMFPACK_CONTROL) -ccall((:umfpack_dl_defaults,:libumfpack), Cvoid, (Ptr{Float64},), umf_ctrl) -const umf_info = Vector{Float64}(undef, UMFPACK_INFO) - -function show_umf_ctrl(level::Real = 2.0) - old_prt::Float64 = umf_ctrl[1] - umf_ctrl[1] = Float64(level) - ccall((:umfpack_dl_report_control, :libumfpack), Cvoid, (Ptr{Float64},), umf_ctrl) - umf_ctrl[1] = old_prt -end - -function show_umf_info(level::Real = 2.0) - old_prt::Float64 = umf_ctrl[1] - umf_ctrl[1] = Float64(level) - ccall((:umfpack_dl_report_info, :libumfpack), Cvoid, - (Ptr{Float64}, Ptr{Float64}), umf_ctrl, umf_info) - umf_ctrl[1] = old_prt -end - -## Should this type be immutable? -mutable struct UmfpackLU{Tv<:UMFVTypes,Ti<:UMFITypes} <: Factorization{Tv} - symbolic::Ptr{Cvoid} - numeric::Ptr{Cvoid} - m::Int - n::Int - colptr::Vector{Ti} # 0-based column pointers - rowval::Vector{Ti} # 0-based row indices - nzval::Vector{Tv} - status::Int -end - -Base.adjoint(F::UmfpackLU) = Adjoint(F) -Base.transpose(F::UmfpackLU) = Transpose(F) - -""" - lu(A::SparseMatrixCSC; check = true) -> F::UmfpackLU - -Compute the LU factorization of a sparse matrix `A`. - -For sparse `A` with real or complex element type, the return type of `F` is -`UmfpackLU{Tv, Ti}`, with `Tv` = [`Float64`](@ref) or `ComplexF64` respectively and -`Ti` is an integer type ([`Int32`](@ref) or [`Int64`](@ref)). - -When `check = true`, an error is thrown if the decomposition fails. -When `check = false`, responsibility for checking the decomposition's -validity (via [`issuccess`](@ref)) lies with the user. - -The individual components of the factorization `F` can be accessed by indexing: - -| Component | Description | -|:----------|:------------------------------------| -| `L` | `L` (lower triangular) part of `LU` | -| `U` | `U` (upper triangular) part of `LU` | -| `p` | right permutation `Vector` | -| `q` | left permutation `Vector` | -| `Rs` | `Vector` of scaling factors | -| `:` | `(L,U,p,q,Rs)` components | - -The relation between `F` and `A` is - -`F.L*F.U == (F.Rs .* A)[F.p, F.q]` - -`F` further supports the following functions: - -- [`\\`](@ref) -- [`cond`](@ref) -- [`det`](@ref) - -!!! note - `lu(A::SparseMatrixCSC)` uses the UMFPACK library that is part of - SuiteSparse. As this library only supports sparse matrices with [`Float64`](@ref) or - `ComplexF64` elements, `lu` converts `A` into a copy that is of type - `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` as appropriate. -""" -function lu(S::SparseMatrixCSC{<:UMFVTypes,<:UMFITypes}; check::Bool = true) - zerobased = getcolptr(S)[1] == 0 - res = UmfpackLU(C_NULL, C_NULL, size(S, 1), size(S, 2), - zerobased ? copy(getcolptr(S)) : decrement(getcolptr(S)), - zerobased ? copy(rowvals(S)) : decrement(rowvals(S)), - copy(nonzeros(S)), 0) - finalizer(umfpack_free_symbolic, res) - umfpack_numeric!(res) - check && (issuccess(res) || throw(LinearAlgebra.SingularException(0))) - return res -end -lu(A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}; - check::Bool = true) where {Ti<:UMFITypes} = - lu(convert(SparseMatrixCSC{Float64,Ti}, A); check = check) -lu(A::SparseMatrixCSC{<:Union{ComplexF16,ComplexF32},Ti}; - check::Bool = true) where {Ti<:UMFITypes} = - lu(convert(SparseMatrixCSC{ComplexF64,Ti}, A); check = check) -lu(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}; - check::Bool = true) where {T<:AbstractFloat} = - throw(ArgumentError(string("matrix type ", typeof(A), "not supported. ", - "Try lu(convert(SparseMatrixCSC{Float64/ComplexF64,Int}, A)) for ", - "sparse floating point LU using UMFPACK or lu(Array(A)) for generic ", - "dense LU."))) -lu(A::SparseMatrixCSC; check::Bool = true) = lu(float(A); check = check) - -""" - lu!(F::UmfpackLU, A::SparseMatrixCSC; check=true) -> F::UmfpackLU - -Compute the LU factorization of a sparse matrix `A`, reusing the symbolic -factorization of an already existing LU factorization stored in `F`. The -sparse matrix `A` must have an identical nonzero pattern as the matrix used -to create the LU factorization `F`, otherwise an error is thrown. - -When `check = true`, an error is thrown if the decomposition fails. -When `check = false`, responsibility for checking the decomposition's -validity (via [`issuccess`](@ref)) lies with the user. - -!!! note - `lu!(F::UmfpackLU, A::SparseMatrixCSC)` uses the UMFPACK library that is part of - SuiteSparse. As this library only supports sparse matrices with [`Float64`](@ref) or - `ComplexF64` elements, `lu!` converts `A` into a copy that is of type - `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{ComplexF64}` as appropriate. - -!!! compat "Julia 1.5" - `lu!` for `UmfpackLU` requires at least Julia 1.5. - -# Examples -```jldoctest -julia> A = sparse(Float64[1.0 2.0; 0.0 3.0]); - -julia> F = lu(A); - -julia> B = sparse(Float64[1.0 1.0; 0.0 1.0]); - -julia> lu!(F, B); - -julia> F \\ ones(2) -2-element Vector{Float64}: - 0.0 - 1.0 -``` -""" -function lu!(F::UmfpackLU, S::SparseMatrixCSC{<:UMFVTypes,<:UMFITypes}; check::Bool=true) - zerobased = getcolptr(S)[1] == 0 - F.m = size(S, 1) - F.n = size(S, 2) - F.colptr = zerobased ? copy(getcolptr(S)) : decrement(getcolptr(S)) - F.rowval = zerobased ? copy(rowvals(S)) : decrement(rowvals(S)) - F.nzval = copy(nonzeros(S)) - - umfpack_numeric!(F, reuse_numeric = false) - check && (issuccess(F) || throw(LinearAlgebra.SingularException(0))) - return F -end -lu!(F::UmfpackLU, A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}; - check::Bool = true) where {Ti<:UMFITypes} = - lu!(F, convert(SparseMatrixCSC{Float64,Ti}, A); check = check) -lu!(F::UmfpackLU, A::SparseMatrixCSC{<:Union{ComplexF16,ComplexF32},Ti}; - check::Bool = true) where {Ti<:UMFITypes} = - lu!(F, convert(SparseMatrixCSC{ComplexF64,Ti}, A); check = check) -lu!(F::UmfpackLU, A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}; - check::Bool = true) where {T<:AbstractFloat} = - throw(ArgumentError(string("matrix type ", typeof(A), "not supported."))) -lu!(F::UmfpackLU, A::SparseMatrixCSC; check::Bool = true) = lu!(F, float(A); check = check) - -size(F::UmfpackLU) = (F.m, F.n) -function size(F::UmfpackLU, dim::Integer) - if dim < 1 - throw(ArgumentError("size: dimension $dim out of range")) - elseif dim == 1 - return Int(F.m) - elseif dim == 2 - return Int(F.n) - else - return 1 - end -end - -function show(io::IO, mime::MIME{Symbol("text/plain")}, F::UmfpackLU) - if F.numeric != C_NULL - if issuccess(F) - summary(io, F); println(io) - println(io, "L factor:") - show(io, mime, F.L) - println(io, "\nU factor:") - show(io, mime, F.U) - else - print(io, "Failed factorization of type $(typeof(F))") - end - end -end - -function deserialize(s::AbstractSerializer, t::Type{UmfpackLU{Tv,Ti}}) where {Tv,Ti} - symbolic = deserialize(s) - numeric = deserialize(s) - m = deserialize(s) - n = deserialize(s) - colptr = deserialize(s) - rowval = deserialize(s) - nzval = deserialize(s) - status = deserialize(s) - obj = UmfpackLU{Tv,Ti}(symbolic, numeric, m, n, colptr, rowval, nzval, status) - - finalizer(umfpack_free_symbolic, obj) - - return obj -end - -# compute the sign/parity of a permutation -function _signperm(p) - n = length(p) - result = 0 - todo = trues(n) - while any(todo) - k = findfirst(todo) - todo[k] = false - result += 1 # increment element count - j = p[k] - while j != k - result += 1 # increment element count - todo[j] = false - j = p[j] - end - result += 1 # increment cycle count - end - return ifelse(isodd(result), -1, 1) -end - -## Wrappers for UMFPACK functions - -# generate the name of the C function according to the value and integer types -umf_nm(nm,Tv,Ti) = "umfpack_" * (Tv === :Float64 ? "d" : "z") * (Ti === :Int64 ? "l_" : "i_") * nm - -for itype in UmfpackIndexTypes - sym_r = umf_nm("symbolic", :Float64, itype) - sym_c = umf_nm("symbolic", :ComplexF64, itype) - num_r = umf_nm("numeric", :Float64, itype) - num_c = umf_nm("numeric", :ComplexF64, itype) - sol_r = umf_nm("solve", :Float64, itype) - sol_c = umf_nm("solve", :ComplexF64, itype) - det_r = umf_nm("get_determinant", :Float64, itype) - det_z = umf_nm("get_determinant", :ComplexF64, itype) - lunz_r = umf_nm("get_lunz", :Float64, itype) - lunz_z = umf_nm("get_lunz", :ComplexF64, itype) - get_num_r = umf_nm("get_numeric", :Float64, itype) - get_num_z = umf_nm("get_numeric", :ComplexF64, itype) - @eval begin - function umfpack_symbolic!(U::UmfpackLU{Float64,$itype}) - if U.symbolic != C_NULL return U end - tmp = Vector{Ptr{Cvoid}}(undef, 1) - @isok ccall(($sym_r, :libumfpack), $itype, - ($itype, $itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Cvoid}, - Ptr{Float64}, Ptr{Float64}), - U.m, U.n, U.colptr, U.rowval, U.nzval, tmp, - umf_ctrl, umf_info) - U.symbolic = tmp[1] - return U - end - function umfpack_symbolic!(U::UmfpackLU{ComplexF64,$itype}) - if U.symbolic != C_NULL return U end - tmp = Vector{Ptr{Cvoid}}(undef, 1) - @isok ccall(($sym_c, :libumfpack), $itype, - ($itype, $itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, Ptr{Cvoid}, - Ptr{Float64}, Ptr{Float64}), - U.m, U.n, U.colptr, U.rowval, real(U.nzval), imag(U.nzval), tmp, - umf_ctrl, umf_info) - U.symbolic = tmp[1] - return U - end - function umfpack_numeric!(U::UmfpackLU{Float64,$itype}; reuse_numeric = true) - if (reuse_numeric && U.numeric != C_NULL) return U end - if U.symbolic == C_NULL umfpack_symbolic!(U) end - tmp = Vector{Ptr{Cvoid}}(undef, 1) - status = ccall(($num_r, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Float64}, Ptr{Float64}), - U.colptr, U.rowval, U.nzval, U.symbolic, tmp, - umf_ctrl, umf_info) - U.status = status - if status != UMFPACK_WARNING_singular_matrix - umferror(status) - end - U.numeric != C_NULL && umfpack_free_numeric(U) - U.numeric = tmp[1] - return U - end - function umfpack_numeric!(U::UmfpackLU{ComplexF64,$itype}; reuse_numeric = true) - if (reuse_numeric && U.numeric != C_NULL) return U end - if U.symbolic == C_NULL umfpack_symbolic!(U) end - tmp = Vector{Ptr{Cvoid}}(undef, 1) - status = ccall(($num_c, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Float64}, Ptr{Float64}), - U.colptr, U.rowval, real(U.nzval), imag(U.nzval), U.symbolic, tmp, - umf_ctrl, umf_info) - U.status = status - if status != UMFPACK_WARNING_singular_matrix - umferror(status) - end - U.numeric != C_NULL && umfpack_free_numeric(U) - U.numeric = tmp[1] - return U - end - function solve!(x::StridedVector{Float64}, lu::UmfpackLU{Float64,$itype}, b::StridedVector{Float64}, typ::Integer) - if x === b - throw(ArgumentError("output array must not be aliased with input array")) - end - if stride(x, 1) != 1 || stride(b, 1) != 1 - throw(ArgumentError("in and output vectors must have unit strides")) - end - umfpack_numeric!(lu) - (size(b,1) == lu.m) && (size(b) == size(x)) || throw(DimensionMismatch()) - @isok ccall(($sol_r, :libumfpack), $itype, - ($itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Cvoid}, Ptr{Float64}, - Ptr{Float64}), - typ, lu.colptr, lu.rowval, lu.nzval, - x, b, lu.numeric, umf_ctrl, - umf_info) - return x - end - function solve!(x::StridedVector{ComplexF64}, lu::UmfpackLU{ComplexF64,$itype}, b::StridedVector{ComplexF64}, typ::Integer) - if x === b - throw(ArgumentError("output array must not be aliased with input array")) - end - if stride(x, 1) != 1 || stride(b, 1) != 1 - throw(ArgumentError("in and output vectors must have unit strides")) - end - umfpack_numeric!(lu) - (size(b, 1) == lu.m) && (size(b) == size(x)) || throw(DimensionMismatch()) - n = size(b, 1) - @isok ccall(($sol_c, :libumfpack), $itype, - ($itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, - Ptr{Float64}, Ptr{Cvoid}, Ptr{Float64}, Ptr{Float64}), - typ, lu.colptr, lu.rowval, lu.nzval, - C_NULL, x, C_NULL, b, - C_NULL, lu.numeric, umf_ctrl, umf_info) - return x - end - function det(lu::UmfpackLU{Float64,$itype}) - mx = Ref{Float64}() - @isok ccall(($det_r,:libumfpack), $itype, - (Ptr{Float64},Ptr{Float64},Ptr{Cvoid},Ptr{Float64}), - mx, C_NULL, lu.numeric, umf_info) - mx[] - end - function det(lu::UmfpackLU{ComplexF64,$itype}) - mx = Ref{Float64}() - mz = Ref{Float64}() - @isok ccall(($det_z,:libumfpack), $itype, - (Ptr{Float64},Ptr{Float64},Ptr{Float64},Ptr{Cvoid},Ptr{Float64}), - mx, mz, C_NULL, lu.numeric, umf_info) - complex(mx[], mz[]) - end - function logabsdet(F::UmfpackLU{T, $itype}) where {T<:Union{Float64,ComplexF64}} # return log(abs(det)) and sign(det) - n = checksquare(F) - issuccess(F) || return log(zero(real(T))), zero(T) - U = F.U - Rs = F.Rs - p = F.p - q = F.q - s = _signperm(p)*_signperm(q)*one(real(T)) - P = one(T) - abs_det = zero(real(T)) - @inbounds for i in 1:n - dg_ii = U[i, i] / Rs[i] - P *= sign(dg_ii) - abs_det += log(abs(dg_ii)) - end - return abs_det, s * P - end - function umf_lunz(lu::UmfpackLU{Float64,$itype}) - lnz = Ref{$itype}() - unz = Ref{$itype}() - n_row = Ref{$itype}() - n_col = Ref{$itype}() - nz_diag = Ref{$itype}() - @isok ccall(($lunz_r,:libumfpack), $itype, - (Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{Cvoid}), - lnz, unz, n_row, n_col, nz_diag, lu.numeric) - (lnz[], unz[], n_row[], n_col[], nz_diag[]) - end - function umf_lunz(lu::UmfpackLU{ComplexF64,$itype}) - lnz = Ref{$itype}() - unz = Ref{$itype}() - n_row = Ref{$itype}() - n_col = Ref{$itype}() - nz_diag = Ref{$itype}() - @isok ccall(($lunz_z,:libumfpack), $itype, - (Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{Cvoid}), - lnz, unz, n_row, n_col, nz_diag, lu.numeric) - (lnz[], unz[], n_row[], n_col[], nz_diag[]) - end - function getproperty(lu::UmfpackLU{Float64, $itype}, d::Symbol) - if d === :L - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - # L is returned in CSR (compressed sparse row) format - Lj = Vector{$itype}(undef, lnz) - Lx = Vector{Float64}(undef, lnz) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - Lp, Lj, Lx, - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, - increment!(Lp), increment!(Lj), Lx))) - elseif d === :U - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, - Up, Ui, Ux, - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), - increment!(Ui), Ux) - elseif d === :p - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - P = Vector{$itype}(undef, n_row) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, - P, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return increment!(P) - elseif d === :q - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Q = Vector{$itype}(undef, n_col) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{$itype}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, - C_NULL, Q, C_NULL, - C_NULL, C_NULL, lu.numeric) - return increment!(Q) - elseif d === :Rs - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, - C_NULL, Rs, lu.numeric) - return Rs - elseif d === :(:) - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - # L is returned in CSR (compressed sparse row) format - Lj = Vector{$itype}(undef, lnz) - Lx = Vector{Float64}(undef, lnz) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - P = Vector{$itype}(undef, n_row) - Q = Vector{$itype}(undef, n_col) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_r, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, - Ptr{$itype}, Ptr{$itype}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), - Lp, Lj, Lx, - Up, Ui, Ux, - P, Q, C_NULL, - C_NULL, Rs, lu.numeric) - return (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, - increment!(Lp), increment!(Lj), - Lx))), - SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), - increment!(Ui), Ux), - increment!(P), increment!(Q), Rs) - else - return getfield(lu, d) - end - end - function getproperty(lu::UmfpackLU{ComplexF64, $itype}, d::Symbol) - if d === :L - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - # L is returned in CSR (compressed sparse row) format - Lj = Vector{$itype}(undef, lnz) - Lx = Vector{Float64}(undef, lnz) - Lz = Vector{Float64}(undef, lnz) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - Lp, Lj, Lx, Lz, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, - increment!(Lp), increment!(Lj), - complex.(Lx, Lz)))) - elseif d === :U - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - Uz = Vector{Float64}(undef, unz) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, C_NULL, - Up, Ui, Ux, Uz, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), - increment!(Ui), complex.(Ux, Uz)) - elseif d === :p - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - P = Vector{$itype}(undef, n_row) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, C_NULL, - P, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return increment!(P) - elseif d === :q - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Q = Vector{$itype}(undef, n_col) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, Q, C_NULL, C_NULL, - C_NULL, C_NULL, lu.numeric) - return increment!(Q) - elseif d === :Rs - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, C_NULL, C_NULL, C_NULL, - C_NULL, Rs, lu.numeric) - return Rs - elseif d === :(:) - umfpack_numeric!(lu) # ensure the numeric decomposition exists - (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Vector{$itype}(undef, n_row + 1) - # L is returned in CSR (compressed sparse row) format - Lj = Vector{$itype}(undef, lnz) - Lx = Vector{Float64}(undef, lnz) - Lz = Vector{Float64}(undef, lnz) - Up = Vector{$itype}(undef, n_col + 1) - Ui = Vector{$itype}(undef, unz) - Ux = Vector{Float64}(undef, unz) - Uz = Vector{Float64}(undef, unz) - P = Vector{$itype}(undef, n_row) - Q = Vector{$itype}(undef, n_col) - Rs = Vector{Float64}(undef, n_row) - @isok ccall(($get_num_z, :libumfpack), $itype, - (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, - Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, - Ptr{$itype}, Ptr{$itype}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Cvoid}, Ptr{Float64}, Ptr{Cvoid}), - Lp, Lj, Lx, Lz, - Up, Ui, Ux, Uz, - P, Q, C_NULL, C_NULL, - C_NULL, Rs, lu.numeric) - return (copy(transpose(SparseMatrixCSC(min(n_row, n_col), n_row, - increment!(Lp), increment!(Lj), - complex.(Lx, Lz)))), - SparseMatrixCSC(min(n_row, n_col), n_col, increment!(Up), - increment!(Ui), complex.(Ux, Uz)), - increment!(P), increment!(Q), Rs) - else - return getfield(lu, d) - end - end - end -end - -# backward compatibility -umfpack_extract(lu::UmfpackLU) = getproperty(lu, :(:)) - -function nnz(lu::UmfpackLU) - lnz, unz, = umf_lunz(lu) - return Int(lnz + unz) -end - -LinearAlgebra.issuccess(lu::UmfpackLU) = lu.status == UMFPACK_OK - -### Solve with Factorization - -import LinearAlgebra.ldiv! - -ldiv!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - ldiv!(B, lu, copy(B)) -ldiv!(translu::Transpose{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = translu.parent; ldiv!(B, transpose(lu), copy(B))) -ldiv!(adjlu::Adjoint{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = adjlu.parent; ldiv!(B, adjoint(lu), copy(B))) -ldiv!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = - ldiv!(B, lu, copy(B)) -ldiv!(translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = - (lu = translu.parent; ldiv!(B, transpose(lu), copy(B))) -ldiv!(adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = - (lu = adjlu.parent; ldiv!(B, adjoint(lu), copy(B))) - -ldiv!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -ldiv!(X::StridedVecOrMat{T}, translu::Transpose{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = translu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat)) -ldiv!(X::StridedVecOrMat{T}, adjlu::Adjoint{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = adjlu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_At)) -ldiv!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -ldiv!(X::StridedVecOrMat{Tb}, translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = - (lu = translu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat)) -ldiv!(X::StridedVecOrMat{Tb}, adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = - (lu = adjlu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_At)) - -function _Aq_ldiv_B!(X::StridedVecOrMat, lu::UmfpackLU, B::StridedVecOrMat, transposeoptype) - if size(X, 2) != size(B, 2) - throw(DimensionMismatch("input and output arrays must have same number of columns")) - end - _AqldivB_kernel!(X, lu, B, transposeoptype) - return X -end -function _AqldivB_kernel!(x::StridedVector{T}, lu::UmfpackLU{T}, - b::StridedVector{T}, transposeoptype) where T<:UMFVTypes - solve!(x, lu, b, transposeoptype) -end -function _AqldivB_kernel!(X::StridedMatrix{T}, lu::UmfpackLU{T}, - B::StridedMatrix{T}, transposeoptype) where T<:UMFVTypes - for col in 1:size(X, 2) - solve!(view(X, :, col), lu, view(B, :, col), transposeoptype) - end -end -function _AqldivB_kernel!(x::StridedVector{Tb}, lu::UmfpackLU{Float64}, - b::StridedVector{Tb}, transposeoptype) where Tb<:Complex - r, i = similar(b, Float64), similar(b, Float64) - solve!(r, lu, Vector{Float64}(real(b)), transposeoptype) - solve!(i, lu, Vector{Float64}(imag(b)), transposeoptype) - map!(complex, x, r, i) -end -function _AqldivB_kernel!(X::StridedMatrix{Tb}, lu::UmfpackLU{Float64}, - B::StridedMatrix{Tb}, transposeoptype) where Tb<:Complex - r = similar(B, Float64, size(B, 1)) - i = similar(B, Float64, size(B, 1)) - for j in 1:size(B, 2) - solve!(r, lu, Vector{Float64}(real(view(B, :, j))), transposeoptype) - solve!(i, lu, Vector{Float64}(imag(view(B, :, j))), transposeoptype) - map!(complex, view(X, :, j), r, i) - end -end - -for Tv in (:Float64, :ComplexF64), Ti in UmfpackIndexTypes - f = Symbol(umf_nm("free_symbolic", Tv, Ti)) - @eval begin - function ($f)(symb::Ptr{Cvoid}) - tmp = [symb] - ccall(($(string(f)), :libumfpack), Cvoid, (Ptr{Cvoid},), tmp) - end - - function umfpack_free_symbolic(lu::UmfpackLU{$Tv,$Ti}) - if lu.symbolic == C_NULL return lu end - umfpack_free_numeric(lu) - ($f)(lu.symbolic) - lu.symbolic = C_NULL - return lu - end - end - - f = Symbol(umf_nm("free_numeric", Tv, Ti)) - @eval begin - function ($f)(num::Ptr{Cvoid}) - tmp = [num] - ccall(($(string(f)), :libumfpack), Cvoid, (Ptr{Cvoid},), tmp) - end - function umfpack_free_numeric(lu::UmfpackLU{$Tv,$Ti}) - if lu.numeric == C_NULL return lu end - ($f)(lu.numeric) - lu.numeric = C_NULL - return lu - end - end -end - -function umfpack_report_symbolic(symb::Ptr{Cvoid}, level::Real) - old_prl::Float64 = umf_ctrl[UMFPACK_PRL] - umf_ctrl[UMFPACK_PRL] = Float64(level) - @isok ccall((:umfpack_dl_report_symbolic, :libumfpack), Int, - (Ptr{Cvoid}, Ptr{Float64}), symb, umf_ctrl) - umf_ctrl[UMFPACK_PRL] = old_prl -end - -umfpack_report_symbolic(symb::Ptr{Cvoid}) = umfpack_report_symbolic(symb, 4.) - -function umfpack_report_symbolic(lu::UmfpackLU, level::Real) - umfpack_report_symbolic(umfpack_symbolic!(lu).symbolic, level) -end - -umfpack_report_symbolic(lu::UmfpackLU) = umfpack_report_symbolic(lu.symbolic,4.) -function umfpack_report_numeric(num::Ptr{Cvoid}, level::Real) - old_prl::Float64 = umf_ctrl[UMFPACK_PRL] - umf_ctrl[UMFPACK_PRL] = Float64(level) - @isok ccall((:umfpack_dl_report_numeric, :libumfpack), Int, - (Ptr{Cvoid}, Ptr{Float64}), num, umf_ctrl) - umf_ctrl[UMFPACK_PRL] = old_prl -end - -umfpack_report_numeric(num::Ptr{Cvoid}) = umfpack_report_numeric(num, 4.) -function umfpack_report_numeric(lu::UmfpackLU, level::Real) - umfpack_report_numeric(umfpack_numeric!(lu).numeric, level) -end - -umfpack_report_numeric(lu::UmfpackLU) = umfpack_report_numeric(lu,4.) - -end # UMFPACK module diff --git a/stdlib/SuiteSparse/src/umfpack_h.jl b/stdlib/SuiteSparse/src/umfpack_h.jl deleted file mode 100644 index 985f9387fcc75..0000000000000 --- a/stdlib/SuiteSparse/src/umfpack_h.jl +++ /dev/null @@ -1,43 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -## UMFPACK - -## Type of solve -const UMFPACK_A = 0 # Ax=b -const UMFPACK_At = 1 # adjoint(A)x=b -const UMFPACK_Aat = 2 # transpose(A)x=b -const UMFPACK_Pt_L = 3 # adjoint(P)Lx=b -const UMFPACK_L = 4 # Lx=b -const UMFPACK_Lt_P = 5 # adjoint(L)Px=b -const UMFPACK_Lat_P = 6 # transpose(L)Px=b -const UMFPACK_Lt = 7 # adjoint(L)x=b -const UMFPACK_Lat = 8 # transpose(L)x=b -const UMFPACK_U_Qt = 9 # U*adjoint(Q)x=b -const UMFPACK_U = 10 # Ux=b -const UMFPACK_Q_Ut = 11 # Q*adjoint(U)x=b -const UMFPACK_Q_Uat = 12 # Q*transpose(U)x=b -const UMFPACK_Ut = 13 # adjoint(U)x=b -const UMFPACK_Uat = 14 # transpose(U)x=b - -## Sizes of Control and Info arrays for returning information from solver -const UMFPACK_INFO = 90 -const UMFPACK_CONTROL = 20 -const UMFPACK_PRL = 1 - -## Status codes -const UMFPACK_OK = 0 -const UMFPACK_WARNING_singular_matrix = 1 -const UMFPACK_WARNING_determinant_underflow = 2 -const UMFPACK_WARNING_determinant_overflow = 3 -const UMFPACK_ERROR_out_of_memory = -1 -const UMFPACK_ERROR_invalid_Numeric_object = -3 -const UMFPACK_ERROR_invalid_Symbolic_object = -4 -const UMFPACK_ERROR_argument_missing = -5 -const UMFPACK_ERROR_n_nonpositive = -6 -const UMFPACK_ERROR_invalid_matrix = -8 -const UMFPACK_ERROR_different_pattern = -11 -const UMFPACK_ERROR_invalid_system = -13 -const UMFPACK_ERROR_invalid_permutation = -15 -const UMFPACK_ERROR_internal_error = -911 -const UMFPACK_ERROR_file_IO = -17 -const UMFPACK_ERROR_ordering_failed = -18 diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl deleted file mode 100644 index 8e2fb231587f1..0000000000000 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ /dev/null @@ -1,945 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using SuiteSparse.CHOLMOD -using SuiteSparse -using DelimitedFiles -using Test -using Random -using Serialization -using LinearAlgebra: - I, cholesky, cholesky!, det, diag, eigmax, ishermitian, isposdef, issuccess, - issymmetric, ldlt, ldlt!, logdet, norm, opnorm, Diagonal, Hermitian, Symmetric, - PosDefException, ZeroPivotException -using SparseArrays -using SparseArrays: getcolptr - -# CHOLMOD tests -Random.seed!(123) - -@testset "Check that the Common and Method Julia structs are consistent with their C counterparts" begin - common_size = ccall((:jl_cholmod_common_size, :libsuitesparse_wrapper), Csize_t, ()) - @test common_size == sizeof(CHOLMOD.Common) - - method_offsets = Vector{Csize_t}(undef,15) - ccall((:jl_cholmod_method_offsets, :libsuitesparse_wrapper), - Nothing, (Ptr{Csize_t},), method_offsets) - @test method_offsets == fieldoffset.(CHOLMOD.Method,1:length(method_offsets)) - - common_offsets = Vector{Csize_t}(undef,107) - ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), - Nothing, (Ptr{Csize_t},), common_offsets) - @test common_offsets == fieldoffset.(CHOLMOD.Common,1:length(common_offsets)) -end - -@testset "based on deps/SuiteSparse-4.0.2/CHOLMOD/Demo/" begin - -# chm_rdsp(joinpath(Sys.BINDIR, "../../deps/SuiteSparse-4.0.2/CHOLMOD/Demo/Matrix/bcsstk01.tri")) -# because the file may not exist in binary distributions and when a system suitesparse library -# is used - -## Result from C program -## ---------------------------------- cholmod_demo: -## norm (A,inf) = 3.57095e+09 -## norm (A,1) = 3.57095e+09 -## CHOLMOD sparse: A: 48-by-48, nz 224, upper. OK -## CHOLMOD dense: B: 48-by-1, OK -## bnorm 1.97917 -## Analyze: flop 6009 lnz 489 -## Factorizing A -## CHOLMOD factor: L: 48-by-48 simplicial, LDL'. nzmax 489. nz 489 OK -## Ordering: AMD fl/lnz 12.3 lnz/anz 2.2 -## ints in L: 782, doubles in L: 489 -## factor flops 6009 nnz(L) 489 (w/no amalgamation) -## nnz(A*A'): 224 -## flops / nnz(L): 12.3 -## nnz(L) / nnz(A): 2.2 -## analyze cputime: 0.0000 -## factor cputime: 0.0000 mflop: 0.0 -## solve cputime: 0.0000 mflop: 0.0 -## overall cputime: 0.0000 mflop: 0.0 -## peak memory usage: 0 (MB) -## residual 2.5e-19 (|Ax-b|/(|A||x|+|b|)) -## residual 1.3e-19 (|Ax-b|/(|A||x|+|b|)) after iterative refinement -## rcond 9.5e-06 - - n = 48 - A = CHOLMOD.Sparse(n, n, - CHOLMOD.SuiteSparse_long[0,1,2,3,6,9,12,15,18,20,25,30,34,36,39,43,47,52,58, - 62,67,71,77,84,90,93,95,98,103,106,110,115,119,123,130,136,142,146,150,155, - 161,167,174,182,189,197,207,215,224], # zero-based column pointers - CHOLMOD.SuiteSparse_long[0,1,2,1,2,3,0,2,4,0,1,5,0,4,6,1,3,7,2,8,1,3,7,8,9, - 0,4,6,8,10,5,6,7,11,6,12,7,11,13,8,10,13,14,9,13,14,15,8,10,12,14,16,7,11, - 12,13,16,17,0,12,16,18,1,5,13,15,19,2,4,14,20,3,13,15,19,20,21,2,4,12,16,18, - 20,22,1,5,17,18,19,23,0,5,24,1,25,2,3,26,2,3,25,26,27,4,24,28,0,5,24,29,6, - 11,24,28,30,7,25,27,31,8,9,26,32,8,9,25,27,31,32,33,10,24,28,30,32,34,6,11, - 29,30,31,35,12,17,30,36,13,31,35,37,14,15,32,34,38,14,15,33,37,38,39,16,32, - 34,36,38,40,12,17,31,35,36,37,41,12,16,17,18,23,36,40,42,13,14,15,19,37,39, - 43,13,14,15,20,21,38,43,44,13,14,15,20,21,37,39,43,44,45,12,16,17,22,36,40, - 42,46,12,16,17,18,23,41,42,46,47], - [2.83226851852e6,1.63544753086e6,1.72436728395e6,-2.0e6,-2.08333333333e6, - 1.00333333333e9,1.0e6,-2.77777777778e6,1.0675e9,2.08333333333e6, - 5.55555555555e6,1.53533333333e9,-3333.33333333,-1.0e6,2.83226851852e6, - -6666.66666667,2.0e6,1.63544753086e6,-1.68e6,1.72436728395e6,-2.0e6,4.0e8, - 2.0e6,-2.08333333333e6,1.00333333333e9,1.0e6,2.0e8,-1.0e6,-2.77777777778e6, - 1.0675e9,-2.0e6,2.08333333333e6,5.55555555555e6,1.53533333333e9,-2.8e6, - 2.8360994695e6,-30864.1975309,-5.55555555555e6,1.76741074446e6, - -15432.0987654,2.77777777778e6,517922.131816,3.89003806848e6, - -3.33333333333e6,4.29857058902e6,-2.6349902747e6,1.97572063531e9, - -2.77777777778e6,3.33333333333e8,-2.14928529451e6,2.77777777778e6, - 1.52734651547e9,5.55555555555e6,6.66666666667e8,2.35916180402e6, - -5.55555555555e6,-1.09779731332e8,1.56411143711e9,-2.8e6,-3333.33333333, - 1.0e6,2.83226851852e6,-30864.1975309,-5.55555555555e6,-6666.66666667, - -2.0e6,1.63544753086e6,-15432.0987654,2.77777777778e6,-1.68e6, - 1.72436728395e6,-3.33333333333e6,2.0e6,4.0e8,-2.0e6,-2.08333333333e6, - 1.00333333333e9,-2.77777777778e6,3.33333333333e8,-1.0e6,2.0e8,1.0e6, - 2.77777777778e6,1.0675e9,5.55555555555e6,6.66666666667e8,-2.0e6, - 2.08333333333e6,-5.55555555555e6,1.53533333333e9,-28935.1851852, - -2.08333333333e6,60879.6296296,-1.59791666667e6,3.37291666667e6, - -28935.1851852,2.08333333333e6,2.41171296296e6,-2.08333333333e6, - 1.0e8,-2.5e6,-416666.666667,1.5e9,-833333.333333,1.25e6,5.01833333333e8, - 2.08333333333e6,1.0e8,416666.666667,5.025e8,-28935.1851852, - -2.08333333333e6,-4166.66666667,-1.25e6,3.98587962963e6,-1.59791666667e6, - -8333.33333333,2.5e6,3.41149691358e6,-28935.1851852,2.08333333333e6, - -2.355e6,2.43100308642e6,-2.08333333333e6,1.0e8,-2.5e6,5.0e8,2.5e6, - -416666.666667,1.50416666667e9,-833333.333333,1.25e6,2.5e8,-1.25e6, - -3.47222222222e6,1.33516666667e9,2.08333333333e6,1.0e8,-2.5e6, - 416666.666667,6.94444444444e6,2.16916666667e9,-28935.1851852, - -2.08333333333e6,-3.925e6,3.98587962963e6,-1.59791666667e6, - -38580.2469136,-6.94444444444e6,3.41149691358e6,-28935.1851852, - 2.08333333333e6,-19290.1234568,3.47222222222e6,2.43100308642e6, - -2.08333333333e6,1.0e8,-4.16666666667e6,2.5e6,-416666.666667, - 1.50416666667e9,-833333.333333,-3.47222222222e6,4.16666666667e8, - -1.25e6,3.47222222222e6,1.33516666667e9,2.08333333333e6,1.0e8, - 6.94444444445e6,8.33333333333e8,416666.666667,-6.94444444445e6, - 2.16916666667e9,-3830.95098171,1.14928529451e6,-275828.470683, - -28935.1851852,-2.08333333333e6,-4166.66666667,1.25e6,64710.5806113, - -131963.213599,-517922.131816,-2.29857058902e6,-1.59791666667e6, - -8333.33333333,-2.5e6,3.50487988027e6,-517922.131816,-2.16567078453e6, - 551656.941366,-28935.1851852,2.08333333333e6,-2.355e6,517922.131816, - 4.57738374749e6,2.29857058902e6,-551656.941367,4.8619365099e8, - -2.08333333333e6,1.0e8,2.5e6,5.0e8,-4.79857058902e6,134990.2747, - 2.47238730198e9,-1.14928529451e6,2.29724661236e8,-5.57173510779e7, - -833333.333333,-1.25e6,2.5e8,2.39928529451e6,9.61679848804e8,275828.470683, - -5.57173510779e7,1.09411960038e7,2.08333333333e6,1.0e8,-2.5e6, - 140838.195984,-1.09779731332e8,5.31278103775e8], 1) - @test CHOLMOD.norm_sparse(A, 0) ≈ 3.570948074697437e9 - @test CHOLMOD.norm_sparse(A, 1) ≈ 3.570948074697437e9 - @test_throws ArgumentError CHOLMOD.norm_sparse(A, 2) - @test CHOLMOD.isvalid(A) - - x = fill(1., n) - b = A*x - - chma = ldlt(A) # LDL' form - @test CHOLMOD.isvalid(chma) - @test unsafe_load(pointer(chma)).is_ll == 0 # check that it is in fact an LDLt - @test chma\b ≈ x - @test nnz(ldlt(A, perm=1:size(A,1))) > nnz(chma) - @test size(chma) == size(A) - chmal = CHOLMOD.FactorComponent(chma, :L) - @test size(chmal) == size(A) - @test size(chmal, 1) == size(A, 1) - - chma = cholesky(A) # LL' form - @test CHOLMOD.isvalid(chma) - @test unsafe_load(pointer(chma)).is_ll == 1 # check that it is in fact an LLt - @test chma\b ≈ x - @test nnz(chma) == 489 - @test nnz(cholesky(A, perm=1:size(A,1))) > nnz(chma) - @test size(chma) == size(A) - chmal = CHOLMOD.FactorComponent(chma, :L) - @test size(chmal) == size(A) - @test size(chmal, 1) == size(A, 1) - - @testset "eltype" begin - @test eltype(Dense(fill(1., 3))) == Float64 - @test eltype(A) == Float64 - @test eltype(chma) == Float64 - end -end - -@testset "lp_afiro example" begin - afiro = CHOLMOD.Sparse(27, 51, - CHOLMOD.SuiteSparse_long[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, - 23,25,27,29,33,37,41,45,47,49,51,53,55,57,59,63,65,67,69,71,75,79,83,87,89, - 91,93,95,97,99,101,102], - CHOLMOD.SuiteSparse_long[2,3,6,7,8,9,12,13,16,17,18,19,20,21,22,23,24,25,26, - 0,1,2,23,0,3,0,21,1,25,4,5,6,24,4,5,7,24,4,5,8,24,4,5,9,24,6,20,7,20,8,20,9, - 20,3,4,4,22,5,26,10,11,12,21,10,13,10,23,10,20,11,25,14,15,16,22,14,15,17, - 22,14,15,18,22,14,15,19,22,16,20,17,20,18,20,19,20,13,15,15,24,14,26,15], - [1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, - 1.0,-1.0,-1.06,1.0,0.301,1.0,-1.0,1.0,-1.0,1.0,1.0,-1.0,-1.06,1.0,0.301, - -1.0,-1.06,1.0,0.313,-1.0,-0.96,1.0,0.313,-1.0,-0.86,1.0,0.326,-1.0,2.364, - -1.0,2.386,-1.0,2.408,-1.0,2.429,1.4,1.0,1.0,-1.0,1.0,1.0,-1.0,-0.43,1.0, - 0.109,1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,1.0,-0.43,1.0,1.0,0.109,-0.43,1.0,1.0, - 0.108,-0.39,1.0,1.0,0.108,-0.37,1.0,1.0,0.107,-1.0,2.191,-1.0,2.219,-1.0, - 2.249,-1.0,2.279,1.4,-1.0,1.0,-1.0,1.0,1.0,1.0], 0) - afiro2 = CHOLMOD.aat(afiro, CHOLMOD.SuiteSparse_long[0:50;], CHOLMOD.SuiteSparse_long(1)) - CHOLMOD.change_stype!(afiro2, -1) - chmaf = cholesky(afiro2) - y = afiro'*fill(1., size(afiro,1)) - sol = chmaf\(afiro*y) # least squares solution - @test CHOLMOD.isvalid(sol) - pred = afiro'*sol - @test norm(afiro * (convert(Matrix, y) - convert(Matrix, pred))) < 1e-8 -end - -@testset "Issue 9160" begin - local A, B - A = sprand(10, 10, 0.1) - A = convert(SparseMatrixCSC{Float64,CHOLMOD.SuiteSparse_long}, A) - cmA = CHOLMOD.Sparse(A) - - B = sprand(10, 10, 0.1) - B = convert(SparseMatrixCSC{Float64,CHOLMOD.SuiteSparse_long}, B) - cmB = CHOLMOD.Sparse(B) - - # Ac_mul_B - @test sparse(cmA'*cmB) ≈ A'*B - - # A_mul_Bc - @test sparse(cmA*cmB') ≈ A*B' - - # A_mul_Ac - @test sparse(cmA*cmA') ≈ A*A' - - # Ac_mul_A - @test sparse(cmA'*cmA) ≈ A'*A - - # A_mul_Ac for symmetric A - A = 0.5*(A + copy(A')) - cmA = CHOLMOD.Sparse(A) - @test sparse(cmA*cmA') ≈ A*A' -end - -@testset "Issue #9915" begin - sparseI = sparse(1.0I, 2, 2) - @test sparseI \ sparseI == sparseI -end - -@testset "test Sparse constructor Symmetric and Hermitian input (and issymmetric and ishermitian)" begin - ACSC = sprandn(10, 10, 0.3) + I - @test issymmetric(Sparse(Symmetric(ACSC, :L))) - @test issymmetric(Sparse(Symmetric(ACSC, :U))) - @test ishermitian(Sparse(Hermitian(complex(ACSC), :L))) - @test ishermitian(Sparse(Hermitian(complex(ACSC), :U))) -end - -@testset "test Sparse constructor for C_Sparse{Cvoid} (and read_sparse)" begin - mktempdir() do temp_dir - testfile = joinpath(temp_dir, "tmp.mtx") - - writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) - @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5;0 0.5 1] - rm(testfile) - - writedlm(testfile, ["%%MatrixMarket matrix coordinate complex Hermitian", - "3 3 4","1 1 1.0 0.0","2 2 1.0 0.0","3 2 0.5 0.5","3 3 1.0 0.0"]) - @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5-0.5im;0 0.5+0.5im 1] - rm(testfile) - - # this also tests that the error message is correctly retrieved from the library - writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","%3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) - @test_throws CHOLMOD.CHOLMODException("indices out of range") sparse(CHOLMOD.Sparse(testfile)) - rm(testfile) - end -end - -@testset "test that Sparse(Ptr) constructor throws the right places" begin - @test_throws ArgumentError CHOLMOD.Sparse(convert(Ptr{CHOLMOD.C_Sparse{Float64}}, C_NULL)) - @test_throws ArgumentError CHOLMOD.Sparse(convert(Ptr{CHOLMOD.C_Sparse{Cvoid}}, C_NULL)) -end - -## The struct pointer must be constructed by the library constructor and then modified afterwards to checks that the method throws -@testset "illegal dtype (for now but should be supported at some point)" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - puint = convert(Ptr{UInt32}, p) - unsafe_store!(puint, CHOLMOD.SINGLE, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) -end - -@testset "illegal dtype" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - puint = convert(Ptr{UInt32}, p) - unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) -end - -@testset "illegal xtype" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - puint = convert(Ptr{UInt32}, p) - unsafe_store!(puint, 3, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 3) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) -end - -@testset "illegal itype I" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - puint = convert(Ptr{UInt32}, p) - unsafe_store!(puint, CHOLMOD.INTLONG, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) -end - -@testset "illegal itype II" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - puint = convert(Ptr{UInt32}, p) - unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) -end - -# Test Dense wrappers (only Float64 supported a present) - -@testset "High level interface" for elty in (Float64, ComplexF64) - local A, b - if elty == Float64 - A = randn(5, 5) - b = randn(5) - else - A = complex.(randn(5, 5), randn(5, 5)) - b = complex.(randn(5), randn(5)) - end - ADense = CHOLMOD.Dense(A) - bDense = CHOLMOD.Dense(b) - - @test_throws BoundsError ADense[6, 1] - @test_throws BoundsError ADense[1, 6] - @test copy(ADense) == ADense - @test CHOLMOD.norm_dense(ADense, 1) ≈ opnorm(A, 1) - @test CHOLMOD.norm_dense(ADense, 0) ≈ opnorm(A, Inf) - @test_throws ArgumentError CHOLMOD.norm_dense(ADense, 2) - @test_throws ArgumentError CHOLMOD.norm_dense(ADense, 3) - - @test CHOLMOD.norm_dense(bDense, 2) ≈ norm(b) - @test CHOLMOD.check_dense(bDense) - - AA = CHOLMOD.eye(3) - unsafe_store!(convert(Ptr{Csize_t}, pointer(AA)), 2, 1) # change size, but not stride, of Dense - @test convert(Matrix, AA) == Matrix(I, 2, 3) -end - -@testset "Low level interface" begin - @test isa(CHOLMOD.zeros(3, 3, Float64), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.zeros(3, 3), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.zeros(3, 3, Float64), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.ones(3, 3), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.eye(3, 4, Float64), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.eye(3, 4), CHOLMOD.Dense{Float64}) - @test isa(CHOLMOD.eye(3), CHOLMOD.Dense{Float64}) - @test isa(copy(CHOLMOD.eye(3)), CHOLMOD.Dense{Float64}) -end - -# Test Sparse and Factor -@testset "test free!" begin - p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Float64}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) - @test CHOLMOD.free!(p) -end - -@testset "Core functionality" for elty in (Float64, ComplexF64) - A1 = sparse([1:5; 1], [1:5; 2], elty == Float64 ? randn(6) : complex.(randn(6), randn(6))) - A2 = sparse([1:5; 1], [1:5; 2], elty == Float64 ? randn(6) : complex.(randn(6), randn(6))) - A1pd = A1'A1 - A1Sparse = CHOLMOD.Sparse(A1) - A2Sparse = CHOLMOD.Sparse(A2) - A1pdSparse = CHOLMOD.Sparse( - size(A1pd, 1), - size(A1pd, 2), - SuiteSparse.decrement(getcolptr(A1pd)), - SuiteSparse.decrement(rowvals(A1pd)), - nonzeros(A1pd)) - - ## High level interface - @test isa(CHOLMOD.Sparse(3, 3, [0,1,3,4], [0,2,1,2], fill(1., 4)), CHOLMOD.Sparse) # Sparse doesn't require columns to be sorted - @test_throws BoundsError A1Sparse[6, 1] - @test_throws BoundsError A1Sparse[1, 6] - @test sparse(A1Sparse) == A1 - for i = 1:size(A1, 1) - A1[i, i] = real(A1[i, i]) - end #Construct Hermitian matrix properly - @test CHOLMOD.sparse(CHOLMOD.Sparse(Hermitian(A1, :L))) == Hermitian(A1, :L) - @test CHOLMOD.sparse(CHOLMOD.Sparse(Hermitian(A1, :U))) == Hermitian(A1, :U) - @test_throws ArgumentError convert(SparseMatrixCSC{elty,Int}, A1pdSparse) - if elty <: Real - @test_throws ArgumentError convert(Symmetric{Float64,SparseMatrixCSC{Float64,Int}}, A1Sparse) - else - @test_throws ArgumentError convert(Hermitian{ComplexF64,SparseMatrixCSC{ComplexF64,Int}}, A1Sparse) - end - @test copy(A1Sparse) == A1Sparse - @test size(A1Sparse, 3) == 1 - if elty <: Real # multiplication only defined for real matrices in CHOLMOD - @test A1Sparse*A2Sparse ≈ A1*A2 - @test_throws DimensionMismatch CHOLMOD.Sparse(A1[:,1:4])*A2Sparse - @test A1Sparse'A2Sparse ≈ A1'A2 - @test A1Sparse*A2Sparse' ≈ A1*A2' - - @test A1Sparse*A1Sparse ≈ A1*A1 - @test A1Sparse'A1Sparse ≈ A1'A1 - @test A1Sparse*A1Sparse' ≈ A1*A1' - - @test A1pdSparse*A1pdSparse ≈ A1pd*A1pd - @test A1pdSparse'A1pdSparse ≈ A1pd'A1pd - @test A1pdSparse*A1pdSparse' ≈ A1pd*A1pd' - - @test_throws DimensionMismatch A1Sparse*CHOLMOD.eye(4, 5, elty) - end - - # Factor - @test_throws ArgumentError cholesky(A1) - @test_throws ArgumentError cholesky(A1) - @test_throws ArgumentError cholesky(A1, shift=1.0) - @test_throws ArgumentError ldlt(A1) - @test_throws ArgumentError ldlt(A1, shift=1.0) - C = A1 + copy(adjoint(A1)) - λmaxC = eigmax(Array(C)) - b = fill(1., size(A1, 1)) - @test_throws PosDefException cholesky(C - 2λmaxC*I) - @test_throws PosDefException cholesky(C, shift=-2λmaxC) - @test_throws ZeroPivotException ldlt(C - C[1,1]*I) - @test_throws ZeroPivotException ldlt(C, shift=-real(C[1,1])) - @test !isposdef(cholesky(C - 2λmaxC*I; check = false)) - @test !isposdef(cholesky(C, shift=-2λmaxC; check = false)) - @test !issuccess(ldlt(C - C[1,1]*I; check = false)) - @test !issuccess(ldlt(C, shift=-real(C[1,1]); check = false)) - F = cholesky(A1pd) - tmp = IOBuffer() - show(tmp, F) - @test tmp.size > 0 - @test isa(CHOLMOD.Sparse(F), CHOLMOD.Sparse{elty}) - @test_throws DimensionMismatch F\CHOLMOD.Dense(fill(elty(1), 4)) - @test_throws DimensionMismatch F\CHOLMOD.Sparse(sparse(fill(elty(1), 4))) - b = fill(1., 5) - bT = fill(elty(1), 5) - @test F'\bT ≈ Array(A1pd)'\b - @test F'\sparse(bT) ≈ Array(A1pd)'\b - @test transpose(F)\bT ≈ conj(A1pd)'\bT - @test F\CHOLMOD.Sparse(sparse(bT)) ≈ A1pd\b - @test logdet(F) ≈ logdet(Array(A1pd)) - @test det(F) == exp(logdet(F)) - let # to test supernodal, we must use a larger matrix - Ftmp = sprandn(100, 100, 0.1) - Ftmp = Ftmp'Ftmp + I - @test logdet(cholesky(Ftmp)) ≈ logdet(Array(Ftmp)) - end - @test logdet(ldlt(A1pd)) ≈ logdet(Array(A1pd)) - @test isposdef(A1pd) - @test !isposdef(A1) - @test !isposdef(A1 + copy(A1') |> t -> t - 2eigmax(Array(t))*I) - - if elty <: Real - @test CHOLMOD.issymmetric(Sparse(A1pd, 0)) - @test CHOLMOD.Sparse(cholesky(Symmetric(A1pd, :L))) == CHOLMOD.Sparse(cholesky(A1pd)) - F1 = CHOLMOD.Sparse(cholesky(Symmetric(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(cholesky(A1pd, shift=2)) - @test F1 == F2 - @test CHOLMOD.Sparse(ldlt(Symmetric(A1pd, :L))) == CHOLMOD.Sparse(ldlt(A1pd)) - F1 = CHOLMOD.Sparse(ldlt(Symmetric(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(ldlt(A1pd, shift=2)) - @test F1 == F2 - else - @test !CHOLMOD.issymmetric(Sparse(A1pd, 0)) - @test CHOLMOD.ishermitian(Sparse(A1pd, 0)) - @test CHOLMOD.Sparse(cholesky(Hermitian(A1pd, :L))) == CHOLMOD.Sparse(cholesky(A1pd)) - F1 = CHOLMOD.Sparse(cholesky(Hermitian(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(cholesky(A1pd, shift=2)) - @test F1 == F2 - @test CHOLMOD.Sparse(ldlt(Hermitian(A1pd, :L))) == CHOLMOD.Sparse(ldlt(A1pd)) - F1 = CHOLMOD.Sparse(ldlt(Hermitian(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(ldlt(A1pd, shift=2)) - @test F1 == F2 - end - - ### cholesky!/ldlt! - F = cholesky(A1pd) - CHOLMOD.change_factor!(F, false, false, true, true) - @test unsafe_load(pointer(F)).is_ll == 0 - CHOLMOD.change_factor!(F, true, false, true, true) - @test CHOLMOD.Sparse(cholesky!(copy(F), A1pd)) ≈ CHOLMOD.Sparse(F) # surprisingly, this can cause small ulp size changes so we cannot test exact equality - @test size(F, 2) == 5 - @test size(F, 3) == 1 - @test_throws ArgumentError size(F, 0) - - F = cholesky(A1pdSparse, shift=2) - @test isa(CHOLMOD.Sparse(F), CHOLMOD.Sparse{elty}) - @test CHOLMOD.Sparse(cholesky!(copy(F), A1pd, shift=2.0)) ≈ CHOLMOD.Sparse(F) # surprisingly, this can cause small ulp size changes so we cannot test exact equality - - F = ldlt(A1pd) - @test isa(CHOLMOD.Sparse(F), CHOLMOD.Sparse{elty}) - @test CHOLMOD.Sparse(ldlt!(copy(F), A1pd)) ≈ CHOLMOD.Sparse(F) # surprisingly, this can cause small ulp size changes so we cannot test exact equality - - F = ldlt(A1pdSparse, shift=2) - @test isa(CHOLMOD.Sparse(F), CHOLMOD.Sparse{elty}) - @test CHOLMOD.Sparse(ldlt!(copy(F), A1pd, shift=2.0)) ≈ CHOLMOD.Sparse(F) # surprisingly, this can cause small ulp size changes so we cannot test exact equality - - @test isa(CHOLMOD.factor_to_sparse!(F), CHOLMOD.Sparse) - @test_throws CHOLMOD.CHOLMODException CHOLMOD.factor_to_sparse!(F) - - ## Low level interface - @test CHOLMOD.nnz(A1Sparse) == nnz(A1) - @test CHOLMOD.speye(5, 5, elty) == Matrix(I, 5, 5) - @test CHOLMOD.spzeros(5, 5, 5, elty) == zeros(elty, 5, 5) - if elty <: Real - @test CHOLMOD.copy(A1Sparse, 0, 1) == A1Sparse - @test CHOLMOD.horzcat(A1Sparse, A2Sparse, true) == [A1 A2] - @test CHOLMOD.vertcat(A1Sparse, A2Sparse, true) == [A1; A2] - svec = fill(elty(1), 1) - @test CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.SCALAR, A1Sparse) == A1Sparse - svec = fill(elty(1), 5) - @test_throws DimensionMismatch CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.SCALAR, A1Sparse) - @test CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.ROW, A1Sparse) == A1Sparse - @test_throws DimensionMismatch CHOLMOD.scale!(CHOLMOD.Dense([svec; 1]), CHOLMOD.ROW, A1Sparse) - @test CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.COL, A1Sparse) == A1Sparse - @test_throws DimensionMismatch CHOLMOD.scale!(CHOLMOD.Dense([svec; 1]), CHOLMOD.COL, A1Sparse) - @test CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.SYM, A1Sparse) == A1Sparse - @test_throws DimensionMismatch CHOLMOD.scale!(CHOLMOD.Dense([svec; 1]), CHOLMOD.SYM, A1Sparse) - @test_throws DimensionMismatch CHOLMOD.scale!(CHOLMOD.Dense(svec), CHOLMOD.SYM, CHOLMOD.Sparse(A1[:,1:4])) - else - @test_throws MethodError CHOLMOD.copy(A1Sparse, 0, 1) == A1Sparse - @test_throws MethodError CHOLMOD.horzcat(A1Sparse, A2Sparse, true) == [A1 A2] - @test_throws MethodError CHOLMOD.vertcat(A1Sparse, A2Sparse, true) == [A1; A2] - end - - if elty <: Real - @test CHOLMOD.ssmult(A1Sparse, A2Sparse, 0, true, true) ≈ A1*A2 - @test CHOLMOD.aat(A1Sparse, [0:size(A1,2)-1;], 1) ≈ A1*A1' - @test CHOLMOD.aat(A1Sparse, [0:1;], 1) ≈ A1[:,1:2]*A1[:,1:2]' - @test CHOLMOD.copy(A1Sparse, 0, 1) == A1Sparse - end - - @test CHOLMOD.Sparse(CHOLMOD.Dense(A1Sparse)) == A1Sparse -end - -@testset "extract factors" begin - Af = float([4 12 -16; 12 37 -43; -16 -43 98]) - As = sparse(Af) - Lf = float([2 0 0; 6 1 0; -8 5 3]) - LDf = float([4 0 0; 3 1 0; -4 5 9]) # D is stored along the diagonal - L_f = float([1 0 0; 3 1 0; -4 5 1]) # L by itself in LDLt of Af - D_f = float([4 0 0; 0 1 0; 0 0 9]) - p = [2,3,1] - p_inv = [3,1,2] - - @testset "cholesky, no permutation" begin - Fs = cholesky(As, perm=[1:3;]) - @test Fs.p == [1:3;] - @test sparse(Fs.L) ≈ Lf - @test sparse(Fs) ≈ As - b = rand(3) - @test Fs\b ≈ Af\b - @test Fs.UP\(Fs.PtL\b) ≈ Af\b - @test Fs.L\b ≈ Lf\b - @test Fs.U\b ≈ Lf'\b - @test Fs.L'\b ≈ Lf'\b - @test Fs.U'\b ≈ Lf\b - @test Fs.PtL\b ≈ Lf\b - @test Fs.UP\b ≈ Lf'\b - @test Fs.PtL'\b ≈ Lf'\b - @test Fs.UP'\b ≈ Lf\b - @test_throws CHOLMOD.CHOLMODException Fs.D - @test_throws CHOLMOD.CHOLMODException Fs.LD - @test_throws CHOLMOD.CHOLMODException Fs.DU - @test_throws CHOLMOD.CHOLMODException Fs.PLD - @test_throws CHOLMOD.CHOLMODException Fs.DUPt - end - - @testset "cholesky, with permutation" begin - Fs = cholesky(As, perm=p) - @test Fs.p == p - Afp = Af[p,p] - Lfp = cholesky(Afp).L - Ls = sparse(Fs.L) - @test Ls ≈ Lfp - @test Ls * Ls' ≈ Afp - P = sparse(1:3, Fs.p, ones(3)) - @test P' * Ls * Ls' * P ≈ As - @test sparse(Fs) ≈ As - b = rand(3) - @test Fs\b ≈ Af\b - @test Fs.UP\(Fs.PtL\b) ≈ Af\b - @test Fs.L\b ≈ Lfp\b - @test Fs.U'\b ≈ Lfp\b - @test Fs.U\b ≈ Lfp'\b - @test Fs.L'\b ≈ Lfp'\b - @test Fs.PtL\b ≈ Lfp\b[p] - @test Fs.UP\b ≈ (Lfp'\b)[p_inv] - @test Fs.PtL'\b ≈ (Lfp'\b)[p_inv] - @test Fs.UP'\b ≈ Lfp\b[p] - @test_throws CHOLMOD.CHOLMODException Fs.PL - @test_throws CHOLMOD.CHOLMODException Fs.UPt - @test_throws CHOLMOD.CHOLMODException Fs.D - @test_throws CHOLMOD.CHOLMODException Fs.LD - @test_throws CHOLMOD.CHOLMODException Fs.DU - @test_throws CHOLMOD.CHOLMODException Fs.PLD - @test_throws CHOLMOD.CHOLMODException Fs.DUPt - end - - @testset "ldlt, no permutation" begin - Fs = ldlt(As, perm=[1:3;]) - @test Fs.p == [1:3;] - @test sparse(Fs.LD) ≈ LDf - @test sparse(Fs) ≈ As - b = rand(3) - @test Fs\b ≈ Af\b - @test Fs.UP\(Fs.PtLD\b) ≈ Af\b - @test Fs.DUP\(Fs.PtL\b) ≈ Af\b - @test Fs.L\b ≈ L_f\b - @test Fs.U\b ≈ L_f'\b - @test Fs.L'\b ≈ L_f'\b - @test Fs.U'\b ≈ L_f\b - @test Fs.PtL\b ≈ L_f\b - @test Fs.UP\b ≈ L_f'\b - @test Fs.PtL'\b ≈ L_f'\b - @test Fs.UP'\b ≈ L_f\b - @test Fs.D\b ≈ D_f\b - @test Fs.D'\b ≈ D_f\b - @test Fs.LD\b ≈ D_f\(L_f\b) - @test Fs.DU'\b ≈ D_f\(L_f\b) - @test Fs.LD'\b ≈ L_f'\(D_f\b) - @test Fs.DU\b ≈ L_f'\(D_f\b) - @test Fs.PtLD\b ≈ D_f\(L_f\b) - @test Fs.DUP'\b ≈ D_f\(L_f\b) - @test Fs.PtLD'\b ≈ L_f'\(D_f\b) - @test Fs.DUP\b ≈ L_f'\(D_f\b) - end - - @testset "ldlt, with permutation" begin - Fs = ldlt(As, perm=p) - @test Fs.p == p - @test sparse(Fs) ≈ As - b = rand(3) - Asp = As[p,p] - LDp = sparse(ldlt(Asp, perm=[1,2,3]).LD) - # LDp = sparse(Fs.LD) - Lp, dp = SuiteSparse.CHOLMOD.getLd!(copy(LDp)) - Dp = sparse(Diagonal(dp)) - @test Fs\b ≈ Af\b - @test Fs.UP\(Fs.PtLD\b) ≈ Af\b - @test Fs.DUP\(Fs.PtL\b) ≈ Af\b - @test Fs.L\b ≈ Lp\b - @test Fs.U\b ≈ Lp'\b - @test Fs.L'\b ≈ Lp'\b - @test Fs.U'\b ≈ Lp\b - @test Fs.PtL\b ≈ Lp\b[p] - @test Fs.UP\b ≈ (Lp'\b)[p_inv] - @test Fs.PtL'\b ≈ (Lp'\b)[p_inv] - @test Fs.UP'\b ≈ Lp\b[p] - @test Fs.LD\b ≈ Dp\(Lp\b) - @test Fs.DU'\b ≈ Dp\(Lp\b) - @test Fs.LD'\b ≈ Lp'\(Dp\b) - @test Fs.DU\b ≈ Lp'\(Dp\b) - @test Fs.PtLD\b ≈ Dp\(Lp\b[p]) - @test Fs.DUP'\b ≈ Dp\(Lp\b[p]) - @test Fs.PtLD'\b ≈ (Lp'\(Dp\b))[p_inv] - @test Fs.DUP\b ≈ (Lp'\(Dp\b))[p_inv] - @test_throws CHOLMOD.CHOLMODException Fs.DUPt - @test_throws CHOLMOD.CHOLMODException Fs.PLD - end - - @testset "Element promotion and type inference" begin - @inferred cholesky(As)\fill(1, size(As, 1)) - @inferred ldlt(As)\fill(1, size(As, 1)) - end -end - -@testset "Issue 11745 - row and column pointers were not sorted in sparse(Factor)" begin - A = Float64[10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10] - @test sparse(cholesky(sparse(A))) ≈ A -end -GC.gc() - -@testset "Issue 11747 - Wrong show method defined for FactorComponent" begin - v = cholesky(sparse(Float64[ 10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10])).L - for s in (sprint(show, MIME("text/plain"), v), sprint(show, v)) - @test occursin("method: simplicial", s) - @test !occursin("#undef", s) - end -end - -@testset "Issue 14076" begin - @test cholesky(sparse([1,2,3,4], [1,2,3,4], Float32[1,4,16,64]))\[1,4,16,64] == fill(1, 4) -end - -@testset "Issue 29367" begin - if Int != Int32 - @test_throws MethodError cholesky(sparse(Int32[1,2,3,4], Int32[1,2,3,4], Float64[1,4,16,64])) - @test_throws MethodError cholesky(sparse(Int32[1,2,3,4], Int32[1,2,3,4], Float32[1,4,16,64])) - @test_throws MethodError ldlt(sparse(Int32[1,2,3,4], Int32[1,2,3,4], Float64[1,4,16,64])) - @test_throws MethodError ldlt(sparse(Int32[1,2,3,4], Int32[1,2,3,4], Float32[1,4,16,64])) - end -end - -@testset "Issue 14134" begin - A = CHOLMOD.Sparse(sprandn(10,5,0.1) + I |> t -> t't) - b = IOBuffer() - serialize(b, A) - seekstart(b) - Anew = deserialize(b) - @test_throws ArgumentError show(Anew) - @test_throws ArgumentError size(Anew) - @test_throws ArgumentError Anew[1] - @test_throws ArgumentError Anew[2,1] - F = cholesky(A) - serialize(b, F) - seekstart(b) - Fnew = deserialize(b) - @test_throws ArgumentError Fnew\fill(1., 5) - @test_throws ArgumentError show(Fnew) - @test_throws ArgumentError size(Fnew) - @test_throws ArgumentError diag(Fnew) - @test_throws ArgumentError logdet(Fnew) -end - -@testset "Issue #28985" begin - @test typeof(cholesky(sparse(I, 4, 4))'\rand(4)) == Array{Float64, 1} - @test typeof(cholesky(sparse(I, 4, 4))'\rand(4,1)) == Array{Float64, 2} -end - -@testset "Issue with promotion during conversion to CHOLMOD.Dense" begin - @test CHOLMOD.Dense(fill(1, 5)) == fill(1, 5, 1) - @test CHOLMOD.Dense(fill(1f0, 5)) == fill(1, 5, 1) - @test CHOLMOD.Dense(fill(1f0 + 0im, 5, 2)) == fill(1, 5, 2) -end - -@testset "Further issue with promotion #14894" begin - x = fill(1., 5) - @test cholesky(sparse(Float16(1)I, 5, 5))\x == x - @test cholesky(Symmetric(sparse(Float16(1)I, 5, 5)))\x == x - @test cholesky(Hermitian(sparse(Complex{Float16}(1)I, 5, 5)))\x == x - @test_throws TypeError cholesky(sparse(BigFloat(1)I, 5, 5)) - @test_throws TypeError cholesky(Symmetric(sparse(BigFloat(1)I, 5, 5))) - @test_throws TypeError cholesky(Hermitian(sparse(Complex{BigFloat}(1)I, 5, 5))) -end - -@testset "test \\ for Factor and StridedVecOrMat" begin - x = rand(5) - A = cholesky(sparse(Diagonal(x.\1))) - @test A\view(fill(1.,10),1:2:10) ≈ x - @test A\view(Matrix(1.0I, 5, 5), :, :) ≈ Matrix(Diagonal(x)) -end - -@testset "Test \\ for Factor and SparseVecOrMat" begin - sparseI = sparse(1.0I, 100, 100) - sparseb = sprandn(100, 0.5) - sparseB = sprandn(100, 100, 0.5) - chI = cholesky(sparseI) - @test chI \ sparseb ≈ sparseb - @test chI \ sparseB ≈ sparseB - @test chI \ sparseI ≈ sparseI -end - -@testset "Real factorization and complex rhs" begin - A = sprandn(5, 5, 0.4) |> t -> t't + I - B = complex.(randn(5, 2), randn(5, 2)) - @test cholesky(A)\B ≈ A\B -end - -@testset "Make sure that ldlt performs an LDLt (Issue #19032)" begin - m, n = 400, 500 - A = sprandn(m, n, .2) - M = [I copy(A'); A -I] - b = M * fill(1., m+n) - F = ldlt(M) - s = unsafe_load(pointer(F)) - @test s.is_super == 0 - @test F\b ≈ fill(1., m+n) - F2 = cholesky(M; check = false) - @test !issuccess(F2) - ldlt!(F2, M) - @test issuccess(F2) - @test F2\b ≈ fill(1., m+n) -end - -@testset "Test that imaginary parts in Hermitian{T,SparseMatrixCSC{T}} are ignored" begin - A = sparse([1,2,3,4,1], [1,2,3,4,2], [complex(2.0,1),2,2,2,1]) - Fs = cholesky(Hermitian(A)) - Fd = cholesky(Hermitian(Array(A))) - @test sparse(Fs) ≈ Hermitian(A) - @test Fs\fill(1., 4) ≈ Fd\fill(1., 4) -end - -@testset "\\ '\\ and transpose(...)\\" begin - # Test that \ and '\ and transpose(...)\ work for Symmetric and Hermitian. This is just - # a dispatch exercise so it doesn't matter that the complex matrix has - # zero imaginary parts - Apre = sprandn(10, 10, 0.2) - I - for A in (Symmetric(Apre), Hermitian(Apre), - Symmetric(Apre + 10I), Hermitian(Apre + 10I), - Hermitian(complex(Apre)), Hermitian(complex(Apre) + 10I)) - local A, x, b - x = fill(1., 10) - b = A*x - @test x ≈ A\b - @test transpose(A)\b ≈ A'\b - end -end - -@testset "Check that Symmetric{SparseMatrixCSC} can be constructed from CHOLMOD.Sparse" begin - Int === Int32 && Random.seed!(124) - A = sprandn(10, 10, 0.1) - B = CHOLMOD.Sparse(A) - C = B'B - # Change internal representation to symmetric (upper/lower) - o = fieldoffset(CHOLMOD.C_Sparse{eltype(C)}, findall(fieldnames(CHOLMOD.C_Sparse{eltype(C)}) .== :stype)[1]) - for uplo in (1, -1) - unsafe_store!(Ptr{Int8}(pointer(C)), uplo, Int(o) + 1) - @test convert(Symmetric{Float64,SparseMatrixCSC{Float64,Int}}, C) ≈ Symmetric(A'A) - end -end - -@testset "Check inputs to Sparse. Related to #20024" for t_ in ( - (2, 2, [1, 2], CHOLMOD.SuiteSparse_long[], Float64[]), - (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1], Float64[]), - (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[], Float64[1.0]), - (2, 2, [1, 2, 3], CHOLMOD.SuiteSparse_long[1], Float64[1.0])) - @test_throws ArgumentError SparseMatrixCSC(t_...) - @test_throws ArgumentError CHOLMOD.Sparse(t_[1], t_[2], t_[3] .- 1, t_[4] .- 1, t_[5]) -end - -@testset "sparse right multiplication of Symmetric and Hermitian matrices #21431" begin - S = sparse(1.0I, 2, 2) - @test issparse(S*S*S) - for T in (Symmetric, Hermitian) - @test issparse(S*T(S)*S) - @test issparse(S*(T(S)*S)) - @test issparse((S*T(S))*S) - end -end - -@testset "Test sparse low rank update for cholesky decomposion" begin - A = SparseMatrixCSC{Float64,CHOLMOD.SuiteSparse_long}(10, 5, [1,3,6,8,10,13], [6,7,1,2,9,3,5,1,7,6,7,9], - [-0.138843, 2.99571, -0.556814, 0.669704, -1.39252, 1.33814, - 1.02371, -0.502384, 1.10686, 0.262229, -1.6935, 0.525239]) - AtA = A'*A - C0 = [1., 2., 0, 0, 0] - # Test both cholesky and LDLt with and without automatic permutations - for F in (cholesky(AtA), cholesky(AtA, perm=1:5), ldlt(AtA), ldlt(AtA, perm=1:5)) - local F - x0 = F\(b = fill(1., 5)) - #Test both sparse/dense and vectors/matrices - for Ctest in (C0, sparse(C0), [C0 2*C0], sparse([C0 2*C0])) - local x, C, F1 - C = copy(Ctest) - F1 = copy(F) - x = (AtA+C*C')\b - - #Test update - F11 = CHOLMOD.lowrankupdate(F1, C) - @test Array(sparse(F11)) ≈ AtA+C*C' - @test F11\b ≈ x - #Make sure we get back the same factor again - F10 = CHOLMOD.lowrankdowndate(F11, C) - @test Array(sparse(F10)) ≈ AtA - @test F10\b ≈ x0 - - #Test in-place update - CHOLMOD.lowrankupdate!(F1, C) - @test Array(sparse(F1)) ≈ AtA+C*C' - @test F1\b ≈ x - #Test in-place downdate - CHOLMOD.lowrankdowndate!(F1, C) - @test Array(sparse(F1)) ≈ AtA - @test F1\b ≈ x0 - - @test C == Ctest #Make sure C didn't change - end - end -end - -@testset "Issue #22335" begin - local A, F - A = sparse(1.0I, 3, 3) - @test issuccess(cholesky(A)) - A[3, 3] = -1 - F = cholesky(A; check = false) - @test !issuccess(F) - @test issuccess(ldlt!(F, A)) - A[3, 3] = 1 - @test A[:, 3:-1:1]\fill(1., 3) == [1, 1, 1] -end - -@testset "Non-positive definite matrices" begin - A = sparse(Float64[1 2; 2 1]) - B = sparse(ComplexF64[1 2; 2 1]) - for M in (A, B, Symmetric(A), Hermitian(B)) - F = cholesky(M; check = false) - @test_throws PosDefException cholesky(M) - @test_throws PosDefException cholesky!(F, M) - @test !issuccess(cholesky(M; check = false)) - @test !issuccess(cholesky!(F, M; check = false)) - end - A = sparse(Float64[0 0; 0 0]) - B = sparse(ComplexF64[0 0; 0 0]) - for M in (A, B, Symmetric(A), Hermitian(B)) - F = ldlt(M; check = false) - @test_throws ZeroPivotException ldlt(M) - @test_throws ZeroPivotException ldlt!(F, M) - @test !issuccess(ldlt(M; check = false)) - @test !issuccess(ldlt!(F, M; check = false)) - end -end - -@testset "Issues #27860 & #28363" begin - for typeA in (Float64, ComplexF64), typeB in (Float64, ComplexF64), transform in (identity, adjoint, transpose) - A = sparse(typeA[2.0 0.1; 0.1 2.0]) - B = randn(typeB, 2, 2) - @test A \ transform(B) ≈ cholesky(A) \ transform(B) ≈ Matrix(A) \ transform(B) - C = randn(typeA, 2, 2) - sC = sparse(C) - sF = typeA <: Real ? cholesky(Symmetric(A)) : cholesky(Hermitian(A)) - @test cholesky(A) \ transform(sC) ≈ Matrix(A) \ transform(C) - @test sF.PtL \ transform(A) ≈ sF.PtL \ Matrix(transform(A)) - end -end - -@testset "Issue #33365" begin - A = Sparse(spzeros(0, 0)) - @test A * A' == A - @test A' * A == A - B = Sparse(spzeros(0, 4)) - @test B * B' == Sparse(spzeros(0, 0)) - @test B' * B == Sparse(spzeros(4, 4)) - C = Sparse(spzeros(3, 0)) - @test C * C' == Sparse(spzeros(3, 3)) - @test C' * C == Sparse(spzeros(0, 0)) -end - -@testset "permutation handling" begin - @testset "default permutation" begin - # Assemble arrow matrix - A = sparse(5I,3,3) - A[:,1] .= 1; A[1,:] .= A[:,1] - - # Ensure cholesky eliminates the fill-in - @test cholesky(A).p[1] != 1 - end - - @testset "user-specified permutation" begin - n = 100 - A = sprand(n,n,5/n) |> t -> t't + I - @test cholesky(A, perm=1:n).p == 1:n - end -end - -@testset "Check common is still in default state" begin - # This test intentially depends on all the above tests! - current_common = CHOLMOD.common[Threads.threadid()] - default_common = CHOLMOD.Common() - @test current_common.print == 0 - for name in ( - :nmethods, - :postorder, - :final_ll, - :supernodal, - ) - @test getproperty(current_common, name) == getproperty(default_common, name) - end -end diff --git a/stdlib/SuiteSparse/test/runtests.jl b/stdlib/SuiteSparse/test/runtests.jl deleted file mode 100644 index cde54e9488818..0000000000000 --- a/stdlib/SuiteSparse/test/runtests.jl +++ /dev/null @@ -1,30 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using Test, Random -using SuiteSparse, LinearAlgebra, SparseArrays - -if Base.USE_GPL_LIBS - include("umfpack.jl") - include("cholmod.jl") - include("spqr.jl") - - # Test multithreaded execution - let p, cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads.jl` - # test both nthreads==1 and nthreads>1. spawn a process to test whichever - # case we are not running currently. - other_nthreads = Threads.nthreads() == 1 ? 4 : 1 - p = run( - pipeline( - setenv( - cmd, - "JULIA_NUM_THREADS" => other_nthreads, - dir=@__DIR__()), - stdout = stdout, - stderr = stderr), - wait = false) - include("threads.jl") - if !success(p) - error("SuiteSparse threads test failed with nthreads == $other_nthreads") - end - end -end diff --git a/stdlib/SuiteSparse/test/spqr.jl b/stdlib/SuiteSparse/test/spqr.jl deleted file mode 100644 index d1802c7ccc3b3..0000000000000 --- a/stdlib/SuiteSparse/test/spqr.jl +++ /dev/null @@ -1,136 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using SuiteSparse.SPQR -using SuiteSparse.CHOLMOD -using SuiteSparse -using LinearAlgebra: I, istriu, norm, qr, rank, rmul!, lmul!, Adjoint, Transpose -using SparseArrays: sparse, sprandn, spzeros, SparseMatrixCSC - -@testset "Sparse QR" begin -m, n = 100, 10 -nn = 100 - -@test size(qr(sprandn(m, n, 0.1)).Q) == (m, m) - -@testset "element type of A: $eltyA" for eltyA in (Float64, ComplexF64) - if eltyA <: Real - A = sparse([1:n; rand(1:m, nn - n)], [1:n; rand(1:n, nn - n)], randn(nn), m, n) - else - A = sparse([1:n; rand(1:m, nn - n)], [1:n; rand(1:n, nn - n)], complex.(randn(nn), randn(nn)), m, n) - end - - F = qr(A) - @test size(F) == (m,n) - @test size(F, 1) == m - @test size(F, 2) == n - @test size(F, 3) == 1 - @test_throws ArgumentError size(F, 0) - - @testset "getindex" begin - @test istriu(F.R) - @test isperm(F.pcol) - @test isperm(F.prow) - @test_throws ErrorException F.T - end - - @testset "apply Q" begin - Q = F.Q - Imm = Matrix{Float64}(I, m, m) - @test Q' * (Q*Imm) ≈ Imm - @test (Imm*Q) * Q' ≈ Imm - - # test that Q'Pl*A*Pr = R - R0 = Q'*Array(A[F.prow, F.pcol]) - @test R0[1:n, :] ≈ F.R - @test norm(R0[n + 1:end, :], 1) < 1e-12 - - offsizeA = Matrix{Float64}(I, m+1, m+1) - @test_throws DimensionMismatch lmul!(Q, offsizeA) - @test_throws DimensionMismatch lmul!(adjoint(Q), offsizeA) - @test_throws DimensionMismatch rmul!(offsizeA, Q) - @test_throws DimensionMismatch rmul!(offsizeA, adjoint(Q)) - end - - @testset "element type of B: $eltyB" for eltyB in (Int, Float64, ComplexF64) - if eltyB == Int - B = rand(1:10, m, 2) - elseif eltyB <: Real - B = randn(m, 2) - else - B = complex.(randn(m, 2), randn(m, 2)) - end - - @inferred A\B - @test A\B[:,1] ≈ Array(A)\B[:,1] - @test A\B ≈ Array(A)\B - @test_throws DimensionMismatch A\B[1:m-1,:] - C, x = A[1:9, :], fill(eltyB(1), 9) - @test C*(C\x) ≈ x # Underdetermined system - end - - # Make sure that conversion to Sparse doesn't use SuiteSparse's symmetric flag - @test qr(SparseMatrixCSC{eltyA}(I, 5, 5)) \ fill(eltyA(1), 5) == fill(1, 5) -end - -@testset "basic solution of rank deficient ls" begin - A = sprandn(m, 5, 0.9)*sprandn(5, n, 0.9) - b = randn(m) - xs = A\b - xd = Array(A)\b - - # check that basic solution has more zeros - @test count(!iszero, xs) < count(!iszero, xd) - @test A*xs ≈ A*xd -end - -@testset "Issue 26367" begin - A = sparse([0.0 1 0 0; 0 0 0 0]) - @test Matrix(qr(A).Q) == Matrix(qr(Matrix(A)).Q) == Matrix(I, 2, 2) -end - -@testset "Issue 26368" begin - A = sparse([0.0 1 0 0; 0 0 0 0]) - F = qr(A) - @test F.Q*F.R == A[F.prow,F.pcol] -end - -@testset "select ordering overdetermined" begin - A = sparse([1:n; rand(1:m, nn - n)], [1:n; rand(1:n, nn - n)], randn(nn), m, n) - b = randn(m) - xref = Array(A) \ b - for ordering ∈ SuiteSparse.SPQR.ORDERINGS - QR = qr(A, ordering=ordering) - x = QR \ b - @test x ≈ xref - end - @test_throws ErrorException qr(A, ordering=Int32(10)) -end - -@testset "select ordering underdetermined" begin - A = sparse([1:n; rand(1:n, nn - n)], [1:n; rand(1:m, nn - n)], randn(nn), n, m) - b = A * ones(m) - for ordering ∈ SuiteSparse.SPQR.ORDERINGS - QR = qr(A, ordering=ordering) - x = QR \ b - # x ≂̸ Array(A) \ b; LAPACK returns a min-norm x while SPQR returns a basic x - @test A * x ≈ b - end - @test_throws ErrorException qr(A, ordering=Int32(10)) -end - -@testset "propertynames of QRSparse" begin - A = sparse([0.0 1 0 0; 0 0 0 0]) - F = qr(A) - @test propertynames(F) == (:R, :Q, :prow, :pcol) - @test propertynames(F, true) == (:R, :Q, :prow, :pcol, :factors, :τ, :cpiv, :rpivinv) -end - -@testset "rank" begin - S = sprandn(10, 5, 1.0)*sprandn(5, 10, 1.0) - @test rank(qr(S)) == 5 - @test rank(S) == 5 - @test all(iszero, (rank(qr(spzeros(10, i))) for i in 1:10)) - @test all(iszero, (rank(spzeros(10, i)) for i in 1:10)) -end - -end diff --git a/stdlib/SuiteSparse/test/threads.jl b/stdlib/SuiteSparse/test/threads.jl deleted file mode 100644 index 29e97500dc988..0000000000000 --- a/stdlib/SuiteSparse/test/threads.jl +++ /dev/null @@ -1,22 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using Test, LinearAlgebra, SparseArrays - -@testset "threaded SuiteSparse tests" begin - A = sprandn(200, 200, 0.2) - b = rand(200) - - function test(n::Integer) - _A = A[1:n, 1:n] - _b = b[1:n] - x = qr(_A) \ _b - return norm(x) - end - - res_threads = zeros(100) - Threads.@threads for i in 1:100 - res_threads[i] = test(i + 100) - end - - @test res_threads ≈ [test(i + 100) for i in 1:100] -end diff --git a/stdlib/SuiteSparse/test/umfpack.jl b/stdlib/SuiteSparse/test/umfpack.jl deleted file mode 100644 index ba8e2f54b975b..0000000000000 --- a/stdlib/SuiteSparse/test/umfpack.jl +++ /dev/null @@ -1,249 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using SuiteSparse.UMFPACK -using SuiteSparse -using SuiteSparse: increment! -using Serialization -using LinearAlgebra: - I, det, issuccess, ldiv!, lu, lu!, Adjoint, Transpose, SingularException, Diagonal -using SparseArrays: nnz, sparse, sprand, sprandn, SparseMatrixCSC - -@testset "UMFPACK wrappers" begin - se33 = sparse(1.0I, 3, 3) - do33 = fill(1., 3) - @test isequal(se33 \ do33, do33) - - # based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c - - A0 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), - increment!([0,4,0,2,1,2,1,4,3,2,1,2]), - [2.,1.,3.,4.,-1.,-3.,3.,6.,2.,1.,4.,2.], 5, 5) - - @testset "Core functionality for $Tv elements" for Tv in (Float64, ComplexF64) - # We might be able to support two index sizes one day - for Ti in Base.uniontypes(SuiteSparse.UMFPACK.UMFITypes) - A = convert(SparseMatrixCSC{Tv,Ti}, A0) - lua = lu(A) - @test nnz(lua) == 18 - @test_throws ErrorException lua.Z - L,U,p,q,Rs = lua.:(:) - @test L == lua.L - @test U == lua.U - @test p == lua.p - @test q == lua.q - @test Rs == lua.Rs - @test (Diagonal(Rs) * A)[p,q] ≈ L * U - - @test det(lua) ≈ det(Array(A)) - logdet_lua, sign_lua = logabsdet(lua) - logdet_A, sign_A = logabsdet(Array(A)) - @test logdet_lua ≈ logdet_A - @test sign_lua ≈ sign_A - - b = [8., 45., -3., 3., 19.] - x = lua\b - @test x ≈ float([1:5;]) - - @test A*x ≈ b - z = complex.(b) - x = ldiv!(lua, z) - @test x ≈ float([1:5;]) - @test z === x - y = similar(z) - ldiv!(y, lua, complex.(b)) - @test y ≈ x - - @test A*x ≈ b - - b = [8., 20., 13., 6., 17.] - x = lua'\b - @test x ≈ float([1:5;]) - - @test A'*x ≈ b - z = complex.(b) - x = ldiv!(adjoint(lua), z) - @test x ≈ float([1:5;]) - @test x === z - y = similar(x) - ldiv!(y, adjoint(lua), complex.(b)) - @test y ≈ x - - @test A'*x ≈ b - x = transpose(lua) \ b - @test x ≈ float([1:5;]) - - @test transpose(A) * x ≈ b - x = ldiv!(transpose(lua), complex.(b)) - @test x ≈ float([1:5;]) - y = similar(x) - ldiv!(y, transpose(lua), complex.(b)) - @test y ≈ x - - @test transpose(A) * x ≈ b - - # Element promotion and type inference - @inferred lua\fill(1, size(A, 2)) - end - end - - @testset "More tests for complex cases" begin - Ac0 = complex.(A0,A0) - for Ti in Base.uniontypes(SuiteSparse.UMFPACK.UMFITypes) - Ac = convert(SparseMatrixCSC{ComplexF64,Ti}, Ac0) - x = fill(1.0 + im, size(Ac,1)) - lua = lu(Ac) - L,U,p,q,Rs = lua.:(:) - @test (Diagonal(Rs) * Ac)[p,q] ≈ L * U - b = Ac*x - @test Ac\b ≈ x - b = Ac'*x - @test Ac'\b ≈ x - b = transpose(Ac)*x - @test transpose(Ac)\b ≈ x - end - end - - @testset "Rectangular cases. elty=$elty, m=$m, n=$n" for - elty in (Float64, ComplexF64), - (m, n) in ((10,5), (5, 10)) - - Random.seed!(30072018) - A = sparse([1:min(m,n); rand(1:m, 10)], [1:min(m,n); rand(1:n, 10)], elty == Float64 ? randn(min(m, n) + 10) : complex.(randn(min(m, n) + 10), randn(min(m, n) + 10))) - F = lu(A) - L, U, p, q, Rs = F.:(:) - @test (Diagonal(Rs) * A)[p,q] ≈ L * U - end - - @testset "Issue #4523 - complex sparse \\" begin - A, b = sparse((1.0 + im)I, 2, 2), fill(1., 2) - @test A * (lu(A)\b) ≈ b - - @test det(sparse([1,3,3,1], [1,1,3,3], [1,1,1,1])) == 0 - end - - @testset "UMFPACK_ERROR_n_nonpositive" begin - @test_throws ArgumentError lu(sparse(Int[], Int[], Float64[], 5, 0)) - end - - @testset "Issue #15099" for (Tin, Tout) in ( - (ComplexF16, ComplexF64), - (ComplexF32, ComplexF64), - (ComplexF64, ComplexF64), - (Float16, Float64), - (Float32, Float64), - (Float64, Float64), - (Int, Float64), - ) - - F = lu(sparse(fill(Tin(1), 1, 1))) - L = sparse(fill(Tout(1), 1, 1)) - @test F.p == F.q == [1] - @test F.Rs == [1.0] - @test F.L == F.U == L - @test F.:(:) == (L, L, [1], [1], [1.0]) - end - - @testset "BigFloat not supported" for T in (BigFloat, Complex{BigFloat}) - @test_throws ArgumentError lu(sparse(fill(T(1), 1, 1))) - end - - @testset "size(::UmfpackLU)" begin - m = n = 1 - F = lu(sparse(fill(1., m, n))) - @test size(F) == (m, n) - @test size(F, 1) == m - @test size(F, 2) == n - @test size(F, 3) == 1 - @test_throws ArgumentError size(F,-1) - end - - @testset "Test aliasing" begin - a = rand(5) - @test_throws ArgumentError SuiteSparse.UMFPACK.solve!(a, lu(sparse(1.0I, 5, 5)), a, SuiteSparse.UMFPACK.UMFPACK_A) - aa = complex(a) - @test_throws ArgumentError SuiteSparse.UMFPACK.solve!(aa, lu(sparse((1.0im)I, 5, 5)), aa, SuiteSparse.UMFPACK.UMFPACK_A) - end - - @testset "Issues #18246,18244 - lu sparse pivot" begin - A = sparse(1.0I, 4, 4) - A[1:2,1:2] = [-.01 -200; 200 .001] - F = lu(A) - @test F.p == [3 ; 4 ; 2 ; 1] - end - - @testset "Test that A[c|t]_ldiv_B!{T<:Complex}(X::StridedMatrix{T}, lu::UmfpackLU{Float64}, B::StridedMatrix{T}) works as expected." begin - N = 10 - p = 0.5 - A = N*I + sprand(N, N, p) - X = zeros(ComplexF64, N, N) - B = complex.(rand(N, N), rand(N, N)) - luA, lufA = lu(A), lu(Array(A)) - @test ldiv!(copy(X), luA, B) ≈ ldiv!(copy(X), lufA, B) - @test ldiv!(copy(X), adjoint(luA), B) ≈ ldiv!(copy(X), adjoint(lufA), B) - @test ldiv!(copy(X), transpose(luA), B) ≈ ldiv!(copy(X), transpose(lufA), B) - end - - @testset "singular matrix" begin - for A in sparse.((Float64[1 2; 0 0], ComplexF64[1 2; 0 0])) - @test_throws SingularException lu(A) - @test !issuccess(lu(A; check = false)) - end - end - - @testset "deserialization" begin - A = 10*I + sprandn(10, 10, 0.4) - F1 = lu(A) - b = IOBuffer() - serialize(b, F1) - seekstart(b) - F2 = deserialize(b) - for nm in (:colptr, :m, :n, :nzval, :rowval, :status) - @test getfield(F1, nm) == getfield(F2, nm) - end - end - - @testset "Reuse symbolic LU factorization" begin - A1 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), - increment!([0,4,0,2,1,2,1,4,3,2,1,2]), - [2.,1.,3.,4.,-1.,-3.,3.,9.,2.,1.,4.,2.], 5, 5) - for Tv in (Float64, ComplexF64, Float16, Float32, ComplexF16, ComplexF32) - for Ti in Base.uniontypes(SuiteSparse.UMFPACK.UMFITypes) - A = convert(SparseMatrixCSC{Tv,Ti}, A0) - B = convert(SparseMatrixCSC{Tv,Ti}, A1) - b = Tv[8., 45., -3., 3., 19.] - F = lu(A) - lu!(F, B) - @test F\b ≈ B\b ≈ Matrix(B)\b - - # singular matrix - C = copy(B) - C[4, 3] = Tv(0) - F = lu(A) - @test_throws SingularException lu!(F, C) - - # change of nonzero pattern - D = copy(B) - D[5, 1] = Tv(1.0) - F = lu(A) - @test_throws ArgumentError lu!(F, D) - end - end - end - -end - -@testset "REPL printing of UmfpackLU" begin - # regular matrix - A = sparse([1, 2], [1, 2], Float64[1.0, 1.0]) - F = lu(A) - facstring = sprint((t, s) -> show(t, "text/plain", s), F) - lstring = sprint((t, s) -> show(t, "text/plain", s), F.L) - ustring = sprint((t, s) -> show(t, "text/plain", s), F.U) - @test facstring == "$(summary(F))\nL factor:\n$lstring\nU factor:\n$ustring" - - # singular matrix - B = sparse(zeros(Float64, 2, 2)) - F = lu(B; check=false) - facstring = sprint((t, s) -> show(t, "text/plain", s), F) - @test facstring == "Failed factorization of type $(summary(F))" -end From 2dfe8d748b74fc4b141c3b16f76e7711e7383a48 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 14 May 2021 11:42:18 -0500 Subject: [PATCH 347/439] Compat annotations for `@something`/`@coalesce` (#40824) --- base/missing.jl | 3 +++ base/some.jl | 3 +++ 2 files changed, 6 insertions(+) diff --git a/base/missing.jl b/base/missing.jl index 1c15786a86a51..3176c56772602 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -452,6 +452,9 @@ f(3) ERROR: `b` is still missing [...] ``` + +!!! compat "Julia 1.7" + This macro is available as of Julia 1.7. """ macro coalesce(args...) expr = :(missing) diff --git a/base/some.jl b/base/some.jl index f762f7f9aa4d1..58280fe727352 100644 --- a/base/some.jl +++ b/base/some.jl @@ -131,6 +131,9 @@ f(3) julia> b === nothing true ``` + +!!! compat "Julia 1.7" + This macro is available as of Julia 1.7. """ macro something(args...) expr = :(nothing) From 9113c01bb1ae0e144dc92f9b0b3e051409f35c0a Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Sat, 15 May 2021 13:35:48 +1000 Subject: [PATCH 348/439] Exception stack API refinements (#29901) * Rename the non-exported `catch_stack()` to the more descriptive name `current_exceptions()`. Keep the old name available but deprecated. * Introduce an ExceptionStack as the return type for the function, which (as an AbstractVector) is API-compatible with the previous type returned by `catch_stack()` Having ExceptionStack gives us a place to integrate exception printing in a natural way. In the same way this should be useful for dispatch in other areas of the ecosystem which want to dispatch on exception stacks. --- NEWS.md | 1 + base/client.jl | 12 +-- base/deprecated.jl | 3 + base/error.jl | 34 ++++--- base/errorshow.jl | 14 ++- base/exports.jl | 1 + base/task.jl | 10 +- doc/src/base/base.md | 2 +- doc/src/manual/control-flow.md | 2 +- doc/src/manual/stacktraces.md | 8 +- src/stackwalk.c | 2 +- stdlib/REPL/src/REPL.jl | 13 ++- stdlib/REPL/test/repl.jl | 2 +- stdlib/Serialization/src/Serialization.jl | 4 +- stdlib/Test/src/Test.jl | 6 +- stdlib/Test/src/logging.jl | 2 +- test/client.jl | 18 +++- test/exceptions.jl | 110 +++++++++++----------- 18 files changed, 138 insertions(+), 106 deletions(-) diff --git a/NEWS.md b/NEWS.md index d93e4d2d5f968..7bacc44220b9e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -87,6 +87,7 @@ Standard library changes ``` ([#39322]) * `@lock` is now exported from Base ([#39588]). +* The experimental function `Base.catch_stack()` has been renamed to `current_exceptions()`, exported from Base and given a more specific return type ([#29901]) #### Package Manager diff --git a/base/client.jl b/base/client.jl index d9df2f04922dd..7e5f1ab5c5d58 100644 --- a/base/client.jl +++ b/base/client.jl @@ -98,13 +98,13 @@ function display_error(io::IO, er, bt) showerror(IOContext(io, :limit => true), er, bt, backtrace = bt!==nothing) println(io) end -function display_error(io::IO, stack::Vector) +function display_error(io::IO, stack::ExceptionStack) printstyled(io, "ERROR: "; bold=true, color=Base.error_color()) bt = Any[ (x[1], scrub_repl_backtrace(x[2])) for x in stack ] show_exception_stack(IOContext(io, :limit => true), bt) println(io) end -display_error(stack::Vector) = display_error(stderr, stack) +display_error(stack::ExceptionStack) = display_error(stderr, stack) display_error(er, bt=nothing) = display_error(stderr, er, bt) function eval_user_input(errio, @nospecialize(ast), show_value::Bool) @@ -143,7 +143,7 @@ function eval_user_input(errio, @nospecialize(ast), show_value::Bool) @error "SYSTEM: display_error(errio, lasterr) caused an error" end errcount += 1 - lasterr = catch_stack() + lasterr = current_exceptions() if errcount > 2 @error "It is likely that something important is broken, and Julia will not be able to continue normally" errcount break @@ -257,7 +257,7 @@ function exec_options(opts) try load_julia_startup() catch - invokelatest(display_error, catch_stack()) + invokelatest(display_error, current_exceptions()) !(repl || is_interactive) && exit(1) end end @@ -291,7 +291,7 @@ function exec_options(opts) try include(Main, PROGRAM_FILE) catch - invokelatest(display_error, catch_stack()) + invokelatest(display_error, current_exceptions()) if !is_interactive::Bool exit(1) end @@ -494,7 +494,7 @@ function _start() try exec_options(JLOptions()) catch - invokelatest(display_error, catch_stack()) + invokelatest(display_error, current_exceptions()) exit(1) end if is_interactive && get(stdout, :color, false) diff --git a/base/deprecated.jl b/base/deprecated.jl index 5cd32a16e50e2..d60cc3393662c 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -250,4 +250,7 @@ cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not re return getfield(x, s) end +# This function was marked as experimental and not exported. +@deprecate catch_stack(task=current_task(); include_bt=true) current_exceptions(task; backtrace=include_bt) false + # END 1.7 deprecations diff --git a/base/error.jl b/base/error.jl index 72c13396e3fc4..9116d00618900 100644 --- a/base/error.jl +++ b/base/error.jl @@ -54,7 +54,7 @@ exception will continue propagation as if it had not been caught. the program state at the time of the error so you're encouraged to instead throw a new exception using `throw(e)`. In Julia 1.1 and above, using `throw(e)` will preserve the root cause exception on the stack, as - described in [`catch_stack`](@ref). + described in [`current_exceptions`](@ref). """ rethrow() = ccall(:jl_rethrow, Bottom, ()) rethrow(@nospecialize(e)) = ccall(:jl_rethrow_other, Bottom, (Any,), e) @@ -123,32 +123,38 @@ function catch_backtrace() return _reformat_bt(bt::Vector{Ptr{Cvoid}}, bt2::Vector{Any}) end +struct ExceptionStack <: AbstractArray{Any,1} + stack +end + """ - catch_stack(task=current_task(); [inclue_bt=true]) + current_exceptions(task=current_task(); [inclue_bt=true]) Get the stack of exceptions currently being handled. For nested catch blocks there may be more than one current exception in which case the most recently -thrown exception is last in the stack. The stack is returned as a Vector of -`(exception,backtrace)` pairs, or a Vector of exceptions if `include_bt` is -false. +thrown exception is last in the stack. The stack is returned as an +`ExceptionStack` which is an AbstractVector of named tuples +`(exception,backtrace)`. If `backtrace` is false, the backtrace in each pair +will be set to `nothing`. Explicitly passing `task` will return the current exception stack on an arbitrary task. This is useful for inspecting tasks which have failed due to uncaught exceptions. -!!! compat "Julia 1.1" - This function is experimental in Julia 1.1 and will likely be renamed in a - future release (see https://github.com/JuliaLang/julia/pull/29901). +!!! compat "Julia 1.7" + This function went by the experiemental name `catch_stack()` in Julia + 1.1–1.6, and had a plain Vector-of-tuples as a return type. """ -function catch_stack(task=current_task(); include_bt=true) - raw = ccall(:jl_get_excstack, Any, (Any,Cint,Cint), task, include_bt, typemax(Cint))::Vector{Any} +function current_exceptions(task=current_task(); backtrace=true) + raw = ccall(:jl_get_excstack, Any, (Any,Cint,Cint), task, backtrace, typemax(Cint))::Vector{Any} formatted = Any[] - stride = include_bt ? 3 : 1 + stride = backtrace ? 3 : 1 for i = reverse(1:stride:length(raw)) - e = raw[i] - push!(formatted, include_bt ? (e,Base._reformat_bt(raw[i+1],raw[i+2])) : e) + exc = raw[i] + bt = backtrace ? Base._reformat_bt(raw[i+1],raw[i+2]) : nothing + push!(formatted, (exception=exc,backtrace=bt)) end - formatted + ExceptionStack(formatted) end ## keyword arg lowering generates calls to this ## diff --git a/base/errorshow.jl b/base/errorshow.jl index ceca8b268e42b..615b1ff4253df 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -849,7 +849,7 @@ function process_backtrace(t::Vector, limit::Int=typemax(Int); skipC = true) return _simplify_include_frames(ret) end -function show_exception_stack(io::IO, stack::Vector) +function show_exception_stack(io::IO, stack) # Display exception stack with the top of the stack first. This ordering # means that the user doesn't have to scroll up in the REPL to discover the # root cause. @@ -886,3 +886,15 @@ function noncallable_number_hint_handler(io, ex, arg_types, kwargs) end Experimental.register_error_hint(noncallable_number_hint_handler, MethodError) + +# ExceptionStack implementation +size(s::ExceptionStack) = size(s.stack) +getindex(s::ExceptionStack, i::Int) = s.stack[i] + +function show(io::IO, ::MIME"text/plain", stack::ExceptionStack) + nexc = length(stack) + printstyled(io, nexc, "-element ExceptionStack", nexc == 0 ? "" : ":\n") + show_exception_stack(io, stack) +end +show(io::IO, stack::ExceptionStack) = show(io, MIME("text/plain"), stack) + diff --git a/base/exports.jl b/base/exports.jl index 125e38930640d..7a2f25072b8cd 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -716,6 +716,7 @@ export # errors backtrace, catch_backtrace, + current_exceptions, error, rethrow, retry, diff --git a/base/task.jl b/base/task.jl index 87b354d052797..2c3e5c44e6d0b 100644 --- a/base/task.jl +++ b/base/task.jl @@ -77,7 +77,7 @@ function showerror(io::IO, ex::TaskFailedException, bt = nothing; backtrace=true end function show_task_exception(io::IO, t::Task; indent = true) - stack = catch_stack(t) + stack = current_exceptions(t) b = IOBuffer() if isempty(stack) # exception stack buffer not available; probably a serialized task @@ -162,7 +162,7 @@ end end elseif field === :backtrace # TODO: this field name should be deprecated in 2.0 - return catch_stack(t)[end][2] + return current_exceptions(t)[end][2] elseif field === :exception # TODO: this field name should be deprecated in 2.0 return t._isexception ? t.result : nothing @@ -434,18 +434,18 @@ function errormonitor(t::Task) try # try to display the failure atomically errio = IOContext(PipeBuffer(), errs::IO) emphasize(errio, "Unhandled Task ") - display_error(errio, catch_stack(t)) + display_error(errio, current_exceptions(t)) write(errs, errio) catch try # try to display the secondary error atomically errio = IOContext(PipeBuffer(), errs::IO) print(errio, "\nSYSTEM: caught exception while trying to print a failed Task notice: ") - display_error(errio, catch_stack()) + display_error(errio, current_exceptions()) write(errs, errio) flush(errs) # and then the actual error, as best we can Core.print(Core.stderr, "while handling: ") - Core.println(Core.stderr, catch_stack(t)[end][1]) + Core.println(Core.stderr, current_exceptions(t)[end][1]) catch e # give up Core.print(Core.stderr, "\nSYSTEM: caught exception of type ", typeof(e).name.name, diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 7d1160dac918b..7364b0c3b50b5 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -354,7 +354,7 @@ Core.throw Base.rethrow Base.backtrace Base.catch_backtrace -Base.catch_stack +Base.current_exceptions Base.@assert Base.Experimental.register_error_hint Base.Experimental.show_error_hints diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 1b785070c0e1a..63832cc4c90c9 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -817,7 +817,7 @@ The power of the `try/catch` construct lies in the ability to unwind a deeply ne immediately to a much higher level in the stack of calling functions. There are situations where no error has occurred, but the ability to unwind the stack and pass a value to a higher level is desirable. Julia provides the [`rethrow`](@ref), [`backtrace`](@ref), [`catch_backtrace`](@ref) -and [`Base.catch_stack`](@ref) functions for more advanced error handling. +and [`current_exceptions`](@ref) functions for more advanced error handling. ### `finally` Clauses diff --git a/doc/src/manual/stacktraces.md b/doc/src/manual/stacktraces.md index 50cdfd5b1ed64..40130d9e7dd44 100644 --- a/doc/src/manual/stacktraces.md +++ b/doc/src/manual/stacktraces.md @@ -185,7 +185,7 @@ ERROR: Whoops! [...] ``` -## Exception stacks and `catch_stack` +## Exception stacks and [`current_exceptions`](@ref) !!! compat "Julia 1.1" Exception stacks requires at least Julia 1.1. @@ -195,7 +195,7 @@ identify the root cause of a problem. The julia runtime supports this by pushing *exception stack* as it occurs. When the code exits a `catch` normally, any exceptions which were pushed onto the stack in the associated `try` are considered to be successfully handled and are removed from the stack. -The stack of current exceptions can be accessed using the experimental [`Base.catch_stack`](@ref) function. For example, +The stack of current exceptions can be accessed using the [`current_exceptions`](@ref) function. For example, ```julia-repl julia> try @@ -204,7 +204,7 @@ julia> try try error("(B) An exception while handling the exception") catch - for (exc, bt) in Base.catch_stack() + for (exc, bt) in current_exceptions() showerror(stdout, exc, bt) println(stdout) end @@ -233,7 +233,7 @@ exiting both catch blocks normally (i.e., without throwing a further exception) and are no longer accessible. The exception stack is stored on the `Task` where the exceptions occurred. When a task fails with uncaught exceptions, -`catch_stack(task)` may be used to inspect the exception stack for that task. +`current_exceptions(task)` may be used to inspect the exception stack for that task. ## Comparison with [`backtrace`](@ref) diff --git a/src/stackwalk.c b/src/stackwalk.c index d117b7146fe77..790b7583cc587 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -335,7 +335,7 @@ JL_DLLEXPORT jl_value_t *jl_get_backtrace(void) // interleaved. JL_DLLEXPORT jl_value_t *jl_get_excstack(jl_task_t* task, int include_bt, int max_entries) { - JL_TYPECHK(catch_stack, task, (jl_value_t*)task); + JL_TYPECHK(current_exceptions, task, (jl_value_t*)task); jl_ptls_t ptls = jl_get_ptls_states(); if (task != ptls->current_task && task->_state == JL_TASK_STATE_RUNNABLE) { jl_error("Inspecting the exception stack of a task which might " diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 2289bc65b368e..54053f2066c71 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -29,8 +29,7 @@ import Base: display, show, AnyDict, - ==, - catch_stack + == _displaysize(io::IO) = displaysize(io)::Tuple{Int,Int} @@ -160,7 +159,7 @@ function eval_user_input(@nospecialize(ast), backend::REPLBackend) println("SYSTEM ERROR: Failed to report error to REPL frontend") println(err) end - lasterr = catch_stack() + lasterr = current_exceptions() end end Base.sigatomic_end() @@ -301,7 +300,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool, println(errio) # an error during printing is likely to leave us mid-line println(errio, "SYSTEM (REPL): showing an error caused an error") try - Base.invokelatest(Base.display_error, errio, catch_stack()) + Base.invokelatest(Base.display_error, errio, current_exceptions()) catch e # at this point, only print the name of the type as a Symbol to # minimize the possibility of further errors. @@ -311,7 +310,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool, end break end - val = catch_stack() + val = current_exceptions() iserr = true end end @@ -835,7 +834,7 @@ function respond(f, repl, main; pass_empty::Bool = false, suppress_on_semicolon: ast = Base.invokelatest(f, line) response = eval_with_backend(ast, backend(repl)) catch - response = Pair{Any, Bool}(catch_stack(), true) + response = Pair{Any, Bool}(current_exceptions(), true) end hide_output = suppress_on_semicolon && ends_with_semicolon(line) print_response(repl, response, !hide_output, hascolor(repl)) @@ -987,7 +986,7 @@ function setup_interface( hist_from_file(hp, hist_path) catch # use REPL.hascolor to avoid using the local variable with the same name - print_response(repl, Pair{Any, Bool}(catch_stack(), true), true, REPL.hascolor(repl)) + print_response(repl, Pair{Any, Bool}(current_exceptions(), true), true, REPL.hascolor(repl)) println(outstream(repl)) @info "Disabling history file for this session" repl.history_file = false diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 34011569659af..d467c82eb4226 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -877,7 +877,7 @@ mutable struct Error19864 <: Exception; end function test19864() @eval Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") buf = IOBuffer() - fake_response = (Any[(Error19864(), Ptr{Cvoid}[])], true) + fake_response = (Base.ExceptionStack([(exception=Error19864(),backtrace=Ptr{Cvoid}[])]),true) REPL.print_response(buf, fake_response, false, false, nothing) return String(take!(buf)) end diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index f644c73762c2f..060dbb2bc011f 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -462,11 +462,11 @@ function serialize(s::AbstractSerializer, t::Task) serialize(s, t.code) serialize(s, t.storage) serialize(s, t.state) - if t._isexception && (stk = Base.catch_stack(t); !isempty(stk)) + if t._isexception && (stk = Base.current_exceptions(t); !isempty(stk)) # the exception stack field is hidden inside the task, so if there # is any information there make a CapturedException from it instead. # TODO: Handle full exception chain, not just the first one. - serialize(s, CapturedException(stk[1][1], stk[1][2])) + serialize(s, CapturedException(stk[1].exception, stk[1].backtrace)) else serialize(s, t.result) end diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index d303b6a7c69aa..9a16d3d25c9be 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -589,7 +589,7 @@ function get_test_result(ex, source) $testret catch _e _e isa InterruptException && rethrow() - Threw(_e, Base.catch_stack(), $(QuoteNode(source))) + Threw(_e, Base.current_exceptions(), $(QuoteNode(source))) end end Base.remove_linenums!(result) @@ -1272,7 +1272,7 @@ function testset_beginend(args, tests, source) err isa InterruptException && rethrow() # something in the test block threw an error. Count that as an # error in this test set - record(ts, Error(:nontest_error, Expr(:tuple), err, Base.catch_stack(), $(QuoteNode(source)))) + record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)))) finally copy!(RNG, oldrng) pop_testset() @@ -1346,7 +1346,7 @@ function testset_forloop(args, testloop, source) err isa InterruptException && rethrow() # Something in the test block threw an error. Count that as an # error in this test set - record(ts, Error(:nontest_error, Expr(:tuple), err, Base.catch_stack(), $(QuoteNode(source)))) + record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)))) end end quote diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index f7ecf90e2bc7f..d333f40b11428 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -184,7 +184,7 @@ macro test_logs(exs...) $(QuoteNode(exs[1:end-1])), logs) end catch e - testres = Error(:test_error, $orig_expr, e, Base.catch_stack(), $sourceloc) + testres = Error(:test_error, $orig_expr, e, Base.current_exceptions(), $sourceloc) end Test.record(Test.get_testset(), testres) value diff --git a/test/client.jl b/test/client.jl index 497cc54b13534..f917e45fb412d 100644 --- a/test/client.jl +++ b/test/client.jl @@ -18,14 +18,22 @@ nested_error_pattern = r""" @testset "display_error" begin # Display of errors which cause more than one entry on the exception stack - err_str = try + excs = try eval(nested_error_expr) catch - excs = Base.catch_stack() - @test typeof.(first.(excs)) == [UndefVarError, DivideError] - sprint(Base.display_error, excs) + Base.current_exceptions() end - @test occursin(nested_error_pattern, err_str) + @test typeof.(first.(excs)) == [UndefVarError, DivideError] + @test occursin(nested_error_pattern, sprint(Base.display_error, excs)) + + @test occursin(r""" + 2-element ExceptionStack: + DivideError: integer division error + Stacktrace:.* + + caused by: UndefVarError: __not_a_binding__ not defined + Stacktrace:.* + """s, sprint(show, excs)) end @testset "Fallback REPL" begin diff --git a/test/exceptions.jl b/test/exceptions.jl index 7b8a54da2c6eb..d8d1e7b45b8b5 100644 --- a/test/exceptions.jl +++ b/test/exceptions.jl @@ -1,52 +1,51 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test -using Base: catch_stack @testset "Basic exception stack handling" begin # Exiting the catch block normally pops the exception try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # Exiting via a finally block does not pop the exception try try error("A") finally - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 end catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 end # The combined try-catch-finally form obeys the same rules as above try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 finally - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # Errors are pushed onto the stack according to catch block nesting try error("RootCause") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 try error("B") catch - stack = catch_stack() + stack = current_exceptions() @test length(stack) == 2 - @test stack[1][1].msg == "RootCause" - @test stack[2][1].msg == "B" + @test stack[1].exception.msg == "RootCause" + @test stack[2].exception.msg == "B" end # Stack pops correctly - stack = catch_stack() + stack = current_exceptions() @test length(stack) == 1 - @test stack[1][1].msg == "RootCause" + @test stack[1].exception.msg == "RootCause" end end @@ -55,7 +54,7 @@ end val = try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 1 end @test val == 1 @@ -64,11 +63,11 @@ end try error("A") catch - length(catch_stack()) + length(current_exceptions()) end end @test test_exc_stack_tailpos() == 1 - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end @testset "Exception stacks - early exit from try or catch" begin @@ -78,7 +77,7 @@ end try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 return end end @@ -88,7 +87,7 @@ end try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 break end end @@ -97,19 +96,19 @@ end try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 break finally - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 for i=1:1 try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 continue end end @@ -117,38 +116,38 @@ end try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 continue finally - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 @goto outofcatch end @label outofcatch try error("A") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 @goto outofcatch2 finally - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end @label outofcatch2 - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # Exiting from a try block in various ways should not affect the exception # stack state. try error("ExceptionInOuterTry") catch - @test length(catch_stack()) == 1 + @test length(current_exceptions()) == 1 function test_exc_stack_try_return() try return @@ -173,8 +172,8 @@ end catch end @label outoftry - @test length(catch_stack()) == 1 - @test catch_stack()[1][1] == ErrorException("ExceptionInOuterTry") + @test length(current_exceptions()) == 1 + @test current_exceptions()[1].exception == ErrorException("ExceptionInOuterTry") end end @@ -195,10 +194,10 @@ end # Explicit return => exception should be popped before finally block return finally - @test length(Base.catch_stack()) == 0 + @test length(Base.current_exceptions()) == 0 end end)() - @test length(Base.catch_stack()) == 0 + @test length(Base.current_exceptions()) == 0 while true try @@ -209,11 +208,11 @@ end # exception should not be popped inside finally block break finally - @test length(Base.catch_stack()) == 1 + @test length(Base.current_exceptions()) == 1 end end end - @test length(Base.catch_stack()) == 0 + @test length(Base.current_exceptions()) == 0 # Nested finally handling with `return`: each finally block should observe # only the active exceptions as according to its nesting depth. @@ -232,16 +231,16 @@ end end finally # At this point err2 is dealt with - @test length(Base.catch_stack()) == 1 - @test Base.catch_stack()[1][1] == ErrorException("err1") + @test length(Base.current_exceptions()) == 1 + @test Base.current_exceptions()[1].exception == ErrorException("err1") end end finally # At this point err1 is dealt with - @test length(Base.catch_stack()) == 0 + @test length(Base.current_exceptions()) == 0 end end)() - @test length(Base.catch_stack()) == 0 + @test length(Base.current_exceptions()) == 0 end @testset "Deep exception stacks" begin @@ -260,10 +259,10 @@ end @test try test_exc_stack_deep(100) catch - @test catch_stack()[1][1] == ErrorException("RootCause") - length(catch_stack()) + @test current_exceptions()[1].exception == ErrorException("RootCause") + length(current_exceptions()) end == 100 - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 end @testset "Exception stacks and Tasks" begin @@ -280,10 +279,10 @@ end @test t.state == :done @test t.result == ErrorException("B") # Task exception state is preserved around task switches - @test length(catch_stack()) == 1 - @test catch_stack()[1][1] == ErrorException("A") + @test length(current_exceptions()) == 1 + @test current_exceptions()[1].exception == ErrorException("A") end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # test rethrow() rethrows correct state bt = [] try @@ -306,7 +305,7 @@ end @test exc == ErrorException("A") @test bt == catch_backtrace() end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # test rethrow with argument bt = [] try @@ -328,7 +327,7 @@ end @test exc == ErrorException("C") @test bt == catch_backtrace() end - @test length(catch_stack()) == 0 + @test length(current_exceptions()) == 0 # Exception stacks on other tasks t = @task try error("A") @@ -338,7 +337,10 @@ end yield(t) @test t.state == :failed @test t.result == ErrorException("B") - @test catch_stack(t, include_bt=false) == [ErrorException("A"), ErrorException("B")] + @test current_exceptions(t, backtrace=false) == [ + (exception=ErrorException("A"),backtrace=nothing), + (exception=ErrorException("B"),backtrace=nothing) + ] # Exception stacks for tasks which never get the chance to start t = @task nothing @test (try @@ -347,12 +349,12 @@ end catch e e end).task.exception == ErrorException("expected") - @test length(catch_stack(t)) == 1 - @test length(catch_stack(t)[1][2]) > 0 # backtrace is nonempty + @test length(current_exceptions(t)) == 1 + @test length(current_exceptions(t)[1].backtrace) > 0 # backtrace is nonempty # Exception stacks should not be accessed on concurrently running tasks t = @task ()->nothing @test_throws ErrorException("Inspecting the exception stack of a task which might "* - "be running concurrently isn't allowed.") catch_stack(t) + "be running concurrently isn't allowed.") current_exceptions(t) end @testset "rethrow" begin @@ -396,5 +398,5 @@ end undef_var_in_catch() [] catch - catch_stack() + current_exceptions() end) == 2 From 5aca7a37be174ad9f4b28d3586ba9cc112c12d75 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Sat, 15 May 2021 12:39:39 -0400 Subject: [PATCH 349/439] Make `StepRangeLen` in operations which may produce zero step (#40320) --- NEWS.md | 1 + base/broadcast.jl | 11 ++++++++--- base/range.jl | 10 +++++++++- test/broadcast.jl | 8 +++++--- test/ranges.jl | 38 +++++++++++++++++++++++++------------- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7bacc44220b9e..ea05d66aac3a6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -60,6 +60,7 @@ Standard library changes * `count` and `findall` now accept an `AbstractChar` argument to search for a character in a string ([#38675]). * `range` now supports the `range(start, stop)` and `range(start, stop, length)` methods ([#39228]). * `range` now supports `start` as an optional keyword argument ([#38041]). +* Some operations on ranges will return a `StepRangeLen` instead of a `StepRange`, to allow the resulting step to be zero. Previously, `λ .* (1:9)` gave an error when `λ = 0`. ([#40320]) * `islowercase` and `isuppercase` are now compliant with the Unicode lower/uppercase categories ([#38574]). * `iseven` and `isodd` functions now support non-`Integer` numeric types ([#38976]). * `escape_string` can now receive a collection of characters in the keyword diff --git a/base/broadcast.jl b/base/broadcast.jl index 4c3f91c50638f..47bd01145cd7d 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -1153,15 +1153,20 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::LinRange, x::Number) = LinRa broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Number, r::LinRange) = LinRange(x - r.start, x - r.stop, length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r1::AbstractRange, r2::AbstractRange) = r1 - r2 -broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::AbstractRange) = range(x*first(r), step=x*step(r), length=length(r)) +# at present Base.range_start_step_length(1,0,5) is an error, so for 0 .* (-2:2) we explicitly construct StepRangeLen: +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::AbstractRange) = StepRangeLen(x*first(r), x*step(r), length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::StepRangeLen{T}) where {T} = StepRangeLen{typeof(x*T(r.ref))}(x*r.ref, x*r.step, length(r), r.offset) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::LinRange) = LinRange(x * r.start, x * r.stop, r.len) -# separate in case of noncommutative multiplication -broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::Number) = range(first(r)*x, step=step(r)*x, length=length(r)) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractFloat, r::OrdinalRange) = + Base.range_start_step_length(x*first(r), x, length(r)) # 0.2 .* (-2:2) needs TwicePrecision +# separate in case of noncommutative multiplication: +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::Number) = StepRangeLen(first(r)*x, step(r)*x, length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::StepRangeLen{T}, x::Number) where {T} = StepRangeLen{typeof(T(r.ref)*x)}(r.ref*x, r.step*x, length(r), r.offset) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::LinRange, x::Number) = LinRange(r.start * x, r.stop * x, r.len) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::OrdinalRange, x::AbstractFloat) = + Base.range_start_step_length(first(r)*x, x, length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(/), r::AbstractRange, x::Number) = range(first(r)/x, step=step(r)/x, length=length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(/), r::StepRangeLen{T}, x::Number) where {T} = diff --git a/base/range.jl b/base/range.jl index 41120e1bcdaf0..ca1f577ecf00a 100644 --- a/base/range.jl +++ b/base/range.jl @@ -927,6 +927,14 @@ end show(io::IO, r::AbstractRange) = print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") +function show(io::IO, r::StepRangeLen) + if step(r) != 0 + print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) + else + # ugly temporary printing, to avoid 0:0:0 etc. + print(io, "StepRangeLen(", repr(first(r)), ", ", repr(step(r)), ", ", repr(length(r)), ")") + end +end function ==(r::T, s::T) where {T<:AbstractRange} isempty(r) && return isempty(s) @@ -1238,7 +1246,7 @@ function _define_range_op(@nospecialize f) r1l = length(r1) (r1l == length(r2) || throw(DimensionMismatch("argument dimensions must match: length of r1 is $r1l, length of r2 is $(length(r2))"))) - range($f(first(r1), first(r2)), step=$f(step(r1), step(r2)), length=r1l) + StepRangeLen($f(first(r1), first(r2)), $f(step(r1), step(r2)), r1l) end function $f(r1::LinRange{T}, r2::LinRange{T}) where T diff --git a/test/broadcast.jl b/test/broadcast.jl index 4c2b92a39bb9f..57a65110a413a 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -1045,6 +1045,8 @@ end end end -# issue 40309 -@test Base.broadcasted_kwsyntax(+, [1], [2]) isa Broadcast.Broadcasted{<:Any, <:Any, typeof(+)} -@test Broadcast.BroadcastFunction(+)(2:3, 2:3) === 4:2:6 +@testset "Issue #40309: still gives a range after #40320" begin + @test Base.broadcasted_kwsyntax(+, [1], [2]) isa Broadcast.Broadcasted{<:Any, <:Any, typeof(+)} + @test Broadcast.BroadcastFunction(+)(2:3, 2:3) == 4:2:6 + @test Broadcast.BroadcastFunction(+)(2:3, 2:3) isa AbstractRange +end diff --git a/test/ranges.jl b/test/ranges.jl index b0693a32527d2..dea5d9b675305 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1082,7 +1082,7 @@ end @test sprint(show, StepRange(1, 2, 5)) == "1:2:5" end -@testset "Issue 11049 and related" begin +@testset "Issue 11049, and related" begin @test promote(range(0f0, stop=1f0, length=3), range(0., stop=5., length=2)) === (range(0., stop=1., length=3), range(0., stop=5., length=2)) @test convert(LinRange{Float64}, range(0., stop=1., length=3)) === LinRange(0., 1., 3) @@ -1144,6 +1144,7 @@ end @test [reverse(range(1.0, stop=27.0, length=1275));] == reverse([range(1.0, stop=27.0, length=1275);]) end + @testset "PR 12200 and related" begin for _r in (1:2:100, 1:100, 1f0:2f0:100f0, 1.0:2.0:100.0, range(1, stop=100, length=10), range(1f0, stop=100f0, length=10)) @@ -1288,8 +1289,8 @@ end @test_throws BoundsError r[4] @test_throws BoundsError r[0] @test broadcast(+, r, 1) === 2:4 - @test 2*r === 2:2:6 - @test r + r === 2:2:6 + @test 2*r == 2:2:6 + @test r + r == 2:2:6 k = 0 for i in r @test i == (k += 1) @@ -1432,14 +1433,14 @@ end @test @inferred(r .+ x) === 3:7 @test @inferred(r .- x) === -1:3 @test @inferred(x .- r) === 1:-1:-3 - @test @inferred(x .* r) === 2:2:10 - @test @inferred(r .* x) === 2:2:10 + @test @inferred(x .* r) == 2:2:10 + @test @inferred(r .* x) == 2:2:10 @test @inferred(r ./ x) === 0.5:0.5:2.5 @test @inferred(x ./ r) == 2 ./ [r;] && isa(x ./ r, Vector{Float64}) @test @inferred(r .\ x) == 2 ./ [r;] && isa(x ./ r, Vector{Float64}) @test @inferred(x .\ r) === 0.5:0.5:2.5 - @test @inferred(2 .* (r .+ 1) .+ 2) === 6:2:14 + @test @inferred(2 .* (r .+ 1) .+ 2) == 6:2:14 end @testset "Bad range calls" begin @@ -1564,17 +1565,22 @@ end # module NonStandardIntegerRangeTest end @testset "constant-valued ranges (issues #10391 and #29052)" begin - for r in ((1:4), (1:1:4), (1.0:4.0)) - is_int = eltype(r) === Int - @test @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] broken=is_int - @test @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] broken=is_int - @test @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] broken=is_int - @test @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] broken=is_int + @testset "with $(nameof(typeof(r))) of $(eltype(r))" for r in ((1:4), (1:1:4), StepRangeLen(1,1,4), (1.0:4.0)) + @test @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r .* 0) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + @test @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + @test @inferred(r - r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r .- r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r .+ (4.0:-1:1)) == [5.0, 5.0, 5.0, 5.0] @test @inferred(0.0 * r) == [0.0, 0.0, 0.0, 0.0] @test @inferred(0.0 .* r) == [0.0, 0.0, 0.0, 0.0] @test @inferred(r / Inf) == [0.0, 0.0, 0.0, 0.0] @test @inferred(r ./ Inf) == [0.0, 0.0, 0.0, 0.0] + + @test eval(Meta.parse(repr(0 * r))) == [0.0, 0.0, 0.0, 0.0] end @test_broken @inferred(range(0, step=0, length=4)) == [0, 0, 0, 0] @@ -1587,7 +1593,7 @@ end @test @inferred(range(0.0, stop=0, length=4)) == [0.0, 0.0, 0.0, 0.0] z4 = 0.0 * (1:4) - @test @inferred(z4 .+ (1:4)) === 1.0:1.0:4.0 + @test @inferred(z4 .+ (1:4)) == 1.0:1.0:4.0 @test @inferred(z4 .+ z4) === z4 end @@ -1889,3 +1895,9 @@ end @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] end + +@testset "PR 40320 nanosoldier" begin + @test 0.2 * (-2:2) == -0.4:0.2:0.4 # from tests of AbstractFFTs, needs Base.TwicePrecision + @test 0.2f0 * (-2:2) == Float32.(-0.4:0.2:0.4) # likewise needs Float64 + @test 0.2 * (-2:1:2) == -0.4:0.2:0.4 +end From b1a4129338113181f01754371633d67bd8d17760 Mon Sep 17 00:00:00 2001 From: Atsushi Sakai Date: Mon, 17 May 2021 07:39:25 +0900 Subject: [PATCH 350/439] RFC: Some degree trigonometric functions, `sind`, `cosd`, `tand`, `asind` , `acosd`, `asecd`, `acsd`, `acotd`, `atand` accept a square matrix. (#39758) * Some degree trigonometric functions, `sind`, `cosd`, `tand`, `asind`, `acosd`, `asecd`, `acsd`, `acotd` accept an square matrix. * add PR number and change argument name to be the same as in the document. * Update NEWS.md * add `atand` for News.md. Co-authored-by: Viral B. Shah --- NEWS.md | 1 + base/special/trig.jl | 32 ++++++++++++++++++++------------ test/math.jl | 29 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index ea05d66aac3a6..93e3b6e523992 100644 --- a/NEWS.md +++ b/NEWS.md @@ -89,6 +89,7 @@ Standard library changes ([#39322]) * `@lock` is now exported from Base ([#39588]). * The experimental function `Base.catch_stack()` has been renamed to `current_exceptions()`, exported from Base and given a more specific return type ([#29901]) +* Some degree trigonometric functions, `sind`, `cosd`, `tand`, `asind`, `acosd`, `asecd`, `acscd`, `acotd`, `atand` now accept an square matrix ([#39758]). #### Package Manager diff --git a/base/special/trig.jl b/base/special/trig.jl index e7b9e2085bb98..363bec0e62c8c 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -1269,22 +1269,30 @@ end sincosd(::Missing) = (missing, missing) for (fd, f, fn) in ((:sind, :sin, "sine"), (:cosd, :cos, "cosine"), (:tand, :tan, "tangent")) - name = string(fd) - @eval begin - @doc """ - $($name)(x) - Compute $($fn) of `x`, where `x` is in degrees. """ ($fd)(z) = ($f)(deg2rad(z)) + for (fu, un) in ((:deg2rad, "degrees"),) + name = string(fd) + @eval begin + @doc """ + $($name)(x) + + Compute $($fn) of `x`, where `x` is in $($un). + If `x` is a matrix, `x` needs to be a square matrix. """ ($fd)(x) = ($f)(($fu).(x)) + end end end for (fd, f, fn) in ((:asind, :asin, "sine"), (:acosd, :acos, "cosine"), (:asecd, :asec, "secant"), (:acscd, :acsc, "cosecant"), (:acotd, :acot, "cotangent")) - name = string(fd) - @eval begin - @doc """ - $($name)(x) - Compute the inverse $($fn) of `x`, where the output is in degrees. """ ($fd)(y) = rad2deg(($f)(y)) + for (fu, un) in ((:rad2deg, "degrees"),) + name = string(fd) + @eval begin + @doc """ + $($name)(x) + + Compute the inverse $($fn) of `x`, where the output is in $($un). + If `x` is a matrix, `x` needs to be a square matrix. """ ($fd)(x) = ($fu).(($f)(x)) + end end end @@ -1294,5 +1302,5 @@ end Compute the inverse tangent of `y` or `y/x`, respectively, where the output is in degrees. """ -atand(y) = rad2deg(atan(y)) -atand(y, x) = rad2deg(atan(y,x)) +atand(y) = rad2deg.(atan(y)) +atand(y, x) = rad2deg.(atan(y,x)) diff --git a/test/math.jl b/test/math.jl index 074358da9c791..120f1075e0818 100644 --- a/test/math.jl +++ b/test/math.jl @@ -341,6 +341,35 @@ end @test Array(acosh.(STAA)) == acosh.(TAA) @test Array(acsch.(STAA)) == acsch.(TAA) @test Array(acoth.(STAA)) == acoth.(TAA) + @test sind(TAA) == sin(deg2rad.(TAA)) + @test cosd(TAA) == cos(deg2rad.(TAA)) + @test tand(TAA) == tan(deg2rad.(TAA)) + @test asind(TAA) == rad2deg.(asin(TAA)) + @test acosd(TAA) == rad2deg.(acos(TAA)) + @test atand(TAA) == rad2deg.(atan(TAA)) + @test asecd(TAA) == rad2deg.(asec(TAA)) + @test acscd(TAA) == rad2deg.(acsc(TAA)) + @test acotd(TAA) == rad2deg.(acot(TAA)) + + m = rand(3,2) # not square matrix + ex = @test_throws DimensionMismatch sind(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch cosd(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch tand(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch asind(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch acosd(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch atand(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch asecd(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch acscd(m) + @test startswith(ex.value.msg, "matrix is not square") + ex = @test_throws DimensionMismatch acotd(m) + @test startswith(ex.value.msg, "matrix is not square") end @testset "check exp2(::Integer) matches exp2(::Float)" begin From 0bae1931889d6f3aecda6c527e9630be837142cf Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Mon, 17 May 2021 16:08:19 +0200 Subject: [PATCH 351/439] Let sparse(x') preserve index type for sparse x (#40836) --- stdlib/SparseArrays/src/sparsematrix.jl | 2 +- stdlib/SparseArrays/test/sparse.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 58dfd88abd339..ffecaaeaf20c0 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -706,7 +706,7 @@ julia> sparse(A) ⋅ ⋅ 1.0 ``` """ -sparse(A::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, A) +sparse(A::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv}, A) sparse(S::AbstractSparseMatrixCSC) = copy(S) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 4c6ca81127129..85fb999cbe677 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -94,6 +94,7 @@ end # with combine @test sparse([1, 1, 2, 2, 2], [1, 2, 1, 2, 2], 1.0, 2, 2, +) == sparse([1, 1, 2, 2], [1, 2, 1, 2], [1.0, 1.0, 1.0, 2.0], 2, 2) @test sparse([1, 1, 2, 2, 2], [1, 2, 1, 2, 2], -1.0, 2, 2, *) == sparse([1, 1, 2, 2], [1, 2, 1, 2], [-1.0, -1.0, -1.0, 1.0], 2, 2) + @test sparse(sparse(Int32.(1:5), Int32.(1:5), trues(5))') isa SparseMatrixCSC{Bool,Int32} end @testset "SparseMatrixCSC construction from UniformScaling" begin From b054be5243ca4611d7bb3c7434b2342d103fbd56 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 18 May 2021 04:37:07 +0200 Subject: [PATCH 352/439] faster `iseven(::BigInt)` (#40850) This method was depending on the generic implementation `iseven(x::Integer) = !isodd(x)` for its efficiency, but this was removed in #38976, making `iseven(::BigInt)` 30 times slower. --- base/gmp.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 90874b01977c2..7d00c2417aad7 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -10,7 +10,7 @@ import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, sum, trailing_zeros, trailing_ones, count_ones, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, - sign, hastypemax, isodd, digits! + sign, hastypemax, isodd, iseven, digits! if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -343,6 +343,7 @@ end rem(x::Integer, ::Type{BigInt}) = BigInt(x) isodd(x::BigInt) = MPZ.tstbit(x, 0) +iseven(x::BigInt) = !isodd(x) function (::Type{T})(x::BigInt) where T<:Base.BitUnsigned if sizeof(T) < sizeof(Limb) From 39caf28d64ec17e4957f0c437e7970b0b11d98cc Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 18 May 2021 11:59:40 -0400 Subject: [PATCH 353/439] Add support for external method tables (#39697) This PR implements a way to keep tables of methods that are not part of the internal method table, but still participate in the special support we have for keeping tables of methods, in particular unification through precompilation and efficient lookup. The intended design use case is to allow for method overlay tables for various non-CPU backends (e.g. GPU and TPU). These backends would like to modify basic function like `sin` to perform better on the device in question (or in the case of TPU to define them over non-LLVM intrinsics). To date, the best available mechanism of achieving this result was to use a Cassette-like pass rewriting every method and injecting an overlay if necessary. However, this approach is somewhat unsatisfying for two reasons: 1. It requires rewriting every function, which has non-trivial performance cost. 2. It is (currently) expensive because of the repeated calls to generated functions. 3. It confuses inference, because suddenly everything is one method. We have hooks to work around this, but support is incomplete. It is also not clear that Cassette it is the best conceptual model, because these methods *are* methods of the same generic function, they just happen to only be applicable for a particular backend. It is worth noting that this PR only gives the ability to keep these tables of methods. It assigns no particular meaning to them and the runtime (and regular inference) do not look at them. They are designed as an implementation detail for external compilers and similar tools. This feature does not replace Cassette for the method-interception use case in the absence of such a compiler, though it could in the future form part of a solution (I'm hoping the AD work will in due course lead to abstractions that would enable a "faster Cassette" which may use part of these fetaures). As such, I'm not sure we'll ever move this out of Experimental, but until such a time that we have a better solution, I think this'll be a useful feature for the GPU stack. With all those disclaimers out of the way, here is a description of the various parts of the current design that deserve discussion: # Demo ```julia julia> using Base.Experimental: @overlay, @MethodTable julia> @MethodTable(mt) # 0 methods: julia> mt # 0 methods: julia> @overlay mt function sin(x::Float64) 1 end julia> @overlay mt function cos(x::Float64) 1 end julia> mt # 2 methods: [1] cos(x::Float64) in Main at REPL[5]:1 [2] sin(x::Float64) in Main at REPL[4]:1 julia> Base._methods_by_ftype(Tuple{typeof(sin), Float64}, mt, 1, typemax(UInt)) 1-element Vector{Any}: Core.MethodMatch(Tuple{typeof(sin), Float64}, svec(), sin(x::Float64) in Main at REPL[4]:1, true) julia> Base._methods_by_ftype(Tuple{typeof(sin), Float64}, 1, typemax(UInt)) 1-element Vector{Any}: Core.MethodMatch(Tuple{typeof(sin), Float64}, svec(Float64), sin(x::T) where T<:Union{Float32, Float64} in Base.Math at special/trig.jl:29, true) ``` # The `@overlay` macro The macro replaces the function name by an `Expr(:overlay, mt, name)`, which then gets piped through to Method def. One particular design aspect here is that I've stopped letting the 4-argument :method Expr introduce new generic functions, reserving this functionality entirely to the 2-argument :method Expr. We already started going this way when we began omitting method names from the 4-argument version. This PR re-uses that name field of the 4-argument version to specify a method table instead. # Identity of methods I think one of the biggest questions of this design is what happens to the identity of methods. Until OpaqueClosure, all methods were uniquely identified by their signatures, with the applicable method table computed from the first argument of the signature. This is important so that incremental compilation can properly merge method tables coming from different .ji files. For these methods, that is of course not the correct method table to use for these methods, so methods that are not part of the internal method table will instead have a backreference to the applicable method table. # Identity of method tables Method tables are identified by the name of their binding in the containing module. To ensure consistency of this mapping, these MethodTables may only be constructed using the `@MethodTable(name)` macro, which simultaneously establishes a const binding in the declaring module. Co-authored-by: Tim Besard --- base/compiler/methodtable.jl | 32 +++++++- base/experimental.jl | 33 ++++++++ base/reflection.jl | 17 ++-- src/codegen.cpp | 98 ++++++++++++----------- src/dump.c | 57 ++++++++++--- src/gf.c | 11 ++- src/interpreter.c | 34 +++++--- src/jltypes.c | 4 +- src/julia-syntax.scm | 22 +++-- src/julia.h | 3 +- src/julia_internal.h | 4 +- src/method.c | 14 +++- stdlib/Serialization/src/Serialization.jl | 3 + stdlib/Test/src/Test.jl | 2 +- test/ambiguous.jl | 6 +- test/compiler/contextual.jl | 76 ++++++++++++++++++ 16 files changed, 319 insertions(+), 97 deletions(-) diff --git a/base/compiler/methodtable.jl b/base/compiler/methodtable.jl index cff9e21fccb41..9b2010afcb05b 100644 --- a/base/compiler/methodtable.jl +++ b/base/compiler/methodtable.jl @@ -28,6 +28,17 @@ struct InternalMethodTable <: MethodTableView world::UInt end +""" + struct OverlayMethodTable <: MethodTableView + +Overlays the internal method table such that specific queries can be redirected to an +external table, e.g., to override existing method. +""" +struct OverlayMethodTable <: MethodTableView + world::UInt + mt::Core.MethodTable +end + """ struct CachedMethodTable <: MethodTableView @@ -54,7 +65,26 @@ function findall(@nospecialize(sig::Type{<:Tuple}), table::InternalMethodTable; _min_val = RefValue{UInt}(typemin(UInt)) _max_val = RefValue{UInt}(typemax(UInt)) _ambig = RefValue{Int32}(0) - ms = _methods_by_ftype(sig, limit, table.world, false, _min_val, _max_val, _ambig) + ms = _methods_by_ftype(sig, nothing, limit, table.world, false, _min_val, _max_val, _ambig) + if ms === false + return missing + end + return MethodLookupResult(ms::Vector{Any}, WorldRange(_min_val[], _max_val[]), _ambig[] != 0) +end + +function findall(@nospecialize(sig::Type{<:Tuple}), table::OverlayMethodTable; limit::Int=typemax(Int)) + _min_val = RefValue{UInt}(typemin(UInt)) + _max_val = RefValue{UInt}(typemax(UInt)) + _ambig = RefValue{Int32}(0) + ms = _methods_by_ftype(sig, table.mt, limit, table.world, false, _min_val, _max_val, _ambig) + if ms === false + return missing + elseif isempty(ms) + # fall back to the internal method table + _min_val[] = typemin(UInt) + _max_val[] = typemax(UInt) + ms = _methods_by_ftype(sig, nothing, limit, table.world, false, _min_val, _max_val, _ambig) + end if ms === false return missing end diff --git a/base/experimental.jl b/base/experimental.jl index 7e30792dda4e8..a2a40294bfb14 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -10,6 +10,7 @@ module Experimental using Base: Threads, sync_varname +using Base.Meta """ Const(A::Array) @@ -256,4 +257,36 @@ end # OpaqueClosure include("opaque_closure.jl") +""" + Experimental.@overlay mt [function def] + +Define a method and add it to the method table `mt` instead of to the global method table. +This can be used to implement a method override mechanism. Regular compilation will not +consider these methods, and you should customize the compilation flow to look in these +method tables (e.g., using [`Core.Compiler.OverlayMethodTable`](@ref)). + +""" +macro overlay(mt, def) + def = macroexpand(__module__, def) # to expand @inline, @generated, etc + if !isexpr(def, [:function, :(=)]) || !isexpr(def.args[1], :call) + error("@overlay requires a function Expr") + end + def.args[1].args[1] = Expr(:overlay, mt, def.args[1].args[1]) + esc(def) +end + +""" + Experimental.@MethodTable(name) + +Create a new MethodTable in the current module, bound to `name`. This method table can be +used with the [`Experimental.@overlay`](@ref) macro to define methods for a function without +adding them to the global method table. +""" +macro MethodTable(name) + isa(name, Symbol) || error("name must be a symbol") + esc(quote + const $name = ccall(:jl_new_method_table, Any, (Any, Any), $(quot(name)), $(__module__)) + end) +end + end diff --git a/base/reflection.jl b/base/reflection.jl index 8fe04defe1d3f..7d7318fadce9e 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -895,13 +895,16 @@ function _methods(@nospecialize(f), @nospecialize(t), lim::Int, world::UInt) end function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt) - return _methods_by_ftype(t, lim, world, false, RefValue{UInt}(typemin(UInt)), RefValue{UInt}(typemax(UInt)), Ptr{Int32}(C_NULL)) + return _methods_by_ftype(t, nothing, lim, world) end -function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, ambig::Bool, min::Array{UInt,1}, max::Array{UInt,1}, has_ambig::Array{Int32,1}) - return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} +function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt) + return _methods_by_ftype(t, mt, lim, world, false, RefValue{UInt}(typemin(UInt)), RefValue{UInt}(typemax(UInt)), Ptr{Int32}(C_NULL)) end -function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, ambig::Bool, min::Ref{UInt}, max::Ref{UInt}, has_ambig::Ref{Int32}) - return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} +function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt, ambig::Bool, min::Array{UInt,1}, max::Array{UInt,1}, has_ambig::Array{Int32,1}) + return ccall(:jl_matching_methods, Any, (Any, Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, mt, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} +end +function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt, ambig::Bool, min::Ref{UInt}, max::Ref{UInt}, has_ambig::Ref{Int32}) + return ccall(:jl_matching_methods, Any, (Any, Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, mt, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} end function _method_by_ftype(args...) @@ -971,7 +974,7 @@ function methods_including_ambiguous(@nospecialize(f), @nospecialize(t)) world = typemax(UInt) min = RefValue{UInt}(typemin(UInt)) max = RefValue{UInt}(typemax(UInt)) - ms = _methods_by_ftype(tt, -1, world, true, min, max, Ptr{Int32}(C_NULL)) + ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL)) isa(ms, Bool) && return ms return MethodList(Method[(m::Core.MethodMatch).method for m in ms], typeof(f).name.mt) end @@ -1533,7 +1536,7 @@ function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false) min = UInt[typemin(UInt)] max = UInt[typemax(UInt)] has_ambig = Int32[0] - ms = _methods_by_ftype(ti, -1, typemax(UInt), true, min, max, has_ambig)::Vector + ms = _methods_by_ftype(ti, nothing, -1, typemax(UInt), true, min, max, has_ambig)::Vector has_ambig[] == 0 && return false if !ambiguous_bottom filter!(ms) do m::Core.MethodMatch diff --git a/src/codegen.cpp b/src/codegen.cpp index bc60798220d52..b8f86e001e985 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -566,7 +566,7 @@ static const auto jlinvoke_func = new JuliaFunction{ static const auto jlmethod_func = new JuliaFunction{ "jl_method_def", [](LLVMContext &C) { return FunctionType::get(T_prjlvalue, - {T_prjlvalue, T_prjlvalue, T_pjlvalue}, false); }, + {T_prjlvalue, T_prjlvalue, T_prjlvalue, T_pjlvalue}, false); }, nullptr, }; static const auto jlgenericfunction_func = new JuliaFunction{ @@ -4398,58 +4398,62 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval) return emit_sparam(ctx, jl_unbox_long(args[0]) - 1); } else if (head == method_sym) { - jl_value_t *mn = args[0]; - assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(mn) || jl_is_slot(mn)); + if (jl_expr_nargs(ex) == 1) { + jl_value_t *mn = args[0]; + assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(mn) || jl_is_slot(mn)); - Value *bp = NULL, *name, *bp_owner = V_null; - jl_binding_t *bnd = NULL; - bool issym = jl_is_symbol(mn); - bool isglobalref = !issym && jl_is_globalref(mn); - jl_module_t *mod = ctx.module; - if (issym || isglobalref) { - if (isglobalref) { - mod = jl_globalref_mod(mn); - mn = (jl_value_t*)jl_globalref_name(mn); - } - JL_TRY { - if (jl_symbol_name((jl_sym_t*)mn)[0] == '@') - jl_errorf("macro definition not allowed inside a local scope"); - name = literal_pointer_val(ctx, mn); - bnd = jl_get_binding_for_method_def(mod, (jl_sym_t*)mn); - } - JL_CATCH { - jl_value_t *e = jl_current_exception(); - // errors. boo. root it somehow :( - bnd = jl_get_binding_wr(ctx.module, (jl_sym_t*)jl_gensym(), 1); - bnd->value = e; - bnd->constp = 1; - raise_exception(ctx, literal_pointer_val(ctx, e)); - return ghostValue(jl_nothing_type); - } - bp = julia_binding_gv(ctx, bnd); - bp_owner = literal_pointer_val(ctx, (jl_value_t*)mod); - } - else if (jl_is_slot(mn) || jl_is_argument(mn)) { - int sl = jl_slot_number(mn)-1; - jl_varinfo_t &vi = ctx.slots[sl]; - bp = vi.boxroot; - name = literal_pointer_val(ctx, (jl_value_t*)slot_symbol(ctx, sl)); - } - if (bp) { - Value *mdargs[5] = { name, literal_pointer_val(ctx, (jl_value_t*)mod), bp, - bp_owner, literal_pointer_val(ctx, bnd) }; - jl_cgval_t gf = mark_julia_type( - ctx, - ctx.builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), - true, - jl_function_type); - if (jl_expr_nargs(ex) == 1) + Value *bp = NULL, *name, *bp_owner = V_null; + jl_binding_t *bnd = NULL; + bool issym = jl_is_symbol(mn); + bool isglobalref = !issym && jl_is_globalref(mn); + jl_module_t *mod = ctx.module; + if (issym || isglobalref) { + if (isglobalref) { + mod = jl_globalref_mod(mn); + mn = (jl_value_t*)jl_globalref_name(mn); + } + JL_TRY { + if (jl_symbol_name((jl_sym_t*)mn)[0] == '@') + jl_errorf("macro definition not allowed inside a local scope"); + name = literal_pointer_val(ctx, mn); + bnd = jl_get_binding_for_method_def(mod, (jl_sym_t*)mn); + } + JL_CATCH { + jl_value_t *e = jl_current_exception(); + // errors. boo. root it somehow :( + bnd = jl_get_binding_wr(ctx.module, (jl_sym_t*)jl_gensym(), 1); + bnd->value = e; + bnd->constp = 1; + raise_exception(ctx, literal_pointer_val(ctx, e)); + return ghostValue(jl_nothing_type); + } + bp = julia_binding_gv(ctx, bnd); + bp_owner = literal_pointer_val(ctx, (jl_value_t*)mod); + } + else if (jl_is_slot(mn) || jl_is_argument(mn)) { + int sl = jl_slot_number(mn)-1; + jl_varinfo_t &vi = ctx.slots[sl]; + bp = vi.boxroot; + name = literal_pointer_val(ctx, (jl_value_t*)slot_symbol(ctx, sl)); + } + if (bp) { + Value *mdargs[5] = { name, literal_pointer_val(ctx, (jl_value_t*)mod), bp, + bp_owner, literal_pointer_val(ctx, bnd) }; + jl_cgval_t gf = mark_julia_type( + ctx, + ctx.builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), + true, + jl_function_type); return gf; + } + emit_error(ctx, "method: invalid declaration"); + return jl_cgval_t(); } Value *a1 = boxed(ctx, emit_expr(ctx, args[1])); Value *a2 = boxed(ctx, emit_expr(ctx, args[2])); - Value *mdargs[3] = { + Value *mdargs[4] = { /*argdata*/a1, + ConstantPointerNull::get(cast(T_prjlvalue)), /*code*/a2, /*module*/literal_pointer_val(ctx, (jl_value_t*)ctx.module) }; diff --git a/src/dump.c b/src/dump.c index 2a6c8318c2095..5771776a8658d 100644 --- a/src/dump.c +++ b/src/dump.c @@ -504,6 +504,11 @@ static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_ jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque); } +enum METHOD_SERIALIZATION_MODE { + METHOD_INTERNAL = 1, + METHOD_EXTERNAL_MT = 2, +}; + static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED { if (jl_serialize_generic(s, v)) { @@ -627,9 +632,10 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li else if (jl_is_method(v)) { write_uint8(s->s, TAG_METHOD); jl_method_t *m = (jl_method_t*)v; - int internal = 1; - internal = m->is_for_opaque_closure || module_in_worklist(m->module); - if (!internal) { + int serialization_mode = 0; + if (m->is_for_opaque_closure || module_in_worklist(m->module)) + serialization_mode |= METHOD_INTERNAL; + if (!(serialization_mode & METHOD_INTERNAL)) { // flag this in the backref table as special uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v); assert(*bp != (uintptr_t)HT_NOTFOUND); @@ -637,8 +643,23 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } jl_serialize_value(s, (jl_value_t*)m->sig); jl_serialize_value(s, (jl_value_t*)m->module); - write_uint8(s->s, internal); - if (!internal) + if (m->external_mt != NULL) { + assert(jl_typeis(m->external_mt, jl_methtable_type)); + jl_methtable_t *mt = (jl_methtable_t*)m->external_mt; + if (!module_in_worklist(mt->module)) { + serialization_mode |= METHOD_EXTERNAL_MT; + } + } + write_uint8(s->s, serialization_mode); + if (serialization_mode & METHOD_EXTERNAL_MT) { + // We reference this method table by module and binding + jl_methtable_t *mt = (jl_methtable_t*)m->external_mt; + jl_serialize_value(s, mt->module); + jl_serialize_value(s, mt->name); + } else { + jl_serialize_value(s, (jl_value_t*)m->external_mt); + } + if (!(serialization_mode & METHOD_INTERNAL)) return; jl_serialize_value(s, m->specializations); jl_serialize_value(s, m->speckeyset); @@ -952,6 +973,10 @@ static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DIS jl_collect_lambdas_from_mod(s, (jl_module_t*)b->value); } } + else if (jl_is_mtable(bv)) { + // a module containing an external method table + jl_collect_methtable_from_mod(s, (jl_methtable_t*)bv); + } } } } @@ -1015,7 +1040,7 @@ static void jl_collect_backedges(jl_array_t *s, jl_array_t *t) size_t min_valid = 0; size_t max_valid = ~(size_t)0; int ambig = 0; - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); + jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); if (matches == jl_false) { valid = 0; break; @@ -1458,8 +1483,18 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ jl_gc_wb(m, m->sig); m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module); jl_gc_wb(m, m->module); - int internal = read_uint8(s->s); - if (!internal) { + int serialization_mode = read_uint8(s->s); + if (serialization_mode & METHOD_EXTERNAL_MT) { + jl_module_t *mt_mod = (jl_module_t*)jl_deserialize_value(s, NULL); + jl_sym_t *mt_name = (jl_sym_t*)jl_deserialize_value(s, NULL); + m->external_mt = jl_get_global(mt_mod, mt_name); + jl_gc_wb(m, m->external_mt); + assert(jl_typeis(m->external_mt, jl_methtable_type)); + } else { + m->external_mt = jl_deserialize_value(s, &m->external_mt); + jl_gc_wb(m, m->external_mt); + } + if (!(serialization_mode & METHOD_INTERNAL)) { assert(loc != NULL && loc != HT_NOTFOUND); arraylist_push(&flagref_list, loc); arraylist_push(&flagref_list, (void*)pos); @@ -1897,7 +1932,7 @@ static void jl_insert_methods(jl_array_t *list) assert(!meth->is_for_opaque_closure); jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_array_ptr_ref(list, i + 1); assert(jl_is_method(meth)); - jl_methtable_t *mt = jl_method_table_for((jl_value_t*)meth->sig); + jl_methtable_t *mt = jl_method_get_table(meth); assert((jl_value_t*)mt != jl_nothing); jl_method_table_insert(mt, meth, simpletype); } @@ -1927,7 +1962,7 @@ static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids) size_t max_valid = ~(size_t)0; int ambig = 0; // TODO: possibly need to included ambiguities too (for the optimizer correctness)? - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); + jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) { valid = 0; } @@ -2465,7 +2500,7 @@ static jl_method_t *jl_recache_method(jl_method_t *m) { assert(!m->is_for_opaque_closure); jl_datatype_t *sig = (jl_datatype_t*)m->sig; - jl_methtable_t *mt = jl_method_table_for((jl_value_t*)m->sig); + jl_methtable_t *mt = jl_method_get_table(m); assert((jl_value_t*)mt != jl_nothing); jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors jl_method_t *_new = jl_lookup_method(mt, sig, m->module->primary_world); diff --git a/src/gf.c b/src/gf.c index 5bdf7c8ec29b0..3cda8ae2a733c 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1876,7 +1876,7 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w // // lim is the max # of methods to return. if there are more, returns jl_false. // -1 for no limit. -JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig) { JL_TIMING(METHOD_MATCH); @@ -1885,10 +1885,13 @@ JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types); if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type) return (jl_value_t*)jl_an_empty_vec_any; - jl_methtable_t *mt = jl_method_table_for(unw); + if (mt == jl_nothing) + mt = (jl_value_t*)jl_method_table_for(unw); + else if (!jl_typeis(mt, jl_methtable_type)) + jl_error("matching_method: `mt` is not a method table"); if ((jl_value_t*)mt == jl_nothing) return jl_false; // indeterminate - ml_matches can't deal with this case - return ml_matches(mt, 0, types, lim, include_ambiguous, 1, world, 1, min_valid, max_valid, ambig); + return ml_matches((jl_methtable_t*)mt, 0, types, lim, include_ambiguous, 1, world, 1, min_valid, max_valid, ambig); } jl_method_instance_t *jl_get_unspecialized(jl_method_instance_t *method JL_PROPAGATES_ROOT) @@ -2067,7 +2070,7 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES size_t min_valid2 = 1; size_t max_valid2 = ~(size_t)0; int ambig = 0; - jl_value_t *matches = jl_matching_methods(types, 1, 1, world, &min_valid2, &max_valid2, &ambig); + jl_value_t *matches = jl_matching_methods(types, jl_nothing, 1, 1, world, &min_valid2, &max_valid2, &ambig); if (*min_valid < min_valid2) *min_valid = min_valid2; if (*max_valid > max_valid2) diff --git a/src/interpreter.c b/src/interpreter.c index 008886f1c99c9..f130c311c1a45 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -78,28 +78,36 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, static jl_value_t *eval_methoddef(jl_expr_t *ex, interpreter_state *s) { jl_value_t **args = jl_array_ptr_data(ex->args); - jl_sym_t *fname = (jl_sym_t*)args[0]; - jl_module_t *modu = s->module; - if (jl_is_globalref(fname)) { - modu = jl_globalref_mod(fname); - fname = jl_globalref_name(fname); - } - assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(fname)); - if (jl_is_symbol(fname)) { + if (jl_expr_nargs(ex) == 1) { + jl_value_t **args = jl_array_ptr_data(ex->args); + jl_sym_t *fname = (jl_sym_t*)args[0]; + jl_module_t *modu = s->module; + if (jl_is_globalref(fname)) { + modu = jl_globalref_mod(fname); + fname = jl_globalref_name(fname); + } + if (!jl_is_symbol(fname)) { + jl_error("method: invalid declaration"); + } jl_value_t *bp_owner = (jl_value_t*)modu; jl_binding_t *b = jl_get_binding_for_method_def(modu, fname); jl_value_t **bp = &b->value; jl_value_t *gf = jl_generic_function_def(b->name, b->owner, bp, bp_owner, b); - if (jl_expr_nargs(ex) == 1) - return gf; + return gf; } - jl_value_t *atypes = NULL, *meth = NULL; - JL_GC_PUSH2(&atypes, &meth); + jl_value_t *atypes = NULL, *meth = NULL, *fname = NULL; + JL_GC_PUSH3(&atypes, &meth, &fname); + + fname = eval_value(args[0], s); + jl_methtable_t *mt = NULL; + if (jl_typeis(fname, jl_methtable_type)) { + mt = (jl_methtable_t*)fname; + } atypes = eval_value(args[1], s); meth = eval_value(args[2], s); - jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module); + jl_method_def((jl_svec_t*)atypes, mt, (jl_code_info_t*)meth, s->module); JL_GC_POP(); return jl_nothing; } diff --git a/src/jltypes.c b/src/jltypes.c index 2ba69caf1991e..73015d2cfe6c1 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2302,6 +2302,7 @@ void jl_init_types(void) JL_GC_DISABLED "specializations", "speckeyset", "slot_syms", + "external_mt", "source", "unspecialized", "generator", @@ -2329,6 +2330,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_array_type, jl_string_type, jl_any_type, + jl_any_type, jl_any_type, // jl_method_instance_type jl_any_type, jl_array_any_type, @@ -2535,7 +2537,7 @@ void jl_init_types(void) JL_GC_DISABLED #endif jl_svecset(jl_methtable_type->types, 10, jl_uint8_type); jl_svecset(jl_methtable_type->types, 11, jl_uint8_type); - jl_svecset(jl_method_type->types, 11, jl_method_instance_type); + jl_svecset(jl_method_type->types, 12, jl_method_instance_type); jl_svecset(jl_method_instance_type->types, 6, jl_code_instance_type); jl_svecset(jl_code_instance_type->types, 9, jl_voidpointer_type); jl_svecset(jl_code_instance_type->types, 10, jl_voidpointer_type); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ca274ef552f5b..dfec6ca980020 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -221,10 +221,11 @@ (define (method-expr-name m) (let ((name (cadr m))) + (let ((name (if (or (length= m 2) (not (pair? name)) (not (quoted? name))) name (cadr name)))) (cond ((not (pair? name)) name) ((eq? (car name) 'outerref) (cadr name)) ;((eq? (car name) 'globalref) (caddr name)) - (else name)))) + (else name))))) ;; extract static parameter names from a (method ...) expression (define (method-expr-static-parameters m) @@ -252,6 +253,13 @@ (pair? (caddr e)) (memq (car (caddr e)) '(quote inert)) (symbol? (cadr (caddr e)))))) +(define (overlay? e) + (and (pair? e) (eq? (car e) 'overlay))) + +(define (sym-ref-or-overlay? e) + (or (overlay? e) + (sym-ref? e))) + ;; convert final (... x) to (curly Vararg x) (define (dots->vararg a) (if (null? a) a @@ -341,14 +349,15 @@ (let* ((names (map car sparams)) (anames (map (lambda (x) (if (underscore-symbol? x) UNUSED x)) (llist-vars argl))) (unused_anames (filter (lambda (x) (not (eq? x UNUSED))) anames)) - (ename (if (nodot-sym-ref? name) name `(null)))) + (ename (if (nodot-sym-ref? name) name + (if (overlay? name) (cadr name) `(null))))) (if (has-dups unused_anames) (error (string "function argument name not unique: \"" (car (has-dups unused_anames)) "\""))) (if (has-dups names) (error "function static parameter names not unique")) (if (any (lambda (x) (and (not (eq? x UNUSED)) (memq x names))) anames) (error "function argument and static parameter names must be distinct")) - (if (or (and name (not (sym-ref? name))) (not (valid-name? name))) + (if (or (and name (not (sym-ref-or-overlay? name))) (not (valid-name? name))) (error (string "invalid function name \"" (deparse name) "\""))) (let* ((loc (maybe-remove-functionloc! body)) (generator (if (expr-contains-p if-generated? body (lambda (x) (not (function-def? x)))) @@ -1130,13 +1139,14 @@ (argl-stmts (lower-destructuring-args argl)) (argl (car argl-stmts)) (name (check-dotop (car argl))) + (argname (if (overlay? name) (caddr name) name)) ;; fill in first (closure) argument (adj-decl (lambda (n) (if (and (decl? n) (length= n 2)) `(|::| |#self#| ,(cadr n)) n))) - (farg (if (decl? name) - (adj-decl name) - `(|::| |#self#| (call (core Typeof) ,name)))) + (farg (if (decl? argname) + (adj-decl argname) + `(|::| |#self#| (call (core Typeof) ,argname)))) (body (insert-after-meta body (cdr argl-stmts))) (argl (cdr argl)) (argl (fix-arglist diff --git a/src/julia.h b/src/julia.h index 8ec461e77126b..ed1cb5156285a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -311,6 +311,7 @@ typedef struct _jl_method_t { jl_array_t *speckeyset; // index lookup by hash into specializations jl_value_t *slot_syms; // compacted list of slot names (String) + jl_value_t *external_mt; // reference to the method table this method is part of, null if part of the internal table jl_value_t *source; // original code template (jl_code_info_t, but may be compressed), null for builtins struct _jl_method_instance_t *unspecialized; // unspecialized executable method instance, or null jl_value_t *generator; // executable code-generating function if available @@ -1400,7 +1401,7 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_module_t *module, jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd); -JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_module_t *module); +JL_DLLEXPORT jl_method_t *jl_method_def(jl_svec_t *argdata, jl_methtable_t *mt, jl_code_info_t *f, jl_module_t *module); JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo); JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src); JL_DLLEXPORT size_t jl_get_world_counter(void) JL_NOTSAFEPOINT; diff --git a/src/julia_internal.h b/src/julia_internal.h index d6170a9d56719..ec45080bcf908 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -548,13 +548,15 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs); jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t *f, jl_value_t **args, size_t nargs); -JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_methtable_t *jl_method_table_for( jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; +JL_DLLEXPORT jl_methtable_t *jl_method_get_table( + jl_method_t *method) JL_NOTSAFEPOINT; jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT); int jl_pointer_egal(jl_value_t *t); diff --git a/src/method.c b/src/method.c index 1d3a593e638ed..f771af9f79603 100644 --- a/src/method.c +++ b/src/method.c @@ -652,6 +652,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) m->roots = NULL; m->ccallable = NULL; m->module = module; + m->external_mt = NULL; m->source = NULL; m->unspecialized = NULL; m->generator = NULL; @@ -764,6 +765,11 @@ JL_DLLEXPORT jl_methtable_t *jl_method_table_for(jl_value_t *argtypes JL_PROPAGA return first_methtable(argtypes, 0); } +JL_DLLEXPORT jl_methtable_t *jl_method_get_table(jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT +{ + return method->external_mt ? (jl_methtable_t*)method->external_mt : jl_method_table_for(method->sig); +} + // get the MethodTable implied by a single given type, or `nothing` JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT { @@ -773,6 +779,7 @@ JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAG jl_array_t *jl_all_methods JL_GLOBALLY_ROOTED; JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, + jl_methtable_t *mt, jl_code_info_t *f, jl_module_t *module) { @@ -801,7 +808,9 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, argtype = jl_new_struct(jl_unionall_type, tv, argtype); } - jl_methtable_t *mt = jl_method_table_for(argtype); + jl_methtable_t *external_mt = mt; + if (!mt) + mt = jl_method_table_for(argtype); if ((jl_value_t*)mt == jl_nothing) jl_error("Method dispatch is unimplemented currently for this method signature"); if (mt->frozen) @@ -830,6 +839,9 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, f = jl_new_code_info_from_ir((jl_expr_t*)f); } m = jl_new_method_uninit(module); + m->external_mt = (jl_value_t*)external_mt; + if (external_mt) + jl_gc_wb(m, external_mt); m->sig = argtype; m->name = name; m->isva = isva; diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 060dbb2bc011f..14d3336b34caf 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -434,6 +434,9 @@ function serialize(s::AbstractSerializer, meth::Method) else serialize(s, nothing) end + if isdefined(meth, :external_mt) + error("cannot serialize Method objects with external method tables") + end nothing end diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 9a16d3d25c9be..674893051fdac 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1594,7 +1594,7 @@ function detect_ambiguities(mods::Module...; for m in Base.MethodList(mt) is_in_mods(m.module, recursive, mods) || continue ambig = Int32[0] - ms = Base._methods_by_ftype(m.sig, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(m.sig, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) ambig[1] == 0 && continue isa(ms, Bool) && continue for match2 in ms diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 8d0c2092f21c2..265d97776c053 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -348,7 +348,7 @@ f35983(::Type, ::Type) = 2 @test length(Base.methods(f35983, (Any, Any))) == 2 @test first(Base.methods(f35983, (Any, Any))).sig == Tuple{typeof(f35983), Type, Type} let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test length(ms) == 1 @test ambig[1] == 0 end @@ -356,14 +356,14 @@ f35983(::Type{Int16}, ::Any) = 3 @test length(Base.methods_including_ambiguous(f35983, (Type, Type))) == 2 @test length(Base.methods(f35983, (Type, Type))) == 2 let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test length(ms) == 2 @test ambig[1] == 1 end struct B38280 <: Real; val; end let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{Type{B38280}, Any}, 1, typemax(UInt), false, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{Type{B38280}, Any}, nothing, 1, typemax(UInt), false, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test ms isa Vector @test length(ms) == 1 @test ambig[1] == 1 diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index bce782d73df87..afbfa1db601f6 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -135,3 +135,79 @@ let method = which(func2, ()) end func3() = func2() @test_throws UndefVarError func3() + + + +## overlay method tables + +module OverlayModule + +using Base.Experimental: @MethodTable, @overlay + +@MethodTable(mt) + +@overlay mt function sin(x::Float64) + 1 +end + +# short function def +@overlay mt cos(x::Float64) = 2 + +end + +methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, nothing, 1, typemax(UInt)) +@test only(methods).method.module === Base.Math + +methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, OverlayModule.mt, 1, typemax(UInt)) +@test only(methods).method.module === OverlayModule + +methods = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, typemax(UInt)) +@test isempty(methods) + +# precompilation + +load_path = mktempdir() +depot_path = mktempdir() +try + pushfirst!(LOAD_PATH, load_path) + pushfirst!(DEPOT_PATH, depot_path) + + write(joinpath(load_path, "Foo.jl"), + """ + module Foo + Base.Experimental.@MethodTable(mt) + Base.Experimental.@overlay mt sin(x::Int) = 1 + end + """) + + # precompiling Foo serializes the overlay method through the `mt` binding in the module + Foo = Base.require(Main, :Foo) + @test length(Foo.mt) == 1 + + write(joinpath(load_path, "Bar.jl"), + """ + module Bar + Base.Experimental.@MethodTable(mt) + end + """) + + write(joinpath(load_path, "Baz.jl"), + """ + module Baz + using Bar + Base.Experimental.@overlay Bar.mt sin(x::Int) = 1 + end + """) + + # when referring an method table in another module, + # the overlay method needs to be discovered explicitly + Bar = Base.require(Main, :Bar) + @test length(Bar.mt) == 0 + Baz = Base.require(Main, :Baz) + @test length(Bar.mt) == 1 +finally + rm(load_path, recursive=true, force=true) + rm(depot_path, recursive=true, force=true) + filter!((≠)(load_path), LOAD_PATH) + filter!((≠)(depot_path), DEPOT_PATH) +end From 8a0a9a738890a02f93f2f06f5c0c21854f3b4822 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 18 May 2021 14:42:25 -0400 Subject: [PATCH 354/439] Revert "Add support for external method tables (#39697)" (#40862) This reverts commit 39caf28d64ec17e4957f0c437e7970b0b11d98cc. --- base/compiler/methodtable.jl | 32 +------- base/experimental.jl | 33 -------- base/reflection.jl | 17 ++-- src/codegen.cpp | 98 +++++++++++------------ src/dump.c | 57 +++---------- src/gf.c | 11 +-- src/interpreter.c | 34 +++----- src/jltypes.c | 4 +- src/julia-syntax.scm | 22 ++--- src/julia.h | 3 +- src/julia_internal.h | 4 +- src/method.c | 14 +--- stdlib/Serialization/src/Serialization.jl | 3 - stdlib/Test/src/Test.jl | 2 +- test/ambiguous.jl | 6 +- test/compiler/contextual.jl | 76 ------------------ 16 files changed, 97 insertions(+), 319 deletions(-) diff --git a/base/compiler/methodtable.jl b/base/compiler/methodtable.jl index 9b2010afcb05b..cff9e21fccb41 100644 --- a/base/compiler/methodtable.jl +++ b/base/compiler/methodtable.jl @@ -28,17 +28,6 @@ struct InternalMethodTable <: MethodTableView world::UInt end -""" - struct OverlayMethodTable <: MethodTableView - -Overlays the internal method table such that specific queries can be redirected to an -external table, e.g., to override existing method. -""" -struct OverlayMethodTable <: MethodTableView - world::UInt - mt::Core.MethodTable -end - """ struct CachedMethodTable <: MethodTableView @@ -65,26 +54,7 @@ function findall(@nospecialize(sig::Type{<:Tuple}), table::InternalMethodTable; _min_val = RefValue{UInt}(typemin(UInt)) _max_val = RefValue{UInt}(typemax(UInt)) _ambig = RefValue{Int32}(0) - ms = _methods_by_ftype(sig, nothing, limit, table.world, false, _min_val, _max_val, _ambig) - if ms === false - return missing - end - return MethodLookupResult(ms::Vector{Any}, WorldRange(_min_val[], _max_val[]), _ambig[] != 0) -end - -function findall(@nospecialize(sig::Type{<:Tuple}), table::OverlayMethodTable; limit::Int=typemax(Int)) - _min_val = RefValue{UInt}(typemin(UInt)) - _max_val = RefValue{UInt}(typemax(UInt)) - _ambig = RefValue{Int32}(0) - ms = _methods_by_ftype(sig, table.mt, limit, table.world, false, _min_val, _max_val, _ambig) - if ms === false - return missing - elseif isempty(ms) - # fall back to the internal method table - _min_val[] = typemin(UInt) - _max_val[] = typemax(UInt) - ms = _methods_by_ftype(sig, nothing, limit, table.world, false, _min_val, _max_val, _ambig) - end + ms = _methods_by_ftype(sig, limit, table.world, false, _min_val, _max_val, _ambig) if ms === false return missing end diff --git a/base/experimental.jl b/base/experimental.jl index a2a40294bfb14..7e30792dda4e8 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -10,7 +10,6 @@ module Experimental using Base: Threads, sync_varname -using Base.Meta """ Const(A::Array) @@ -257,36 +256,4 @@ end # OpaqueClosure include("opaque_closure.jl") -""" - Experimental.@overlay mt [function def] - -Define a method and add it to the method table `mt` instead of to the global method table. -This can be used to implement a method override mechanism. Regular compilation will not -consider these methods, and you should customize the compilation flow to look in these -method tables (e.g., using [`Core.Compiler.OverlayMethodTable`](@ref)). - -""" -macro overlay(mt, def) - def = macroexpand(__module__, def) # to expand @inline, @generated, etc - if !isexpr(def, [:function, :(=)]) || !isexpr(def.args[1], :call) - error("@overlay requires a function Expr") - end - def.args[1].args[1] = Expr(:overlay, mt, def.args[1].args[1]) - esc(def) -end - -""" - Experimental.@MethodTable(name) - -Create a new MethodTable in the current module, bound to `name`. This method table can be -used with the [`Experimental.@overlay`](@ref) macro to define methods for a function without -adding them to the global method table. -""" -macro MethodTable(name) - isa(name, Symbol) || error("name must be a symbol") - esc(quote - const $name = ccall(:jl_new_method_table, Any, (Any, Any), $(quot(name)), $(__module__)) - end) -end - end diff --git a/base/reflection.jl b/base/reflection.jl index 7d7318fadce9e..8fe04defe1d3f 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -895,16 +895,13 @@ function _methods(@nospecialize(f), @nospecialize(t), lim::Int, world::UInt) end function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt) - return _methods_by_ftype(t, nothing, lim, world) + return _methods_by_ftype(t, lim, world, false, RefValue{UInt}(typemin(UInt)), RefValue{UInt}(typemax(UInt)), Ptr{Int32}(C_NULL)) end -function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt) - return _methods_by_ftype(t, mt, lim, world, false, RefValue{UInt}(typemin(UInt)), RefValue{UInt}(typemax(UInt)), Ptr{Int32}(C_NULL)) +function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, ambig::Bool, min::Array{UInt,1}, max::Array{UInt,1}, has_ambig::Array{Int32,1}) + return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} end -function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt, ambig::Bool, min::Array{UInt,1}, max::Array{UInt,1}, has_ambig::Array{Int32,1}) - return ccall(:jl_matching_methods, Any, (Any, Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, mt, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} -end -function _methods_by_ftype(@nospecialize(t), mt::Union{Core.MethodTable, Nothing}, lim::Int, world::UInt, ambig::Bool, min::Ref{UInt}, max::Ref{UInt}, has_ambig::Ref{Int32}) - return ccall(:jl_matching_methods, Any, (Any, Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, mt, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} +function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, ambig::Bool, min::Ref{UInt}, max::Ref{UInt}, has_ambig::Ref{Int32}) + return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}, Ptr{Int32}), t, lim, ambig, world, min, max, has_ambig)::Union{Array{Any,1}, Bool} end function _method_by_ftype(args...) @@ -974,7 +971,7 @@ function methods_including_ambiguous(@nospecialize(f), @nospecialize(t)) world = typemax(UInt) min = RefValue{UInt}(typemin(UInt)) max = RefValue{UInt}(typemax(UInt)) - ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL)) + ms = _methods_by_ftype(tt, -1, world, true, min, max, Ptr{Int32}(C_NULL)) isa(ms, Bool) && return ms return MethodList(Method[(m::Core.MethodMatch).method for m in ms], typeof(f).name.mt) end @@ -1536,7 +1533,7 @@ function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false) min = UInt[typemin(UInt)] max = UInt[typemax(UInt)] has_ambig = Int32[0] - ms = _methods_by_ftype(ti, nothing, -1, typemax(UInt), true, min, max, has_ambig)::Vector + ms = _methods_by_ftype(ti, -1, typemax(UInt), true, min, max, has_ambig)::Vector has_ambig[] == 0 && return false if !ambiguous_bottom filter!(ms) do m::Core.MethodMatch diff --git a/src/codegen.cpp b/src/codegen.cpp index b8f86e001e985..bc60798220d52 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -566,7 +566,7 @@ static const auto jlinvoke_func = new JuliaFunction{ static const auto jlmethod_func = new JuliaFunction{ "jl_method_def", [](LLVMContext &C) { return FunctionType::get(T_prjlvalue, - {T_prjlvalue, T_prjlvalue, T_prjlvalue, T_pjlvalue}, false); }, + {T_prjlvalue, T_prjlvalue, T_pjlvalue}, false); }, nullptr, }; static const auto jlgenericfunction_func = new JuliaFunction{ @@ -4398,62 +4398,58 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval) return emit_sparam(ctx, jl_unbox_long(args[0]) - 1); } else if (head == method_sym) { - if (jl_expr_nargs(ex) == 1) { - jl_value_t *mn = args[0]; - assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(mn) || jl_is_slot(mn)); + jl_value_t *mn = args[0]; + assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(mn) || jl_is_slot(mn)); - Value *bp = NULL, *name, *bp_owner = V_null; - jl_binding_t *bnd = NULL; - bool issym = jl_is_symbol(mn); - bool isglobalref = !issym && jl_is_globalref(mn); - jl_module_t *mod = ctx.module; - if (issym || isglobalref) { - if (isglobalref) { - mod = jl_globalref_mod(mn); - mn = (jl_value_t*)jl_globalref_name(mn); - } - JL_TRY { - if (jl_symbol_name((jl_sym_t*)mn)[0] == '@') - jl_errorf("macro definition not allowed inside a local scope"); - name = literal_pointer_val(ctx, mn); - bnd = jl_get_binding_for_method_def(mod, (jl_sym_t*)mn); - } - JL_CATCH { - jl_value_t *e = jl_current_exception(); - // errors. boo. root it somehow :( - bnd = jl_get_binding_wr(ctx.module, (jl_sym_t*)jl_gensym(), 1); - bnd->value = e; - bnd->constp = 1; - raise_exception(ctx, literal_pointer_val(ctx, e)); - return ghostValue(jl_nothing_type); - } - bp = julia_binding_gv(ctx, bnd); - bp_owner = literal_pointer_val(ctx, (jl_value_t*)mod); - } - else if (jl_is_slot(mn) || jl_is_argument(mn)) { - int sl = jl_slot_number(mn)-1; - jl_varinfo_t &vi = ctx.slots[sl]; - bp = vi.boxroot; - name = literal_pointer_val(ctx, (jl_value_t*)slot_symbol(ctx, sl)); - } - if (bp) { - Value *mdargs[5] = { name, literal_pointer_val(ctx, (jl_value_t*)mod), bp, - bp_owner, literal_pointer_val(ctx, bnd) }; - jl_cgval_t gf = mark_julia_type( - ctx, - ctx.builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), - true, - jl_function_type); + Value *bp = NULL, *name, *bp_owner = V_null; + jl_binding_t *bnd = NULL; + bool issym = jl_is_symbol(mn); + bool isglobalref = !issym && jl_is_globalref(mn); + jl_module_t *mod = ctx.module; + if (issym || isglobalref) { + if (isglobalref) { + mod = jl_globalref_mod(mn); + mn = (jl_value_t*)jl_globalref_name(mn); + } + JL_TRY { + if (jl_symbol_name((jl_sym_t*)mn)[0] == '@') + jl_errorf("macro definition not allowed inside a local scope"); + name = literal_pointer_val(ctx, mn); + bnd = jl_get_binding_for_method_def(mod, (jl_sym_t*)mn); + } + JL_CATCH { + jl_value_t *e = jl_current_exception(); + // errors. boo. root it somehow :( + bnd = jl_get_binding_wr(ctx.module, (jl_sym_t*)jl_gensym(), 1); + bnd->value = e; + bnd->constp = 1; + raise_exception(ctx, literal_pointer_val(ctx, e)); + return ghostValue(jl_nothing_type); + } + bp = julia_binding_gv(ctx, bnd); + bp_owner = literal_pointer_val(ctx, (jl_value_t*)mod); + } + else if (jl_is_slot(mn) || jl_is_argument(mn)) { + int sl = jl_slot_number(mn)-1; + jl_varinfo_t &vi = ctx.slots[sl]; + bp = vi.boxroot; + name = literal_pointer_val(ctx, (jl_value_t*)slot_symbol(ctx, sl)); + } + if (bp) { + Value *mdargs[5] = { name, literal_pointer_val(ctx, (jl_value_t*)mod), bp, + bp_owner, literal_pointer_val(ctx, bnd) }; + jl_cgval_t gf = mark_julia_type( + ctx, + ctx.builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), + true, + jl_function_type); + if (jl_expr_nargs(ex) == 1) return gf; - } - emit_error(ctx, "method: invalid declaration"); - return jl_cgval_t(); } Value *a1 = boxed(ctx, emit_expr(ctx, args[1])); Value *a2 = boxed(ctx, emit_expr(ctx, args[2])); - Value *mdargs[4] = { + Value *mdargs[3] = { /*argdata*/a1, - ConstantPointerNull::get(cast(T_prjlvalue)), /*code*/a2, /*module*/literal_pointer_val(ctx, (jl_value_t*)ctx.module) }; diff --git a/src/dump.c b/src/dump.c index 5771776a8658d..2a6c8318c2095 100644 --- a/src/dump.c +++ b/src/dump.c @@ -504,11 +504,6 @@ static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_ jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque); } -enum METHOD_SERIALIZATION_MODE { - METHOD_INTERNAL = 1, - METHOD_EXTERNAL_MT = 2, -}; - static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED { if (jl_serialize_generic(s, v)) { @@ -632,10 +627,9 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li else if (jl_is_method(v)) { write_uint8(s->s, TAG_METHOD); jl_method_t *m = (jl_method_t*)v; - int serialization_mode = 0; - if (m->is_for_opaque_closure || module_in_worklist(m->module)) - serialization_mode |= METHOD_INTERNAL; - if (!(serialization_mode & METHOD_INTERNAL)) { + int internal = 1; + internal = m->is_for_opaque_closure || module_in_worklist(m->module); + if (!internal) { // flag this in the backref table as special uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v); assert(*bp != (uintptr_t)HT_NOTFOUND); @@ -643,23 +637,8 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } jl_serialize_value(s, (jl_value_t*)m->sig); jl_serialize_value(s, (jl_value_t*)m->module); - if (m->external_mt != NULL) { - assert(jl_typeis(m->external_mt, jl_methtable_type)); - jl_methtable_t *mt = (jl_methtable_t*)m->external_mt; - if (!module_in_worklist(mt->module)) { - serialization_mode |= METHOD_EXTERNAL_MT; - } - } - write_uint8(s->s, serialization_mode); - if (serialization_mode & METHOD_EXTERNAL_MT) { - // We reference this method table by module and binding - jl_methtable_t *mt = (jl_methtable_t*)m->external_mt; - jl_serialize_value(s, mt->module); - jl_serialize_value(s, mt->name); - } else { - jl_serialize_value(s, (jl_value_t*)m->external_mt); - } - if (!(serialization_mode & METHOD_INTERNAL)) + write_uint8(s->s, internal); + if (!internal) return; jl_serialize_value(s, m->specializations); jl_serialize_value(s, m->speckeyset); @@ -973,10 +952,6 @@ static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DIS jl_collect_lambdas_from_mod(s, (jl_module_t*)b->value); } } - else if (jl_is_mtable(bv)) { - // a module containing an external method table - jl_collect_methtable_from_mod(s, (jl_methtable_t*)bv); - } } } } @@ -1040,7 +1015,7 @@ static void jl_collect_backedges(jl_array_t *s, jl_array_t *t) size_t min_valid = 0; size_t max_valid = ~(size_t)0; int ambig = 0; - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); + jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); if (matches == jl_false) { valid = 0; break; @@ -1483,18 +1458,8 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ jl_gc_wb(m, m->sig); m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module); jl_gc_wb(m, m->module); - int serialization_mode = read_uint8(s->s); - if (serialization_mode & METHOD_EXTERNAL_MT) { - jl_module_t *mt_mod = (jl_module_t*)jl_deserialize_value(s, NULL); - jl_sym_t *mt_name = (jl_sym_t*)jl_deserialize_value(s, NULL); - m->external_mt = jl_get_global(mt_mod, mt_name); - jl_gc_wb(m, m->external_mt); - assert(jl_typeis(m->external_mt, jl_methtable_type)); - } else { - m->external_mt = jl_deserialize_value(s, &m->external_mt); - jl_gc_wb(m, m->external_mt); - } - if (!(serialization_mode & METHOD_INTERNAL)) { + int internal = read_uint8(s->s); + if (!internal) { assert(loc != NULL && loc != HT_NOTFOUND); arraylist_push(&flagref_list, loc); arraylist_push(&flagref_list, (void*)pos); @@ -1932,7 +1897,7 @@ static void jl_insert_methods(jl_array_t *list) assert(!meth->is_for_opaque_closure); jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_array_ptr_ref(list, i + 1); assert(jl_is_method(meth)); - jl_methtable_t *mt = jl_method_get_table(meth); + jl_methtable_t *mt = jl_method_table_for((jl_value_t*)meth->sig); assert((jl_value_t*)mt != jl_nothing); jl_method_table_insert(mt, meth, simpletype); } @@ -1962,7 +1927,7 @@ static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids) size_t max_valid = ~(size_t)0; int ambig = 0; // TODO: possibly need to included ambiguities too (for the optimizer correctness)? - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); + jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, -1, 0, jl_world_counter, &min_valid, &max_valid, &ambig); if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) { valid = 0; } @@ -2500,7 +2465,7 @@ static jl_method_t *jl_recache_method(jl_method_t *m) { assert(!m->is_for_opaque_closure); jl_datatype_t *sig = (jl_datatype_t*)m->sig; - jl_methtable_t *mt = jl_method_get_table(m); + jl_methtable_t *mt = jl_method_table_for((jl_value_t*)m->sig); assert((jl_value_t*)mt != jl_nothing); jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors jl_method_t *_new = jl_lookup_method(mt, sig, m->module->primary_world); diff --git a/src/gf.c b/src/gf.c index 3cda8ae2a733c..5bdf7c8ec29b0 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1876,7 +1876,7 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w // // lim is the max # of methods to return. if there are more, returns jl_false. // -1 for no limit. -JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig) { JL_TIMING(METHOD_MATCH); @@ -1885,13 +1885,10 @@ JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t * jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types); if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type) return (jl_value_t*)jl_an_empty_vec_any; - if (mt == jl_nothing) - mt = (jl_value_t*)jl_method_table_for(unw); - else if (!jl_typeis(mt, jl_methtable_type)) - jl_error("matching_method: `mt` is not a method table"); + jl_methtable_t *mt = jl_method_table_for(unw); if ((jl_value_t*)mt == jl_nothing) return jl_false; // indeterminate - ml_matches can't deal with this case - return ml_matches((jl_methtable_t*)mt, 0, types, lim, include_ambiguous, 1, world, 1, min_valid, max_valid, ambig); + return ml_matches(mt, 0, types, lim, include_ambiguous, 1, world, 1, min_valid, max_valid, ambig); } jl_method_instance_t *jl_get_unspecialized(jl_method_instance_t *method JL_PROPAGATES_ROOT) @@ -2070,7 +2067,7 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES size_t min_valid2 = 1; size_t max_valid2 = ~(size_t)0; int ambig = 0; - jl_value_t *matches = jl_matching_methods(types, jl_nothing, 1, 1, world, &min_valid2, &max_valid2, &ambig); + jl_value_t *matches = jl_matching_methods(types, 1, 1, world, &min_valid2, &max_valid2, &ambig); if (*min_valid < min_valid2) *min_valid = min_valid2; if (*max_valid > max_valid2) diff --git a/src/interpreter.c b/src/interpreter.c index f130c311c1a45..008886f1c99c9 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -78,36 +78,28 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, static jl_value_t *eval_methoddef(jl_expr_t *ex, interpreter_state *s) { jl_value_t **args = jl_array_ptr_data(ex->args); + jl_sym_t *fname = (jl_sym_t*)args[0]; + jl_module_t *modu = s->module; + if (jl_is_globalref(fname)) { + modu = jl_globalref_mod(fname); + fname = jl_globalref_name(fname); + } + assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(fname)); - if (jl_expr_nargs(ex) == 1) { - jl_value_t **args = jl_array_ptr_data(ex->args); - jl_sym_t *fname = (jl_sym_t*)args[0]; - jl_module_t *modu = s->module; - if (jl_is_globalref(fname)) { - modu = jl_globalref_mod(fname); - fname = jl_globalref_name(fname); - } - if (!jl_is_symbol(fname)) { - jl_error("method: invalid declaration"); - } + if (jl_is_symbol(fname)) { jl_value_t *bp_owner = (jl_value_t*)modu; jl_binding_t *b = jl_get_binding_for_method_def(modu, fname); jl_value_t **bp = &b->value; jl_value_t *gf = jl_generic_function_def(b->name, b->owner, bp, bp_owner, b); - return gf; + if (jl_expr_nargs(ex) == 1) + return gf; } - jl_value_t *atypes = NULL, *meth = NULL, *fname = NULL; - JL_GC_PUSH3(&atypes, &meth, &fname); - - fname = eval_value(args[0], s); - jl_methtable_t *mt = NULL; - if (jl_typeis(fname, jl_methtable_type)) { - mt = (jl_methtable_t*)fname; - } + jl_value_t *atypes = NULL, *meth = NULL; + JL_GC_PUSH2(&atypes, &meth); atypes = eval_value(args[1], s); meth = eval_value(args[2], s); - jl_method_def((jl_svec_t*)atypes, mt, (jl_code_info_t*)meth, s->module); + jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module); JL_GC_POP(); return jl_nothing; } diff --git a/src/jltypes.c b/src/jltypes.c index 73015d2cfe6c1..2ba69caf1991e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2302,7 +2302,6 @@ void jl_init_types(void) JL_GC_DISABLED "specializations", "speckeyset", "slot_syms", - "external_mt", "source", "unspecialized", "generator", @@ -2330,7 +2329,6 @@ void jl_init_types(void) JL_GC_DISABLED jl_array_type, jl_string_type, jl_any_type, - jl_any_type, jl_any_type, // jl_method_instance_type jl_any_type, jl_array_any_type, @@ -2537,7 +2535,7 @@ void jl_init_types(void) JL_GC_DISABLED #endif jl_svecset(jl_methtable_type->types, 10, jl_uint8_type); jl_svecset(jl_methtable_type->types, 11, jl_uint8_type); - jl_svecset(jl_method_type->types, 12, jl_method_instance_type); + jl_svecset(jl_method_type->types, 11, jl_method_instance_type); jl_svecset(jl_method_instance_type->types, 6, jl_code_instance_type); jl_svecset(jl_code_instance_type->types, 9, jl_voidpointer_type); jl_svecset(jl_code_instance_type->types, 10, jl_voidpointer_type); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index dfec6ca980020..ca274ef552f5b 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -221,11 +221,10 @@ (define (method-expr-name m) (let ((name (cadr m))) - (let ((name (if (or (length= m 2) (not (pair? name)) (not (quoted? name))) name (cadr name)))) (cond ((not (pair? name)) name) ((eq? (car name) 'outerref) (cadr name)) ;((eq? (car name) 'globalref) (caddr name)) - (else name))))) + (else name)))) ;; extract static parameter names from a (method ...) expression (define (method-expr-static-parameters m) @@ -253,13 +252,6 @@ (pair? (caddr e)) (memq (car (caddr e)) '(quote inert)) (symbol? (cadr (caddr e)))))) -(define (overlay? e) - (and (pair? e) (eq? (car e) 'overlay))) - -(define (sym-ref-or-overlay? e) - (or (overlay? e) - (sym-ref? e))) - ;; convert final (... x) to (curly Vararg x) (define (dots->vararg a) (if (null? a) a @@ -349,15 +341,14 @@ (let* ((names (map car sparams)) (anames (map (lambda (x) (if (underscore-symbol? x) UNUSED x)) (llist-vars argl))) (unused_anames (filter (lambda (x) (not (eq? x UNUSED))) anames)) - (ename (if (nodot-sym-ref? name) name - (if (overlay? name) (cadr name) `(null))))) + (ename (if (nodot-sym-ref? name) name `(null)))) (if (has-dups unused_anames) (error (string "function argument name not unique: \"" (car (has-dups unused_anames)) "\""))) (if (has-dups names) (error "function static parameter names not unique")) (if (any (lambda (x) (and (not (eq? x UNUSED)) (memq x names))) anames) (error "function argument and static parameter names must be distinct")) - (if (or (and name (not (sym-ref-or-overlay? name))) (not (valid-name? name))) + (if (or (and name (not (sym-ref? name))) (not (valid-name? name))) (error (string "invalid function name \"" (deparse name) "\""))) (let* ((loc (maybe-remove-functionloc! body)) (generator (if (expr-contains-p if-generated? body (lambda (x) (not (function-def? x)))) @@ -1139,14 +1130,13 @@ (argl-stmts (lower-destructuring-args argl)) (argl (car argl-stmts)) (name (check-dotop (car argl))) - (argname (if (overlay? name) (caddr name) name)) ;; fill in first (closure) argument (adj-decl (lambda (n) (if (and (decl? n) (length= n 2)) `(|::| |#self#| ,(cadr n)) n))) - (farg (if (decl? argname) - (adj-decl argname) - `(|::| |#self#| (call (core Typeof) ,argname)))) + (farg (if (decl? name) + (adj-decl name) + `(|::| |#self#| (call (core Typeof) ,name)))) (body (insert-after-meta body (cdr argl-stmts))) (argl (cdr argl)) (argl (fix-arglist diff --git a/src/julia.h b/src/julia.h index ed1cb5156285a..8ec461e77126b 100644 --- a/src/julia.h +++ b/src/julia.h @@ -311,7 +311,6 @@ typedef struct _jl_method_t { jl_array_t *speckeyset; // index lookup by hash into specializations jl_value_t *slot_syms; // compacted list of slot names (String) - jl_value_t *external_mt; // reference to the method table this method is part of, null if part of the internal table jl_value_t *source; // original code template (jl_code_info_t, but may be compressed), null for builtins struct _jl_method_instance_t *unspecialized; // unspecialized executable method instance, or null jl_value_t *generator; // executable code-generating function if available @@ -1401,7 +1400,7 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_module_t *module, jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd); -JL_DLLEXPORT jl_method_t *jl_method_def(jl_svec_t *argdata, jl_methtable_t *mt, jl_code_info_t *f, jl_module_t *module); +JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_module_t *module); JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo); JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src); JL_DLLEXPORT size_t jl_get_world_counter(void) JL_NOTSAFEPOINT; diff --git a/src/julia_internal.h b/src/julia_internal.h index ec45080bcf908..d6170a9d56719 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -548,15 +548,13 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs); jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t *f, jl_value_t **args, size_t nargs); -JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_methtable_t *jl_method_table_for( jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; -JL_DLLEXPORT jl_methtable_t *jl_method_get_table( - jl_method_t *method) JL_NOTSAFEPOINT; jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT); int jl_pointer_egal(jl_value_t *t); diff --git a/src/method.c b/src/method.c index f771af9f79603..1d3a593e638ed 100644 --- a/src/method.c +++ b/src/method.c @@ -652,7 +652,6 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) m->roots = NULL; m->ccallable = NULL; m->module = module; - m->external_mt = NULL; m->source = NULL; m->unspecialized = NULL; m->generator = NULL; @@ -765,11 +764,6 @@ JL_DLLEXPORT jl_methtable_t *jl_method_table_for(jl_value_t *argtypes JL_PROPAGA return first_methtable(argtypes, 0); } -JL_DLLEXPORT jl_methtable_t *jl_method_get_table(jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT -{ - return method->external_mt ? (jl_methtable_t*)method->external_mt : jl_method_table_for(method->sig); -} - // get the MethodTable implied by a single given type, or `nothing` JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT { @@ -779,7 +773,6 @@ JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAG jl_array_t *jl_all_methods JL_GLOBALLY_ROOTED; JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, - jl_methtable_t *mt, jl_code_info_t *f, jl_module_t *module) { @@ -808,9 +801,7 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, argtype = jl_new_struct(jl_unionall_type, tv, argtype); } - jl_methtable_t *external_mt = mt; - if (!mt) - mt = jl_method_table_for(argtype); + jl_methtable_t *mt = jl_method_table_for(argtype); if ((jl_value_t*)mt == jl_nothing) jl_error("Method dispatch is unimplemented currently for this method signature"); if (mt->frozen) @@ -839,9 +830,6 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, f = jl_new_code_info_from_ir((jl_expr_t*)f); } m = jl_new_method_uninit(module); - m->external_mt = (jl_value_t*)external_mt; - if (external_mt) - jl_gc_wb(m, external_mt); m->sig = argtype; m->name = name; m->isva = isva; diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 14d3336b34caf..060dbb2bc011f 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -434,9 +434,6 @@ function serialize(s::AbstractSerializer, meth::Method) else serialize(s, nothing) end - if isdefined(meth, :external_mt) - error("cannot serialize Method objects with external method tables") - end nothing end diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 674893051fdac..9a16d3d25c9be 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1594,7 +1594,7 @@ function detect_ambiguities(mods::Module...; for m in Base.MethodList(mt) is_in_mods(m.module, recursive, mods) || continue ambig = Int32[0] - ms = Base._methods_by_ftype(m.sig, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(m.sig, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) ambig[1] == 0 && continue isa(ms, Bool) && continue for match2 in ms diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 265d97776c053..8d0c2092f21c2 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -348,7 +348,7 @@ f35983(::Type, ::Type) = 2 @test length(Base.methods(f35983, (Any, Any))) == 2 @test first(Base.methods(f35983, (Any, Any))).sig == Tuple{typeof(f35983), Type, Type} let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test length(ms) == 1 @test ambig[1] == 0 end @@ -356,14 +356,14 @@ f35983(::Type{Int16}, ::Any) = 3 @test length(Base.methods_including_ambiguous(f35983, (Type, Type))) == 2 @test length(Base.methods(f35983, (Type, Type))) == 2 let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, nothing, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, -1, typemax(UInt), true, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test length(ms) == 2 @test ambig[1] == 1 end struct B38280 <: Real; val; end let ambig = Int32[0] - ms = Base._methods_by_ftype(Tuple{Type{B38280}, Any}, nothing, 1, typemax(UInt), false, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) + ms = Base._methods_by_ftype(Tuple{Type{B38280}, Any}, 1, typemax(UInt), false, UInt[typemin(UInt)], UInt[typemax(UInt)], ambig) @test ms isa Vector @test length(ms) == 1 @test ambig[1] == 1 diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index afbfa1db601f6..bce782d73df87 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -135,79 +135,3 @@ let method = which(func2, ()) end func3() = func2() @test_throws UndefVarError func3() - - - -## overlay method tables - -module OverlayModule - -using Base.Experimental: @MethodTable, @overlay - -@MethodTable(mt) - -@overlay mt function sin(x::Float64) - 1 -end - -# short function def -@overlay mt cos(x::Float64) = 2 - -end - -methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, nothing, 1, typemax(UInt)) -@test only(methods).method.module === Base.Math - -methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, OverlayModule.mt, 1, typemax(UInt)) -@test only(methods).method.module === OverlayModule - -methods = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, typemax(UInt)) -@test isempty(methods) - -# precompilation - -load_path = mktempdir() -depot_path = mktempdir() -try - pushfirst!(LOAD_PATH, load_path) - pushfirst!(DEPOT_PATH, depot_path) - - write(joinpath(load_path, "Foo.jl"), - """ - module Foo - Base.Experimental.@MethodTable(mt) - Base.Experimental.@overlay mt sin(x::Int) = 1 - end - """) - - # precompiling Foo serializes the overlay method through the `mt` binding in the module - Foo = Base.require(Main, :Foo) - @test length(Foo.mt) == 1 - - write(joinpath(load_path, "Bar.jl"), - """ - module Bar - Base.Experimental.@MethodTable(mt) - end - """) - - write(joinpath(load_path, "Baz.jl"), - """ - module Baz - using Bar - Base.Experimental.@overlay Bar.mt sin(x::Int) = 1 - end - """) - - # when referring an method table in another module, - # the overlay method needs to be discovered explicitly - Bar = Base.require(Main, :Bar) - @test length(Bar.mt) == 0 - Baz = Base.require(Main, :Baz) - @test length(Bar.mt) == 1 -finally - rm(load_path, recursive=true, force=true) - rm(depot_path, recursive=true, force=true) - filter!((≠)(load_path), LOAD_PATH) - filter!((≠)(depot_path), DEPOT_PATH) -end From 0bd886297d2757adf75d346a7dbb438fd839f8e6 Mon Sep 17 00:00:00 2001 From: Rogerluo Date: Tue, 18 May 2021 22:28:06 -0400 Subject: [PATCH 355/439] allow `pkgdir` to accept paths (#40839) * allow pkgdir accept paths * add docs Co-authored-by: Ian Butterworth --- base/loading.jl | 25 +++++++++++++++++++------ test/loading.jl | 5 +++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index ca7ab7cb6b391..10a59de688b7c 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -316,16 +316,29 @@ function pathof(m::Module) end """ - pkgdir(m::Module) + pkgdir(m::Module[, paths::String...]) - Return the root directory of the package that imported module `m`, - or `nothing` if `m` was not imported from a package. - """ -function pkgdir(m::Module) +Return the root directory of the package that imported module `m`, +or `nothing` if `m` was not imported from a package. Optionally further +path component strings can be provided to construct a path within the +package root. + +```julia +julia> pkgdir(Foo) +"/path/to/Foo.jl" + +julia> pkgdir(Foo, "src", "file.jl") +"/path/to/Foo.jl/src/file.jl" +``` + +!!! compat "Julia 1.7" + The optional argument `paths` requires at least Julia 1.7. +""" +function pkgdir(m::Module, paths::String...) rootmodule = Base.moduleroot(m) path = pathof(rootmodule) path === nothing && return nothing - return dirname(dirname(path)) + return joinpath(dirname(dirname(path)), paths...) end ## generic project & manifest API ## diff --git a/test/loading.jl b/test/loading.jl index cf9aa32952a66..d94abd889dcfc 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -314,6 +314,11 @@ module NotPkgModule; end @test pkgdir(Foo.SubFoo1) == normpath(abspath(@__DIR__, "project/deps/Foo1")) @test pkgdir(Foo.SubFoo2) == normpath(abspath(@__DIR__, "project/deps/Foo1")) @test pkgdir(NotPkgModule) === nothing + + @test pkgdir(Foo, "src") == normpath(abspath(@__DIR__, "project/deps/Foo1/src")) + @test pkgdir(Foo.SubFoo1, "src") == normpath(abspath(@__DIR__, "project/deps/Foo1/src")) + @test pkgdir(Foo.SubFoo2, "src") == normpath(abspath(@__DIR__, "project/deps/Foo1/src")) + @test pkgdir(NotPkgModule, "src") === nothing end end From 97209b68b0eb4bb1f5d6435d4a2596f5dc8f5cdb Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 19 May 2021 12:33:07 +0900 Subject: [PATCH 356/439] refactor inference code (#40837) - use `SlotNumber` instead of `Slot` in pre-optimization phase; `TypeSlot` doesn't appear in pre-optimization phase, and I think we can just use `SlotNumber` instead of `Slot` and streamline the code - annotate `StateUpdate.var::SlotNumber`, and remove unnecessary checks within `stupdate(1)!` - rename `s` to `states` in `typeinf_local` for more clarity --- base/compiler/abstractinterpretation.jl | 50 ++++++++++++------------- base/compiler/typeinfer.jl | 10 ++--- base/compiler/typelattice.jl | 44 +++++++++------------- 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 3a72f9c8a6a80..16b521cf901b5 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -184,7 +184,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end condval = maybe_extract_const_bool(this_conditional) for i = 1:length(argtypes) - fargs[i] isa Slot || continue + fargs[i] isa SlotNumber || continue if this_conditional isa InterConditional && this_conditional.slot == i vtype = this_conditional.vtype elsetype = this_conditional.elsetype @@ -222,7 +222,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), # find the first argument which supports refinment, # and intersect all equvalent arguments with it arg = fargs[i] - arg isa Slot || continue # can't refine + arg isa SlotNumber || continue # can't refine old = argtypes[i] old isa Type || continue # unlikely to refine id = slot_id(arg) @@ -980,10 +980,10 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U # try to simulate this as a real conditional (`cnd ? x : y`), so that the penalty for using `ifelse` instead isn't too high a = ssa_def_slot(fargs[3], sv) b = ssa_def_slot(fargs[4], sv) - if isa(a, Slot) && slot_id(cnd.var) == slot_id(a) + if isa(a, SlotNumber) && slot_id(cnd.var) == slot_id(a) tx = (cnd.vtype ⊑ tx ? cnd.vtype : tmeet(tx, widenconst(cnd.vtype))) end - if isa(b, Slot) && slot_id(cnd.var) == slot_id(b) + if isa(b, SlotNumber) && slot_id(cnd.var) == slot_id(b) ty = (cnd.elsetype ⊑ ty ? cnd.elsetype : tmeet(ty, widenconst(cnd.elsetype))) end return tmerge(tx, ty) @@ -1004,7 +1004,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U # perform very limited back-propagation of type information for `is` and `isa` if f === isa a = ssa_def_slot(fargs[2], sv) - if isa(a, Slot) + if isa(a, SlotNumber) aty = widenconst(argtypes[2]) if rt === Const(false) return Conditional(a, Union{}, aty) @@ -1027,7 +1027,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U aty = argtypes[2] bty = argtypes[3] # if doing a comparison to a singleton, consider returning a `Conditional` instead - if isa(aty, Const) && isa(b, Slot) + if isa(aty, Const) && isa(b, SlotNumber) if rt === Const(false) aty = Union{} elseif rt === Const(true) @@ -1037,7 +1037,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U end return Conditional(b, aty, bty) end - if isa(bty, Const) && isa(a, Slot) + if isa(bty, Const) && isa(a, SlotNumber) if rt === Const(false) bty = Union{} elseif rt === Const(true) @@ -1048,10 +1048,10 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U return Conditional(a, bty, aty) end # narrow the lattice slightly (noting the dependency on one of the slots), to promote more effective smerge - if isa(b, Slot) + if isa(b, SlotNumber) return Conditional(b, rt === Const(false) ? Union{} : bty, rt === Const(true) ? Union{} : bty) end - if isa(a, Slot) + if isa(a, SlotNumber) return Conditional(a, rt === Const(false) ? Union{} : aty, rt === Const(true) ? Union{} : aty) end elseif f === Core.Compiler.not_int @@ -1355,7 +1355,7 @@ function abstract_eval_special_value(interp::AbstractInterpreter, @nospecialize( return Const((e::QuoteNode).value) elseif isa(e, SSAValue) return abstract_eval_ssavalue(e::SSAValue, sv.src) - elseif isa(e, Slot) || isa(e, Argument) + elseif isa(e, SlotNumber) || isa(e, Argument) return (vtypes[slot_id(e)]::VarState).typ elseif isa(e, GlobalRef) return abstract_eval_global(e.mod, e.name) @@ -1499,7 +1499,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), elseif e.head === :isdefined sym = e.args[1] t = Bool - if isa(sym, Slot) + if isa(sym, SlotNumber) vtyp = vtypes[slot_id(sym)] if vtyp.typ === Bottom t = Const(false) # never assigned previously @@ -1631,7 +1631,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) @assert !frame.inferred frame.dont_work_on_me = true # mark that this function is currently on the stack W = frame.ip - s = frame.stmt_types + states = frame.stmt_types n = frame.nstmts nargs = frame.nargs def = frame.linfo.def @@ -1656,7 +1656,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) edges === nothing || empty!(edges) frame.stmt_info[pc] = nothing stmt = frame.src.code[pc] - changes = s[pc]::VarTable + changes = states[pc]::VarTable t = nothing hd = isa(stmt, Expr) ? stmt.head : nothing @@ -1695,14 +1695,14 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) changes_else = conditional_changes(changes_else, condt.elsetype, condt.var) changes = conditional_changes(changes, condt.vtype, condt.var) end - newstate_else = stupdate!(s[l], changes_else) + newstate_else = stupdate!(states[l], changes_else) if newstate_else !== nothing # add else branch to active IP list if l < frame.pc´´ frame.pc´´ = l end push!(W, l) - s[l] = newstate_else + states[l] = newstate_else end end elseif isa(stmt, ReturnNode) @@ -1750,16 +1750,16 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) l = stmt.args[1]::Int frame.cur_hand = Pair{Any,Any}(l, frame.cur_hand) # propagate type info to exception handler - old = s[l] + old = states[l] newstate_catch = stupdate!(old, changes) if newstate_catch !== nothing if l < frame.pc´´ frame.pc´´ = l end push!(W, l) - s[l] = newstate_catch + states[l] = newstate_catch end - typeassert(s[l], VarTable) + typeassert(states[l], VarTable) frame.handler_at[l] = frame.cur_hand elseif hd === :leave for i = 1:((stmt.args[1])::Int) @@ -1773,12 +1773,12 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) end frame.src.ssavaluetypes[pc] = t lhs = stmt.args[1] - if isa(lhs, Slot) + if isa(lhs, SlotNumber) changes = StateUpdate(lhs, VarState(t, false), changes, false) end elseif hd === :method fname = stmt.args[1] - if isa(fname, Slot) + if isa(fname, SlotNumber) changes = StateUpdate(fname, VarState(Any, false), changes, false) end elseif hd === :inbounds || hd === :meta || hd === :loopinfo || hd === :code_coverage_effect @@ -1799,7 +1799,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) # the handling for Expr(:enter) propagates all changes from before the try/catch # so this only needs to propagate any changes l = frame.cur_hand.first::Int - if stupdate1!(s[l]::VarTable, changes::StateUpdate) !== false + if stupdate1!(states[l]::VarTable, changes::StateUpdate) !== false if l < frame.pc´´ frame.pc´´ = l end @@ -1817,19 +1817,19 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) pc´ > n && break # can't proceed with the fast-path fall-through frame.handler_at[pc´] = frame.cur_hand - newstate = stupdate!(s[pc´], changes) + newstate = stupdate!(states[pc´], changes) if isa(stmt, GotoNode) && frame.pc´´ < pc´ # if we are processing a goto node anyways, # (such as a terminator for a loop, if-else, or try block), # consider whether we should jump to an older backedge first, # to try to traverse the statements in approximate dominator order if newstate !== nothing - s[pc´] = newstate + states[pc´] = newstate end push!(W, pc´) pc = frame.pc´´ elseif newstate !== nothing - s[pc´] = newstate + states[pc´] = newstate pc = pc´ elseif pc´ in W pc = pc´ @@ -1842,7 +1842,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) nothing end -function conditional_changes(changes::VarTable, @nospecialize(typ), var::Slot) +function conditional_changes(changes::VarTable, @nospecialize(typ), var::SlotNumber) oldtyp = (changes[slot_id(var)]::VarState).typ # approximate test for `typ ∩ oldtyp` being better than `oldtyp` # since we probably formed these types with `typesubstract`, the comparison is likely simple diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 9087020ac6304..765aaa730ff18 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -539,7 +539,7 @@ function annotate_slot_load!(e::Expr, vtypes::VarTable, sv::InferenceState, unde subex = e.args[i] if isa(subex, Expr) annotate_slot_load!(subex, vtypes, sv, undefs) - elseif isa(subex, Slot) + elseif isa(subex, SlotNumber) e.args[i] = visit_slot_load!(subex, vtypes, sv, undefs) end end @@ -548,13 +548,13 @@ end function annotate_slot_load(@nospecialize(e), vtypes::VarTable, sv::InferenceState, undefs::Array{Bool,1}) if isa(e, Expr) annotate_slot_load!(e, vtypes, sv, undefs) - elseif isa(e, Slot) + elseif isa(e, SlotNumber) return visit_slot_load!(e, vtypes, sv, undefs) end return e end -function visit_slot_load!(sl::Slot, vtypes::VarTable, sv::InferenceState, undefs::Array{Bool,1}) +function visit_slot_load!(sl::SlotNumber, vtypes::VarTable, sv::InferenceState, undefs::Array{Bool,1}) id = slot_id(sl) s = vtypes[id] vt = widenconditional(ignorelimited(s.typ)) @@ -583,7 +583,7 @@ function record_slot_assign!(sv::InferenceState) if isa(st_i, VarTable) && isa(expr, Expr) && expr.head === :(=) lhs = expr.args[1] rhs = expr.args[2] - if isa(lhs, Slot) + if isa(lhs, SlotNumber) vt = widenconst(sv.src.ssavaluetypes[i]) if vt !== Bottom id = slot_id(lhs) @@ -659,7 +659,7 @@ function type_annotate!(sv::InferenceState, run_optimizer::Bool) body[i] = ReturnNode(annotate_slot_load(expr.val, st_i, sv, undefs)) elseif isa(expr, GotoIfNot) body[i] = GotoIfNot(annotate_slot_load(expr.cond, st_i, sv, undefs), expr.dest) - elseif isa(expr, Slot) + elseif isa(expr, SlotNumber) body[i] = visit_slot_load!(expr, st_i, sv, undefs) end else diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 07a15aeb30a4b..6391d4029b58e 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -33,7 +33,7 @@ import Core: Const, PartialStruct # end # ``` struct Conditional - var::Slot + var::SlotNumber vtype elsetype function Conditional( @@ -84,7 +84,7 @@ end const VarTable = Array{Any,1} struct StateUpdate - var::Union{Slot,SSAValue} + var::SlotNumber vtype::VarState state::VarTable conditional::Bool @@ -321,20 +321,18 @@ ignorelimited(typ::LimitedAccuracy) = typ.typ function stupdate!(state::Nothing, changes::StateUpdate) newst = copy(changes.state) - if isa(changes.var, Slot) - changeid = slot_id(changes.var::Slot) - newst[changeid] = changes.vtype - # remove any Conditional for this Slot from the vtable - # (unless this change is came from the conditional) - if !changes.conditional - for i = 1:length(newst) - newtype = newst[i] - if isa(newtype, VarState) - newtypetyp = ignorelimited(newtype.typ) - if isa(newtypetyp, Conditional) && slot_id(newtypetyp.var) == changeid - newtypetyp = widenwrappedconditional(newtype.typ) - newst[i] = VarState(newtypetyp, newtype.undef) - end + changeid = slot_id(changes.var) + newst[changeid] = changes.vtype + # remove any Conditional for this slot from the vtable + # (unless this change is came from the conditional) + if !changes.conditional + for i = 1:length(newst) + newtype = newst[i] + if isa(newtype, VarState) + newtypetyp = ignorelimited(newtype.typ) + if isa(newtypetyp, Conditional) && slot_id(newtypetyp.var) == changeid + newtypetyp = widenwrappedconditional(newtype.typ) + newst[i] = VarState(newtypetyp, newtype.undef) end end end @@ -343,11 +341,8 @@ function stupdate!(state::Nothing, changes::StateUpdate) end function stupdate!(state::VarTable, changes::StateUpdate) - if !isa(changes.var, Slot) - return stupdate!(state, changes.state) - end newstate = nothing - changeid = slot_id(changes.var::Slot) + changeid = slot_id(changes.var) for i = 1:length(state) if i == changeid newtype = changes.vtype @@ -355,7 +350,7 @@ function stupdate!(state::VarTable, changes::StateUpdate) newtype = changes.state[i] end oldtype = state[i] - # remove any Conditional for this Slot from the vtable + # remove any Conditional for this slot from the vtable # (unless this change is came from the conditional) if !changes.conditional && isa(newtype, VarState) newtypetyp = ignorelimited(newtype.typ) @@ -390,11 +385,8 @@ stupdate!(state::Nothing, changes::VarTable) = copy(changes) stupdate!(state::Nothing, changes::Nothing) = nothing function stupdate1!(state::VarTable, change::StateUpdate) - if !isa(change.var, Slot) - return false - end - changeid = slot_id(change.var::Slot) - # remove any Conditional for this Slot from the catch block vtable + changeid = slot_id(change.var) + # remove any Conditional for this slot from the catch block vtable # (unless this change is came from the conditional) if !change.conditional for i = 1:length(state) From 4211c3f6c83678cbed968c61755476ccc491eb6e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 18 May 2021 23:36:53 -0400 Subject: [PATCH 357/439] fix #40855, alignment calculation in `julia_const_to_llvm` (#40864) This appears as a regression due to doing more constant folding in 1.6+ --- src/intrinsics.cpp | 5 +++-- test/compiler/codegen.jl | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 834034d367a9f..deb174f700c77 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -202,8 +202,9 @@ static Constant *julia_const_to_llvm(jl_codectx_t &ctx, const void *ptr, jl_data const uint8_t *ov = (const uint8_t*)ptr + offs; if (jl_is_uniontype(ft)) { // compute the same type layout as julia_struct_to_llvm - size_t fsz = jl_field_size(bt, i); - size_t al = jl_field_align(bt, i); + size_t fsz = 0, al = 0; + (void)jl_islayout_inline(ft, &fsz, &al); + fsz = jl_field_size(bt, i); uint8_t sel = ((const uint8_t*)ptr)[offs + fsz - 1]; jl_value_t *active_ty = jl_nth_union_component(ft, sel); size_t active_sz = jl_datatype_size(active_ty); diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 97a9d45d7ecf3..a080cd550d10f 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -561,3 +561,12 @@ function f32843(vals0, v) vals end @test_throws UndefVarError f32843([6], Vector[[1]]) + +# issue #40855, struct constants with union fields +@enum T40855 X40855 +struct A40855 + d::Union{Nothing, T40855} + b::Union{Nothing, Int} +end +g() = string(A40855(X40855, 1)) +@test g() == "$(@__MODULE__).A40855($(@__MODULE__).X40855, 1)" From 5868354bbdd3934e18262375376ea9642d2a9202 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Sat, 15 May 2021 21:58:27 +0900 Subject: [PATCH 358/439] form conditional constraint from non-`Conditional` object We can form a conditional constraint from a branch condition itself when its type isn't already `Conditional` but can be refined as `Conditional(condx, Const(true), Const(false))`. --- base/compiler/abstractinterpretation.jl | 10 +++++++--- test/compiler/inference.jl | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 16b521cf901b5..0f2e2b78d6be5 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1667,13 +1667,17 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) elseif isa(stmt, GotoNode) pc´ = (stmt::GotoNode).label elseif isa(stmt, GotoIfNot) - condt = abstract_eval_value(interp, stmt.cond, changes, frame) + condx = stmt.cond + condt = abstract_eval_value(interp, condx, changes, frame) if condt === Bottom empty!(frame.pclimitations) - end - if condt === Bottom break end + if !(isa(condt, Const) || isa(condt, Conditional)) && isa(condx, SlotNumber) + # if this non-`Conditional` object is a slot, we form and propagate + # the conditional constraint on it + condt = Conditional(condx, Const(true), Const(false)) + end condval = maybe_extract_const_bool(condt) l = stmt.dest::Int if !isempty(frame.pclimitations) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index b6eb4acb3cf1d..96ab411c654a0 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -1833,6 +1833,24 @@ end end == Any[Tuple{Int,Int}] end +@testset "conditional constraint propagation from non-`Conditional` object" begin + @test Base.return_types((Bool,)) do b + if b + return !b ? nothing : 1 # ::Int + else + return 0 + end + end == Any[Int] + + @test Base.return_types((Any,)) do b + if b + return b # ::Bool + else + return nothing + end + end == Any[Union{Bool,Nothing}] +end + function f25579(g) h = g[] t = (h === nothing) From fd4ca66ed41f7d1690fc701a60381d651e6cf43b Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Wed, 19 May 2021 19:06:55 +0530 Subject: [PATCH 359/439] Small typo fixes (#40873) --- doc/src/manual/interfaces.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 264639bc6d28c..7333434b87afb 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -479,7 +479,7 @@ they are iterable collections of their characters (see [Strings](@ref) for more) The next two steps (selecting the output array and implementation) are dependent upon determining a single answer for a given set of arguments. Broadcast must take all the varied types of its arguments and collapse them down to just one output array and one -implementation. Broadcast calls this single answer a "style." Every broadcastable object +implementation. Broadcast calls this single answer a "style". Every broadcastable object each has its own preferred style, and a promotion-like system is used to combine these styles into a single answer — the "destination style". @@ -549,7 +549,7 @@ Base.showarg(io::IO, A::ArrayAndChar, toplevel) = print(io, typeof(A), " with ch ``` -You might want broadcasting to preserve the `char` "metadata." First we define +You might want broadcasting to preserve the `char` "metadata". First we define ```jldoctest ArrayAndChar; output = false Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}() From 193125426e6ce66d9c68d9942a4d5d578a28cfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Wed, 19 May 2021 17:12:45 +0200 Subject: [PATCH 360/439] Add `@inbounds` in push! (#40816) --- base/array.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index 6e5b9b148a043..9c522855957fe 100644 --- a/base/array.jl +++ b/base/array.jl @@ -965,7 +965,7 @@ function push!(a::Array{T,1}, item) where T # convert first so we don't grow the array if the assignment won't work itemT = convert(T, item) _growend!(a, 1) - a[end] = itemT + @inbounds a[end] = itemT return a end From 743a37898d447d047002efcc19ce59825ef63cc1 Mon Sep 17 00:00:00 2001 From: Will Pazner <11493037+pazner@users.noreply.github.com> Date: Wed, 19 May 2021 11:04:34 -0700 Subject: [PATCH 361/439] Add indexing and other array operations to MethodList (#40863) Make MethodList subtype of AbstractArray{Method,1} Define size and getindex for MethodList. The definitions of length, isempty, iterate, and eltype follow from those defined for AbstractArray, and so can be removed. --- base/methodshow.jl | 1 + base/reflection.jl | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/base/methodshow.jl b/base/methodshow.jl index 961328c7c9684..937ff02a1786d 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -295,6 +295,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru end show(io::IO, ms::MethodList) = show_method_table(io, ms) +show(io::IO, ::MIME"text/plain", ms::MethodList) = show_method_table(io, ms) show(io::IO, mt::Core.MethodTable) = show_method_table(io, MethodList(mt)) function inbase(m::Module) diff --git a/base/reflection.jl b/base/reflection.jl index 8fe04defe1d3f..118d590321ed5 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -915,15 +915,13 @@ end # high-level, more convenient method lookup functions # type for reflecting and pretty-printing a subset of methods -mutable struct MethodList +mutable struct MethodList <: AbstractArray{Method,1} ms::Array{Method,1} mt::Core.MethodTable end -length(m::MethodList) = length(m.ms) -isempty(m::MethodList) = isempty(m.ms) -iterate(m::MethodList, s...) = iterate(m.ms, s...) -eltype(::Type{MethodList}) = Method +size(m::MethodList) = size(m.ms) +getindex(m::MethodList, i) = m.ms[i] function MethodList(mt::Core.MethodTable) ms = Method[] From 6f867eb3ea1576b96482eb593da000b0850183b4 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 19 May 2021 20:06:56 +0200 Subject: [PATCH 362/439] tweak the type of quotes for functions in llvm code output (#40869) --- src/disasm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disasm.cpp b/src/disasm.cpp index 94dc91ee23905..778a090598016 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -249,7 +249,7 @@ void DILineInfoPrinter::emit_lineinfo(raw_ostream &Out, std::vector if (frame.Line != UINT_MAX && frame.Line != 0) Out << ":" << frame.Line; StringRef method = StringRef(frame.FunctionName).rtrim(';'); - Out << " within `" << method << "'"; + Out << " within `" << method << "`"; if (collapse_recursive) { while (nctx < nframes) { const DILineInfo &frame = DI.at(nframes - 1 - nctx); From 613de2c1f2988994c04dda0de246fab23a0727f6 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Wed, 19 May 2021 14:09:54 -0400 Subject: [PATCH 363/439] Fix #40846, wrong results from `Float64 .* StepRange` (#40847) --- base/broadcast.jl | 4 ++-- test/ranges.jl | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 47bd01145cd7d..f9d41a13ff618 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -1159,14 +1159,14 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::StepRangeLen{T}) StepRangeLen{typeof(x*T(r.ref))}(x*r.ref, x*r.step, length(r), r.offset) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Number, r::LinRange) = LinRange(x * r.start, x * r.stop, r.len) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractFloat, r::OrdinalRange) = - Base.range_start_step_length(x*first(r), x, length(r)) # 0.2 .* (-2:2) needs TwicePrecision + Base.range_start_step_length(x*first(r), x*step(r), length(r)) # 0.2 .* (-2:2) needs TwicePrecision # separate in case of noncommutative multiplication: broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::Number) = StepRangeLen(first(r)*x, step(r)*x, length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::StepRangeLen{T}, x::Number) where {T} = StepRangeLen{typeof(T(r.ref)*x)}(r.ref*x, r.step*x, length(r), r.offset) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::LinRange, x::Number) = LinRange(r.start * x, r.stop * x, r.len) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::OrdinalRange, x::AbstractFloat) = - Base.range_start_step_length(first(r)*x, x, length(r)) + Base.range_start_step_length(first(r)*x, step(r)*x, length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(/), r::AbstractRange, x::Number) = range(first(r)/x, step=step(r)/x, length=length(r)) broadcasted(::DefaultArrayStyle{1}, ::typeof(/), r::StepRangeLen{T}, x::Number) where {T} = diff --git a/test/ranges.jl b/test/ranges.jl index dea5d9b675305..8dcff017c4556 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1581,6 +1581,19 @@ end @test @inferred(r ./ Inf) == [0.0, 0.0, 0.0, 0.0] @test eval(Meta.parse(repr(0 * r))) == [0.0, 0.0, 0.0, 0.0] + + # Not constant-valued, but related methods: + @test @inferred(-1 * r) == [-1,-2,-3,-4] + @test @inferred(r * -1) == [-1,-2,-3,-4] + @test @inferred(r / -1) == [-1,-2,-3,-4] + + @test @inferred(-1.0 .* r) == [-1,-2,-3,-4] + @test @inferred(r .* -1.0) == [-1,-2,-3,-4] + @test @inferred(r ./ -1.0) == [-1,-2,-3,-4] + + @test @inferred(-1 * reverse(r)) == [-4,-3,-2,-1] + @test @inferred(-1.0 .* reverse(r)) == [-4,-3,-2,-1] + @test @inferred(reverse(r) ./ -1.0) == [-4,-3,-2,-1] end @test_broken @inferred(range(0, step=0, length=4)) == [0, 0, 0, 0] @@ -1896,8 +1909,14 @@ end @test_throws BoundsError r[true:true:true] end -@testset "PR 40320 nanosoldier" begin +@testset "PR 40320 fixes" begin + # found by nanosoldier @test 0.2 * (-2:2) == -0.4:0.2:0.4 # from tests of AbstractFFTs, needs Base.TwicePrecision @test 0.2f0 * (-2:2) == Float32.(-0.4:0.2:0.4) # likewise needs Float64 @test 0.2 * (-2:1:2) == -0.4:0.2:0.4 + + # https://github.com/JuliaLang/julia/issues/40846 + @test 0.1 .* (3:-1:1) ≈ [0.3, 0.2, 0.1] + @test (10:-1:1) * 0.1 == 1:-0.1:0.1 + @test 0.2 * (-2:2:2) == [-0.4, 0, 0.4] end From 00b1807a3bff6acdaddb88360af9809bb3bbca82 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 19 May 2021 11:29:40 -0700 Subject: [PATCH 364/439] Document Fix1 and Fix2 (#36094) Co-authored-by: Jameson Nash --- doc/src/base/base.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 7364b0c3b50b5..1e419460bef53 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -254,6 +254,8 @@ Base.:(|>) Base.:(∘) Base.ComposedFunction Base.splat +Base.Fix1 +Base.Fix2 ``` ## Syntax From d93a1c867ba1ffa7f803c93b580ee9b53b3f3d00 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 19 May 2021 18:08:42 -0400 Subject: [PATCH 365/439] Move analyzegc pipeline to buildkite (#40826) * add the analyzegc pipeline * fixup! add the analyzegc pipeline * add step for llvmpasses * Add newline at end of file * Break buildkite output up into sections This will give us the ability to time different portions of the build as well Co-authored-by: Dilum Aluthge Co-authored-by: Elliot Saba --- .buildkite/pipeline.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .buildkite/pipeline.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 0000000000000..e63431649f897 --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,28 @@ +steps: + - label: "analyzegc" + commands: + - echo "--- Install apt-get pre-reqs" + - apt-get update + - apt-get install -y build-essential libatomic1 python python3 gfortran perl wget m4 cmake pkg-config curl + - echo "--- Install in-tree LLVM dependencies" + - make -j 6 -C deps install-llvm install-clang install-llvm-tools install-libuv install-utf8proc install-unwind + - echo "+++ run clangsa/analyzegc" + - make -j 6 -C test/clangsa + - make -j 6 -C src analyzegc + agents: + queue: "juliacpu" # this should be julia -- also in pipeline settings + # os: linux # tag missing for juliacpu queue + timeout_in_minutes: 60 + - label: "llvmpasses" + commands: + - echo "--- Install apt-get pre-reqs" + - apt-get update + - apt-get install -y build-essential libatomic1 python python3 gfortran perl wget m4 cmake pkg-config curl + - echo "+++ run llvmpasses" + - make -j 6 release + - make -j 6 -C src install-analysis-deps + - make -j 6 -C test/llvmpasses + agents: + queue: "juliacpu" # this should be julia -- also in pipeline settings + # os: linux # tag missing for juliacpu queue + timeout_in_minutes: 60 From c4ee1fac2dad966d8481e01c93eb6cf7613ac172 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 20 May 2021 08:34:10 +0200 Subject: [PATCH 366/439] restore performance of `hash` for `BigInt` and `Rational{BigInt}` (#40881) When the code was moved out of hashing2.jl, some imports where missed, cancelling the benefits of #33790. --- base/gmp.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 7d00c2417aad7..0fa475a2c6801 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -10,7 +10,7 @@ import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, sum, trailing_zeros, trailing_ones, count_ones, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, - sign, hastypemax, isodd, iseven, digits! + sign, hastypemax, isodd, iseven, digits!, hash, hash_integer if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -769,8 +769,11 @@ end if Limb === UInt # this condition is true most (all?) of the time, and in this case we can define - # an optimized version of the above hash_integer(::Integer, ::UInt) method for BigInt - # used e.g. for Rational{BigInt} + # an optimized version for BigInt of hash_integer (used e.g. for Rational{BigInt}), + # and of hash + + using .Base: hash_uint + function hash_integer(n::BigInt, h::UInt) GC.@preserve n begin s = n.size @@ -800,7 +803,7 @@ if Limb === UInt limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) - nd = ndigits0z(x, 2) + nd = Base.ndigits0z(x, 2) idx = _divLimb(pow) + 1 shift = _modLimb(pow) % UInt upshift = BITS_PER_LIMB - shift From 79ee2b40d45cbbae2e5da02227e6a40bfd686198 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 20 May 2021 09:57:07 +0200 Subject: [PATCH 367/439] improve hashing performance for uuid (#40879) * improve hashing performance for uuid --- base/uuid.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/uuid.jl b/base/uuid.jl index 16ffdcefccc8d..ff4df68ddb7c8 100644 --- a/base/uuid.jl +++ b/base/uuid.jl @@ -31,6 +31,11 @@ end UInt128(u::UUID) = u.value +let + uuid_hash_seed = UInt === UInt64 ? 0xd06fa04f86f11b53 : 0x96a1f36d + Base.hash(uuid::UUID, h::UInt) = hash(uuid_hash_seed, hash(convert(NTuple{2, UInt64}, uuid), h)) +end + let @inline function uuid_kernel(s, i, u) _c = UInt32(@inbounds codeunit(s, i)) From 605a14aea21f52f83044dfd2398d5f1d26e1375e Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Thu, 20 May 2021 09:00:16 -0400 Subject: [PATCH 368/439] Update editors and IDEs (#40883) * Update editors and IDEs cc @pfitzseb (Should we still include Juno?), and @fonsp (added Pluto) [ci skip] [skip ci] * Update README.md --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 38566819e0d2e..cb1fc2bdd8180 100644 --- a/README.md +++ b/README.md @@ -144,10 +144,7 @@ Support for editing Julia is available for many [Sublime Text](https://github.com/JuliaEditorSupport/Julia-sublime), and many others. -Supported IDEs include: [Juno](http://junolab.org/) (Atom plugin), -[julia-vscode](https://github.com/JuliaEditorSupport/julia-vscode) (VS -Code plugin), and -[julia-intellij](https://github.com/JuliaEditorSupport/julia-intellij) -(IntelliJ IDEA plugin). The popular [Jupyter](https://jupyter.org/) -notebook interface is available through -[IJulia](https://github.com/JuliaLang/IJulia.jl). +Supported IDEs include: [julia-vscode](https://github.com/JuliaEditorSupport/julia-vscode) (VS +Code plugin), [Juno](http://junolab.org/) (Atom plugin). [Jupyter](https://jupyter.org/) +notebooks are available through the [IJulia](https://github.com/JuliaLang/IJulia.jl) package, and +[Pluto](https://github.com/fonsp/Pluto.jl) notebooks through the Pluto.jl package. From 27066a7ad2eb2950ac02281cb3dfc0c8eb1733f4 Mon Sep 17 00:00:00 2001 From: Qfl3x <20775896+Qfl3x@users.noreply.github.com> Date: Thu, 20 May 2021 14:31:55 +0100 Subject: [PATCH 369/439] Added string literal docs (#40835) Co-authored-by: Simeon Schaub --- base/docs/basedocs.jl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 5efe97ed9debc..d45fbd3ee07d2 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -2698,4 +2698,46 @@ A quoted piece of code, that does not support interpolation. See the [manual sec """ QuoteNode + +""" + " +`"` Is used to delimit string literals. + +# Examples + +```jldoctest +julia> "Hello World!" +"Hello World!" + +julia> "Hello World!\\n" +"Hello World!\\n" +``` + +See also [`\"""`](@ref \"\"\"). +""" +kw"\"" + +""" + \""" +`\"""` is used to delimit string literals. Strings created by triple quotation marks can contain `"` characters without escaping and are dedented to the level of the least-indented line. This is useful for defining strings within code that is indented. + +# Examples + +```jldoctest +julia> \"""Hello World!\""" +"Hello World!" + +julia> \"""Contains "quote" characters\""" +"Contains \\"quote\\" characters" + +julia> \""" + Hello, + world.\""" +"Hello,\\nworld." +``` + +See also [`"`](@ref \") +""" +kw"\"\"\"" + end From 9117b4d6d6f90d53216dcb2c0fc8a0bf8627ccd6 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 20 May 2021 12:42:25 -0400 Subject: [PATCH 370/439] Syntax for multidimensional arrays (#33697) Co-authored-by: Matt Bauman Co-authored-by: Jeff Bezanson Co-authored-by: Simeon Schaub --- NEWS.md | 7 +- base/abstractarray.jl | 369 ++++++++++++++++++++++++++++++++++++++- base/arrayshow.jl | 52 ++++-- base/exports.jl | 1 + base/reducedim.jl | 4 +- doc/src/base/arrays.md | 1 + doc/src/devdocs/ast.md | 36 ++-- doc/src/manual/arrays.md | 144 +++++++++++++-- src/ast.scm | 13 ++ src/julia-parser.scm | 173 ++++++++++++------ src/julia-syntax.scm | 121 ++++++++++++- test/abstractarray.jl | 45 ++++- test/offsetarray.jl | 6 +- test/show.jl | 11 ++ test/syntax.jl | 20 +++ 15 files changed, 894 insertions(+), 109 deletions(-) diff --git a/NEWS.md b/NEWS.md index 93e3b6e523992..169ebd2fa742e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,11 @@ New language features as `.&&` and `.||`. ([#39594]) * `⫪` (U+2AEA, `\Top`, `\downvDash`) and `⫫` (U+2AEB, `\Bot`, `\upvDash`, `\indep`) may now be used as binary operators with comparison precedence. ([#39403]) +* Repeated semicolons may now be used inside array literals to separate dimensions of an array, + with the number of semicolons specifying the particular dimension. Just as the single semicolon + in `[A; B]` has always described concatenating along the first dimension (vertically), now two + semicolons `[A;; B]` do so in the second dimension (horizontally), three semicolons `;;;` in the + third, and so on. ([#33697]) Language changes ---------------- @@ -148,7 +153,7 @@ Standard library changes Deprecated or removed --------------------- -- Multiple successive semicolons in an array expresion were previously ignored (e.g. `[1 ;; 2] == [1 ; 2]`). Multiple semicolons are being reserved for future syntax and may have different behavior in a future release. +- Multiple successive semicolons in an array expresion were previously ignored (e.g., `[1 ;; 2] == [1 ; 2]`). This is now being used to separate dimensions for array literals. (see **New language features**) External dependencies diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2cbe4b501e718..fd5d631a08c44 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1829,6 +1829,25 @@ dimensions for every new input array and putting zero blocks elsewhere. For exam `cat(matrices...; dims=(1,2))` builds a block diagonal matrix, i.e. a block matrix with `matrices[1]`, `matrices[2]`, ... as diagonal blocks and matching zero blocks away from the diagonal. + +julia> cat(a, b, dims=3) +2×2×4 Array{Int64, 3}: +[:, :, 1] = + 1 2 + 3 4 + +[:, :, 2] = + 5 6 + 7 8 + +[:, :, 3] = + 9 10 + 11 12 + +[:, :, 4] = + 13 14 + 15 16 +``` """ @inline cat(A...; dims) = _cat(dims, A...) _cat(catdims, A::AbstractArray{T}...) where {T} = cat_t(T, A...; dims=catdims) @@ -1886,7 +1905,7 @@ julia> hvcat((3,3), a,b,c,d,e,f) 1 2 3 4 5 6 -julia> [a b;c d; e f] +julia> [a b; c d; e f] 3×2 Matrix{Int64}: 1 2 3 4 @@ -2013,6 +2032,354 @@ function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T T[rs...;] end +# nd concatenation + +""" + hvncat(dims::Tuple{Vararg{Int}}, row_first, values...) + hvncat(shape::Tuple{Vararg{Tuple}}, row_first, values...) + +Horizontal, vertical, and n-dimensional concatenation of many `values` in one call. + +This function is called +for block matrix syntax. The first argument either specifies the shape of the concatenation, +similar to `hvcat`, as a tuple of tuples, or the dimensions that specify the key number of +elements along each axis, and is used to determine the output dimensions. The `dims` form +is more performant, and is used by default when the concatenation operation has the same +number of elements along each axis (e.g., [a b; c d;;; e f ; g h]). The `shape` form is used +when the number of elements along each axis is unbalanced (e.g., [a b ; c]). Unbalanced +syntax needs additional validation overhead. + +# Examples +```jldoctest +julia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6 +(1, 2, 3, 4, 5, 6) + +julia> [a b c;;; d e f] +1×3×2 Array{Int64, 3}: +[:, :, 1] = + 1 2 3 + +[:, :, 2] = + 4 5 6 + +julia> hvncat((2,1,3), false, a,b,c,d,e,f) +2×1×3 Array{Int64, 3}: +[:, :, 1] = + 1 + 2 + +[:, :, 2] = + 3 + 4 + +[:, :, 3] = + 5 + 6 + +julia> [a b;;; c d;;; e f] +1×2×3 Array{Int64, 3}: +[:, :, 1] = + 1 2 + +[:, :, 2] = + 3 4 + +[:, :, 3] = + 5 6 + +julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f) +1×3×2 Array{Int64, 3}: +[:, :, 1] = + 1 2 3 + +[:, :, 2] = + 4 5 6 +``` +""" +hvncat(::Tuple{}, ::Bool) = [] +hvncat(::Tuple{}, ::Bool, xs...) = [] +hvncat(::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = vcat(xs...) # methods assume 2+ dimensions +hvncat(dimsshape::Tuple, row_first::Bool, xs...) = _hvncat(dimsshape, row_first, xs...) +hvncat(dim::Int, xs...) = _hvncat(dim, true, xs...) + +_hvncat(::Union{Tuple, Int}, ::Bool) = [] +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs...) = _typed_hvncat(promote_eltypeof(xs...), dimsshape, row_first, xs...) +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::T...) where T<:Number = _typed_hvncat(T, dimsshape, row_first, xs...) +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::Number...) = _typed_hvncat(promote_typeof(xs...), dimsshape, row_first, xs...) +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray...) = _typed_hvncat(promote_eltype(xs...), dimsshape, row_first, xs...) +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray{T}...) where T = _typed_hvncat(T, dimsshape, row_first, xs...) + +typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() +typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() +typed_hvncat(T::Type, ::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = typed_vcat(T, xs...) # methods assume 2+ dimensions +typed_hvncat(T::Type, dimsshape::Tuple, row_first::Bool, xs...) = _typed_hvncat(T, dimsshape, row_first, xs...) +typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) + +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs::Number...) where T = Vector{T}() +function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} + A = Array{T, N}(undef, dims...) + lengtha = length(A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations + lengthx = length(xs) # Cuts from 3 allocations to 1. + if lengtha != lengthx + throw(ArgumentError("argument count does not match specified shape (expected $lengtha, got $lengthx)")) + end + hvncat_fill!(A, row_first, xs) + return A +end + +function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple) + # putting these in separate functions leads to unnecessary allocations + if row_first + nr, nc = size(A, 1), size(A, 2) + nrc = nr * nc + @inbounds na = prod(size(A)[3:end]) + k = 1 + @inbounds for d ∈ 1:na + dd = nrc * (d - 1) + for i ∈ 1:nr + Ai = dd + i + for j ∈ 1:nc + A[Ai] = xs[k] + k += 1 + Ai += nr + end + end + end + else + @inbounds for k ∈ eachindex(xs) + A[k] = xs[k] + end + end +end + +_typed_hvncat(T::Type, dim::Int, ::Bool, xs...) = _typed_hvncat(T, Val(dim), xs...) # catches from _hvncat type promoters +_typed_hvncat(::Type{T}, ::Val) where T = Vector{T}() +_typed_hvncat(T::Type, ::Val{N}, xs::Number...) where N = _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(xs)), false, xs...) +function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} + # optimization for arrays that can be concatenated by copying them linearly into the destination + # conditions: the elements must all have 1- or 0-length dimensions above N + @inbounds for a ∈ as + ndims(a) <= N || all(x -> size(a, x) == 1, (N + 1):ndims(a)) || + return _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(as)), false, as...) + end + + nd = max(N, ndims(as[1])) + + Ndim = 0 + @inbounds for i ∈ 1:lastindex(as) + Ndim += cat_size(as[i], N) + for d ∈ 1:N - 1 + cat_size(as[1], d) == cat_size(as[i], d) || throw(ArgumentError("mismatched size along axis $d in element $i")) + end + end + + @inbounds A = Array{T, nd}(undef, ntuple(d -> cat_size(as[1], d), N - 1)..., Ndim, ntuple(x -> 1, nd - N)...) + k = 1 + @inbounds for a ∈ as + for i ∈ eachindex(a) + A[k] = a[i] + k += 1 + end + end + return A +end + +function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N} + # optimization for scalars and 1-length arrays that can be concatenated by copying them linearly + # into the destination + nd = N + Ndim = 0 + @inbounds for a ∈ as + if a isa AbstractArray + cat_size(a, N) == length(a) || + throw(ArgumentError("all dimensions of elements other than $N must be of length 1")) + nd = max(nd, ndims(a)) + end + Ndim += cat_size(a, N) + end + + @inbounds A = Array{T, nd}(undef, ntuple(x -> 1, N - 1)..., Ndim, ntuple(x -> 1, nd - N)...) + + k = 1 + @inbounds for a ∈ as + if a isa AbstractArray + lena = length(a) + copyto!(A, k, a, 1, lena) + k += lena + else + A[k] = a + k += 1 + end + end + return A +end + +function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, as...) where {T, N} + d1 = row_first ? 2 : 1 + d2 = row_first ? 1 : 2 + + # discover dimensions + @inbounds nd = max(N, ndims(as[1])) + outdims = zeros(Int, nd) + + # discover number of rows or columns + @inbounds for i ∈ 1:dims[d1] + outdims[d1] += cat_size(as[i], d1) + end + + currentdims = zeros(Int, nd) + blockcount = 0 + @inbounds for i ∈ eachindex(as) + currentdims[d1] += cat_size(as[i], d1) + if currentdims[d1] == outdims[d1] + currentdims[d1] = 0 + for d ∈ (d2, 3:nd...) + currentdims[d] += cat_size(as[i], d) + if outdims[d] == 0 # unfixed dimension + blockcount += 1 + if blockcount == (d > length(dims) ? 1 : dims[d]) # last expected member of dimension + outdims[d] = currentdims[d] + currentdims[d] = 0 + blockcount = 0 + else + break + end + else # fixed dimension + if currentdims[d] == outdims[d] # end of dimension + currentdims[d] = 0 + elseif currentdims[d] < outdims[d] # dimension in progress + break + else # exceeded dimension + ArgumentError("argument $i has too many elements along axis $d") |> throw + end + end + end + elseif currentdims[d1] > outdims[d1] # exceeded dimension + ArgumentError("argument $i has too many elements along axis $d1") |> throw + end + end + + # calling sum() leads to 3 extra allocations + len = 0 + for a ∈ as + len += cat_length(a) + end + outlen = prod(outdims) + outlen == 0 && ArgumentError("too few elements in arguments, unable to infer dimensions") |> throw + len == outlen || ArgumentError("too many elements in arguments; expected $(outlen), got $(len)") |> throw + + # copy into final array + A = Array{T, nd}(undef, outdims...) + # @assert all(==(0), currentdims) + outdims .= 0 + hvncat_fill!(A, currentdims, outdims, d1, d2, as) + return A +end + +function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Bool, as...) where {T, N} + d1 = row_first ? 2 : 1 + d2 = row_first ? 1 : 2 + shape = collect(shape) # saves allocations later + @inbounds shapelength = shape[end][1] + lengthas = length(as) + shapelength == lengthas || throw(ArgumentError("number of elements does not match shape; expected $(shapelength), got $lengthas)")) + + # discover dimensions + @inbounds nd = max(N, ndims(as[1])) + outdims = zeros(Int, nd) + currentdims = zeros(Int, nd) + blockcounts = zeros(Int, nd) + shapepos = ones(Int, nd) + + @inbounds for i ∈ eachindex(as) + wasstartblock = false + for d ∈ 1:N + ad = (d < 3 && row_first) ? (d == 1 ? 2 : 1) : d + dsize = cat_size(as[i], ad) + blockcounts[d] += 1 + + if d == 1 || i == 1 || wasstartblock + currentdims[d] += dsize + elseif dsize != cat_size(as[i - 1], ad) + ArgumentError("argument $i has a mismatched number of elements along axis $ad; expected $(cat_size(as[i - 1], ad)), got $dsize") |> throw + end + + wasstartblock = blockcounts[d] == 1 # remember for next dimension + + isendblock = blockcounts[d] == shape[d][shapepos[d]] + if isendblock + if outdims[d] == 0 + outdims[d] = currentdims[d] + elseif outdims[d] != currentdims[d] + ArgumentError("argument $i has a mismatched number of elements along axis $ad; expected $(abs(outdims[d] - (currentdims[d] - dsize))), got $dsize") |> throw + end + currentdims[d] = 0 + blockcounts[d] = 0 + shapepos[d] += 1 + end + end + end + + if row_first + @inbounds outdims[1], outdims[2] = outdims[2], outdims[1] + end + + # @assert all(==(0), currentdims) + # @assert all(==(0), blockcounts) + + # copy into final array + A = Array{T, nd}(undef, outdims...) + hvncat_fill!(A, currentdims, blockcounts, d1, d2, as) + return A +end + +@inline function hvncat_fill!(A::Array{T, N}, scratch1::Vector{Int}, scratch2::Vector{Int}, d1::Int, d2::Int, as::Tuple{Vararg}) where {T, N} + outdims = size(A) + offsets = scratch1 + inneroffsets = scratch2 + @inbounds for a ∈ as + if isa(a, AbstractArray) + for ai ∈ a + Ai = hvncat_calcindex(offsets, inneroffsets, outdims, N) + A[Ai] = ai + + for j ∈ 1:N + inneroffsets[j] += 1 + inneroffsets[j] < cat_size(a, j) && break + inneroffsets[j] = 0 + end + end + else + Ai = hvncat_calcindex(offsets, inneroffsets, outdims, N) + A[Ai] = a + end + + for j ∈ (d1, d2, 3:N...) + offsets[j] += cat_size(a, j) + offsets[j] < outdims[j] && break + offsets[j] = 0 + end + end +end + +@propagate_inbounds function hvncat_calcindex(offsets::Vector{Int}, inneroffsets::Vector{Int}, + outdims::Tuple{Vararg{Int}}, nd::Int) + Ai = inneroffsets[1] + offsets[1] + 1 + for j ∈ 2:nd + increment = inneroffsets[j] + offsets[j] + for k ∈ 1:j-1 + increment *= outdims[k] + end + Ai += increment + end + Ai +end + +cat_length(a::AbstractArray) = length(a) +cat_length(::Any) = 1 + ## Reductions and accumulates ## function isequal(A::AbstractArray, B::AbstractArray) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index f942f87787484..1e9f3e59729e6 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -271,17 +271,21 @@ end # typeinfo agnostic # n-dimensional arrays -show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices::Bool) = - _show_nd(io, inferencebarrier(a), print_matrix, label_slices, map(unitrange, axes(a))) +show_nd(io::IO, a::AbstractArray, print_matrix::Function, show_full::Bool) = + _show_nd(io, inferencebarrier(a), print_matrix, show_full, map(unitrange, axes(a))) -function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Function, label_slices::Bool, axs::Tuple{Vararg{AbstractUnitRange}}) +function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Function, show_full::Bool, axs::Tuple{Vararg{AbstractUnitRange}}) limit::Bool = get(io, :limit, false) if isempty(a) return end tailinds = tail(tail(axs)) nd = ndims(a)-2 - for I in CartesianIndices(tailinds) + show_full || print(io, "[") + Is = CartesianIndices(tailinds) + lastidxs = first(Is).I + reached_last_d = false + for I in Is idxs = I.I if limit for i = 1:nd @@ -296,7 +300,9 @@ function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Functio @goto skip end end - print(io, "...\n\n") + print(io, ";"^(i+2)) + print(io, " \u2026 ") + show_full && print(io, "\n\n") @goto skip end if ind[firstindex(ind)+2] < ii <= ind[end-3] @@ -305,13 +311,29 @@ function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Functio end end end - if label_slices + if show_full _show_nd_label(io, a, idxs) end slice = view(a, axs[1], axs[2], idxs...) - print_matrix(io, slice) - print(io, idxs == map(last,tailinds) ? "" : "\n\n") + if show_full + print_matrix(io, slice) + print(io, idxs == map(last,tailinds) ? "" : "\n\n") + else + idxdiff = lastidxs .- idxs .< 0 + if any(idxdiff) + lastchangeindex = 2 + findlast(idxdiff) + print(io, ";"^lastchangeindex) + lastchangeindex == ndims(a) && (reached_last_d = true) + print(io, " ") + end + print_matrix(io, slice) + end @label skip + lastidxs = idxs + end + if !show_full + reached_last_d || print(io, ";"^(nd+2)) + print(io, "]") end end @@ -386,9 +408,9 @@ end preceded by `prefix`, supposed to encode the type of the elements. """ _show_nonempty(io::IO, X::AbstractMatrix, prefix::String) = - _show_nonempty(io, inferencebarrier(X), prefix, axes(X)) + _show_nonempty(io, inferencebarrier(X), prefix, false, axes(X)) -function _show_nonempty(io::IO, @nospecialize(X::AbstractMatrix), prefix::String, axs::Tuple{AbstractUnitRange,AbstractUnitRange}) +function _show_nonempty(io::IO, @nospecialize(X::AbstractMatrix), prefix::String, drop_brackets::Bool, axs::Tuple{AbstractUnitRange,AbstractUnitRange}) @assert !isempty(X) limit = get(io, :limit, false)::Bool indr, indc = axs @@ -407,7 +429,7 @@ function _show_nonempty(io::IO, @nospecialize(X::AbstractMatrix), prefix::String cdots = true end end - print(io, prefix, "[") + drop_brackets || print(io, prefix, "[") for rr in (rr1, rr2) for i in rr for cr in (cr1, cr2) @@ -429,12 +451,16 @@ function _show_nonempty(io::IO, @nospecialize(X::AbstractMatrix), prefix::String end last(rr) != last(indr) && rdots && print(io, "\u2026 ; ") end - print(io, "]") + if !drop_brackets + nc > 1 || print(io, ";;") + print(io, "]") + end + return nothing end _show_nonempty(io::IO, X::AbstractArray, prefix::String) = - show_nd(io, X, (io, slice) -> _show_nonempty(io, slice, prefix), false) + show_nd(io, X, (io, slice) -> _show_nonempty(io, inferencebarrier(slice), prefix, true, axes(slice)), false) # a specific call path is used to show vectors (show_vector) _show_nonempty(::IO, ::AbstractVector, ::String) = diff --git a/base/exports.jl b/base/exports.jl index 7a2f25072b8cd..36a78c544acae 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -391,6 +391,7 @@ export first, hcat, hvcat, + hvncat, indexin, argmax, argmin, diff --git a/base/reducedim.jl b/base/reducedim.jl index ff2b24db740ef..5851cfcc0cd1f 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -999,7 +999,7 @@ julia> findmin(A, dims=1) ([1.0 2.0], CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2)]) julia> findmin(A, dims=2) -([1.0; 3.0], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1)]) +([1.0; 3.0;;], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1);;]) ``` """ findmin(A::AbstractArray; dims=:) = _findmin(A, dims) @@ -1046,7 +1046,7 @@ julia> findmax(A, dims=1) ([3.0 4.0], CartesianIndex{2}[CartesianIndex(2, 1) CartesianIndex(2, 2)]) julia> findmax(A, dims=2) -([2.0; 4.0], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2)]) +([2.0; 4.0;;], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2);;]) ``` """ findmax(A::AbstractArray; dims=:) = _findmax(A, dims) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 0493ae1e35e72..1dc2d8ed926af 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -141,6 +141,7 @@ Base.cat Base.vcat Base.hcat Base.hvcat +Base.hvncat Base.vect Base.circshift Base.circshift! diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index af89290618fec..d02606840c431 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -63,23 +63,25 @@ call. Finally, chains of comparisons have their own special expression structure ### Bracketed forms -| Input | AST | -|:------------------------ |:------------------------------------ | -| `a[i]` | `(ref a i)` | -| `t[i;j]` | `(typed_vcat t i j)` | -| `t[i j]` | `(typed_hcat t i j)` | -| `t[a b; c d]` | `(typed_vcat t (row a b) (row c d))` | -| `a{b}` | `(curly a b)` | -| `a{b;c}` | `(curly a (parameters c) b)` | -| `[x]` | `(vect x)` | -| `[x,y]` | `(vect x y)` | -| `[x;y]` | `(vcat x y)` | -| `[x y]` | `(hcat x y)` | -| `[x y; z t]` | `(vcat (row x y) (row z t))` | -| `[x for y in z, a in b]` | `(comprehension x (= y z) (= a b))` | -| `T[x for y in z]` | `(typed_comprehension T x (= y z))` | -| `(a, b, c)` | `(tuple a b c)` | -| `(a; b; c)` | `(block a (block b c))` | +| Input | AST | +|:------------------------ |:------------------------------------------------- | +| `a[i]` | `(ref a i)` | +| `t[i;j]` | `(typed_vcat t i j)` | +| `t[i j]` | `(typed_hcat t i j)` | +| `t[a b; c d]` | `(typed_vcat t (row a b) (row c d))` | +| `t[a b;;; c d]` | `(typed_ncat t 3 (row a b) (row c d))` | +| `a{b}` | `(curly a b)` | +| `a{b;c}` | `(curly a (parameters c) b)` | +| `[x]` | `(vect x)` | +| `[x,y]` | `(vect x y)` | +| `[x;y]` | `(vcat x y)` | +| `[x y]` | `(hcat x y)` | +| `[x y; z t]` | `(vcat (row x y) (row z t))` | +| `[x;y;; z;t;;;]` | `(ncat 3 (nrow 2 (nrow 1 x y) (nrow 1 z t)))` | +| `[x for y in z, a in b]` | `(comprehension x (= y z) (= a b))` | +| `T[x for y in z]` | `(typed_comprehension T x (= y z))` | +| `(a, b, c)` | `(tuple a b c)` | +| `(a; b; c)` | `(block a (block b c))` | ### Macros diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 2afc264556713..c3c014ccb64fe 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -5,8 +5,8 @@ technical computing languages pay a lot of attention to their array implementati of other containers. Julia does not treat arrays in any special way. The array library is implemented almost completely in Julia itself, and derives its performance from the compiler, just like any other code written in Julia. As such, it's also possible to define custom array types by inheriting -from [`AbstractArray`](@ref). See the [manual section on the AbstractArray interface](@ref man-interface-array) for more details -on implementing a custom array type. +from [`AbstractArray`](@ref). See the [manual section on the AbstractArray interface](@ref man-interface-array) +for more details on implementing a custom array type. An array is a collection of objects stored in a multi-dimensional grid. In the most general case, an array may contain objects of type [`Any`](@ref). For most computational purposes, arrays should contain @@ -126,7 +126,7 @@ Any[] ### [Concatenation](@id man-array-concatenation) -If the arguments inside the square brackets are separated by semicolons (`;`) or newlines +If the arguments inside the square brackets are separated by single semicolons (`;`) or newlines instead of commas, then their contents are _vertically concatenated_ together instead of the arguments being used as elements themselves. @@ -154,7 +154,7 @@ julia> [1:2 6 ``` -Similarly, if the arguments are separated by tabs or spaces, then their contents are +Similarly, if the arguments are separated by tabs or spaces or double semicolons, then their contents are _horizontally concatenated_ together. ```jldoctest @@ -171,9 +171,13 @@ julia> [[1,2] [4,5] [7,8]] julia> [1 2 3] # Numbers can also be horizontally concatenated 1×3 Matrix{Int64}: 1 2 3 + +julia> [1;; 2;; 3;; 4] +1×4 Matrix{Int64}: + 1 2 3 4 ``` -Using semicolons (or newlines) and spaces (or tabs) can be combined to concatenate +Single semicolons (or newlines) and spaces (or tabs) can be combined to concatenate both horizontally and vertically at the same time. ```jldoctest @@ -189,17 +193,135 @@ julia> [zeros(Int, 2, 2) [1; 2] 0 0 1 0 0 2 3 4 5 + +julia> [[1 1]; 2 3; [4 4]] +3×2 Matrix{Int64}: + 1 1 + 2 3 + 4 4 +``` + +Spaces (and tabs) have a higher precedence than semicolons, performing any horizontal +concatenations first and then concatenating the result. Using double semicolons for the +horizontal concatenation, on the other hand, performs any vertical concatenations before +horizontally concatenating the result. + +```jldoctest +julia> [zeros(Int, 2, 2) ; [3 4] ;; [1; 2] ; 5] +3×3 Matrix{Int64}: + 0 0 1 + 0 0 2 + 3 4 5 + +julia> [1:2; 4;; 1; 3:4] +3×2 Matrix{Int64}: + 1 1 + 2 3 + 4 4 +``` + +Just as `;` and `;;` concatenate in the first and second dimension, using more semicolons +extends this same general scheme. The number of semicolons in the separator specifies the +particular dimension, so `;;;` concetenates in the third dimension, `;;;;` in the 4th, and +so on. Fewer semicolons take precedence, so the lower dimensions are generally concatenated +first. + +```jldoctest +julia> [1; 2;; 3; 4;; 5; 6;;; + 7; 8;; 9; 10;; 11; 12] +2×3×2 Array{Int64, 3}: +[:, :, 1] = + 1 3 5 + 2 4 6 + +[:, :, 2] = + 7 9 11 + 8 10 12 +``` + +Like before, spaces (and tabs) for horizontal concatenation have a higher precedence than +any number of semicolons. Thus, higher dimensional arrays can also be written by specifying +their rows first, with their elements textually arranged in a manner similar to their layout: + +```jldoctest +julia> [1 3 5 + 2 4 6;;; + 7 9 11 + 8 10 12] +2×3×2 Array{Int64, 3}: +[:, :, 1] = + 1 3 5 + 2 4 6 + +[:, :, 2] = + 7 9 11 + 8 10 12 + +julia> [1 2;;; 3 4;;;; 5 6;;; 7 8] +1×2×2×2 Array{Int64, 4}: +[:, :, 1, 1] = + 1 2 + +[:, :, 2, 1] = + 3 4 + +[:, :, 1, 2] = + 5 6 + +[:, :, 2, 2] = + 7 8 + +julia> [[1 2;;; 3 4];;;; [5 6];;; [7 8]] +1×2×2×2 Array{Int64, 4}: +[:, :, 1, 1] = + 1 2 + +[:, :, 2, 1] = + 3 4 + +[:, :, 1, 2] = + 5 6 + +[:, :, 2, 2] = + 7 8 +``` + +Although they both mean concatenation in the second dimension, spaces (or tabs) and `;;` +cannot appear in the same array expression unless the double semicolon is simply serving as +a "line continuation" character. This allows a single horizontal concatenation to span +multiple lines (without the line break being interpreted as a vertical concatenation). + +```jldoctest +julia> [1 2 ;; + 3 4] +1×4 Matrix{Int64}: + 1 2 3 4 +``` + +Terminating semicolons may also be used to add trailing length 1 dimensions. + +```jldoctest +julia> [1;;] +1×1 Matrix{Int64}: + 1 + +julia> [2; 3;;;] +2×1×1 Array{Int64, 3}: +[:, :, 1] = + 2 + 3 ``` More generally, concatenation can be accomplished through the [`cat`](@ref) function. These syntaxes are shorthands for function calls that themselves are convenience functions: -| Syntax | Function | Description | -|:----------------- |:--------------- |:-------------------------------------------------- | -| | [`cat`](@ref) | concatenate input arrays along dimension(s) `k` | -| `[A; B; C; ...]` | [`vcat`](@ref) | shorthand for `cat(A...; dims=1) | -| `[A B C ...]` | [`hcat`](@ref) | shorthand for `cat(A...; dims=2) | -| `[A B; C D; ...]` | [`hvcat`](@ref) | simultaneous vertical and horizontal concatenation | +| Syntax | Function | Description | +|:---------------------- |:---------------- |:---------------------------------------------------------------------------------------------------------- | +| | [`cat`](@ref) | concatenate input arrays along dimension(s) `k` | +| `[A; B; C; ...]` | [`vcat`](@ref) | shorthand for `cat(A...; dims=1) | +| `[A B C ...]` | [`hcat`](@ref) | shorthand for `cat(A...; dims=2) | +| `[A B; C D; ...]` | [`hvcat`](@ref) | simultaneous vertical and horizontal concatenation | +| `[A; C;; B; D;;; ...]` | [`hvncat`](@ref) | simultaneous n-dimensional concatenation, where number of semicolons indicate the dimension to concatenate | ### Typed array literals diff --git a/src/ast.scm b/src/ast.scm index 6ed530718e3db..d89cae95ad185 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -61,6 +61,12 @@ (else (string e)))) +(define (deparse-semicolons n) + ; concatenate n semicolons + (if (<= n 0) + "" + (string ";" (deparse-semicolons (1- n))))) + (define (deparse e (ilvl 0)) (cond ((or (symbol? e) (number? e)) (string e)) ((string? e) (print-to-string e)) @@ -134,7 +140,14 @@ ((hcat) (string #\[ (deparse-arglist (cdr e) " ") #\])) ((typed_hcat) (string (deparse (cadr e)) (deparse (cons 'hcat (cddr e))))) + ((ncat) (string #\[ (deparse-arglist (cddr e) (string (deparse-semicolons (cadr e)) " ")) + (if (= (length (cddr e)) 1) + (deparse-semicolons (cadr e)) + "") #\])) + ((typed_ncat) (string (deparse (cadr e)) + (deparse (cons 'ncat (cddr e))))) ((row) (deparse-arglist (cdr e) " ")) + ((nrow) (deparse-arglist (cddr e) (string (deparse-semicolons (cadr e)) " "))) ((braces) (string #\{ (deparse-arglist (cdr e) ", ") #\})) ((bracescat) (string #\{ (deparse-arglist (cdr e) "; ") #\})) ((string) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index c6510dcbd9536..9f176f95829db 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1218,6 +1218,8 @@ (loop (list* 'typed_vcat ex (cdr al)))) ((comprehension) (loop (list* 'typed_comprehension ex (cdr al)))) + ((ncat) + (loop (list* 'typed_ncat ex (cdr al)))) (else (error "unknown parse-cat result (internal error)"))))))) ((|.|) (disallow-space s ex t) @@ -1849,60 +1851,123 @@ (take-token s)) `(comprehension ,gen)))) -(define (parse-matrix s first closer gotnewline last-end-symbol) - (define (fix head v) (cons head (reverse v))) - (define (update-outer v outer) - (cond ((null? v) outer) - ((null? (cdr v)) (cons (car v) outer)) - (else (cons (fix 'row v) outer)))) - (define semicolon (eqv? (peek-token s) #\;)) +(define (parse-array s first closer gotnewline last-end-symbol) + (define (fix head v) + (cons head (reverse v))) + (define (unfixrow l) + (cons (reverse (cdaar l)) (if (and (null? (cdar l)) (null? (cdr l))) + '() + (cons (cdar l) (cdr l))))) + (define (fixcat head d v) + (cons head (cons d (reverse v)))) + (define (ncons a n l) + (if (< n 1) + l + (ncons a (1- n) (cons a l)))) + (define (fix-level ah n) + (if (length= ah 1) + (car ah) + (if (= n 1) + (fix 'row ah) + (fixcat 'nrow (1- n) ah)))) + (define (collapse-level n l i) + (if (> n 0) + (let* ((lhfix (fix-level (car l) i)) + (lnew (if (null? (cdr l)) + (list (list lhfix)) + (cons (cons lhfix (cadr l)) (cddr l))))) + (collapse-level (1- n) lnew (1+ i))) + l)) + (define (parse-array-inner s a is-row-first semicolon-count max-level closer gotnewline gotlinesep) + (define (process-semicolon next) + (set! semicolon-count (1+ semicolon-count)) + (set! max-level (max max-level semicolon-count)) + (if (and (null? is-row-first) (= semicolon-count 2) (not (eqv? next #\;))) + ; finding ;; that isn't a row-separator makes it column-first + (set! is-row-first #f)) + (set! a (collapse-level 1 a semicolon-count))) + (define (restore-lower-dim-lists next) + (if (and (not gotlinesep) (not (memv next (list #\; 'for closer #\newline)))) + (set! a (ncons '() semicolon-count a)))) + (let ((t (if (or gotnewline (eqv? (peek-token s) #\newline)) + #\newline + (require-token s)))) + (if (eqv? t closer) + (begin + (take-token s) + (set! a (collapse-level (- max-level semicolon-count) a (1+ semicolon-count))) + (cond ((= max-level 0) + (if (length= (car a) 1) + (fix 'vect (car a)) + (fix 'hcat (car a)))) + ((= max-level 1) + (fix 'vcat (car a))) + (else + (fixcat 'ncat max-level (car a))))) + (case t + ((#\newline) + (or gotnewline (take-token s)) + (let ((next (peek-token s))) + (if (and (> semicolon-count 0) (eqv? next #\;)) + (error (string "semicolons may appear before or after a line break in an array expression, " + "but not both"))) + (if (and (= semicolon-count 0) + (not (memv next (list #\; 'for closer #\newline)))) + ; treat a linebreak prior to a value as a semicolon if no previous semicolons observed + (process-semicolon next)) + (restore-lower-dim-lists next) + (parse-array-inner s a is-row-first semicolon-count max-level closer #f gotlinesep))) + ((#\;) + (or gotnewline (take-token s)) + (let ((next (peek-token s))) + (let ((is-line-sep + (if (and (not (null? is-row-first)) is-row-first (= semicolon-count 1)) + (cond ((eqv? next #\newline) #t) ; [a b ;;... + ((not (or (eof-object? next) (eqv? next #\;))) ; [a b ;;... + (error (string "cannot mix space and ;; separators in an array expression, " + "except to wrap a line"))) + (else #f)) ; [a b ;; for REPL, [a ;;... + #f))) ; [a ; b ;; c ; d... + (if is-line-sep + (begin (set! a (unfixrow a)) + (set! max-level + (if (null? (cdr a)) + 0 ; no prior single semicolon + max-level))) + (begin (process-semicolon next) + (restore-lower-dim-lists next))) + (parse-array-inner s a is-row-first semicolon-count max-level closer #f is-line-sep)))) + ((#\,) + (error "unexpected comma in array expression")) + ((#\] #\}) + (error (string "unexpected \"" t "\""))) + ((for) + (if (and (length= (car a) 1) + (null? (cdr a))) + (begin ;; if we get here, there must have been some kind of space or separator + ;;(expect-space-before s 'for) + (take-token s) + (parse-comprehension s (caar a) closer)) + (error "invalid comprehension syntax"))) + (else + (if (and (not gotlinesep) (pair? (car a)) (not (ts:space? s))) + (error (string "expected \"" closer "\" or separator in arguments to \"" + (if (eqv? closer #\]) #\[ #\{) " " closer + "\"; got \"" + (deparse (caar a)) t "\""))) + (let ((u (parse-eq* s))) + (set! a (cons (cons u (car a)) (cdr a))) + (if (= (length (car a)) 2) + ; at least 2 elements separated by space found [a b...], [a; b c...] + (if (null? is-row-first) + (set! is-row-first #t) + (if (not is-row-first) + (error (string "cannot mix space and \";;\" separators in an array expression, " + "except to wrap a line")))))) + (parse-array-inner s a is-row-first 0 max-level closer #f #f)))))) ;; if a [ ] expression is a cat expression, `end` is not special (with-bindings ((end-symbol last-end-symbol)) - (let loop ((vec (list first)) - (outer '())) - (let ((t (if (or (eqv? (peek-token s) #\newline) gotnewline) - #\newline - (require-token s)))) - (if (eqv? t closer) - (begin (take-token s) - (if (pair? outer) - (fix 'vcat (update-outer vec outer)) - (if (or (null? vec) (null? (cdr vec))) - (fix 'vect vec) ; [x] => (vect x) - (fix 'hcat vec)))) ; [x y] => (hcat x y) - (case t - ((#\;) - (take-token s) - (if (eqv? (peek-token s) #\;) - (parser-depwarn s (string "Multiple semicolons in an array concatenation expression currently have no effect, " - "but may have a new meaning in a future version of Julia.") - "Please remove extra semicolons to preserve forward compatibility e.g. [1;;3] => [1;3].")) - (set! gotnewline #f) - (loop '() (update-outer vec outer))) - ((#\newline) - (or gotnewline (take-token s)) - (set! gotnewline #f) - (loop '() (update-outer vec outer))) - ((#\,) - (error "unexpected comma in matrix expression")) - ((#\] #\}) - (error (string "unexpected \"" t "\""))) - ((for) - (if (and (not semicolon) - (length= outer 1) - (null? vec)) - (begin ;; if we get here, there must have been some kind of space or separator - ;;(expect-space-before s 'for) - (take-token s) - (parse-comprehension s (car outer) closer)) - (error "invalid comprehension syntax"))) - (else - (if (and (pair? vec) (not (ts:space? s))) - (error (string "expected \"" closer "\" or separator in arguments to \"" - (if (eqv? closer #\]) #\[ #\{) " " closer - "\"; got \"" - (deparse (car vec)) t "\""))) - (loop (cons (parse-eq* s) vec) outer)))))))) + (parse-array-inner s (list (list first)) '() 0 0 closer gotnewline #f))) (define (expect-space-before s t) (if (not (ts:space? s)) @@ -1929,9 +1994,9 @@ (take-token s) (if (memv (peek-token s) (list #\, closer)) (parse-vect s first closer) - (parse-matrix s first closer #t last-end-symbol))) + (parse-array s first closer #t last-end-symbol))) (else - (parse-matrix s first closer #f last-end-symbol))))))) + (parse-array s first closer #f last-end-symbol))))))) (define (kw-to-= e) (if (kwarg? e) (cons '= (cdr e)) e)) (define (=-to-kw e) (if (assignment? e) (cons 'kw (cdr e)) e)) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ca274ef552f5b..6bc8401c9b3dd 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1599,7 +1599,7 @@ ,(expand-update-operator op op= (car e) rhs T)))) (else (if (and (pair? lhs) (eq? op= '=) - (not (memq (car lhs) '(|.| tuple vcat typed_hcat typed_vcat)))) + (not (memq (car lhs) '(|.| tuple vcat ncat typed_hcat typed_vcat typed_ncat)))) (error (string "invalid assignment location \"" (deparse lhs) "\""))) (expand-update-operator- op op= lhs rhs declT)))) @@ -1976,6 +1976,113 @@ ,@(apply append rows)))) `(call ,@vcat ,@a)))))) +(define (expand-ncat e (hvncat '((top hvncat)))) + (define (is-row a) (and (pair? a) + (or (eq? (car a) 'row) + (eq? (car a) 'nrow)))) + (define (is-1d a) (not (any is-row a))) + (define (sum xs) (foldl + 0 xs)) + (define (get-shape a is-row-first d) + (define (zip xss) (apply map list xss)) + (define (get-next x) + (cond ((or (not (is-row x)) + (and (eq? (car x) 'nrow) (> d (1+ (cadr x)))) + (and (eq? (car x) 'row) (> d 1))) + (list x)) + ((eq? (car x) 'nrow) (cddr x)) + (else (cdr x)))) + ; describe the shape of the concatenation + (cond ((or (= d 0) + (and (not is-row-first) (= d 1))) + (length a)) + ((and is-row-first (= d 3)) + (get-shape a is-row-first (1- d))) + (else + (let ((ashape + (map (lambda (x) + (get-shape (get-next x) is-row-first (1- d))) + a))) + (if (pair? (car ashape)) + (let ((zipashape (zip ashape))) + (cons (sum (car zipashape)) + (cons (car zipashape) + (map (lambda (x) + (apply append x)) + (cdr zipashape))))) + (list (sum ashape) ashape)))))) + (define (get-dims a is-row-first d) + (cond ((and (< d 2) (not (is-row (car a)))) + (list (length a))) + ((= d 1) + (list (car (get-dims (cdar a) is-row-first 0)) (length a))) + ((and (= d 3) is-row-first) + (get-dims a is-row-first 2)) + (else + (let ((anext (if (and (pair? (car a)) + (eq? (caar a) 'nrow) + (= d (1+ (cadar a)))) + (cddar a) + (list (car a))))) + (cons (length a) (get-dims anext is-row-first (1- d))))))) + (define (is-balanced s) + ; determine whether there are exactly the same number of elements along each axis + (= 0 (sum (map (lambda (x y) + (sum (map (lambda (z) + (- z y)) + x))) + (cdr s) (map car (cdr s)))))) + (define (hasrows-flatten a) + ; (car ) stores if a row was observed + (foldl (lambda (x y) + (let ((r (car y)) + (yt (cdr y))) + (if (is-row x) + (if (eq? (car x) 'nrow) + (let* ((raflat (append (hasrows-flatten (cddr x)))) + (aflat (cdr raflat)) + (rinner (car raflat)) + (r (if (null? (or r rinner)) + (and r rinner) + r))) + (if (and (not (null? r)) + (or (null? rinner) (and (not r) rinner)) + (and (= (cadr x) 2) r)) + (error "cannot mix space and ;; separators in an array expression, except to wrap a line")) + (cons (if (and (= (cadr x) 2) (null? r)) + #f + r) + (append aflat yt))) + (if (or (null? r) r) + (cons #t (append (reverse (cdr x)) yt)) + (error "cannot mix space and ;; separators in an array expression, except to wrap a line"))) + (cons r (cons x yt))))) + (list '()) a)) + (define (tf a) (if a '(true) '(false))) + (define (tuplize s) + (cons 'tuple (reverse (map (lambda (x) + (cons 'tuple x)) + (cons (list (car s)) (cdr s)))))) + (let* ((d (cadr e)) + (a (cddr e)) + (raflat (hasrows-flatten a)) + (r (car raflat)) + (is-row-first (if (null? r) #f r)) + (aflat (reverse (cdr raflat)))) + (if (any assignment? aflat) + (error (string "misplaced assignment statement in \"" (deparse e) "\""))) + (if (has-parameters? aflat) + (error "unexpected parameters in array expression")) + (expand-forms + (if (is-1d a) + `(call ,@hvncat ,d ,@aflat) + (if (any vararg? aflat) + (error (string "Splatting ... in an hvncat with multiple dimensions is not supported")) + (let ((shape (get-shape a is-row-first d))) + (if (is-balanced shape) + (let ((dims `(tuple ,@(reverse (get-dims a is-row-first d))))) + `(call ,@hvncat ,dims ,(tf is-row-first) ,@aflat)) + `(call ,@hvncat ,(tuplize shape) ,(tf is-row-first) ,@aflat)))))))) + (define (expand-property-destruct lhss x) (if (not (length= lhss 1)) (error (string "invalid assignment location \"" (deparse lhs) "\""))) @@ -2220,7 +2327,7 @@ (expand-tuple-destruct lhss x)))) ((typed_hcat) (error "invalid spacing in left side of indexed assignment")) - ((typed_vcat) + ((typed_vcat typed_ncat) (error "unexpected \";\" in left side of indexed assignment")) ((ref) ;; (= (ref a . idxs) rhs) @@ -2257,7 +2364,7 @@ `(block ,@(cdr e) (decl ,(car e) ,T) (= ,(car e) ,rhs)))))) - ((vcat) + ((vcat ncat) ;; (= (vcat . args) rhs) (error "use \"(a, b) = ...\" to assign multiple values")) (else @@ -2493,6 +2600,8 @@ 'vcat expand-vcat + 'ncat expand-ncat + 'typed_hcat (lambda (e) (if (any assignment? (cddr e)) @@ -2505,6 +2614,12 @@ (e (cdr e))) (expand-vcat e `((top typed_vcat) ,t) `((top typed_hvcat) ,t) `((top typed_hvcat_rows) ,t)))) + 'typed_ncat + (lambda (e) + (let ((t (cadr e)) + (e (cdr e))) + (expand-ncat e `((top typed_hvncat) ,t)))) + '|'| (lambda (e) (expand-forms `(call |'| ,(cadr e)))) 'generator diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 6c5ed26a1c289..05ec3efef1aab 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1317,8 +1317,45 @@ end end end -@testset "reduce(vcat, ...) inferrence #40277" begin - x_vecs = ([5, ], [1.0, 2.0, 3.0]) - @test @inferred(reduce(vcat, x_vecs)) == [5.0, 1.0, 2.0, 3.0] - @test @inferred(reduce(vcat, ([10.0], [20.0], Bool[]))) == [10.0, 20.0] +@testset "hvncat" begin + a = fill(1, (2,3,2,4,5)) + b = fill(2, (1,1,2,4,5)) + c = fill(3, (1,2,2,4,5)) + d = fill(4, (1,1,1,4,5)) + e = fill(5, (1,1,1,4,5)) + f = fill(6, (1,1,1,4,5)) + g = fill(7, (2,3,1,4,5)) + h = fill(8, (3,3,3,1,2)) + i = fill(9, (3,2,3,3,2)) + j = fill(10, (3,1,3,3,2)) + + result = [a; b c ;;; d e f ; g ;;;;; h ;;;; i j] + @test size(result) == (3,3,3,4,7) + @test result == [a; [b ;; c] ;;; [d e f] ; g ;;;;; h ;;;; i ;; j] + @test result == cat(cat([a ; b c], [d e f ; g], dims = 3), cat(h, [i j], dims = 4), dims = 5) + + # terminating semicolons extend dimensions + @test [1;] == [1] + @test [1;;] == fill(1, (1,1)) + + for v in (1, fill(1), fill(1,1,1), fill(1, 1, 1, 1)) + @test_throws ArgumentError [v; v;; v] + @test_throws ArgumentError [v; v;; v; v; v] + @test_throws ArgumentError [v; v; v;; v; v] + @test_throws ArgumentError [v; v;; v; v;;; v; v;; v; v;; v; v] + @test_throws ArgumentError [v; v;; v; v;;; v; v] + @test_throws ArgumentError [v; v;; v; v;;; v; v; v;; v; v] + @test_throws ArgumentError [v; v;; v; v;;; v; v;; v; v; v] + # ensure a wrong shape with the right number of elements doesn't pass through + @test_throws ArgumentError [v; v;; v; v;;; v; v; v; v] + + @test [v; v;; v; v] == fill(1, ndims(v) == 3 ? (2, 2, 1) : (2,2)) + @test [v; v;; v; v;;;] == fill(1, 2, 2, 1) + @test [v; v;; v; v] == fill(1, ndims(v) == 3 ? (2, 2, 1) : (2,2)) + @test [v v; v v;;;] == fill(1, 2, 2, 1) + @test [v; v;; v; v;;; v; v;; v; v;;] == fill(1, 2, 2, 2) + @test [v; v; v;; v; v; v;;; v; v; v;; v; v; v;;] == fill(1, 3, 2, 2) + @test [v v; v v;;; v v; v v] == fill(1, 2, 2, 2) + @test [v v v; v v v;;; v v v; v v v] == fill(1, 2, 3, 2) + end end diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 96a44c71e5483..58a683ac90c57 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -231,9 +231,9 @@ targets1 = ["0-dimensional OffsetArray(::Array{Float64, 0}) with eltype Float64: "1×1×1×1 OffsetArray(::Array{Float64, 4}, 2:2, 3:3, 4:4, 5:5) with eltype Float64 with indices 2:2×3:3×4:4×5:5:\n[:, :, 4, 5] =\n 1.0"] targets2 = ["(fill(1.0), fill(1.0))", "([1.0], [1.0])", - "([1.0], [1.0])", - "([1.0], [1.0])", - "([1.0], [1.0])"] + "([1.0;;], [1.0;;])", + "([1.0;;;], [1.0;;;])", + "([1.0;;;;], [1.0;;;;])"] @testset "printing of OffsetArray with n=$n" for n = 0:4 a = OffsetArray(fill(1.,ntuple(Returns(1),n)), ntuple(identity,n)) show(IOContext(io, :limit => true), MIME("text/plain"), a) diff --git a/test/show.jl b/test/show.jl index 2dde201b06dfb..358b792de105b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2286,3 +2286,14 @@ end s = sprint(show, MIME("text/plain"), Function) @test s == "Function" end + +@testset "printing inline n-dimensional arrays and one-column matrices" begin + @test replstr([Int[1 2 3 ;;; 4 5 6]]) == "1-element Vector{Array{$Int, 3}}:\n [1 2 3;;; 4 5 6]" + @test replstr([Int[1 2 3 ;;; 4 5 6;;;;]]) == "1-element Vector{Array{$Int, 4}}:\n [1 2 3;;; 4 5 6;;;;]" + @test replstr([fill(1, (20,20,20))]) == "1-element Vector{Array{$Int, 3}}:\n [1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1;;; 1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1;;; 1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1;;; … ;;; 1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1;;; 1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1;;; 1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1]" + @test replstr([fill(1, 5, 1)]) == "1-element Vector{Matrix{$Int}}:\n [1; 1; … ; 1; 1;;]" + @test replstr([fill(1, 5, 2)]) == "1-element Vector{Matrix{$Int}}:\n [1 1; 1 1; … ; 1 1; 1 1]" + @test replstr([[1;]]) == "1-element Vector{Vector{$Int}}:\n [1]" + @test replstr([[1;;]]) == "1-element Vector{Matrix{$Int}}:\n [1;;]" + @test replstr([[1;;;]]) == "1-element Vector{Array{$Int, 3}}:\n [1;;;]" +end diff --git a/test/syntax.jl b/test/syntax.jl index d934e9358baac..448595ff1a8d7 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2699,6 +2699,26 @@ end @test Meta.isexpr(Meta.@lower(f((; a, b::Int)) = a + b), :error) end +# #33697 +@testset "N-dimensional concatenation" begin + @test :([1 2 5; 3 4 6;;; 0 9 3; 4 5 4]) == + Expr(:ncat, 3, Expr(:nrow, 1, Expr(:row, 1, 2, 5), Expr(:row, 3, 4, 6)), + Expr(:nrow, 1, Expr(:row, 0, 9, 3), Expr(:row, 4, 5, 4))) + @test :([1 ; 2 ;; 3 ; 4]) == Expr(:ncat, 2, Expr(:nrow, 1, 1, 2), Expr(:nrow, 1, 3, 4)) + + @test_throws ParseError Meta.parse("[1 2 ;; 3 4]") # cannot mix spaces and ;; except as line break + @test :([1 2 ;; + 3 4]) == :([1 2 3 4]) + @test :([1 2 ;; + 3 4 ; 2 3 4 5]) == :([1 2 3 4 ; 2 3 4 5]) + + @test Meta.parse("[1;\n]") == :([1;]) # ensure line breaks following semicolons are treated correctly + @test Meta.parse("[1;\n\n]") == :([1;]) + @test Meta.parse("[1\n;]") == :([1;]) # semicolons following a linebreak are fine + @test Meta.parse("[1\n;;; 2]") == :([1;;; 2]) + @test_throws ParseError Meta.parse("[1;\n;2]") # semicolons cannot straddle a line break +end + # issue #25652 x25652 = 1 x25652_2 = let (x25652, _) = (x25652, nothing) From 7ba81e852695bb42a1c6d5f543bd55f02d799a2c Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 10 May 2021 12:53:54 -0400 Subject: [PATCH 371/439] [LLVM] Upgrade to LLVM 12 --- Makefile | 2 +- deps/Versions.make | 10 +- deps/checksums/clang | 118 ++++--- deps/checksums/llvm | 468 +++++++++++++------------- stdlib/libLLVM_jll/Project.toml | 4 +- stdlib/libLLVM_jll/src/libLLVM_jll.jl | 2 +- 6 files changed, 301 insertions(+), 303 deletions(-) diff --git a/Makefile b/Makefile index d16cf2855087b..4bd51f2af495e 100644 --- a/Makefile +++ b/Makefile @@ -189,7 +189,7 @@ else JL_PRIVATE_LIBS-$(USE_SYSTEM_ZLIB) += libz endif ifeq ($(USE_LLVM_SHLIB),1) -JL_PRIVATE_LIBS-$(USE_SYSTEM_LLVM) += libLLVM libLLVM-11jl +JL_PRIVATE_LIBS-$(USE_SYSTEM_LLVM) += libLLVM libLLVM-12jl endif JL_PRIVATE_LIBS-$(USE_SYSTEM_LIBUNWIND) += libunwind diff --git a/deps/Versions.make b/deps/Versions.make index 93d7be4a932ec..f2e4a821eb94e 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -15,7 +15,7 @@ CSL_JLL_NAME := CompilerSupportLibraries # Clang (paired with LLVM, only here as a JLL download) CLANG_JLL_NAME := Clang -CLANG_JLL_VER := 11.0.1+3 +CLANG_JLL_VER := 12.0.0+0 # DSFMT DSFMT_VER := 2.2.4 @@ -44,14 +44,14 @@ LIBUV_VER := 2 LIBUV_JLL_NAME := LibUV # LLVM -LLVM_VER := 11.0.1 -LLVM_ASSERT_JLL_VER := 11.0.1+3 +LLVM_VER := 12.0.0 +LLVM_ASSERT_JLL_VER := 12.0.0+0 LLVM_JLL_NAME := libLLVM # LLVM_tools (downloads LLVM_jll to get things like `lit` and `opt`) LLVM_TOOLS_JLL_NAME := LLVM -LLVM_TOOLS_JLL_VER := 11.0.1+3 -LLVM_TOOLS_ASSERT_JLL_VER := 11.0.1+3 +LLVM_TOOLS_JLL_VER := 12.0.0+0 +LLVM_TOOLS_ASSERT_JLL_VER := 12.0.0+0 # LLVM libunwind LLVMUNWIND_VER := 11.0.1 diff --git a/deps/checksums/clang b/deps/checksums/clang index 8d0505b5103d7..7dec72fad1db5 100644 --- a/deps/checksums/clang +++ b/deps/checksums/clang @@ -1,60 +1,58 @@ -clang-11.0.1.src.tar.xz/md5/b4cb0b74b1f3292a89c9720f3e1e2934 -clang-11.0.1.src.tar.xz/sha512/bb98ffb0a992c9907795f7bb7492196f7195fdb5e292e8a764a7a1a8cc078dcf60bebf26ed3db116f78b7022a600c996fd2645e5f6e5d24e4ed99392e1f08df3 -Clang.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/55c50726cd43c1b49a222ec92ea05431 -Clang.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/009b29068af7d8a008e34853faa3ce1e20817d3a7975fe4ca5657d1303e546410c903af345356fb94c88f8e95474895e68414a5a04096b2e9bdeed732780637e -Clang.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/e5d8d1d5364dba4c5891c9a127ee358d -Clang.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/a5efd0a4c0b05ab6ac55081a28cace0cffcd3eefeaa872d239711f667425808f29939c90a327bbf8664d2d065d1b807ed802c161599b7fbda29f554ba9148b48 -Clang.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/67716fd169ad7cb464a576cc10d42ad0 -Clang.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/5780d34b24fc786406f4f4f814ee6b8bf6366964d7252b61ea7dd3a09283ffb266270d76c2580ca1285a753d68922cd42d2d75b9527d331747325c22224536b7 -Clang.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/77e3d4ff674493fda7958b9ad950e934 -Clang.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/813a0cac9ae4972fe426451b9fa0d640f25ff5edfe22624a621cbbe737f7977259d062710f44475139c8298265336fcc67fc28dc7eeddd95039bef44dc080ac4 -Clang.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/e53b1db80024cc3a1152d7694291cbbd -Clang.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/f6b9c15655ca8bb54cd568728fe5ac33df62abbf07029816e892b0483afbb5adc69fde1789b90687137be491fa0351fa5806cf6d869232b3cbb4b42e1f7a5a64 -Clang.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/7ae72cb4b33be0250402f29217e32c53 -Clang.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/1b85e78a78c2bd437c3b21855bb36f8200543d0daa3c2d7be68d5c75ee06a74534e9b8b80ac6048fe05c426e441af3ff019076bf2d045152eb142d7d5769b525 -Clang.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/b83a93c3da36d8eb469f5fd39e8bcb9d -Clang.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/9aab7d5f9be0ce1580ed9d3b3c4da0bff1fff7094794d58620e1fb646ac7733708162f69ad281cd441c4cbbec8985c9906887f4979e5a5ebec8a05c6be06c91e -Clang.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/ea570204363ae3b62965a000e6a3948e -Clang.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/21c9a1418029d5ca0d3d16e943914d8a4932bdbaee1152f74af681349abaebfe4d87a2f51ff06196cea59363b3bec706c629d61f5a37cf0e75cd645fed2ae835 -Clang.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/63130e9a585a747e8f8e31a1b71a27b8 -Clang.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/27f3f72afa62b4f6c8e80d5934cc17119336c65ee070f05d98182e7e83fd02f0ab439a924165c7e6a414409eb2d2044ddf778c0e3e7a6994643b5d0d8b3e2ab9 -Clang.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/0d85a6ace70f1295202ba1c50c5948f4 -Clang.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/574c289c06283e8c2530e64bafb5ff606c27e76a2577acf84112e1ee9b8a3b299abde1e68dfd92700fa472dd6032af02399cca8b436136a5642ce545272398f2 -Clang.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/595279b252dbab5d6411db0d6a514985 -Clang.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/6a1e55e09cfc2325772f11a67f3e7e43872ce07fcceea6852649635778bd472e3e9e6cd0e7e2bf5dbefa1bf0862bae478329b8aedb48b4d7d8cf6ea074e98ce8 -Clang.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/6f973ced20fd2dabf60b12b5ff3b0cb7 -Clang.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/dfc77ef9b13111d5b2d6cdd4d27b0df086ee7a79b535bfc2dcbcc5d9014d0cb0f583c792f812100d64eeadf938645ebe3af72d2df45b396b15b3bc54a0dc3d40 -Clang.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/f96d5a441a56ee914372249fa0cb83e7 -Clang.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/dc2f4afbad26afe4eb43054c70674674a1258f6a1bb17ebd989179336e3de119b976c3429880b3e614668ec5da6c9401346c0fdb8fb45311e818a948c5a2e851 -Clang.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/7f18573c99258f1887aba30228bab25e -Clang.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/6fa4296f59515ca058d2012ab200e65d4c1f130f40b7a3796d4237f6bf9a72f0a3872bbf83ef1865e7c1cdb75de9c5dd3385a64c55be6741fdb91bd5ef00c6de -Clang.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/dd8333ce489719b53cf4f83300ec5c91 -Clang.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/356497a88871fa9a725d0206b09462cf4af96cb866724e7c9ca7a7060bea62a6b39426cb2a17d000d17b04052cc78893008c78b1a1c3cf30d6f84f10cda73fd6 -Clang.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/f82aa0d21872e9b50ef238d004ff28d3 -Clang.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/a2c216727acf6a42c5b914321541a752cdc3cc0b64ae39d1ede1588935ef9d8a4678e5d6f61b2bc1df96a1b4d63812c14e5e6adec7f2babc3175ebfb72421334 -Clang.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/3317c99fba259bddb9f351e79564c831 -Clang.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/bda2aa0decf76b787986a9a308a3832856cce9545b2c75da49193f23e64ac00dd839d243aa85737f28288c284b9770c1f5408deb4e5440293262d14df2ec759c -Clang.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/826749b99dc7b5f24bac5d0531e84468 -Clang.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/e15ba270c2ad915be5d0072830b97e4d66daa2e18b3ba4db8f9687633c3ef0dfc1ee312f4fbdd1c921374709f68cb1b4bc9e58b9ffcbdd200c1eb665fa9a595b -Clang.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/2f217eae89b066e190243b1c120cc46a -Clang.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/526846408cced1707b85f1e40796eb1607d47fb1509435fe7e28368a74e84fa56276aaf9fcab47664615cfe4349c7af3b1ad9995126e888e9002e1a4d20cb1cd -Clang.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/6b6472551ff2e00249fb39ce80df330d -Clang.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/1d2780eb20c2f43659ab2502ff88334a7bf827bb533d37de058e524e9fee9a8ace431761495e93dc9564c80e94aa569066c235bc958cf893c4de5249c4a12676 -Clang.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/74cdafebc133bc54bffabb40547622db -Clang.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/afcad373d30eb465964e17e70b66fd3ea72c1565b1bceb811d82188368a788fdf6a18e388be6d329d9a632f68890d26b878ac0e107ec975b93fc1aec81bab89e -Clang.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/a4cb1dfe2b86f24b52d730835f8ee31c -Clang.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/4526942c33bb4789d3b5975023abdff81d747ecc26b9863c7ea61f87550506d2102a8f83e21085ebbc743ba2be8ddb2b6d4e12a65c9a58e02f6254a335d934f2 -Clang.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/b9bd14c451a9e8efd28c916a85cdb442 -Clang.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/7cf7ba37c600669f12a74e6760ee5b166b6de4f7e817b9ddf133275a242335ed9a460c226a3f4102cec47bb552d8258b34cf3cedd35b16756f1efb5a3608250e -Clang.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/9e930813e07758c80ca7a1575886afc7 -Clang.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/e0dce74b7377256fa65f1e6ce461ef5a6424b6ddb157be36393cd8038153afbecf460c966979e267d1de5cb0ed4509a093ed58210eb3cb69391d16b938a4e7a4 -Clang.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/6e345f292464e430d3408826d0ce9573 -Clang.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/f802e46a46a2946641f07b8b2ef41fee8efbe98e13d23a8ee01047831992b6f115d157520e44879978e27e994da4b63c1a09e6ace63b7c1a1f6351ec04c4885d -Clang.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/ec61190097b601446985c96ca3ffc58e -Clang.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/00de2b64bda05e27f5129d5702894823517f5da01a42892ee20f69e55b6004b0c1020ecb941330243a565048ed249d827612dc3ce69687401c731ac168566049 -Clang.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/dac3f7585db42a3e8eae4d563abc5d68 -Clang.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/082ff3234db9b36346553b5c97d5b7dd55f7458aa4f1f1d358e4d4ee2c7805525514c18c35d319a22c56e6c3bfdd4160ff0a2157f24e1123c5879d167f1a2d13 -Clang.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/81aa45c118d96afe17accb9a0e02ea49 -Clang.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/240979d6e958ad75b6100b5a4fe650c21076dd06b8c9ff13fa397b34bf9816d2d8b8c3ed6040235ef82d11d885cfbda20e5500af3ba3034442744d201264acb0 -Clang.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/b1695d5e231249c07b5cd9d868b6434d -Clang.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/24a33877f7b97a67cd8acc21ce23d31802bea13f416b5bbf28c262277f4a9e8f6a2cdee642d4d49b7d9b7948bc538f3b1bacb259ab0298e58db910044ebcceaf +Clang.v12.0.0+0.aarch64-apple-darwin.tar.gz/md5/980c74812ecb2910ce5ff89f50adeb4e +Clang.v12.0.0+0.aarch64-apple-darwin.tar.gz/sha512/3d732de9268f4ee3550cb8cd25547025f0c3c2b42733da68570ba40906aac590c51de8819f1643d40f3c2310f666eb1d5adff6beaf1a811e1358f71a2b2e693e +Clang.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/4cb0061a62021a9f2e8c4c38cc116a32 +Clang.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/628844979ab97b7e95578cc6a2f01be4853e2e451321baa209d8ef80a3a77f58403f8c905e89ac48570daeae72b10a5dd21de948cc3e886918eec67f87168d2c +Clang.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/98216114af0c5080f2054012986df84a +Clang.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/8f615879985a7840b0c1dec53aaa4f77025464cc32594e3dfd7148ce36201cf0221641fc6de867f605b784d98a2ab360c1aabf1bb98d77363e35d6225f4bce17 +Clang.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/f9ac91da205acb64c95dace753035a45 +Clang.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/91739206d79d6c75586289205a40c71b922cd42c96564c174b0707a7cc136e77cfbeadbee820ec7ab0e0bfc36f481b88818d3579a205b2d6ae65d7701eb817e6 +Clang.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/7679a6f941daada0225667c017fe50c6 +Clang.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/aa1532188095bb73dfcea86dc5965302b6a3099c4c95787c0b3ab01ca5c53c7a533325308af6c109d1aa50f69153c57fd5e502f41f2af41dbcf3b039d5f1defa +Clang.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/01056c4c0a86f8684643a06fefa92f27 +Clang.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/bff88b75e7214135cd6c9e797c47cc5dc2d3f2b9bd8e3cf9f1c7ade3bcb205ca916b63b5c6f2067f4de306dddc4efef36c9089a49562c8d656b95d45c957cfd9 +Clang.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/88e9b5fde388021ef88896d39968b3fe +Clang.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/aa5ab4375f532629b22a81d927a23bab60c819ae16982a1dc797a043fd3622d2b5a9c0e4f3195d2974df3383438a844c276efe3a60fee1c99ec7d3a10064cd45 +Clang.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/4415d5e19f1e4bf2719b4851ca428ea1 +Clang.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/200d43017d05ca59374950b557eadb5f2630bf70378a2970dbac4da2ada8e2428c786b9f3c1a2774ed863baf34d8ac667c294c2bb46e51125c40a3aa0125b596 +Clang.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/c8b618d1fb0685f0023c3440918923a0 +Clang.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/4b85961d98cd47105cb88a187ac52072af7af27c81defa35b2bbf36a0841c0d7745a294373fde503989bfc22245ba45a1c9d253e7bda5a28381dd6ab9b677238 +Clang.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/d6d6a8fb56ca4e44304310f5ce7e14cd +Clang.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/dd3a039d3a3099fd8e0f135443ed9145891179437dcc1cd851da3b54d4815058190e2f6ede97d2f0357629e0d173395a86537732b0354bc87ae5815638d402ca +Clang.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/f0431cd3ad402d8faec1efcddd7f7fef +Clang.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/0d5e7b96a15db5bd09457aa27aefd05b8f530ff348956ce1699503a03adfd6abec84fee080aa5cac54a7d4eca42730f7f9cd6b13c23e3b13f4d2392f08fcf688 +Clang.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/1579ee70c12a5c38f84e9c52610b196b +Clang.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/91841937b8c1e3dc4c223a4dae48e7d4fa307df2cc692e512c469994bfabcba897078bc95c4141e5384f53be31d160ee750b60382005d7e5acf99532f47b4566 +Clang.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/75aaeadab3001679561ebd56193cd90c +Clang.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/7096f0bdb478c2cd76cee8f3ea47ecf8565af0702901f5c6351233458d2c66d3ea61e3f065ae9e90960dc7e0bd6fa1a0c6d160934fe409a663e4eefa23e6c5d6 +Clang.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/md5/987c4b1b50d9bb56e598839e383f79b9 +Clang.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/e3b827ce6f250a2264700991720585b154bba9c6713da7fa619a5e9e0829c7b02b909e3f73ab9149f58de2e27566a7d47723043d6de5fd027b1233452bd1d2f9 +Clang.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/md5/e8297a60b87199cab225418ec49503ae +Clang.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/9b341cdd57982d269df2d8158a5101f451f09031e1e784b593c78aa272c392eb7328b1c328a2f29d494b5ad4ef1e1ef96d01772f176be6395a8503f983e18d56 +Clang.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/md5/46f27859be1f7e162499e846d9532a37 +Clang.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/sha512/5173beba0ba2423c978cc3663e3b6673752efaef34547efe1e1015a18bc5cb1129ebdec3dacbe9894832601d87efffbebb263790d88ae198cd985636cba3fdfe +Clang.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/md5/00ef76971a4783c7e63a86ccae8b15b3 +Clang.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/sha512/f5e5f89f541df4b1da164392da0ea5397be62138e203f321b0b771942646530acdc621ca36a6e6c15df32c0d722fe9b0b5845c7ac58bf24966ae503979a6e8c8 +Clang.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/8761cdd4810ffe1b3eb3537fb3e03218 +Clang.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/e5f011a2f74a032ef0ac429acc615b02d3d6bc07271acf2279afd947c1151914533456cf5b111ae7f4c868f7ee739ccd9623ce3ca2850b3cda3db53bfddc8aac +Clang.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/0048f8c3014f9baf26e9d4e10ea2a893 +Clang.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/9ac2b0e47d86877bb47f5ff1bb7cfef3c0dcbeb813c770c29e2fac232cab0c06f39b5b2fad15d975d50a9590e9cce3c251e3a3c6ebd87b0656c93ed14a08c901 +Clang.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/b5833c865313b442da0b8bbe47a7ec51 +Clang.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/ef2c7cef9703248a0d09ae0a2b1d09496575411d6a846557a47628c9471824ec6f8b9ec361bb0c6bfe1ad5c27c1160900638b185cd46f21ad0eaf341e9caf600 +Clang.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/e76c4776341d23d2f87d87f2f9b32acd +Clang.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/e855521dfa1fb07fdbfb3afec0bf27d346bcf316c68dd0b3898ecee9d2e79f02d7bae9763e1c046b9ef6730458b40bdf35f737d0bece9a965c68223c6e1ada96 +Clang.v12.0.0+0.x86_64-apple-darwin.tar.gz/md5/d2522f901fe5fc2f1dc4c9d3c0a82e29 +Clang.v12.0.0+0.x86_64-apple-darwin.tar.gz/sha512/3efb4423573861ecdeaf0a82e7c15c1cc767016ceb9e9a5132a7ecdc2075bc0d8e8326d6bf9e02b649b6c324319fcea471d0e1727e595515488be7b39cfd07d1 +Clang.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/88488b8e890dc41c7c6ac19d1b405a6f +Clang.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/dff87a31cc19147c9105ecff15cc0cc671a0f683b6dd3d86446b6a53c745256ebd1a951d0b83e26ad2e29aef6bb044b6c00d30c4647a3eaa0cad45fc1fb70f20 +Clang.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/1b5bde42bd922cbcc06ffaa5c96f3664 +Clang.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/af499fc2aa6b35cb67414782a9cdb9e21dfafb2d5678c7ba9f95bbd92650c8b7f90879f86ba55b445ce4a42947ec495c1a6fdd6e768742bf8c3cba7552e2bd4e +Clang.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/a3922ad0741b490daa6e21b91056324f +Clang.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/257732327901f32d3baa7e1fc202f266e578b5bb9d929949a900505b664213c9c8c132b109ee93f96c37bde3c4d2c7b806a45f44e93f55af1973fbe45c47c621 +Clang.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/42a813253b2f820bfc4328c55687b096 +Clang.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/ab4843e2d252f1ad6435d506483c29c752573b6be70c363a3207e8a45d09850f2cec5381ac5491694e69ede5cf0b102f61e5f54d7bce81b049bfce9b6552e194 +Clang.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/md5/b17ec22a9dbb88dcf956ccfbb62f6609 +Clang.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/sha512/d885e4a50e6f57b8314752a590d5ae72b78eec3feb838ad1a66116cc2fb1b4254b77ab36bb86de416ad93e58dc2d60086eaed27ed29399f200355191daf43123 +Clang.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/819b09f861dde64cde72c061feeb1baf +Clang.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/4f2e8c402e2a184f115311f129fe731b6445422cfcf7ffb9b1ae577e9588f5d0de040ba6c3eac3263fd3d51cbf10ab822bed24be0a3d8766084adc23c04b082b +Clang.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/080587a6f5a463efc06362d40730334e +Clang.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/46e47a06c996094b385b5939e73ac831a0c08da7e113683433e0e559a5627c43242311be0d6f2ba992d65bc3b5edfab3045b1d06ef26f6b87045c14111845260 diff --git a/deps/checksums/llvm b/deps/checksums/llvm index 296796224f288..aa0124f257b44 100644 --- a/deps/checksums/llvm +++ b/deps/checksums/llvm @@ -1,234 +1,234 @@ -LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/181e555215a01db6017bef6b75b857f6 -LLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/7940b4494e5806319d013feb42771884c320b964fc674abfd8979169fe32bfbfa03558195e520a108fd645a4c7a06ef918d59cd411dbd086b6a46f80e5ff2c9c -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/b02bb670ea84bcca20f318ffb26a79fd -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/f05004c2fd6fbfdfe502e4f83babb7c29f9863e900e711c86023e878808eb1a31ff0285c3288a616a2dbecd7dfe3036fdf4465a64633af723f10c2fce68aa84d -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/9aae2250dca2c2e8aa305d0175596fbd -LLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/0ca30244061b3bd6f0b0a6bbbf61fc40b02db00b3e9bca4aa79013ac12137aa7e872ba7113c6bad3ca08225431a9d9a4d2267852606e8360b866e5752f027965 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/f3c3b9667ec2ab3dd9f3663859a0a736 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/5b1abc1967009154a71fc43813a80d37e1c8531575938b2682212478b51591def16a7141292844568ce65f76bc686a7e9f7a4d77b9311a57226ccd43d8494d48 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/98505793b877160dfc7466284fea9e71 -LLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/90a0b9d8da40eaf29d9d7448a3611ee264eb90cd947fa68a6e5e2757d580e82bfbe8ffe3d31c2c2f1eade66d2d4b69a7dd79830b813b62ac7bba289281325559 -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/fdc1abc12cf08fae3d4e110976e5967e -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/6157dec83258fff29d54fe2f3783a7975a4487a5bc1b98f8355054970ad958eb26ee11f7a2f60c5ab8ae5c8e799275fc712051b00039a14febd0db66520d29b8 -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/2c492cfd7cac00863fe373f8d91ce84c -LLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/654e9842373cb52114407340f8cf4c5954966ba677cae9aa085e22a3ed167bb1670286f3f3dcb6798913fee45937da0327817a97f48db021d997c22862b039ef -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/81b6c3bcb6b5e595f5fc12aee8596bfb -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/8360352c772c69f9cd9469b41ee7494534248ae0480f7661f9303747cb3a87e26d5659fbf32d7dd11ba70b4f24812cf94dacd7565b92b42c9d63da388b8e93e0 -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/c9559f735a8419e77a874dd75451d726 -LLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/64cb59c966a1f42d1f31e32cf584602cd1a6a3bb5c3d805197c8e3cd96ebfc1ad3959bf52be2767d88110fe0025307f1e1982e9029630dd5438e94886da21366 -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/bacdfbffc987ab1e4e0a023c4f1cb636 -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/d9f772a958ff3621f10bc562833a7121a4b3c3aec8d8d03694554714dd54537aa89af0e080f16ffdcf965ae33bd1bb05d9659beeaa86ffb7e553a4202b924a0f -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/018802fd42e68b24459c4040df0019cc -LLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/ddcf9f104f47485cea67d0e5862393c2161e6aaf2e1cced1b0600b5b2dfb3c35895d00e47349de298cc9164665cc8cc8af3249997b716872fe23bb58bb1ea370 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/dc1ccc83441df682b09624bf7047aaf9 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/b717137c831f698cd9b3339e5beb0a2e9d6fd8c59961f91d70b8e76d8b1ef7bd9ef610a49d02d45bd6e7130262f37601a780e33509b78e2b1caafd40eeead7d1 -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/74749fde3378518041fcae2e447370ea -LLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/b60715831b4583679455ceffe82acc19ef6c7fe3798b02f3df8a08a129a4f80fbfd7ab59c663db4f4418285dc3551e536c3edda2e24310d10cecdd89596588fd -LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/0d403181fae7d966c536ee0cd6e39c12 -LLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/71728fdc4b559df058d9ddc6dcd1dfae4d2dc854e2038ba14baef62e1cba7f3e2c7565fd2942b069690497989e846d0b5a572e0bbea8de7873752e43bc6827c5 -LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/791e288d0acc976ddf18776540b21ca2 -LLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/49dc3c9a2952f928d51c0af64c9f87b441c05a3f7c497be7564052936bb44c4e5dbc05dca3b69d9123d784647f6ca1c528ece5bc11ad39059fb8d465582ff394 -LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/da303f41ec8ad7329e826a5e94af8889 -LLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/39deaf22f9e5c2422eefaea6d64c8d78d3235385edb43ce050f8f34c5c9d128c7b155adb2af5c1f0653f92932324f9a8a564df6dc97009402842e98b4b9a17de -LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/3c5c77b8534eb0756c112193e4028838 -LLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/9b00f22b169f17f1766e40da5a7aee602cf0b1f34ae97cdd02f59f3f7613f192dfa6a0235764a175efe4cf1ddcc1850d37052ea45e16947f0d1ad79deb6812d9 -LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/757aab5c47122ed033f987847a95ec0c -LLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/de54c3f21959ebcb081601deb01bbbafe415b05cc7240fce230483b2901d77f89575a74384fb55c919bfe25a8ca8cde2f2e0c6f4f6a809fc73499f4752f2043a -LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/c7f3d289428d68802eaea4cae65e043c -LLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/54fcb15fd2019dc0f5c3db10c24c9d21d8159e923b215dd000d6107a136b69ff240bc447b2a280a023f25e98880a86ea89cd42e1e3caacabeb59a4ba18b96d32 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/a3032d9310fdfcea2c0e6aa2cc27fe49 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/a8f8c4739b17f902f08307dc2f154ebe90a229299d476d8723cffe504cdfa91a8c36aadab4c12c1db4ea8cc056de17b66e68e1f086ad5d30d5f2edcc53da2337 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/ba581dd66006b02e1e7643b93af14499 -LLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/8037109625c8cab5e310ff95aa852bd792b35f04b6830870962add89caaf0efbe001d08d6f870044e998a7b14216700a806eb132daadc5c4accd77baeebfb15e -LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/9d9c737b6e98a41086a1802283730757 -LLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/b24025364052233f977c17bb5f9675b4404fb4b197f35752a8a2591ac9786eb8aa5b4053ca4269e6c4de9daf401f88b0361880c3b3201be2db91626f9cad9030 -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/ef4535f1aaa5867e9dc4401e894086eb -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/a1d7e4bdc72f33ec669023c89d4dcba8bd4b644e7c38e27784ab0f052e8efc08cb0cb89c38d5ee471961c8c8bfd6eaecc89898e70093a494f6cc53b9a36652eb -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/bcae5538b46ba7241b429dd568faa1b7 -LLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/f336e5d7d007298027efe39a9b50afb32376d1361622097fac6a0530ce8a834f0cfb6d8abf05cf964bb5159b0864bedac978fb95031cb84672e0bc0b037d03aa -LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/353ba4a877af02d2a986cb4917fc6cbc -LLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ea038f9a12a84df32e62d877320eb041d2363b1714ded05508b1fdfb2a874a6964114833a7435feaad1040fd31a533acd29e48731f49e8df3b60fcea04f565fc -LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/81d43dea36a9e2ba628263b1af36461b -LLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/a99b2dbdaf55cd36e8ead346fc7fae4ecd430cb98895343d6a409d0ea95406836048638dd5ab73129a2b2a637abd1e997515d8de1e9e5e8449e0f9d747773d4c -LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/0f83ccf57dcb7814976a57c42c91c454 -LLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/06c3a97b6ec4f9095e8e978ccab0e65e03d26f99d90485c7893b6a41a53a4e5a8e8e531592e20f9d73a1100fe87f7fad793dc6cd19b09ae0bdaec5c362b7b4ac -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/8db6882c343f0ff1ed3137c1a17a1676 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/a3fbc239389eaae152f4a21e5b50b6afd09adeb75d8e32754dfba5da3815991dd05ef5c403ef9539bdd47cad3f9b2c7066a61e3f40243f7bd237a7480172be86 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bee41a179343b54359aba1b159110a39 -LLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/3db19d091bd52cfc2018a25f28bf7714f6337bd93b24349ad90d2954f60317189e5e65241ff114c9f7cd15933b685f0a4a193d45daf21af593fe2890ab98843e -LLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/574a70c914cfd54913a1d530f26a3961 -LLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/d7774e12566563905079699b28e056f403dde49078fe49b5e0cf4dc56ef1db457ffcc45bb0fba380e0768c9a5e5eddfe88fb1021205f6ad6565b3c6dd2e07dfc -LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/6a6866d3f5dd438410465ca3c75b0af0 -LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/ebf55880264d68876df2a82e3e105d13834fe379942270c5b054c50f7eb3c8f4b821ac171a7081bb378b178ca386c608c1340db6d693885bd79d53f958c9e601 -LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/a5623a828b84769cac493494c9c6d3d0 -LLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/410ed00c107a6e05f322d4ea6eca9f16f7e4e986c335201e4a7092cfb20d7638fd9166176414dee782d0e656ee4b2252eea7055dcc526cecf6136ff47033dcf8 -LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/bf3323c7d6480fcfd75834e3240e7582 -LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/6fcdafe8de348020c4ecd75fe3ab0a7fca833b97545a4711c74a0f7646a64f302577c5d4bb55a77fb65b4d78dcabee670ea6c01f88c8730a7b9cc4fdae824557 -LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/fdc19a6e662037860b0a17d9b6c3a57e -LLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/c30e08f6f2b926716e4e8594cabe66ef555eaa1f0cfa2ff578bc7fc550facd7a4c72eb3315dc68b11a4a76c62032bd7d6ca42ef472bafec76e1354d51276ac94 -LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/a570eb7a0a54a2175e8d65ba4d575bcc -LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/4944957b89ae0b61cded44f2fae879449a3d0bded0f4f515f0d1cdf6cac8bf834f5665b8d734e56e4818b07c639cd2617e033042fd358888a4bf808be1984f43 -LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/f5adea7936399d7ab1eaa8b71735e1c6 -LLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/40daec8c3dc618e54032d645ab7d5914d1be4d02e16e5368b68826bb0c34461c767240535f757cf83afedb36b117cc809a371d7ef1e7d369d3d9ab19ba293f52 -LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/7b4759412d408ffc5d65295f2f6c31b0 -LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/f074208696be67c8107c8a9d188923642dcb839db82a871c5ee9778295ec5b18f7a7135fc65e4a0ac51cf20254bf1902f83b347fd10fa4e9c618acc9b52cb1fa -LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/d0aae4b55b3940727c4f88f7003e83bc -LLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/ed62c5f919dbe72991f8466ba35ccf4be70e9deb4fcde47674acff75a7db7e5c4c4864dc3bb8869185e607d6e7be318b6f164465cb36b24f09426348701f51d6 -LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/f213dd3241c44763703a140528a05005 -LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/b2b56174fe9c5d6b8be0b111e0326c5916b6c7b97b8fa1c488ac5135a27d522d2422ed833436f49a76effdf575b8709025cab73a9487e895e3833d98f0d7c164 -LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/84f215e794678522449f8a8de56d9372 -LLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/9d2ce1d97c9323481b6a6a13c8b3866772d3e9047b4969e3715867de903308887ebcf7fbe9c417f5a8f21e9fa3e5d6b0bc72dde94b441074d0e05aebc5962d5e -LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/9b65ba3b076d4d1d4ba9ee6eb332350d -LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/cf952eaf6bfc00e346985ff17165349309e9602edf2f44991897cdba4f1ed59429792bf7fe1d32e27674f7ec65926cd6ba070d62f35c812876ab685b517e0b49 -LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/95986e68c2d10a6231520d727cae100c -LLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/065c99fcb52ed9e0f750715412f7ed80ba994dab3d6618da768b65ece144b6a17d4032604b47436f02f69c0f98b628245324af37c06a85166baa673bce2732f5 -LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/9388137e938f1e87ec0f7004989e29c4 -LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/5391a1e53c24456d9062a87c1cc7213a3042e56d9e97a2b775e77af8596c1acc4b1fa0ae860db834ed8b2033257222b7993b2edede59ceac2dc468a3bb590b20 -LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/ec4c8597ab5a356e53d405e2d2b2af00 -LLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/0b088ea2a639d17945c7bbc52505c108d12d9ce3c22b4083c98ba47ce4450d90dba025491a3fbebc6a1ce7a8098b3655f9cbaa828e9159996a8f735359fa5efd -LLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/51270032209dbca8cab5e083fc1bdd74 -LLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/7eac24bb3aabfbe3bb64c4a28f4f8939bbc6677eeb27ed377d69ecdcff8e7e8cafd792181db41873b09ede991b0b5e02d3bbab5d21da120d2cb573fdd4849bff -LLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/323faee592864ff277b73ba03227d5bc -LLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/a45f96554b234ea03560338ac4d94af292af9731bf9022a30dacaf6ffbab293d599787f8aaaadb95de2364379037953ae13864b6fd4baf4281cb565589aefb8d -LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/6fa5b4a5c945d91edd07ac663a7c9b32 -LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/0e1782adbfc5d27c3bac951580a8bcc0683963fda9f9ea5b98d50bef11e5b4d61d59216a24006e23c467ed46b7f0e7bd4223bd9732642e729615dcb23910126b -LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/7d17ae9f78a02936d4c5f4d764940444 -LLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/bed864a3b8fbc6a178be479bb4ffb5c2fe8d24059e08a626dfc6b8bd75f8b7e7bb7758e38aa5da98e4dd1ab6e3179b3a968fcaf309a06b4d663d0d0819053241 -LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/4e774c9ecedb46eb3ef189bff2bfed8c -LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/de1220a01bda6065cc125bb968de7d7b1c4f54ede47e3b411dad02eab38d620ef2016ae4a71034ce7c4d9996b615e190c6ad373b31d045d3e3e78f6d19d9dc52 -LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/2559547bb81c94199e3f165983be91cb -LLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/deba81e6bd36e0bea4a5627570807d9942adb578f79a7a0bb32f5e489219d1d0483ccd6e5ffec5315b1582fdb50f67a985af6f738199118fe6aa7da6d4838f63 -LLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/8618c79f170124dd5e585995fe028d45 -LLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/68fd57412805f12c81525fb4ff5d9a3223b3fd435f7828d47f914dd5af7d6ed546d0b37b94bcdeb57fd0aad7ab672353f547a62af0b2da5f941b5ad03b65a00f -LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/825d637c6c1010431f567505b1639766 -LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/42bb554cc858b8af03f7f3b8d99ba017a5948951e1b653478e52477eba8a93e9d7a2dd9e50cdbc3ed6563483b01b12b5142a7aaae3534f4e5bc88b5e9298b3f2 -LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/dbf66bbc19a9c4331820e570e70456dc -LLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/914e4831cb6873555739a300454cc6123634232a4bcee2bfad6e405e4af8e55f36b05ea4d164803b1b46ab6efaf2e38e6f1322962d044a21a070b53b4fc749e1 -LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/9ac711e2feba8e641601dfa934499478 -LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/f6cd0b432e4b19b2e5d6ac48aa2173d606a1126067cdf8d35b32dcf0cf8cb032a9ad537256fc7e16fab3173147240589969799c70822b7bd126c60b66566c519 -LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/e0262bcc1991c3d2818e0ab2cb06cd5f -LLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/cbe609b686ae5a09fa54878a8557e294331e3c384a7d4a6385c9feb66f0087208399a0f7b55adb267a38704c4fa3850e7254dd8454f78933a1bf24fd15dd1f40 -LLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/5b63bc9dbb26c2c707391a0a245e9f7f -LLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/6dec55c91ae2c2384eb1915ed1377bd987baa82dbe6dd2382ea866f2c02a8415a0b0d511c1ef21dc034b199801523d4cc9c0e4b58c6c590489f375b8be845794 -LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/1d14014582c5fc00067a9c7383c9cf63 -LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/c304544b642a715f99d0b5f50e8ad55b8acf79af64169b7f1a6e3ae75d61317991afa352b5d078845cef20a800eee36fc0b21340c6616c21b9706f704b8ad7cd -LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/1e7dd492c73e042da4ab0b15f885add1 -LLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/94cce6053b3d8cbafb98d7f737e51f04c044376c3203c236d228ed61d0a65cb136d0dd355609fbc5d4746794610d18ac3aad8168a61809e4ae4316dd51147587 -libLLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/7b2400d9ae3ed7a9091011b7951c8ce7 -libLLVM.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/9078fc8c24d1749b303f5c7843bbb6b5322080e4adfca0b96d7757454783617253dfcee07f24d1adaf3768563d298029a69bb75d39dc0701d024c27c66e50fd3 -libLLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/712ea06bba40025d5ad86229585e1eb9 -libLLVM.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/6260d68dd30f8950370db956dc85ad9ba1e474e9c27781ca2640d8d669d3fe34fdf2e020922e4f11d88c4394bb1e72f81f211e656684682207418b954f78102b -libLLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/941dc9c8a4d11cd7cc0bf5edb47ae822 -libLLVM.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/0ae65d99a49713aaace58e31f539c07727c34f30e089134c64b96b35dd061f44fd9889372364b1c9a36fe295a005160210cdfdf937c23e834ffa1b4260c6705b -libLLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/1bf46309788bf2827e337376a7a7355a -libLLVM.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/86dcde04d89730219b22dd67ee113942ef689125cfa6d3c5294387561b7771caf948e889a0cc93128159427704500c793b62e6a6cd39a372ff6be735fbb0fdf6 -libLLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/09e727bddee3132c944ed1404c421c2c -libLLVM.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/00a5f853557ca1f65fc807d3109357b211ba1935de66e2d3b59c8e00b4837c04b2ea72d6c6417a8fd788835938abaa8a4fed9e36d3f9cc009260150417465d72 -libLLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/46e656d8225b534bfcc01f7ceb8592cd -libLLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/325f4d521fed87fa75b296dfc8ea83e4fe5b04e8902f66d15d2f020b5b32236184a7b31a92eb5e0acc9597b1a21f94e6b4101f9844615767b03e6c2782c08760 -libLLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/26c52c856334ed443dadb7874a808946 -libLLVM.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/e1bc796fcaa258e8c650c83c0b533f95bfc932c389d0ea507fbfecfd1d8829e746d53377508f909971d83b4247a0b31c31d2d1106cedc84234536ac19d2dc37e -libLLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/c223e17dc0eb63e02625ed269b5c4064 -libLLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/90d29712769299ff526c7c7a4307bff6e519e1e5d991b4bf4279f5231263eae6103f0887ed2310c45052c904cb05d5b059ecc3ae0d124540fb0886f8c9cbf61c -libLLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/54def908d9d9d93e0c16770344761dc3 -libLLVM.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/d89b9ef23fd2bc0f974e343cf4254747a4ca2918bdcd9080846a56f2580626b80c7fe326488083e57330d857227e7bdd43455fd5f6c9dc90fdd0f9eda3c751c0 -libLLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/c927115d9435d5712dfd6aec848404b6 -libLLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/53050300ce37e79900677b3a447570b19518bc3ab0d13958274544686bba378742d7c6ad87b850a63f825a5fbeca0287f8b67332adc81962911e43cf952c9806 -libLLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/3dcfb85331c0bb7184bc10403a22447d -libLLVM.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/9615b09038238a1cdabe1638a5550feb8498c9889cd805c5876350d7d5185a4ba467f2a97d2c4e192adfb59cfea76afb109e3c9687de183951a535b6b8271d5f -libLLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/8b918180fafba11ae565771ed6839d6b -libLLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/29bf5de468872c0eb90603d2981e891536da58d60bfb2d0c095dbd9ad7c3390276117164077bb89f95ed3cb21a03c0e1245c4a92cd46bc9ed25e4204fdc69e8d -libLLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/3f7054e973baa77535629c08f7b22cab -libLLVM.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/e10819701d77d14bf28bae2fbd69ea03007ee6cce1d6c54e9dbbbcc5dca8d6c2351ee21007ba19da827c445626f5b4bb7e345d54971ba1a35e04278ed9d9b83c -libLLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/16c1530e3df1d137674503bf02423ffd -libLLVM.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/8284f5a7cf1f0fa8664031e16ebc12b7d5131de8efc7bc9e77fdf33a084294e40917f723ba9b9f56384f527ffb7bf4c7f04a2dff8953d25a2f473c90322f61d2 -libLLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/81670b1d368e9791705b71ae56373952 -libLLVM.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/dc0525dd275492ccd24533b89aa91a85660cb30cc3eb22f3c6fb10c854c890b5103048c802e06566aaf60d70bb00806ccd0552945573b78cc797295918968fca -libLLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/827cfc808c50b301c1645a21327692bf -libLLVM.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/dc504771c7cb465e40e4f6ce4b62b1f5114018209010e7bb199c2753438c1c78534d1aae39246d06fdca96f799b20c89e20a51cbf06a9ba318d0ff827d3a8519 -libLLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/fdb9e3d33d3b0e2051548d6a55d03daf -libLLVM.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/2cdf2fd7706c4e4ad80b12f6fc77a0389d4d015e3550c346f17fa0905dea058eccdd8e5b167477ff8ffb74cd1fe673af5c7ae5a13404da0b59232cb0e66669b7 -libLLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/f486dfa62a336cd7d9e1b00602fc1177 -libLLVM.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/8264c0cbd63fc4dc17472526723ce6ce4072b276d06a95156a259f8f2b2524e1ac6c5ca768a974f8f1b65bd0674336f7922225d4be5edb90680e549774f7d05e -libLLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/fbf1949afaa7e4d14722fc21c3dc7892 -libLLVM.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/3c897e31218f1975456d2769678f99c14b6308a464beea2fa6a4f534f355b5e9a7ef51c3f5fb0f44123ccb3c4854b906b96bb35a9ec01e1a1f39df903fadb30f -libLLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/2e82ea13c59bf22f085768766d6dd8a4 -libLLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/664323d8461e5c64e26d8fb84d3d4bc68a8bc2020b3b397545aa651bfdc0539b83ca2c9bec80314322ce821ff225ae48e96521e23b159a684e74a244bb02bb72 -libLLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/04f3934d4421e452673e015dbbe052e7 -libLLVM.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/b8a0a8b6c56dc0ad4b6e179efc8461e69e01e69de8dc02b46644f74dcb859a5d6ae293b38b2091298e5024b7bbef041cb5332b095e6a3be9e44fcb8c21b54353 -libLLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/487f852d540a46d03a804318067cab8b -libLLVM.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/9158b5c8cfcc3dd75d835d6fae6b026bd57aaa60e8685d0777de8b31c5b644b40ac470a38632f6b0aa5eed85e1d001d3789a7f2989530f03f5e8dd95b947223e -libLLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/6f73bcabc8c748b997ce2d9433e7c910 -libLLVM.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/3152c54501343e575dccb928e55f2624340cf53e84dd67cc606e8a6ec18bd3b8c4121089962fd99af54acaab70279172b65aa35fb7ee50b53cc83db188febc07 -libLLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/4036faca6177ec29d38ae3d93e0a757a -libLLVM.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/0875703148d4f3056731247a6395c268e7a34edb5b25c9e1cddf507c13afd2f03d261088129fe822028a02e34842e41c48eda20b572b33d714d17b5b7c6f549b -libLLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/b1aa10a625f7e069023e10fed0ce6ff9 -libLLVM.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/b196521d0fcb830f137d4d67526a3fb46ae0f7591f290e3e0e45c7d2d412518d6b29e005edb38fc5d56b987f5f47f7bd272addfe0cfb1a9e41752f028bd0750f -libLLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/154eb676aa0b1fefe0f4bc2418deedc7 -libLLVM.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/91a79167fd025092a8f36cc37909a2b3f2591cb2f00809a6846e7abb8a41aa1c2f0f0c1e29d4365266c79c3cbacdce2325b58d09b1250806ea8f9e031a7b4c75 -libLLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/1a566cbd9e79eacfc7a76ac3defc4b6e -libLLVM.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/535a4e7c665d34e59b5490066373ce21c400001ed86e38b4f5ec7de9ea758b91fc58dadadb239213c4e27185eff33a29466250d978d3dbfa08e794f50ca6c3d7 -libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/97e8cfab218937f77421285f0dab30ad -libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/cd514c19006f4f997b8530109a8b2f0099df1e0af7c0e5fe85dea65b01056cfd2b959190e17a3da8a3a223c59859aadd7486d1b6a71ab3207242e9bea891d546 -libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/f4ab87e307e014acf4600dc0a1d8120f -libLLVM.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/a44840a51cad8a7d0db296a3f3613372562c3c5464bb2f1a8e0352d9e521bcaa83053a70d0e369d75718cdd142584f24bd727b6717401174a270835ab40205a1 -libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/md5/1468270825363bffb3d99d3ca9216d7d -libLLVM_assert.v11.0.1+3.aarch64-apple-darwin.tar.gz/sha512/b94c1273553204440b5f51a3b1fa8c96ad8eae2090e50c3cf10fed44f960e5d0a6c95d967b7e006f842d550cc59b06ed8585962399772e1c2d6d1e6cf7686567 -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/md5/5ea96996524ebc1c69794d7e9ba2b252 -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx03.tar.gz/sha512/8fd7d5debae5277a5d099c24c195ed1c110f95169bc05ebe42fbb697683f2012a95507b682dd978a25918582dcfd548233d26a3e74a3098e85758dd63b5ba98e -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/md5/49e5dedbdcad40a5966aca51c8913d3b -libLLVM_assert.v11.0.1+3.aarch64-linux-gnu-cxx11.tar.gz/sha512/107a57a298416760c2f806901080963c2b1b3d09f16bef698db6e28b084c36f86796956deff096b4e014a61b29319e1fe1ed95f6a807ab3f1a6350288f85160a -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/md5/7d594f4af283181513816fe50d299861 -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx03.tar.gz/sha512/f074bca4a57c827c16558783b7efe8d31f12d4a0500a374ed9303a4beba2e848343d9d66da4bd0643c8df10004a6b7a9074a0f99bdba6e2b7eae939a892c7a0f -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/md5/1328f6c829ddc5361e5217aa9d2ba1f0 -libLLVM_assert.v11.0.1+3.aarch64-linux-musl-cxx11.tar.gz/sha512/238fc6e8eeed72f6fc23b9ea5e9083b8812447799fbb73ba13b2613c6ae0d35cdd8835276e8c9e34450d8c682121cf28601dbc6ce6c160ccabe7c36043441d78 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/f863e9b6afea27c93b04575194bd83b7 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/deb3d89d5cdfdeee2a8665d79e2cf77dca693c66bdfd5e10fdba9cb54cefce27a85aed76804ade511a65aff5e1a99f66748b827253ffdaca6c5c55c5947e4d5d -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/0fc8a804ddcb6bebc2ca285697427a60 -libLLVM_assert.v11.0.1+3.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/8cc0f98bc20bcaa47a6c6e28a559018b572b27c2c3507554abd2d5a09ecc36219881ab391625f47a581cf7a569534b693760abbe3b31a31b111c3a751051bc55 -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/md5/eaf1aa0154ba5906a48848b1fd4770da -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/e4531b5eb09be3ac6440e32dcface0360cc75595da00fa1bd178306e9780bd26eb7413a705d4b49d3d7eafd8f403a448bad9aae40bad56fb40bbea8db75e5f06 -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/md5/57307cc154a85a84297f94f71593829d -libLLVM_assert.v11.0.1+3.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/c8c8d35982a7df99ec468b688dee8ccf627512c6f009aea27cbd7fc8d350bcb915136753c18fc1a0ebcf621d9540d1995fae3f7532c31dfe70f1b3ea07275695 -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/701b49c22b69b6e4a91cc1559b3b2622 -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/1173b249d04df31a3d17e120666953654ce3274b749e137a24e137faa28b424a3a60bff9bf3c23f8299cdcb6b77fcf883b60654abced4b854e6080788a4093ea -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/e781f504156bdf748cbebbae86173fcf -libLLVM_assert.v11.0.1+3.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/572d0eadc5f3c495aef529d03fe3a3f890cac655fb7b8fc7dba92943023355a4494f72a2de5bb302756d5bbc36658b32babe4efdeca2f85f0b9f244f3c5e650e -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/md5/b460698fc6f652366a0b869bfb2b1646 -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/00f3caefa2885be6550f20a86048057b6beb17044ea822ffa9fb9df65c848eb7ffafbac4f6546ca16a1dfc344cfb851b7d42cc3a7f3f8a2b19a5044748a6f64e -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/md5/b4f0efa367651e7e37976cb7052eda02 -libLLVM_assert.v11.0.1+3.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/5af81df4c76dad4ab5387e3006f350f9387dbda5b131adb2b75669dde284a281af34f041dd00a0e8b6e0e8e92e7e4138fec5f83a6e2fc82fca8c3c6a637900a1 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/md5/ee47fdaec1107506ace19f70d090622f -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx03.tar.gz/sha512/32c7702bc599f06be6c5403574b1cece6d07b2c9787bd3b08e73a3746a187956609f2b7cdf0c673fbdd3105030138cf0c622a08e59f4180cea5109cc486fc570 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/md5/d6a47e2c969aed82c377f42248b54b75 -libLLVM_assert.v11.0.1+3.i686-linux-gnu-cxx11.tar.gz/sha512/c95f7e895832deed7d99155ada1df46e1dd1e43dd24fb8aaf94e4109f301b8163b8c8f83f3a2fd65d7b445e4d194f456e2cdd93ba36ed70ac4131c805a0c89e0 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/md5/158ce4bcdb7cdf26faad269a6133e2eb -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx03.tar.gz/sha512/f19f556f25e602da754e666476686411d484297cbe1d51f8d21e167feb241c44e1b94d502b4984649340c515dcf38a53be9d949805c29ca0e959101900f68fc7 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/md5/fe72914bc292072e1f474ffb41e01a99 -libLLVM_assert.v11.0.1+3.i686-linux-musl-cxx11.tar.gz/sha512/87a300e6928b69a4ddc59a375a9c172cbef82dd14ee101ac97ea1a652e1e4cb69d8c1ba61f4e4c2889884c58a571a257cd3390a504ceb88b0cb4a514143541b8 -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/md5/309fdd429e740941e0deab08f1043c5b -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx03.tar.gz/sha512/b01bcb83a6ef208692bd26899e7e75177f6bd619afeae0dc46217ece0f79bd81d2f07fedf70084478fe1f8abcc2d031a0ea06b55ac55a34f3facabb38a2a993f -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/md5/a9ee212809e891f147916cb6568f8b0e -libLLVM_assert.v11.0.1+3.i686-w64-mingw32-cxx11.tar.gz/sha512/927a010c326dac7faa4ce822b7ed01048b825a8050ae03d11963a864bf8f70b810e58985d37ec04cb69e7ca5c8a4956438f8c5f50dc8af90dc00bb10c0b6dd28 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/md5/6a2f2cd6cad70e27029f4a7c78196589 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/77bee805988a0df69cda34c5196f29234d5e4c7cf55da2154fd5a4f431123cfa3ef870a7ee10dd773eeb446647f500edca844cc89d1fc39d04caea6be58ce6a1 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/md5/f780073977fddf46200103b476ba4176 -libLLVM_assert.v11.0.1+3.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/40107288f36fe50e8f60fcd7b18a9058f36a6794cf8e8f06328437fb77f0890e1b890aba7f931329d98219faaf922dc14474f66340e6a70b8309f171e2bbc901 -libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/md5/db4d528b06836c46d46755fc93cceaea -libLLVM_assert.v11.0.1+3.x86_64-apple-darwin.tar.gz/sha512/cb62a0db35f0f1cc4723c2313eed265c4e11dc6b225d5b30afd7e2aae0c79b0dc23558640a409862a31ccbe337e4c6e4c1a35f3c93251a1c714dedf5f4637716 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/md5/b00cef3645e589cb217d8df10173124c -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx03.tar.gz/sha512/4de8fd6f90a5f85278c1045731e71855969b615e228a6b63bf53c84b145c3d8db4a7fc236301249e6ac195ee13fe62b0c23dee1c50c968ba74a1f9857e5ae3d8 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/md5/d326d3cd8918ef4abf4aa26a93f77310 -libLLVM_assert.v11.0.1+3.x86_64-linux-gnu-cxx11.tar.gz/sha512/ae49a764b848d179d8799793a79ba3cf03ece82d84e4d26b1f48256ce159984b1c54439db1f7b928f0526a85fb3b11021e9620104ae0404b7b85824aeb59d42f -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/md5/10f34bf03747a92e6cdb6ed206b21724 -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx03.tar.gz/sha512/ed06c31ae0024e60f7ac3a77dcde37e8aa545b280e0aef669edd6cf3f060b6acb90072c488f91a44bab6e573a3e50576a4b0a11f12596a63729a46547a7276af -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/md5/55ad55e3e093d1a3c32775036c68f629 -libLLVM_assert.v11.0.1+3.x86_64-linux-musl-cxx11.tar.gz/sha512/d1a30dd14b64c49397c45b2e53aa6099585ef22014fd9091dda39a7ccf03c78b85b018f3844c90c56aff47c6725bc5dfd73b5e6402ea13f73109aea6debaa276 -libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/7d88bc9491b83793e39f494f45b7e636 -libLLVM_assert.v11.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/c6065593e89f861661ec9c1fb35e416496e79e9e0f56e5ed4b7ba9fbf8b236716ff7733bb60b5de8942b6f9aca5705e0236e7fcbedb24109767fc12c29542d01 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/md5/a012e6c9829ec51f260bbdedb20a2863 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx03.tar.gz/sha512/24dc81297cab5d7eafa47de5d0ab5ca0b3da3ffd032de94488c81556d5ebaec850884dd561e14de98fa7dc0104d45acdd0298e0b0339dbb7351a9dbaa32320f5 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/md5/bc0f8437c9f2aba1a7e696cafd3b4618 -libLLVM_assert.v11.0.1+3.x86_64-w64-mingw32-cxx11.tar.gz/sha512/ac640918e72b169fffd4a43f1453965ea0ba734c582c3f6b04cd6f020b032b4745ed79208a43ba1c1f700f0122596466da4ed881a89a67f6df3a62141dab9f04 -llvm-11.0.1.src.tar.xz/md5/6ec7ae9fd43da9b87cda15b3ab9cc7af -llvm-11.0.1.src.tar.xz/sha512/b42c67ef88e09dd94171f85cdf49a421a15cfc82ff715c7ce6de22f98cefbe6c7cdf6bf4af7ca017d56ecf6aa3e36df3d823a78cf2dd5312de4301b54b43dbe8 +libLLVM_assert.v12.0.0+0.aarch64-apple-darwin.tar.gz/md5/1e5a6d26e657b2900c9c3914dfbad9e9 +libLLVM_assert.v12.0.0+0.aarch64-apple-darwin.tar.gz/sha512/e2846fa7e2503309dfb57159acbf8ca5836fffb1a2a81fc60e88743d13eb67491c5a8977bc3dce7d75de799ff9bb963029abb23dec5450085e480940bd3f4bbb +libLLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/9b6a0cf448686b657caffe308a8512fa +libLLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/151f3c29ea0f21f6a4d4be8b127aad2cdfd0b97ed3f8cf8d518be28f2b3fdaaff29eac04b57b5a5ce0aa3ce137e1afc2fec2e619ea2dd119520ae815e0e064c1 +libLLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/8b4eab1d6ec21bf412a3ca8eaba04f3d +libLLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/13009a160683ab073a0a3e089f17d006b1d74273a65b51d16f4e731b47352c972ea0487a79e02084c4f4f72f61bbd1f169b7bbdacb6974e5fa53944d444ec290 +libLLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/d1e35884644357a76dd4fa6f7429bccf +libLLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/d0918e7886c9ff6771d3ff809a25a56a7a2154b4713ed2f47f3e0b75748524f5465fa742c771e1fb954e3757a3341ca3f5e8f659225e0edb49f0c50b9dec995f +libLLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/ab814bef54de513926548605795ee56b +libLLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/18aa8f235963f24ff15854708418640eae32c061b663574391d8c70880926a9ea6038cd2d875ee616fc5b247aae6503c6bbe09738d5fd0b65ca92e976057c8f6 +libLLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/6fd292d8e348f895efc567a566a36a98 +libLLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/1b03e5de348c9f563fc31c2325817380df6b995a5f352effd434f786f760612ea53efbae2ddc37251b3dcef73eea88c71869a197006ecd0ec6f860ffdacca5ec +libLLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/7377e0370c12506893231c4d8e1a28bd +libLLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/c91aa4226f065c62cf16f9815b0cd34548dfff38cb1a05e0e122ff659c3db2ad6d28d83d9d7ec4d28227b2a5de1d2b48812e50f6af838e69eedbbd8cc153f131 +libLLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/faa491409f4e9d822e9e34f6f2db36ad +libLLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/a07245c310755567e9e33b26c0f0282eae40abf1a1a1c22a77b6412709b191433ec497e16662f229558e49089d68a1c904cd282c548c02370ed902f544eb5cd5 +libLLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/b42b08d46b64df98e3ab493341ac015a +libLLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/da2bd53fab48f8b46971639d6ed81b9e57467a6c4a7a3a63984c08f1b799f7352352ba28892a7789811879e3740073487b885d9974b6285fd03da16edca24f2b +libLLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/52e678465021c06611f86411a8f41e9e +libLLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/01964e97bb231899b6064734f756d8099bf141674ed6d231108dbb6c901f3079444cd620493b0ea7e8bf1fbd2899f288ed02df3c855e5af87d7db93a9fd60108 +libLLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/c5a5977de4429a0a38e4cf025d57660a +libLLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/a5e4aed882ca2cbf0a8a8ff5b0c8e4eaadeaf7491ea1887ee5fae628a5d46906e7d480b784b1d1fd190c921cecebcaa243ff39df5a1776a82abcfe4095bf3d07 +libLLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/bb83098ced1081fa0c06ddb84b6cf0fa +libLLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/e217bb8fe434954191b2b2f0a00d6e32e39557b9ff95a2417a13f3a6a25f2266c180e66c98495b1946171d1652ca62689140814d5337e0e00b4abc15179f2879 +libLLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/77161f57a346fc7f6b9aa1d36db55879 +libLLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/e53440cacd74eb6eb48e4de0b720df177bb9b8c90e682685efcf65f98bc4bc6f990c60ccdb426e85a80db8005dbad1efa5be69e2dc326953d1c0177734f6a84b +libLLVM_assert.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/md5/33deaff11953a1f1f78658461010b258 +libLLVM_assert.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/61383ed8e872e21c3419d64928e29c3f1e074c03973ee456062ef774b71cb27785afa47c641ce9db14a144fb66a7f8c53215448721c49ebf3b37674ed04a75e7 +libLLVM_assert.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/md5/65f47baee13c6e2cd9f0f3cd95bd724d +libLLVM_assert.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/6f814647393445c5a6ec05cd8c89a3ad106bde4a2197ee0a8bd8e64f1575245d695a01bcfb02861ad452f7d881114a5fb4ab145aa2211b42fc34b07ffec2ccbe +libLLVM_assert.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/md5/107c0e969aac6bc376588481f3ab4748 +libLLVM_assert.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/sha512/aaf8677bdf4fdf5751a0133c00dfefb28cdf5076d62d749d9bb81f29af2a3f35438b3c4c0aa71fc87214670bb63a2428712a1c07fc46dae217cdef27b9b0c550 +libLLVM_assert.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/md5/b6f7084de25b6b49631a2f2aba8da96e +libLLVM_assert.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/sha512/75f91fd66da8d1e041c9ed0e8fd69ece5601d909caf10eaf30992b6eb5b743653d97648766fe0782862dc0891a234f3aef05df3b6c04848d4371addbae8bb419 +libLLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/c36270a831b06d5b3654ec7a9fd35b09 +libLLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/25a095c12ac43dc36fd32b0ceacf9bc10b240a360a45fa0b0fdde367a40dc22a83bb3a6267426c0c02f14f221046c0b453417eae4cc0539ca116149f8ea480ef +libLLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/8f0c51901b55ff5374c25a0e9bdeae99 +libLLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/a1387d07d63d0e33632bf77702271bf624fa29bd8e689054d3f71734451d39ef09abb9fb63f78cb6aa1f6f5bbe54737f72740aeb63a94fc6876a600ede5ed159 +libLLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/9a456e2d31115b296b212305988cbf0a +libLLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/9c93bbdf9b9d11654aa134cdd7b50198a7b49e86148ba3257cf6cb1003fe9d22f568e45ed5b26f4e0db7fb3128f57dadbef9f4494827c66b2957988305aa9b20 +libLLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/efe3eec267a6224e5e8f1458be4fcda6 +libLLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/d5e90b29242b6aeab8b4ec6d37938a5ab15e1b1546f87f795d45b8f9a1520d24408e8b2c3a26cfb4b61c6d3228f98d490e2a0abf375b8afec0fd0e866a833197 +libLLVM_assert.v12.0.0+0.x86_64-apple-darwin.tar.gz/md5/475530f8b87ac033069c4073ba25f62c +libLLVM_assert.v12.0.0+0.x86_64-apple-darwin.tar.gz/sha512/ae46db3687de3bca657968624d95ec3afed99fc3d07271681ae9cc587baed2b391c17b4b0905cb4da3727a44c7698b248dced4b44c688242042c096f9b2c2a46 +libLLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/888d7bd8ceb30a482438d0fa7526d6a5 +libLLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/b494736aa3c4378bccc5f72db20fdbc488bb383ec4f569be18848fe1aa712aa6dcd00df1a8c651ed266981e70f4f1e9ba2bf04cc410ef02140f988c21dc9730c +libLLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/7fb8dee0396a2ef772612de81c4ce222 +libLLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/ce1bcc5465e61944c4720f615de3bc234d2d2a3d8fed986aa919ba1840c0fa9a8ff4b7e5fd1f8e063bbd153ca1977718a91ac2e1ab2623a4b744d8ca98c3191a +libLLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/ae631966f7a9f28ff105ae2c5c9b45e2 +libLLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/da3c1b1335f891b1121fa5f1f8fa4d9705c2bfcc3d98f80ef86f453e4db2d7e4c391b462ff471a87a01403558f81241aff7fbb8f7a05d815b5e15099877f9f3c +libLLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/a4f21af04ce1407eb8d16e9b4704bfd5 +libLLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/bc6ada66aecb448f28f61f261d0e7cc009643ec0582c46ab7756e09bb4ba2ffecea8883213e6605144084abbeb1e12ccaf6e2a15b1797151a6aa0522453c0af5 +libLLVM_assert.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/md5/0fee3ab691bab69b30f3ce5721c871db +libLLVM_assert.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/sha512/4b9adee9596d37b336434a74e3aa007f83afeeeccbeaa16c942dc117f2990d1485887860eae7eee74aec2b4bea0f674aa3c6abbe621ddc26a76697e7ab1be986 +libLLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/2dcc9f9c8e8ea1c96b19d48e9c4da039 +libLLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/86a518a72558cae62e2b393503bf34e768d5999d2b773b22ae5cffdd6a413780fd8afcb88d8862a62529f3f3238eb50dd5d1210814d417beb01814bbdc029540 +libLLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/0392a6e2b4d2ea9177d57ed1c6758344 +libLLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/e0306b68650e758121a577133321d07fe42d6e1ff5a1b4fa5ae91d522e0a196f63d0a8465005e8d49a39c3182c1f86be8f79ae3c5da1943b1c5ad3b45dbb90a7 +libLLVM.v12.0.0+0.aarch64-apple-darwin.tar.gz/md5/758342103dc72bef1e97045b61326c12 +libLLVM.v12.0.0+0.aarch64-apple-darwin.tar.gz/sha512/38632deb61b0bdcc509b6781ee8981697e2ed68ddf9c874328b8de613621fbdc04dcd8e8f7e839812ff3b553c8ace00c32bf391b1cd7bd01359df0223400b49f +libLLVM.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/e46e23c1cb0116a64d4c6c362f36c273 +libLLVM.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/2f3a8870ccc0a2b9f8a0a1a46a1e3add68e412ca63b5dd2f3179d5c3f20c1c387d93493b4e3523fa1ecfaf676ec13fe8b97908e26d079ee140e24a03ae4138e3 +libLLVM.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/6b29c384991d030f0192cc21d8ba6b07 +libLLVM.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/c4f90df89d6315b93f574f0149c8b66185252770d7580a96728dabf9b4a3a66abf6f534b528540ddde791e6719e97857069c8b5154bcb134369253be3d51c052 +libLLVM.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/d00dd86e4a94b22976c8674d42eb9830 +libLLVM.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/7bc5e67ddc45a481ed3349098e581eb8db65b4408478db44b053850b9e534b9ffde27674ec22f3600a794a7a5d334d649907205d58016e6984ae2b8ec675959c +libLLVM.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/f44c529d8c9afb2c6a5c555bb6a38177 +libLLVM.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/1c6c7320495d822f4e9ef209f726ef9793d130b28416b8ca7b60d124e5ea54d6a92d73596ae33078b00e863026196177f9ae291a338d00378169f4f0199f8fb3 +libLLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/a49912cfcf61750103f740d60de921bc +libLLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/3f4d803d5eb62ec23558c739d3afa8bcaa7cf371171019950548d46a07e2e9be771ed1a135995960d7e8b344cd149abe4f50b547889a5b7d30a5fc97a80e6f33 +libLLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/18b0841f11b5d3b8bd30c6a6711f3e84 +libLLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/e891c7d7188593b1c99b8e84ed8b0d9430367886eb1e06923675f666bb206649f570b818080598cca21603693241b8f8474e268a3ddbc5e85cf2640a7648a57a +libLLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/d0f7682d75992f21e9f4583632af01e5 +libLLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/8f14d78b55a923e497fc72866850ec227ced1f600eae5b1f8060adf25dcc8382ebb4992474a1557b411f010e2fcd356168f2ada79b867ed5afeb82ec4a3fc30e +libLLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/4b4030175961593cea3d63219cb2a5bc +libLLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/d3348b34db7e51c66c29e7ec835c5b8287a7f6f4abed97cbd2cae0b9ce6f975aee1e1eadea7e281cb6ac180de209deee277e1b7c2553b67dbf3faf5b0c00d96e +libLLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/25a752523cef3c8a0630ca80bc612251 +libLLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/ea8257ca590509ff1fe3c1b8379305be067c257e812269ee4af5df35cca1176400e85502b17cedab20e879e082f4bdfb8fe1dd34d83e786afe1c9914931c61df +libLLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/09971322fd89c0b1102fdfffaec53721 +libLLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/6b5b7169c96e7b7510a6b084af0d36b893a46a1c2c4a966e89f23878ac2e9eafbe3c21c062eed818f200c9eb2083261ba4ee76786af5ceb5f05621f79548ee7d +libLLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/a7dd5765f7e530a40b72f44b5dfb8b38 +libLLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/c4b119dd79a810001b81b4eb103013b8d7fb8443c060becc3900e6f7379b91e38b70aedeab980062ee53ddec04592aa6790c62bfc59c556423edf9b94218d060 +libLLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/f61a1d6e04a4c5c00bb0d31e997184bf +libLLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/831dbd3e5e16d4fe6c38fef6f2656f54b3532fac1c1c05121d0d35d6c9de328cd06329ab85f100975097211586bd1fcc3249f8e77661941c9746843d2adb0a6b +libLLVM.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/md5/4e368d4b4901825f115a3e58483036e1 +libLLVM.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/0211a7213e1d5dddc64be17c39b330b12d7361613e0a798d007bde9d3f4f3fb7259df8212c1809a45759118ab36af4bae0c1f35a66e88a4195c899a6341c21ba +libLLVM.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/md5/cacce4ec7289a2a86e9bcc91580a4a5f +libLLVM.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/04d71994344fdbf60f01128e8c8fe3c5f940ea3bd72a5eff154d913298893bb73b399eeef1240bab779ba477a02b8ddb647068c76946fcb35f9a530d7fecccea +libLLVM.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/md5/c242c47e4047bad01c15142eb6623fa6 +libLLVM.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/sha512/225b9ea08454ebd5b24ac1d4442023d21f4727072baa16730b23d71d0dfd1be713bb992868038f8e982af590f499bf6d2b4e64bd3cbff537fa41c1f8d271eb32 +libLLVM.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/md5/7843fcb202beb55d6aa87600a6d60342 +libLLVM.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/sha512/d8c9f6f865e2f1058bd0d3f5b04a799483f1a94336ec82161a8c26e8bf5070b714663cf5d62733c9d4006b9a6e145873a31198e780632f039dc43a980216407e +libLLVM.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/ea045ca69935f5035071be6ae719ee7d +libLLVM.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/06a9b4f762bc08c827ec2d8bc6ff26ebe7af6c8d049bd1015f5d006d7927f7c6ec5d1310b0e74da59994b10c866d2e3358717e36d398d3c01a53455f5f94eaee +libLLVM.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/cbb10916045594f8c509d158bc9eba2d +libLLVM.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/7ae2b3dc6e54bff8db71ab3208cf7d28a4c35819528d6cde17530e8a5509501d7aff18a75e851d93cb2682b0996d78f00e09db6ac11c2bd9bd57d349af8a3c14 +libLLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/f59fa032a3f5d8fda741a7fb2c7908ea +libLLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/bac6f46e34660cf8b231a1d68eeaedc82f77518296cad4aa6d54ed3661c45c02b3d442e30c37c8b4b8cd0e0701a5ba49b080ffc842e6b58f6f19375250978231 +libLLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/92f7fc40a1ffb473046d5493b329fa69 +libLLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/1f0256620164ee67b6936fc2005a66dba889dae4c0f92b16fa33fc6a3b4146ad1b119db8569a50b1716e2464b0e4def09cc68cb81aff96c234717e507d64b3ac +libLLVM.v12.0.0+0.x86_64-apple-darwin.tar.gz/md5/de7a0f428a9d6c53feb42cf1224744d1 +libLLVM.v12.0.0+0.x86_64-apple-darwin.tar.gz/sha512/f9f7adb7e80d2192692fae80909bd2a87d5a471cfbcab6e335750011b77abae89dbb2b5a81151bbc34739ee3828e3e84a844b46fbc63c279710f3e12c0369642 +libLLVM.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/38dec37c1b969bd38739dcc88c795ede +libLLVM.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/9b0afbe6119925a6a2d7f03208ef4676209e6c6532c78f0badd87564636bc417058097c2038108d6aecf399ae5ed3a8629d75a00f36277a7e97483da92a5c963 +libLLVM.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/68ef2be45e6228a974215cf76c630a8f +libLLVM.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/a8e48578b6ccdce02b3e03d7c20de8df90ab40ac99a029169c8dd15907e41b917579bcb0f677dafcf039f95c9be0395b2ee5503ac6e20d9ef62517b5a213f521 +libLLVM.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/8422319066043fc91f69795c10e085ac +libLLVM.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/e072e786f4ed2a891b251e43f6b62f6916c3f2d88afdde12a132a468f77281fe6b52438862cec25726a501ae76ee5d9e920fd5a2a8c2ede91999958c157134b8 +libLLVM.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/1251650b38740bcf2203ef52a9dc07fe +libLLVM.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/afa9b543a1930440b7e82aec6ff82549de6e1fcf88fa24c20e541ca66843bbf471f30fecc6af5e4e514cf383e91834c0cbbf231f0d97f2af9a99122ba13a6477 +libLLVM.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/md5/673870380f49f24097e9aa040bbae2b2 +libLLVM.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/sha512/88ba49a5063fe67bc91906d2b7d2044238faaa7a1ff52e10625f49d79a9d986de3b3a09b32e76f38f8bdeefadadab233ad8510881ed6ea7c4925b5d6c7396ed1 +libLLVM.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/6ff0f20bad03e04ea511fbe99a4a8c87 +libLLVM.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/b0496090fe91b7d8485883b3643f170c4a5533bd6bd388ddbb04e189d0073e44ccb31caa2cdbdff49f430c1180dd8c0d1fbffdd2fee83e5be52aaf362c0cd178 +libLLVM.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/1de026b6896ee464493d0b760c938faf +libLLVM.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/113ff6c2a706bbd334fd6882f56d1238fe0decd3e80b528166500ac5f831bb321d078b48ebb1883ed0ca5ea22516a9b3ca49fb32cc21b03fa985ddf69208deaa +llvm-12.0.0.src.tar.xz/md5/ceab21c9081e122a88d82216a80d0dc0 +llvm-12.0.0.src.tar.xz/sha512/ec17153ef774a1e08085763bda7d0dfce6802fbaa17e89831695ce1b2eb015a6c2aebfaa9fe7985a83b9c51bd75d40bb4f1fc706dc16d4c0dc2b2722a1d8a24e +LLVM_assert.v12.0.0+0.aarch64-apple-darwin.tar.gz/md5/9c1db1cec729fc7f9b65a135290ba820 +LLVM_assert.v12.0.0+0.aarch64-apple-darwin.tar.gz/sha512/684f8fb95bb99fc672d9ecbac831f3d6a68e906c8f0050bdeaac522f8b3ccedf8e54dd23667de3fd0c03f241471df221cd0a965036411b523b0e4016be89e896 +LLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/1e84cba3d675739d2064ace317e8852a +LLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/2bd3cac963c0b54d23b1471f26b892c95400c2adea45be4a40dace6a0a456297c44c5edc2aba7d977c6afee1b8ca41c43171b8d99e04fa223ba9df877b8ec614 +LLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/16a1d1b3006b5181e3b27c01775865b2 +LLVM_assert.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/6c34f0d2d30965a1b826edf98031cbe96cb480998816d351eb2e361acd868d35c11249da0a9273469aadb7f55851e97cbfdd1f5536fc9d7310410c192a592a23 +LLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/b43babd0f88939f70f24d6ba6c42d93f +LLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/5aa5c686ed1d75bfff26deed4975eee7eeace2516c93e2d2a88c86d2f88e67f894f24d777d3891dcf962281794143eaca720eaa8dd9c774da3b69346beb50a04 +LLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/ad72b54cbca417fb2fcbc22885315c51 +LLVM_assert.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/f2d7ddbecc040c8ceb4fffe0240a15a8b18b697ad605fc8c29e16f8502e72e9e8281bac4634e84f95d86ea5cc3abd4fd0fc437b3ee986027bfca6b6efbf39d54 +LLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/176daaa135bdae4140cd64699500af7a +LLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/c08598773fdb8cbfeeb4e8b6802f90b0139b89e50d7434a7976c36416a2378db7873f49f81810204291c9edae72d82f3716b61df36411b0639b148fc838095fe +LLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/68c15927b4db3e2507b89e82f3332757 +LLVM_assert.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/e8598844215ed87fe6a1be05465e80100f433d649b4fabeace1de111626577a5747fc27b109de532c024cbd3f3e8261df0d4bd0eeffdc1928354f1ebf501ebcb +LLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/94cb1baaef471aaa4e07a2a0367caca9 +LLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/bb440e622e2da9f194a2804933131cdc4c084dd27567276e90a6638d6bb15d726abbb40bfbcb81d9934ae2472f1267068bf4f40043e7c928d12316eda66e4806 +LLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/1fb3a0ac1d0511ebd20f9520050a5f1e +LLVM_assert.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/5453dd469aaaee937d2a89c03fc382c52dcc1742070e6310f2394d4753fdde32bf91fc51e078d2aa00f3bf78cb73ba4e5721e008f84428e1269549af04689368 +LLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/c6c7d20f7bae0e4dd52b538bdb0ab1ce +LLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/cc1f792fa7dbb91470106d84c168c3d5e3c519079c8514039fbda8692f987ac994b1cf8d6b96995f47ab32ff55cff42bf53d278a78b21378ebea9c03f1b53d43 +LLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/c2fe748bb8e95fc1c22585109c372a37 +LLVM_assert.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/f94a13e0da4a51b4e3f3697ce88ff2ab7d41918e2d25894cb6e41622be9f3c888d6715574e8cbafc3a20bfcc2164a1c9b417c2c66bc420b445e11c5265a96f7f +LLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/ad087a60c33f5eda018ab8e2966bbfa8 +LLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/d0a4d1eb39491eff08c2991f8876a4e097071b337c4a5ddc783c51a1fa109810db67c5edd2e9b6dbef7e7fadc78224ab45864bee8e9b9e35f0325e49bfdcb6b5 +LLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/0015dc719aed7ac0ce2bd16f11bcf53c +LLVM_assert.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/de224f36068bce30adb7472e40d0b3ba3e3fe739fe9ed62ddec825fa922bdd075dc081401cd55abd14a303551ff5a047cc98b2a077f367c105953c8e27764d86 +LLVM_assert.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/md5/f9ed12bd7fe3e616016b81bd3c56caa7 +LLVM_assert.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/9287a724fc4b0a0c098a71c4ff4aaf50c3ca79120e13b3ce718c206a0dab1f239137175e6e8b46559fecb373650ddd8224e04194042eb62c974ebce84ace6ebd +LLVM_assert.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/md5/04dd433225feb65b499bee9b93698265 +LLVM_assert.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/2e1d1d9f5ded294890f37dc8c2449d9d66541d242d3aea76f3f170cb319be20b3f7d5a296c0631b6a8b713627c8f952c07de9151e88e1ef4ecb9a6f622595cb6 +LLVM_assert.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/md5/2cbf070301e7ca4a54ddfbd4420f18ae +LLVM_assert.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/sha512/5a7a2212d0e99130b9f2dca5311e2ac14622976f8d129b120754df9c130047369e2bc57757e8b0bd48430c0637dd886fc85b2143e233d503cb4c92b6bf9735b5 +LLVM_assert.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/md5/ec1eefe92eb1a0ffc08c2761f6bd0ac3 +LLVM_assert.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/sha512/6e54c1eaa55aef60c8a98e3870c1e18392a862b79cb482cc92e7346918cbf886f0845c6bcb0e75dade163bdf60b86d6888dbba30eb088ff0d4cac04624abb2db +LLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/9b282bc5b379138b634613dc27451588 +LLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/7969075ec1f8a367bf14cc19185bd1ac66631ddfe8faec955969600cc5e3548a82f2775271cdac71807df7f0fe38106bc6ba28b60514c9461513e9cb9e39de59 +LLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/c2af10728a4cdca9223f2769a5b41572 +LLVM_assert.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/4ed5303b5bb58fc6fba82c260f368398ba7df17ec9cec8e1ce9fe5f608e19c67cecb62043cc8e20599210d6c438e2d29381ec9d3a8bcdeb11b7676022f21664e +LLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/b8d7c5bc69c532251738e123124a046f +LLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/82bff8f8afe76ab38300a9e7fcba93ee07191230c1b2a0ee5bc98c6a1c94899a3da6eafd113ce7d938c27881f2af571534586e4adcdd1ca51ecd399fe56cd484 +LLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/defb081814ccc0cd6732ae3e3cde034d +LLVM_assert.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/5dd21608cc271d9a4d065bb336301d0e797cc40ed7fdae3a4370b7ef0f93d868e784e8c79ef37ec33b057a2eb86d07720bd0d7c178c9c28f4368724a5d0783d2 +LLVM_assert.v12.0.0+0.x86_64-apple-darwin.tar.gz/md5/212f317b4d01dd033e1eaada7076bfb2 +LLVM_assert.v12.0.0+0.x86_64-apple-darwin.tar.gz/sha512/19a222b4d1a239219498d5a4d67142047e00746ff6548c7adaac40196cc1b3088e320f26fc8c12b2ad41eed37d6dc3738af61a1dcbb81ac42f28e6bba0da1d54 +LLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/5afaaaba76df2d7d5a1c50d51ef45ef2 +LLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/2bf44283938600faa845b0b8b48f08d1826f80e48264fdc95ec828593afa8e592e0e697cd5b9e4ef959200a776ef3f85cf9c35e98fc908f526e082d4c4b4b340 +LLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/aa41affb6459858a9beabf583842134b +LLVM_assert.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/3b35ed3bad9c7e88c3d937548bf9af24b270c1faf4aae9ecaaaef8000b02ef17f90d425f7506a9716c1aaf3c7247472d2098ab7ecbdb4010f478602a2ba9c5ff +LLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/0429e7474dc3d250b0fc8772beed5b5e +LLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/13c180d03d337e911769793bd4624b75be846fb67d71aa0f0ff837c232e14d5d016aaa2fa2b986676297f3bbcc2599f104ebf4877e7110f92888e5c4d95f9ee9 +LLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/e4403471e47034e849cc66610724cd50 +LLVM_assert.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/957df75539a723b680173d823bf96e542dc4cffb4b05b64783a9d60f0f0bafc1b0d1113fb9c4ae25ffe7e36c4764804a2f98fd9cc2468e2af3f1fa0e77929788 +LLVM_assert.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/md5/070bd8e25a76b980564f9160bdaa66f3 +LLVM_assert.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/sha512/c7c03229c34dbb715e2c59ce3c9d404f5b6a337506952bbee594c2109a0824c4962575f8ae9801a89a30d5569a85f05e4c1c4fd231ecdfe36d3ca7488799d3c5 +LLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/1b7726c382c08e3e24fc1ec35b8c015c +LLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/029c084d83ee049f45b1026757d631751cd2edc6c7e10deeec398baab792e8cce366fad5c971a120154ed2b6cd28b6659090dee7402e8f904bf43371b4170048 +LLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/2c6d5945a5ee5b4d216acc6fdf22b54a +LLVM_assert.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/f086e0c58eff5560c23bb9444270005407e66afeb969b4e5bfb1eb041a3479939ada7014c696e1dc50b0aa2717928887d434941d5266bf16264375dd3acfb67d +LLVM.v12.0.0+0.aarch64-apple-darwin.tar.gz/md5/8837684991656303d1ccd1da16cef6ab +LLVM.v12.0.0+0.aarch64-apple-darwin.tar.gz/sha512/de2a74fc6c305a8353168ab7e5849706e29fd4b66936bf4a8b6b9cf9dbaa2b7c30a30c118cf59f1421eaa399e7b5a7efa52ccb9ee4c2ce55c7afb9ceb2050a23 +LLVM.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/4597b32ca87cbab6ca3de44ad0ff33d9 +LLVM.v12.0.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/648233efb5037da8928e6d584ce7c0176fd41fd3ab66ffc36bc15fa0829bf4b19d554fdbfe7ad6d1fce28be5d66ee3e650871f4ca0973afeebb19ca4aa0cc596 +LLVM.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/fa65be0be8c747801bf518e036d6b87e +LLVM.v12.0.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/cb9d926450b9e2d805ed3cde63db738eb4bfa2073382f52acdece2ca46019da0205b305db10af8feb96832016b0d10ad766e37b7f986541ef07b3877526a745c +LLVM.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/d8ada1b149428e1b363a3776208778c0 +LLVM.v12.0.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/5cbb49cfa03aef5f455a282dd76a7943d0a791bc3e2818d0e8bdebe3b072202a35d1a37119bf2fbb8082f18af99c1aa935b1f07b7a8a6ec3d0fdf05d7d7d0f1d +LLVM.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/f7af27355d90e71ed8d3b643ea058801 +LLVM.v12.0.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/27043b1229ae05e4502eff589a04469ede3f4b701aa62d33f69c9cb57ec5c84ecd1c1a312a3853b27a6f32281c41b62098b623a6a592671a7f53947eac7d955f +LLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/0f19ff6eb5d6874f386a55dd903a3808 +LLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/fc57dc902c574701555a86b404fa07ba676252b405cfc130fe253adc7bba7518ebeb6e984846f1a75fc192292fb5f546c3269960419351991aef74adfe6ce30b +LLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/bb054c404683edecdcaa8b4e6c5d1969 +LLVM.v12.0.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/10de5dbad00bd92e47c6a77d249e45ceae2cb790893c6472e91a8ce9d8f3f03f736f598d9930bf6bb53411f490f971559b281ef38b0cc953ff3aab766ff20cbc +LLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/81c6b866133c044922149e8da3330234 +LLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/b56ba063e89320a72e4db45e1ea31ea5f2238d3f317f3c8ea042a36b312f9c4a02eeb9da722cf34aac0e7d703c66d996b0f2c0c8b0e61b38e1e10d7c6a872270 +LLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/0cf3669c60ccb6304566a612ec84dd96 +LLVM.v12.0.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/a9b91abbcb1130e3bf83ffffa7c74e74a663f12fd79c1429f804af5d2a6dc71863bd387a080153fb241488baf9d0c9a3c317c92c7c95553fafb6714463b65e4e +LLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/971bdc3c1e5f200d6d5e0791de47fc8c +LLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/71d50e5852892a8777076022dbe615c49363bd2321975a0fe93202a93518a9064c805966eb2b09783fb2679b589059e8673072fccbcf2110584b25e4174db365 +LLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/2352473188a90f6b1df3613ff9f162ee +LLVM.v12.0.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/6f0e5a8eaf0d7976d31648370423caf9518f44182cd45fe7732d918d4cb2fcf302a5e1deb0856beed3064230e41581441a2ca339db7412a636c930e20bc8fefd +LLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/6e9d5b4cda3fc8faf5d3b82d384e69c5 +LLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/ea0ebee79f685ea25d2be85656ae21cf18dac72874342ff960b6fbdc89c60383a2d6af8f36d14621cbc9bd534cbeb0f8a58c791c724e5469aa48d50606c2c08c +LLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/4ab6e621226d158701368af6af0b8c1b +LLVM.v12.0.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/3ead9d5227bfae81251d5327c98e28a4f888206176835626e24603fa2638354f4bd0f9880fdd14919091c756a9ee5d0901d76af8555b67094cdf7b6094fb2afa +LLVM.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/md5/799676b765c76572ec4217fea32a569f +LLVM.v12.0.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/6a712ae86de5bacacbf805f9f53e7274a9f25c8b0dec28cbad756e6ac3e190ff1e6576a1d132659208f114cd36703bff0f049180b5e1ae7a49e05175db1689a4 +LLVM.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/md5/a14269eaee410d35904760ee26029a13 +LLVM.v12.0.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/bc5208ed6d365da10e7c9f9b4a771cab0ec7f2d340e8c35184e80ab093b7b79fc8e2735e6baf7fde6e7f4910d0fa893012c3635291528a0575ccfeae5a2baece +LLVM.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/md5/8c01b166aeddb75916a24b5bc4a5288d +LLVM.v12.0.0+0.i686-linux-musl-cxx03.tar.gz/sha512/51b6436452cc3dafdd0bdd03852a3ba131740b8bc701abd50d5123d08ff04b8be03051192fff26ccc4c446a3d1b08981fb66619c080d9450e52071dde62fa31a +LLVM.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/md5/b95bf3b5d2a0db37ff16fa6dceb4c55f +LLVM.v12.0.0+0.i686-linux-musl-cxx11.tar.gz/sha512/9fe5a3c4fc758c25eae7fa8886607e8cd926f6d15d65fa1dd2f745a38d885eaf248c2c199cee73bfd25bd98e65392dfde2004a9c63c061aa2c7d8a465b469b0c +LLVM.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/f714f857ac90c159a390d6f5d761e067 +LLVM.v12.0.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/4befbb7f17f717669eb670cb18b9e60026c84722e0b8d7b4cc91e27c8c05b27d7b04b50b2ef20ffaf30cfb785f951836d08ec824f6b8fa95ff6b30d21c252212 +LLVM.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/9648a00d069ed91628d0214366df6477 +LLVM.v12.0.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/a5fa4c4015e1ad450767f694cf0ce701aff5c3a20916745f60ad788f933029418b8303dccfe818be482862fb59bc889d8c4c0ffa3f8104a1f957a8f5578bb442 +LLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/1b05656cd5ea85d90c0ff7e0f3d2bb09 +LLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/070628a05d0beb3efb12831725db2da0b55910180290842b63373a39a73e305a6c87b91615ef7f31dd771813e32d6d93b6260a2200ed62ca14c04bf713d775c3 +LLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/0c41e6d77cea62b37d2b04cea3e3e865 +LLVM.v12.0.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/ec6c2a9e4de3921a2237ae0deefeef084713a0e8afdac63bc82a6ec4954ded1935696ada3e452d8c3929320d33a7ee6a861f3ad969e740e313639f72eaa33678 +LLVM.v12.0.0+0.x86_64-apple-darwin.tar.gz/md5/d716a03e7300f2c8b6cfd157baf82841 +LLVM.v12.0.0+0.x86_64-apple-darwin.tar.gz/sha512/be4bc5164d80db972cd4c0ce7e4325ad058243cc27850ca288635d191c0ac3b3428217623a01a312cfe4700a2af014eca03e06f4a345f52b5308185a38a2de65 +LLVM.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/c4ef15b188097912a8893395e079d6fa +LLVM.v12.0.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/2f06bfddbb907de527517b4a455bb7398b36a7bf9f72fcad778f2586425cbe90be9b3eb9d1cc03ff6b7e5fa6d04a0a06988aa9d2003e748163a7e7460102ced7 +LLVM.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/3ec8ed370b0995c3fb3062768d9211c1 +LLVM.v12.0.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/6e2414c5c4cc2696c951b928253bbed88b576d207772c2f14e483aa4f84fe16d0b8731c955ba7680596d29b5339f4ef90d1a2f8edac1a196b22923af09f6cbd1 +LLVM.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/a186e057c1141e7efe465be3c07a167a +LLVM.v12.0.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/5e88b8a5a79889a7d402af9c49a1b7743dafc3572161b3137060066c5de18d48f7e6f6abc837ec1e794e22bb6dee3dd1663526c31b852be48c2c3f9d0ab85505 +LLVM.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/ae4a90d5826c5b3db4085c90f91a42f5 +LLVM.v12.0.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/5bf3edbd72f86401d0f63803dbb0ef0ba9a835bd8cb9cece09e54807c0966d75b0ba68b6a0b337e40f8f754c04e0b6e95565baa4320a47a2b7f9d69c1e45de61 +LLVM.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/md5/1f3679db43d3b4b2fd2b2a4a8f92ddce +LLVM.v12.0.0+0.x86_64-unknown-freebsd.tar.gz/sha512/5ae1316d5327177975fcb7d4342760b66ba6bf7f38b90cdc04f77a00cb5d924b2dd041c1f354b9855001fae01b8cb301b486ee16db7daf4d0c41fcdf3e78fe39 +LLVM.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/441c0fc39bd0db777bf1c4a05a00d7eb +LLVM.v12.0.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/7cd2556e0a7d6a9ee93cc23ee5e755d7f777edad22b838867d25c00c742e4591dcad40496388a149b54df25aa5697aa025d49a061614ea6d20c67f29ac66a484 +LLVM.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/62f73d2ba5ccae272f6d85c6477d78e9 +LLVM.v12.0.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/a0f47a38994632c36502ec2f1b1d32f3f3c487062c7d47c38318ec6e85eb802a0e9d331b9743611eac86ef6d90c02960a6604f892aa295a88688905af6907b34 diff --git a/stdlib/libLLVM_jll/Project.toml b/stdlib/libLLVM_jll/Project.toml index 6954f96dff80c..5db781e86a88c 100644 --- a/stdlib/libLLVM_jll/Project.toml +++ b/stdlib/libLLVM_jll/Project.toml @@ -1,10 +1,10 @@ name = "libLLVM_jll" uuid = "8f36deef-c2a5-5394-99ed-8e07531fb29a" -version = "11.0.1+3" +version = "12.0.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [compat] -julia = "1.6" +julia = "1.7" diff --git a/stdlib/libLLVM_jll/src/libLLVM_jll.jl b/stdlib/libLLVM_jll/src/libLLVM_jll.jl index 702ed5c0ef867..0b7681d72bb43 100644 --- a/stdlib/libLLVM_jll/src/libLLVM_jll.jl +++ b/stdlib/libLLVM_jll/src/libLLVM_jll.jl @@ -23,7 +23,7 @@ if Sys.iswindows() elseif Sys.isapple() const libLLVM = "@rpath/libLLVM.dylib" else - const libLLVM = "libLLVM-11jl.so" + const libLLVM = "libLLVM-12jl.so" end function __init__() From 6a81238a125c2572fbcd376375737372f46ce416 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 11 May 2021 18:53:31 -0400 Subject: [PATCH 372/439] [LLVM] fix name of libLLVM on Windows --- deps/llvm.mk | 2 +- src/sys.c | 9 ++++++++- stdlib/libLLVM_jll/src/libLLVM_jll.jl | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/deps/llvm.mk b/deps/llvm.mk index 7e2b7357db3d0..c436a1a08a78c 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -553,7 +553,7 @@ LLVM_INSTALL = \ cp -r $$(LLVM_SRC_DIR)/utils/lit $2$$(build_depsbindir)/ && \ $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P cmake_install.cmake ifeq ($(OS), WINNT) -LLVM_INSTALL += && cp $2$$(build_shlibdir)/LLVM.dll $2$$(build_depsbindir) +LLVM_INSTALL += && cp $2$$(build_shlibdir)/libLLVM.dll $2$$(build_depsbindir) endif ifeq ($(OS),Darwin) # https://github.com/JuliaLang/julia/issues/29981 diff --git a/src/sys.c b/src/sys.c index 684e000026c6d..664489397977b 100644 --- a/src/sys.c +++ b/src/sys.c @@ -13,6 +13,7 @@ #include "julia.h" #include "julia_internal.h" +#include "llvm-version.h" #ifdef _OS_WINDOWS_ #include @@ -668,7 +669,13 @@ JL_DLLEXPORT jl_value_t *jl_get_libllvm(void) JL_NOTSAFEPOINT { HMODULE mod; // FIXME: GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS on LLVMContextCreate, // but that just points to libjulia.dll - if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "LLVM", &mod)) +#if JL_LLVM_VERSION <= 110000 + const char* libLLVM = "LLVM"; +#else + const char* libLLVM = "libLLVM"; +#endif + + if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, libLLVM, &mod)) return jl_nothing; char path[MAX_PATH]; diff --git a/stdlib/libLLVM_jll/src/libLLVM_jll.jl b/stdlib/libLLVM_jll/src/libLLVM_jll.jl index 0b7681d72bb43..5186cb13e0be9 100644 --- a/stdlib/libLLVM_jll/src/libLLVM_jll.jl +++ b/stdlib/libLLVM_jll/src/libLLVM_jll.jl @@ -19,7 +19,7 @@ libLLVM_handle = C_NULL libLLVM_path = "" if Sys.iswindows() - const libLLVM = "LLVM.dll" + const libLLVM = "libLLVM.dll" elseif Sys.isapple() const libLLVM = "@rpath/libLLVM.dylib" else From 72fc1e17b1cdba278bec4c558afd6334a496436d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 11 May 2021 19:02:14 -0400 Subject: [PATCH 373/439] [AARCH64][LLVM] Rename fmi/pa to flagm/pauth --- src/features_aarch64.h | 6 +++--- src/processor_arm.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/features_aarch64.h b/src/features_aarch64.h index 6a834610f0cde..88d988a35f03f 100644 --- a/src/features_aarch64.h +++ b/src/features_aarch64.h @@ -35,11 +35,11 @@ JL_FEATURE_DEF(fp16fml, 23, 0) // HWCAP_ASIMDFHM, ARMv8.2-FHM JL_FEATURE_DEF(dit, 24, 0) // HWCAP_DIT, ARMv8.4-DIT. Required in ARMv8.4 // JL_FEATURE_DEF(uscat, 25, UINT32_MAX) // HWCAP_USCAT, ARMv8.4-LSE JL_FEATURE_DEF_NAME(rcpc_immo, 26, 0, "rcpc-immo") // HWCAP_ILRCPC, ARMv8.4-RCPC. Required in ARMv8.4 -JL_FEATURE_DEF(fmi, 27, 0) // HWCAP_FLAGM, ARMv8.4-CondM. Requird in ARMv8.4 +JL_FEATURE_DEF(flagm, 27, 120000) // HWCAP_FLAGM, ARMv8.4-CondM. Required in ARMv8.4 JL_FEATURE_DEF(ssbs, 28, 0) // HWCAP_SSBS JL_FEATURE_DEF(sb, 29, 0) // HWCAP_SB. Required in ARMv8.5 -JL_FEATURE_DEF(pa, 30, 0) // HWCAP_PACA -// JL_FEATURE_DEF(pa, 31, 0) // HWCAP_PACG. Merged with `pa`. +JL_FEATURE_DEF(pauth, 30, 120000) // HWCAP_PACA +// JL_FEATURE_DEF(pa, 31, 0) // HWCAP_PACG. Merged with `pauth`. // hwcap2 JL_FEATURE_DEF(ccdp, 32 + 0, 0) // HWCAP2_DCPODP, ARMv8.2-DCCVADP. Required in ARMv8.5 diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index 908b7889f3a01..a411314e34e9d 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -215,7 +215,7 @@ static constexpr FeatureDep deps[] = { {ccdp, ccpp}, {sve, fullfp16}, {fp16fml, fullfp16}, - {altnzcv, fmi}, + {altnzcv, flagm}, {sve2, sve}, {sve2_aes, sve2}, {sve2_aes, aes}, @@ -237,7 +237,7 @@ constexpr auto armv8_2a = armv8_1a | get_feature_masks(v8_2a, ccpp); constexpr auto armv8_2a_crypto = armv8_2a | get_feature_masks(aes, sha2); constexpr auto armv8_3a = armv8_2a | get_feature_masks(v8_3a, jsconv, complxnum, rcpc); constexpr auto armv8_3a_crypto = armv8_3a | get_feature_masks(aes, sha2); -constexpr auto armv8_4a = armv8_3a | get_feature_masks(v8_4a, dit, rcpc_immo, fmi); +constexpr auto armv8_4a = armv8_3a | get_feature_masks(v8_4a, dit, rcpc_immo, flagm); constexpr auto armv8_4a_crypto = armv8_4a | get_feature_masks(aes, sha2); constexpr auto armv8_5a = armv8_4a | get_feature_masks(v8_5a, sb, ccdp, altnzcv, fptoint); constexpr auto armv8_6a = armv8_5a | get_feature_masks(v8_6a, i8mm, bf16); @@ -256,7 +256,7 @@ constexpr auto armv8_6a = armv8_5a | get_feature_masks(v8_6a, i8mm, bf16); // .SM4: sm4 // .DP: dotprod // .FHM: fp16fml -// .TS: fmi, altnzcz +// .TS: flagm, altnzcz // .RNDR: rand // ID_AA64ISAR1_EL1 @@ -1191,7 +1191,7 @@ static NOINLINE std::pair> _get_host_cpu() features[1] = (uint32_t)jl_getauxval(AT_HWCAP2); #ifdef _CPU_AARCH64_ if (test_nbit(features, 31)) // HWCAP_PACG - set_bit(features, Feature::pa, true); + set_bit(features, Feature::pauth, true); #endif auto cpuinfo = get_cpuinfo(); auto arch = get_elf_arch(); @@ -1419,7 +1419,7 @@ static inline void enable_depends(FeatureList &features) if (test_nbit(features, Feature::v8_4a)) { set_bit(features, Feature::dit, true); set_bit(features, Feature::rcpc_immo, true); - set_bit(features, Feature::fmi, true); + set_bit(features, Feature::flagm, true); } if (test_nbit(features, Feature::v8_5a)) { set_bit(features, Feature::sb, true); From 7df16be0bfafee6d304ee0690366fa33845cc8d6 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 12 May 2021 18:44:40 -0400 Subject: [PATCH 374/439] [LLVM] add correlated value propagation after jump threading --- src/aotcompile.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index db3f9f4b0e22e..4cc22d1275282 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -692,6 +692,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createSROAPass()); PM->add(createInstSimplifyLegacyPass()); PM->add(createJumpThreadingPass()); + PM->add(createCorrelatedValuePropagationPass()); PM->add(createReassociatePass()); @@ -743,6 +744,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, // loops over Union-typed arrays to vectorize. PM->add(createInstructionCombiningPass()); PM->add(createJumpThreadingPass()); + PM->add(createCorrelatedValuePropagationPass()); PM->add(createDeadStoreEliminationPass()); // More dead allocation (store) deletion before loop optimization From 8ae50e0cea280e5cc7310a648c280e90c592ed04 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 19 May 2021 22:37:05 -0400 Subject: [PATCH 375/439] [LLVM] Set StackProtectorGuard mode to Global x-ref: https://reviews.llvm.org/D88631 Co-authored-by: Takafumi Arakaki --- src/codegen.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index bc60798220d52..63d9946b2b673 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7930,6 +7930,10 @@ extern "C" void jl_init_llvm(void) // and to ensure that it is 16-byte aligned for out-going calls, // to ensure compatibility with GCC codes options.StackAlignmentOverride = 16; +#endif +#ifdef JL_DEBUG_BUILD + // LLVM defaults to tls stack guard, which causes issues with Julia's tls implementation + options.StackProtectorGuard = StackProtectorGuards::Global; #endif Triple TheTriple(sys::getProcessTriple()); #if defined(FORCE_ELF) From a0422e3e1dc37261c2829b51694e760e8b79a733 Mon Sep 17 00:00:00 2001 From: "Y. Zhai" Date: Fri, 21 May 2021 16:17:39 +0800 Subject: [PATCH 376/439] Correct the error in doc of workers() (#40896) --- stdlib/Distributed/src/cluster.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 8b68287aad8d7..f485384aa1fec 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -851,7 +851,7 @@ julia> nprocs() 3 julia> workers() -5-element Array{Int64,1}: +2-element Array{Int64,1}: 2 3 ``` From bd46639275391ac5f48fa9db75695f1e3adf5e3c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 21 May 2021 13:30:25 +0200 Subject: [PATCH 377/439] make ssair output consistent with #40869 (#40885) --- base/compiler/ssair/show.jl | 2 +- doc/src/devdocs/reflection.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 72f17e5505324..9250c75df6cf3 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -455,7 +455,7 @@ function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false) if frame.line != typemax(frame.line) && frame.line != 0 print(io, ":", frame.line) end - print(io, " within `", method_name(frame), "'") + print(io, " within `", method_name(frame), "`") if collapse method = method_name(frame) while nctx < nframes diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index fbf0fd58d86a4..1a99f040a4493 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -96,7 +96,7 @@ as assignments, branches, and calls: ```jldoctest julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] )) :($(Expr(:thunk, CodeInfo( - @ none within `top-level scope' + @ none within `top-level scope` 1 ─ %1 = 1 + 2 │ %2 = sin(0.5) │ %3 = Base.vect(%1, %2) From a56938c9f4a9812d1f6f7377b6c232a06a40feb8 Mon Sep 17 00:00:00 2001 From: matthias314 <56549971+matthias314@users.noreply.github.com> Date: Fri, 21 May 2021 09:43:35 -0400 Subject: [PATCH 378/439] Make `broadcastable` treat `Char` like `Number` (#40877) --- base/broadcast.jl | 2 +- base/multidimensional.jl | 2 +- test/char.jl | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index f9d41a13ff618..d7546643220ba 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -699,7 +699,7 @@ Base.RefValue{String}("hello") """ broadcastable(x::Union{Symbol,AbstractString,Function,UndefInitializer,Nothing,RoundingMode,Missing,Val,Ptr,AbstractPattern,Pair}) = Ref(x) broadcastable(::Type{T}) where {T} = Ref{Type{T}}(T) -broadcastable(x::Union{AbstractArray,Number,Ref,Tuple,Broadcasted}) = x +broadcastable(x::Union{AbstractArray,Number,Char,Ref,Tuple,Broadcasted}) = x # Default to collecting iterables — which will error for non-iterables broadcastable(x) = collect(x) broadcastable(::Union{AbstractDict, NamedTuple}) = throw(ArgumentError("broadcasting over dictionaries and `NamedTuple`s is reserved")) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index bf4e09dd12a49..474e19e7e5f5b 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -828,7 +828,7 @@ uncolon(inds::Tuple{}, I::Tuple{Colon, Vararg{Any}}) = Slice(OneTo(1)) uncolon(inds::Tuple, I::Tuple{Colon, Vararg{Any}}) = Slice(inds[1]) ### From abstractarray.jl: Internal multidimensional indexing definitions ### -getindex(x::Number, i::CartesianIndex{0}) = x +getindex(x::Union{Number,Char}, ::CartesianIndex{0}) = x getindex(t::Tuple, i::CartesianIndex{1}) = getindex(t, i.I[1]) # These are not defined on directly on getindex to avoid diff --git a/test/char.jl b/test/char.jl index abc8db33cb4a7..279adb628ed17 100644 --- a/test/char.jl +++ b/test/char.jl @@ -99,6 +99,7 @@ end #getindex(c::Char) = c for x in testarrays @test getindex(x) == x + @test getindex(x, CartesianIndex()) == x end #first(c::Char) = c @@ -290,6 +291,7 @@ end @testset "broadcasting of Char" begin @test identity.('a') == 'a' + @test 'a' .* ['b', 'c'] == ["ab", "ac"] end @testset "code point format of U+ syntax (PR 33291)" begin From db8d09609ccd0e99c480a9c6180a29e776359441 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Fri, 21 May 2021 15:48:27 +0200 Subject: [PATCH 379/439] remove separate verbose IRCode lineprinter (#40889) ref https://github.com/JuliaLang/julia/pull/40459#discussion_r612352449 --- base/compiler/ssair/show.jl | 44 +------------------------------------ test/show.jl | 2 +- 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 9250c75df6cf3..1f1c838c62ae7 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -712,48 +712,6 @@ end _strip_color(s::String) = replace(s, r"\e\[\d+m" => "") -# corresponds to `verbose_linetable=true` -function ircode_verbose_linfo_printer(code::IRCode) - stmts = code.stmts - max_depth = maximum(compute_inlining_depth(code.linetable, stmts[i][:line]) for i in 1:length(stmts.line)) - last_stack = Ref(Int[]) - used = stmts_used(code, false) - maxlength_idx = if isempty(used) - 0 - else - maxused = maximum(used) - length(string(maxused)) - end - - function (io::IO, indent::String, idx::Int) - idx == 0 && return "" - cols = (displaysize(io)::Tuple{Int,Int})[2] - stmt = stmts[idx] - - stack = compute_loc_stack(code.linetable, stmt[:line]) - # We need to print any stack frames that did not exist in the last stack - ndepth = max(1, length(stack)) - rail = string(" "^(max_depth+1-ndepth), "│"^ndepth) - start_column = cols - max_depth - 10 - for (i, x) in enumerate(stack) - if i > length(last_stack[]) || last_stack[][i] != x - entry = code.linetable[x] - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) - print(io, indent) - ssa_guard = " "^(maxlength_idx + 4 + i) - entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry.line) " - width_hline = start_column - length(entry_label) - length(_strip_color(indent)) + max_depth - i - width_hline = max(width_hline, 0) # don't error on overlong method/file names - hline = string("─"^width_hline, "┐") - printstyled(io, string(entry_label, hline), "\n"; color=:light_black) - end - end - last_stack[] = stack - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) - return "" - end -end - function statementidx_lineinfo_printer(f, code::IRCode) printer = f(code.linetable) function (io::IO, indent::String, idx::Int) @@ -796,7 +754,7 @@ function stmts_used(code::CodeInfo) end function default_config(code::IRCode; verbose_linetable=false) - return IRShowConfig(verbose_linetable ? ircode_verbose_linfo_printer(code) + return IRShowConfig(verbose_linetable ? statementidx_lineinfo_printer(code) : inline_linfo_printer(code); bb_color=:normal) end diff --git a/test/show.jl b/test/show.jl index 358b792de105b..6990323afd1da 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2011,7 +2011,7 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] io = IOBuffer() Base.IRShow.show_ir(io, ir, Base.IRShow.default_config(ir; verbose_linetable=true)) seekstart(io) - @test count(contains(r"my_fun28173 at a{80}:\d+"), eachline(io)) == 9 + @test count(contains(r"@ a{80}:\d+ within `my_fun28173"), eachline(io)) == 10 end # Verify that extra instructions at the end of the IR From 64940ec12e1029177d9180a61782dd95c46fe60f Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Fri, 21 May 2021 21:59:28 +0800 Subject: [PATCH 380/439] Make partition support non-1-indexed vector. (#40830) For a high dimension array, at least `OffsetArrays.jl` return a 1-indexed vector after reshape, so the current implementation seems ok. I believe that the view of Base's Range types has been mapped to `getindex` correctly, so I think we don't need a separate routine. Co-authored-by: Johnny Chen --- base/iterators.jl | 12 ++++++------ test/iterators.jl | 5 +++++ test/offsetarray.jl | 9 +++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/base/iterators.jl b/base/iterators.jl index dbebe900e0659..2ae6347a4b849 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1171,15 +1171,15 @@ function length(itr::PartitionIterator) return cld(l, itr.n) end -function iterate(itr::PartitionIterator{<:AbstractRange}, state=1) - state > length(itr.c) && return nothing - r = min(state + itr.n - 1, length(itr.c)) +function iterate(itr::PartitionIterator{<:AbstractRange}, state = firstindex(itr.c)) + state > lastindex(itr.c) && return nothing + r = min(state + itr.n - 1, lastindex(itr.c)) return @inbounds itr.c[state:r], r + 1 end -function iterate(itr::PartitionIterator{<:AbstractArray}, state=1) - state > length(itr.c) && return nothing - r = min(state + itr.n - 1, length(itr.c)) +function iterate(itr::PartitionIterator{<:AbstractArray}, state = firstindex(itr.c)) + state > lastindex(itr.c) && return nothing + r = min(state + itr.n - 1, lastindex(itr.c)) return @inbounds view(itr.c, state:r), r + 1 end diff --git a/test/iterators.jl b/test/iterators.jl index c4b438d279693..de3dbda921cbd 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -2,6 +2,7 @@ using Base.Iterators using Random +using Base: IdentityUnitRange @test Base.IteratorSize(Any) isa Base.SizeUnknown @@ -848,3 +849,7 @@ end @test cumprod(x + 1 for x in 1:3) == [2, 6, 24] @test accumulate(+, (x^2 for x in 1:3); init=100) == [101, 105, 114] end + +@testset "proper patition for non-1-indexed vector" begin + @test partition(IdentityUnitRange(11:19), 5) |> collect == [11:15,16:19] # IdentityUnitRange +end diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 58a683ac90c57..811d3dd26f509 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -2,6 +2,7 @@ isdefined(Main, :OffsetArrays) || @eval Main include("testhelpers/OffsetArrays.jl") using .Main.OffsetArrays +import .Main.OffsetArrays: IdOffsetRange using DelimitedFiles using Random using LinearAlgebra @@ -786,3 +787,11 @@ end @test b[i] == a[r[i]] end end + +@testset "proper patition for non-1-indexed vector" begin + @test Iterators.partition(OffsetArray(1:10,10), 5) |> collect == [1:5,6:10] # OffsetVector + @test Iterators.partition(OffsetArray(collect(1:10),10), 5) |> collect == [1:5,6:10] # OffsetVector + @test Iterators.partition(OffsetArray(reshape(1:9,3,3), (3,3)), 5) |> collect == [1:5,6:9] #OffsetMatrix + @test Iterators.partition(OffsetArray(reshape(collect(1:9),3,3), (3,3)), 5) |> collect == [1:5,6:9] #OffsetMatrix + @test Iterators.partition(IdOffsetRange(2:7,10), 5) |> collect == [12:16,17:17] # IdOffsetRange +end From ef673537f8622fcaea92ac85e07962adcc17745b Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Fri, 21 May 2021 10:02:06 -0400 Subject: [PATCH 381/439] faster dropdims (#40895) --- base/abstractarraymath.jl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index fc1adf90d7d6e..4dd24214a63fc 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -88,13 +88,8 @@ function _dropdims(A::AbstractArray, dims::Dims) dims[j] == dims[i] && throw(ArgumentError("dropped dims must be unique")) end end - d = () - for i = 1:ndims(A) - if !in(i, dims) - d = tuple(d..., axes(A, i)) - end - end - reshape(A, d::typeof(_sub(axes(A), dims))) + ax = _foldoneto((ds, d) -> d in dims ? ds : (ds..., axes(A,d)), (), Val(ndims(A))) + reshape(A, ax::typeof(_sub(axes(A), dims))) end _dropdims(A::AbstractArray, dim::Integer) = _dropdims(A, (Int(dim),)) From ddbedfaf428d2a7e54391b3ca361bd54d517ffa3 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 21 May 2021 17:47:55 +0200 Subject: [PATCH 382/439] [LLVM] Tune SimplifyCFG options --- src/aotcompile.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 4cc22d1275282..c9e7a60ef7d7f 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #if defined(USE_POLLY) #include #include @@ -616,11 +617,20 @@ void addMachinePasses(legacy::PassManagerBase *PM, TargetMachine *TM) } + // this defines the set of optimization passes defined for Julia at various optimization levels. // it assumes that the TLI and TTI wrapper passes have already been added. void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool lower_intrinsics, bool dump_native) { + // Note: LLVM 12 disabled the hoisting of common instruction + // before loop vectorization (https://reviews.llvm.org/D84108). + // + // TODO: CommonInstruction hoisting/sinking enables AllocOpt + // to merge allocations and sometimes eliminate them, + // since AllocOpt does not handle PhiNodes. + // Enable this instruction hoisting because of this and Union benchmarks. + auto simplifyCFGOptions = SimplifyCFGOptions().hoistCommonInsts(true); #ifdef JL_DEBUG_BUILD PM->add(createGCInvariantVerifierPass(true)); PM->add(createVerifierPass()); @@ -628,7 +638,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createConstantMergePass()); if (opt_level < 2) { - PM->add(createCFGSimplificationPass()); + PM->add(createCFGSimplificationPass(simplifyCFGOptions)); if (opt_level == 1) { PM->add(createSROAPass()); PM->add(createInstructionCombiningPass()); @@ -672,7 +682,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createBasicAAWrapperPass()); } - PM->add(createCFGSimplificationPass()); + PM->add(createCFGSimplificationPass(simplifyCFGOptions)); PM->add(createDeadCodeEliminationPass()); PM->add(createSROAPass()); @@ -686,7 +696,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createAllocOptPass()); // consider AggressiveInstCombinePass at optlevel > 2 PM->add(createInstructionCombiningPass()); - PM->add(createCFGSimplificationPass()); + PM->add(createCFGSimplificationPass(simplifyCFGOptions)); if (dump_native) PM->add(createMultiVersioningPass()); PM->add(createSROAPass()); @@ -753,12 +763,21 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, // see if all of the constant folding has exposed more loops // to simplification and deletion // this helps significantly with cleaning up iteration - PM->add(createCFGSimplificationPass()); + PM->add(createCFGSimplificationPass()); // See note above, don't hoist instructions before LV PM->add(createLoopDeletionPass()); PM->add(createInstructionCombiningPass()); PM->add(createLoopVectorizePass()); PM->add(createLoopLoadEliminationPass()); - PM->add(createCFGSimplificationPass()); + // Cleanup after LV pass + PM->add(createInstructionCombiningPass()); + PM->add(createCFGSimplificationPass( // Aggressive CFG simplification + SimplifyCFGOptions() + .forwardSwitchCondToPhi(true) + .convertSwitchToLookupTable(true) + .needCanonicalLoops(false) + .hoistCommonInsts(true) + .sinkCommonInsts(true) + )); PM->add(createSLPVectorizerPass()); // might need this after LLVM 11: //PM->add(createVectorCombinePass()); From 8539c1a3ff3429e343149f6ca98844bced9cbeb4 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 21 May 2021 18:30:49 +0200 Subject: [PATCH 383/439] fixup! [LLVM] Tune SimplifyCFG options --- src/aotcompile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index c9e7a60ef7d7f..93683d320e6b9 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -776,7 +776,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, .convertSwitchToLookupTable(true) .needCanonicalLoops(false) .hoistCommonInsts(true) - .sinkCommonInsts(true) + // .sinkCommonInsts(true) // FIXME: Causes assertion in llvm-late-lowering )); PM->add(createSLPVectorizerPass()); // might need this after LLVM 11: From d730fd3c31b4c0b636710f048a3fe445515837d8 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Fri, 21 May 2021 19:59:48 +0200 Subject: [PATCH 384/439] Adjust LQ show to other factorizations (#40897) --- stdlib/LinearAlgebra/src/lq.jl | 36 ++++++++++++++++++++++----------- stdlib/LinearAlgebra/test/lq.jl | 23 ++++++++++++++++++--- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lq.jl b/stdlib/LinearAlgebra/src/lq.jl index f6a2d3e29f85f..606e8c3dd006e 100644 --- a/stdlib/LinearAlgebra/src/lq.jl +++ b/stdlib/LinearAlgebra/src/lq.jl @@ -22,9 +22,15 @@ julia> A = [5. 7.; -2. -4.] -2.0 -4.0 julia> S = lq(A) -LQ{Float64, Matrix{Float64}} with factors L and Q: -[-8.60233 0.0; 4.41741 -0.697486] -[-0.581238 -0.813733; -0.813733 0.581238] +LQ{Float64, Matrix{Float64}} +L factor: +2×2 Matrix{Float64}: + -8.60233 0.0 + 4.41741 -0.697486 +Q factor: +2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}}: + -0.581238 -0.813733 + -0.813733 0.581238 julia> S.L * S.Q 2×2 Matrix{Float64}: @@ -90,9 +96,15 @@ julia> A = [5. 7.; -2. -4.] -2.0 -4.0 julia> S = lq(A) -LQ{Float64, Matrix{Float64}} with factors L and Q: -[-8.60233 0.0; 4.41741 -0.697486] -[-0.581238 -0.813733; -0.813733 0.581238] +LQ{Float64, Matrix{Float64}} +L factor: +2×2 Matrix{Float64}: + -8.60233 0.0 + 4.41741 -0.697486 +Q factor: +2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}}: + -0.581238 -0.813733 + -0.813733 0.581238 julia> S.L * S.Q 2×2 Matrix{Float64}: @@ -141,12 +153,12 @@ Base.propertynames(F::LQ, private::Bool=false) = getindex(A::LQPackedQ, i::Integer, j::Integer) = lmul!(A, setindex!(zeros(eltype(A), size(A, 2)), 1, j))[i] -function show(io::IO, ::MIME"text/plain", C::LQ) - println(io, typeof(C), " with factors L and Q:") - io = IOContext(io, :compact => true) - show(io, C.L) - println(io) - show(io, C.Q) +function show(io::IO, mime::MIME{Symbol("text/plain")}, F::LQ) + summary(io, F); println(io) + println(io, "L factor:") + show(io, mime, F.L) + println(io, "\nQ factor:") + show(io, mime, F.Q) end LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) diff --git a/stdlib/LinearAlgebra/test/lq.jl b/stdlib/LinearAlgebra/test/lq.jl index 6e21b9ac6c1cc..883793c55d4dd 100644 --- a/stdlib/LinearAlgebra/test/lq.jl +++ b/stdlib/LinearAlgebra/test/lq.jl @@ -56,9 +56,6 @@ rectangularQ(Q::LinearAlgebra.LQPackedQ) = convert(Array, Q) @test l*q ≈ a @test Array(lqa) ≈ a @test Array(copy(lqa)) ≈ a - lstring = sprint(show, l, context = :compact=>true) - qstring = sprint(show, q, context = :compact=>true) - @test sprint(show,MIME"text/plain"(),lqa) == "$(typeof(lqa)) with factors L and Q:\n$lstring\n$qstring" @test LinearAlgebra.Factorization{eltya}(lqa) === lqa @test Matrix{eltya}(q) isa Matrix{eltya} # test Array{T}(LQPackedQ{T}) @@ -203,4 +200,24 @@ end end end +@testset "REPL printing" begin + bf = IOBuffer() + show(bf, "text/plain", lq(Matrix(I, 4, 4))) + seekstart(bf) + @test String(take!(bf)) == """ +LinearAlgebra.LQ{Float64, Matrix{Float64}} +L factor: +4×4 Matrix{Float64}: + 1.0 0.0 0.0 0.0 + 0.0 1.0 0.0 0.0 + 0.0 0.0 1.0 0.0 + 0.0 0.0 0.0 1.0 +Q factor: +4×4 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}}: + 1.0 0.0 0.0 0.0 + 0.0 1.0 0.0 0.0 + 0.0 0.0 1.0 0.0 + 0.0 0.0 0.0 1.0""" +end + end # module TestLQ From 59a9df1ba42c0d01ec6c0039793b7a7e1db02e6e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 21 May 2021 16:39:14 -0400 Subject: [PATCH 385/439] change setup_stdio default method to support any IO (#40780) fixes #39984 --- base/cmd.jl | 1 + base/filesystem.jl | 3 ++- base/process.jl | 66 ++++++++++++++++++++++------------------------ base/stream.jl | 1 + test/spawn.jl | 8 ++++++ 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/base/cmd.jl b/base/cmd.jl index 0d66cb932a04a..93138ed6b459b 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -165,6 +165,7 @@ rawhandle(x::OS_HANDLE) = x if OS_HANDLE !== RawFD rawhandle(x::RawFD) = Libc._get_osfhandle(x) end +setup_stdio(stdio::Union{DevNull,OS_HANDLE,RawFD}, ::Bool) = (stdio, false) const Redirectable = Union{IO, FileRedirect, RawFD, OS_HANDLE} const StdIOSet = NTuple{3, Redirectable} diff --git a/base/filesystem.jl b/base/filesystem.jl index 191f6537d8041..35703132cae86 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -42,7 +42,7 @@ import .Base: IOError, _UVError, _sizeof_uv_fs, check_open, close, eof, eventloop, fd, isopen, bytesavailable, position, read, read!, readavailable, seek, seekend, show, skip, stat, unsafe_read, unsafe_write, write, transcode, uv_error, - rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize + setup_stdio, rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize import .Base.RefValue @@ -76,6 +76,7 @@ if OS_HANDLE !== RawFD end rawhandle(file::File) = file.handle +setup_stdio(file::File, ::Bool) = (file, false) # Filesystem.open, not Base.open function open(path::AbstractString, flags::Integer, mode::Integer=0) diff --git a/base/process.jl b/base/process.jl index e7a460b0e8ead..0a2caccad30d4 100644 --- a/base/process.jl +++ b/base/process.jl @@ -74,26 +74,28 @@ const SpawnIOs = Vector{Any} # convenience name for readability # handle marshalling of `Cmd` arguments from Julia to C @noinline function _spawn_primitive(file, cmd::Cmd, stdio::SpawnIOs) loop = eventloop() - iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout - let h = rawhandle(io) - h === C_NULL ? (0x00, UInt(0)) : - h isa OS_HANDLE ? (0x02, UInt(cconvert(@static(Sys.iswindows() ? Ptr{Cvoid} : Cint), h))) : - h isa Ptr{Cvoid} ? (0x04, UInt(h)) : - error("invalid spawn handle $h from $io") - end - for io in stdio] - handle = Libc.malloc(_sizeof_uv_process) - disassociate_julia_struct(handle) # ensure that data field is set to C_NULL - err = ccall(:jl_spawn, Int32, - (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Tuple{Cint, UInt}}, Int, - UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}), - file, cmd.exec, loop, handle, - iohandles, length(iohandles), - cmd.flags, - cmd.env === nothing ? C_NULL : cmd.env, - isempty(cmd.dir) ? C_NULL : cmd.dir, - @cfunction(uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32))) + GC.@preserve stdio begin + iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout + let h = rawhandle(io) + h === C_NULL ? (0x00, UInt(0)) : + h isa OS_HANDLE ? (0x02, UInt(cconvert(@static(Sys.iswindows() ? Ptr{Cvoid} : Cint), h))) : + h isa Ptr{Cvoid} ? (0x04, UInt(h)) : + error("invalid spawn handle $h from $io") + end + for io in stdio] + handle = Libc.malloc(_sizeof_uv_process) + disassociate_julia_struct(handle) # ensure that data field is set to C_NULL + err = ccall(:jl_spawn, Int32, + (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Tuple{Cint, UInt}}, Int, + UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}), + file, cmd.exec, loop, handle, + iohandles, length(iohandles), + cmd.flags, + cmd.env === nothing ? C_NULL : cmd.env, + isempty(cmd.dir) ? C_NULL : cmd.dir, + @cfunction(uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32))) + end if err != 0 ccall(:jl_forceclose_uv, Cvoid, (Ptr{Cvoid},), handle) # will call free on handle eventually throw(_UVError("could not spawn " * repr(cmd), err)) @@ -209,10 +211,10 @@ function setup_stdio(stdio::PipeEndpoint, child_readable::Bool) rd, wr = link_pipe(!child_readable, child_readable) try open_pipe!(stdio, child_readable ? wr : rd) - catch ex + catch close_pipe_sync(rd) close_pipe_sync(wr) - rethrow(ex) + rethrow() end child = child_readable ? rd : wr return (child, true) @@ -251,18 +253,18 @@ function setup_stdio(stdio::FileRedirect, child_readable::Bool) return (io, true) end -# incrementally move data between an IOBuffer and a system Pipe +# incrementally move data between an arbitrary IO and a system Pipe # TODO: probably more efficient (when valid) to use `stdio` directly as the # PipeEndpoint buffer field in some cases -function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool) +function setup_stdio(stdio::IO, child_readable::Bool) parent = PipeEndpoint() rd, wr = link_pipe(!child_readable, child_readable) try open_pipe!(parent, child_readable ? wr : rd) - catch ex + catch close_pipe_sync(rd) close_pipe_sync(wr) - rethrow(ex) + rethrow() end child = child_readable ? rd : wr try @@ -271,24 +273,18 @@ function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool) @async try write(in, out) catch ex - @warn "Process error" exception=(ex, catch_backtrace()) + @warn "Process I/O error" exception=(ex, catch_backtrace()) finally close(parent) end end - catch ex + catch close_pipe_sync(child) - rethrow(ex) + rethrow() end return (child, true) end -function setup_stdio(io, child_readable::Bool) - # if there is no specialization, - # assume that rawhandle is defined for it - return (io, false) -end - close_stdio(stdio::OS_HANDLE) = close_pipe_sync(stdio) close_stdio(stdio) = close(stdio) diff --git a/base/stream.jl b/base/stream.jl index 509bc9953add6..2a23e97b4652c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -282,6 +282,7 @@ end lock(s::LibuvStream) = lock(s.lock) unlock(s::LibuvStream) = unlock(s.lock) +setup_stdio(stream::LibuvStream) = (stream, false) rawhandle(stream::LibuvStream) = stream.handle unsafe_convert(::Type{Ptr{Cvoid}}, s::Union{LibuvStream, LibuvServer}) = s.handle diff --git a/test/spawn.jl b/test/spawn.jl index 75c7252ab673e..e6dae394cbd2b 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -697,7 +697,15 @@ let text = "input-test-text" @test read(proc, String) == string(length(text), '\n') @test success(proc) @test String(take!(b)) == text + + out = PipeBuffer() + proc = run(catcmd, IOBuffer(SubString(text)), out) + @test success(proc) + @test proc.out === proc.err === proc.in === devnull + @test String(take!(out)) == text end + + @test repr(Base.CmdRedirect(``, devnull, 0, false)) == "pipeline(``, stdin>Base.DevNull())" @test repr(Base.CmdRedirect(``, devnull, 1, true)) == "pipeline(``, stdout Date: Fri, 21 May 2021 16:16:57 -0500 Subject: [PATCH 386/439] Fix issue with concatenating strings and arrays together (#40900) --- base/abstractarray.jl | 9 ++++++--- test/abstractarray.jl | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index fd5d631a08c44..c4f61b0d08642 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2186,6 +2186,9 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} return A end +cat_ndims(a) = 0 +cat_ndims(a::AbstractArray) = ndims(a) + function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N} # optimization for scalars and 1-length arrays that can be concatenated by copying them linearly # into the destination @@ -2195,7 +2198,7 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N} if a isa AbstractArray cat_size(a, N) == length(a) || throw(ArgumentError("all dimensions of elements other than $N must be of length 1")) - nd = max(nd, ndims(a)) + nd = max(nd, cat_ndims(a)) end Ndim += cat_size(a, N) end @@ -2221,7 +2224,7 @@ function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, d2 = row_first ? 1 : 2 # discover dimensions - @inbounds nd = max(N, ndims(as[1])) + @inbounds nd = max(N, cat_ndims(as[1])) outdims = zeros(Int, nd) # discover number of rows or columns @@ -2287,7 +2290,7 @@ function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Boo shapelength == lengthas || throw(ArgumentError("number of elements does not match shape; expected $(shapelength), got $lengthas)")) # discover dimensions - @inbounds nd = max(N, ndims(as[1])) + @inbounds nd = max(N, cat_ndims(as[1])) outdims = zeros(Int, nd) currentdims = zeros(Int, nd) blockcounts = zeros(Int, nd) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 05ec3efef1aab..4e5e92881d601 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1358,4 +1358,9 @@ end @test [v v; v v;;; v v; v v] == fill(1, 2, 2, 2) @test [v v v; v v v;;; v v v; v v v] == fill(1, 2, 3, 2) end + + # mixed scalars and arrays work, for numbers and strings + for v = (1, "test") + @test [v v;;; fill(v, 1, 2)] == fill(v, 1, 2, 2) + end end From a075e9f4706d613067de9896ce57bafa80d07319 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 21 May 2021 16:17:13 -0500 Subject: [PATCH 387/439] Disallow space-separated semicolons in array expression (#40903) --- src/julia-parser.scm | 2 ++ test/syntax.jl | 1 + 2 files changed, 3 insertions(+) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 9f176f95829db..1f594ff0a1414 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1919,6 +1919,8 @@ (parse-array-inner s a is-row-first semicolon-count max-level closer #f gotlinesep))) ((#\;) (or gotnewline (take-token s)) + (if (and (> semicolon-count 0) (ts:space? s)) ; disallow [a; ;b] + (error "multiple semicolons must be adjacent in an array expression")) (let ((next (peek-token s))) (let ((is-line-sep (if (and (not (null? is-row-first)) is-row-first (= semicolon-count 1)) diff --git a/test/syntax.jl b/test/syntax.jl index 448595ff1a8d7..d7e136f92dfcc 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2717,6 +2717,7 @@ end @test Meta.parse("[1\n;]") == :([1;]) # semicolons following a linebreak are fine @test Meta.parse("[1\n;;; 2]") == :([1;;; 2]) @test_throws ParseError Meta.parse("[1;\n;2]") # semicolons cannot straddle a line break + @test_throws ParseError Meta.parse("[1; ;2]") # semicolons cannot be separated by a space end # issue #25652 From ffce554a6775c165b9400d6ccde07c9715b55a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Raz=20Guzm=C3=A1n=20Macedo?= Date: Fri, 21 May 2021 16:19:01 -0500 Subject: [PATCH 388/439] add brief cat matrix doctests (#40800) Co-authored-by: Michael Abbott <32575566+mcabbott@users.noreply.github.com> --- base/abstractarray.jl | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c4f61b0d08642..33c549d060273 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1830,23 +1830,22 @@ dimensions for every new input array and putting zero blocks elsewhere. For exam `matrices[1]`, `matrices[2]`, ... as diagonal blocks and matching zero blocks away from the diagonal. -julia> cat(a, b, dims=3) -2×2×4 Array{Int64, 3}: -[:, :, 1] = - 1 2 - 3 4 - -[:, :, 2] = - 5 6 - 7 8 +See also [`hcat`](@ref), [`vcat`](@ref), [`hvcat`](@ref), [`repeat`](@ref). -[:, :, 3] = - 9 10 - 11 12 - -[:, :, 4] = - 13 14 - 15 16 +# Examples +```jldoctest +julia> cat([1 2; 3 4], [pi, pi], fill(10, 2,3,1); dims=2) +2×6×1 Array{Float64, 3}: +[:, :, 1] = + 1.0 2.0 3.14159 10.0 10.0 10.0 + 3.0 4.0 3.14159 10.0 10.0 10.0 + +julia> cat(true, trues(2,2), trues(4)', dims=(1,2)) +4×7 Matrix{Bool}: + 1 0 0 0 0 0 0 + 0 1 1 0 0 0 0 + 0 1 1 0 0 0 0 + 0 0 0 1 1 1 1 ``` """ @inline cat(A...; dims) = _cat(dims, A...) From d6701bb94c031a70258893b93efbced7d216828a Mon Sep 17 00:00:00 2001 From: Pramodh Gopalan V Date: Sat, 22 May 2021 02:50:18 +0530 Subject: [PATCH 389/439] LinearAlgebra: Add bareiss det for BigInt Matrices (#40128) :: Take 2 (#40868) --- NEWS.md | 1 + stdlib/LinearAlgebra/src/generic.jl | 52 ++++++++++++++++++++++++++++ stdlib/LinearAlgebra/test/generic.jl | 5 +++ 3 files changed, 58 insertions(+) diff --git a/NEWS.md b/NEWS.md index 169ebd2fa742e..27074440b3b49 100644 --- a/NEWS.md +++ b/NEWS.md @@ -108,6 +108,7 @@ Standard library changes * The shape of an `UpperHessenberg` matrix is preserved under certain arithmetic operations, e.g. when multiplying or dividing by an `UpperTriangular` matrix. ([#40039]) * `cis(A)` now supports matrix arguments ([#40194]). * `dot` now supports `UniformScaling` with `AbstractMatrix` ([#40250]). +* `det(M::AbstractMatrix{BigInt})` now calls `det_bareiss(M)`, which uses the [Bareiss](https://en.wikipedia.org/wiki/Bareiss_algorithm) algorithm to calculate precise values.([#40868]). #### Markdown diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ec8e9df654c46..e0e7cebe2b0e1 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1558,6 +1558,9 @@ function det(A::AbstractMatrix{T}) where T end det(x::Number) = x +# Resolve Issue #40128 +det(A::AbstractMatrix{BigInt}) = det_bareiss(A) + """ logabsdet(M) @@ -1620,6 +1623,55 @@ logdet(A) = log(det(A)) const NumberArray{T<:Number} = AbstractArray{T} +exactdiv(a, b) = a/b +exactdiv(a::Integer, b::Integer) = div(a, b) + +""" + det_bareiss!(M) + +Calculates the determinant of a matrix using the +[Bareiss Algorithm](https://en.wikipedia.org/wiki/Bareiss_algorithm) using +inplace operations. + +# Examples +```jldoctest +julia> M = [1 0; 2 2] +2×2 Matrix{Int64}: + 1 0 + 2 2 + +julia> LinearAlgebra.det_bareiss!(M) +2 +``` +""" +function det_bareiss!(M) + n = checksquare(M) + sign, prev = Int8(1), one(eltype(M)) + for i in 1:n-1 + if iszero(M[i,i]) # swap with another col to make nonzero + swapto = findfirst(!iszero, @view M[i,i+1:end]) + isnothing(swapto) && return zero(prev) + sign = -sign + Base.swapcols!(M, i, i + swapto) + end + for k in i+1:n, j in i+1:n + M[j,k] = exactdiv(M[j,k]*M[i,i] - M[j,i]*M[i,k], prev) + end + prev = M[i,i] + end + return sign * M[end,end] +end +""" + LinearAlgebra.det_bareiss(M) + +Calculates the determinant of a matrix using the +[Bareiss Algorithm](https://en.wikipedia.org/wiki/Bareiss_algorithm). +Also refer to [`det_bareiss!`](@ref). +""" +det_bareiss(M) = det_bareiss!(copy(M)) + + + """ promote_leaf_eltypes(itr) diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 92baaa6363b4f..cde16288f8f67 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -355,6 +355,11 @@ end @test [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]] ≈ [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]] end +@testset "Issue 40128" begin + @test det(BigInt[9 1 8 0; 0 0 8 7; 7 6 8 3; 2 9 7 7])::BigInt == -1 + @test det(BigInt[1 big(2)^65+1; 3 4])::BigInt == (4 - 3*(big(2)^65+1)) +end + # Minimal modulo number type - but not subtyping Number struct ModInt{n} k From e3dbc99b51b4b76b5277e1433f795c0f692104da Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sun, 23 May 2021 00:15:12 +0530 Subject: [PATCH 390/439] [NFC] add a space (#40914) --- doc/src/manual/distributed-computing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index 16f57314e945b..bfcfb883e8228 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -656,7 +656,7 @@ Once finalized, a reference becomes invalid and cannot be used in any further ca ## Local invocations Data is necessarily copied over to the remote node for execution. This is the case for both -remotecalls and when data is stored to a[`RemoteChannel`](@ref) / [`Future`](@ref Distributed.Future) on +remotecalls and when data is stored to a [`RemoteChannel`](@ref) / [`Future`](@ref Distributed.Future) on a different node. As expected, this results in a copy of the serialized objects on the remote node. However, when the destination node is the local node, i.e. the calling process id is the same as the remote node id, it is executed From 7429cb74e82609dd1edb9793c92c2b984a548b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Sun, 23 May 2021 13:34:50 +0200 Subject: [PATCH 391/439] Update inference.md --- doc/src/devdocs/inference.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/src/devdocs/inference.md b/doc/src/devdocs/inference.md index c8fea74995595..6181a1f64c846 100644 --- a/doc/src/devdocs/inference.md +++ b/doc/src/devdocs/inference.md @@ -37,9 +37,8 @@ m = first(mths) interp = Core.Compiler.NativeInterpreter() sparams = Core.svec() # this particular method doesn't have type-parameters optimize = true # run all inference optimizations -cached = false # force inference to happen (do not use cached results) types = Tuple{typeof(convert), atypes.parameters...} # Tuple{typeof(convert), Type{Int}, UInt} -Core.Compiler.typeinf_code(interp, types, sparams, optimize, cached) +Core.Compiler.typeinf_code(interp, m, types, sparams, optimize) ``` If your debugging adventures require a `MethodInstance`, you can look it up by From a8a42e98a4092a8afd5e1d8fadd9a1c5f9ab55ff Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sun, 23 May 2021 15:01:59 +0200 Subject: [PATCH 392/439] ccall docs: Fix type in Indirect Calls section Fixes a typo in the code example for a `dlsym` macro. A very small fix, but this just cost me, a Julia novice, half an hour :) --- doc/src/manual/calling-c-and-fortran-code.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 312e668afbd3f..89d535fd54344 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -928,7 +928,7 @@ macro dlsym(func, lib) let zlocal = $z[] if zlocal == C_NULL zlocal = dlsym($(esc(lib))::Ptr{Cvoid}, $(esc(func)))::Ptr{Cvoid} - $z[] = $zlocal + $z[] = zlocal end zlocal end From 3bbe22e589ecaa6062c370c4a9673a9b277a3a70 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Sun, 23 May 2021 09:02:40 -0400 Subject: [PATCH 393/439] Set up a few code owners (#40925) Co-authored-by: Viral B. Shah --- .github/CODEOWNERS | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 865abeebd82af..2e7d0f4692e73 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,7 @@ -/.github/workflows/ @JuliaLang/github-actions +/.github/ @JuliaLang/github-actions +/.buildkite/ @JuliaLang/github-actions +/src/ @JuliaLang/compiler +/stdlib/LinearAlgebra/ @JuliaLang/linearalgebra +/stdlib/libblastrampoline_jll/ @staticfloat +/test/ @JuliaLang/test + From 4ecbc16df572f54d3f05d872f13f31f9e6abc7ef Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Sun, 23 May 2021 09:29:21 -0400 Subject: [PATCH 394/439] Pare down the CODEOWNERS [skip ci] [ci skip] (#40929) --- .github/CODEOWNERS | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2e7d0f4692e73..6cab5b68b11e9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,7 +1,3 @@ +CODEOWNERS @JuliaLang/github-actions /.github/ @JuliaLang/github-actions /.buildkite/ @JuliaLang/github-actions -/src/ @JuliaLang/compiler -/stdlib/LinearAlgebra/ @JuliaLang/linearalgebra -/stdlib/libblastrampoline_jll/ @staticfloat -/test/ @JuliaLang/test - From 6f71de4193717f9267e98b4188aa6e4547146375 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 24 May 2021 18:16:26 -0400 Subject: [PATCH 395/439] move some shared properties to TypeName (#40741) --- base/compiler/abstractinterpretation.jl | 4 +- base/compiler/ssair/passes.jl | 10 +-- base/compiler/tfuncs.jl | 30 +++++---- base/compiler/typelimits.jl | 2 +- base/deepcopy.jl | 2 +- base/errorshow.jl | 2 +- base/pointer.jl | 2 +- base/reflection.jl | 14 ++--- base/refpointer.jl | 2 +- base/refvalue.jl | 2 +- base/show.jl | 2 +- src/abi_aarch64.cpp | 6 +- src/abi_arm.cpp | 2 +- src/builtins.c | 50 ++++++++++++--- src/cgutils.cpp | 25 ++++---- src/codegen.cpp | 4 +- src/datatype.c | 63 +++++-------------- src/dump.c | 26 ++++---- src/jltypes.c | 61 +++++++----------- src/julia.h | 21 ++++--- src/rtutils.c | 2 +- src/staticdata.c | 2 +- src/subtype.c | 2 +- src/typemap.c | 2 +- .../InteractiveUtils/src/InteractiveUtils.jl | 2 +- stdlib/REPL/src/docview.jl | 6 +- stdlib/Serialization/src/Serialization.jl | 16 ++--- sysimage.mk | 2 +- test/ccall.jl | 12 ++-- test/compiler/inference.jl | 6 +- test/compiler/inline.jl | 4 +- 31 files changed, 191 insertions(+), 195 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 0f2e2b78d6be5..465948c610c42 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1407,7 +1407,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), end elseif e.head === :new t = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv))[1] - if isconcretetype(t) && !t.mutable + if isconcretetype(t) && !t.name.mutable args = Vector{Any}(undef, length(e.args)-1) ats = Vector{Any}(undef, length(e.args)-1) anyconst = false @@ -1444,7 +1444,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), end elseif e.head === :splatnew t = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv))[1] - if length(e.args) == 2 && isconcretetype(t) && !t.mutable + if length(e.args) == 2 && isconcretetype(t) && !t.name.mutable at = abstract_eval_value(interp, e.args[2], vtypes, sv) n = fieldcount(t) if isa(at, Const) && isa(at.val, Tuple) && n == length(at.val) && diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index f27c71c2bcd6c..114b8c6033615 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -328,8 +328,8 @@ function lift_leaves(compact::IncrementalCompact, @nospecialize(stmt), if isa(typ, UnionAll) typ = unwrap_unionall(typ) end - (isa(typ, DataType) && (!typ.abstract)) || return nothing - @assert !typ.mutable + (isa(typ, DataType) && (!typ.name.abstract)) || return nothing + @assert !typ.name.mutable if length(def.args) < 1 + field if field > fieldcount(typ) return nothing @@ -625,7 +625,7 @@ function getfield_elim_pass!(ir::IRCode) if isa(typ, UnionAll) typ = unwrap_unionall(typ) end - if typ isa DataType && !typ.mutable + if typ isa DataType && !typ.name.mutable process_immutable_preserve(new_preserves, compact, def) old_preserves[pidx] = nothing continue @@ -662,7 +662,7 @@ function getfield_elim_pass!(ir::IRCode) def, typeconstraint = stmt.args[2], struct_typ - if struct_typ.mutable + if struct_typ.name.mutable isa(def, SSAValue) || continue let intermediaries = IdSet() callback = function(@nospecialize(pi), ssa::AnySSAValue) @@ -775,7 +775,7 @@ function getfield_elim_pass!(ir::IRCode) end # Could still end up here if we tried to setfield! and immutable, which would # error at runtime, but is not illegal to have in the IR. - typ.mutable || continue + typ.name.mutable || continue # Partition defuses by field fielddefuse = SSADefUse[SSADefUse() for _ = 1:fieldcount(typ)] ok = true diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 214087781a44f..25631d9594c98 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -28,15 +28,17 @@ const DATATYPE_NAME_FIELDINDEX = fieldindex(DataType, :name) const DATATYPE_PARAMETERS_FIELDINDEX = fieldindex(DataType, :parameters) const DATATYPE_TYPES_FIELDINDEX = fieldindex(DataType, :types) const DATATYPE_SUPER_FIELDINDEX = fieldindex(DataType, :super) -const DATATYPE_MUTABLE_FIELDINDEX = fieldindex(DataType, :mutable) const DATATYPE_INSTANCE_FIELDINDEX = fieldindex(DataType, :instance) -const DATATYPE_ABSTRACT_FIELDINDEX = fieldindex(DataType, :abstract) const DATATYPE_NAMES_FIELDINDEX = fieldindex(DataType, :names) +const DATATYPE_HASH_FIELDINDEX = fieldindex(DataType, :hash) const TYPENAME_NAME_FIELDINDEX = fieldindex(Core.TypeName, :name) const TYPENAME_MODULE_FIELDINDEX = fieldindex(Core.TypeName, :module) const TYPENAME_NAMES_FIELDINDEX = fieldindex(Core.TypeName, :names) const TYPENAME_WRAPPER_FIELDINDEX = fieldindex(Core.TypeName, :wrapper) +const TYPENAME_MUTABLE_FIELDINDEX = fieldindex(Core.TypeName, :mutable) +const TYPENAME_ABSTRACT_FIELDINDEX = fieldindex(Core.TypeName, :abstract) +const TYPENAME_HASH_FIELDINDEX = fieldindex(Core.TypeName, :hash) ########## # tfuncs # @@ -88,7 +90,7 @@ function instanceof_tfunc(@nospecialize(t)) # a real instance must be within the declared bounds of the type, # so we can intersect with the original wrapper. tr = typeintersect(tr, t′′.name.wrapper) - isconcrete = !t′′.abstract + isconcrete = !t′′.name.abstract if tr === Union{} # runtime unreachable (our inference Type{T} where S is # uninhabited with any runtime T that exists) @@ -271,7 +273,7 @@ function isdefined_tfunc(@nospecialize(arg1), @nospecialize(sym)) return Bool end a1 = unwrap_unionall(a1) - if isa(a1, DataType) && !a1.abstract + if isa(a1, DataType) && !a1.name.abstract if a1 === Module Symbol <: widenconst(sym) || return Bottom if isa(sym, Const) && isa(sym.val, Symbol) && isa(arg1, Const) && isdefined(arg1.val, sym.val) @@ -404,7 +406,7 @@ function nfields_tfunc(@nospecialize(x)) isa(x, Conditional) && return Const(0) x = unwrap_unionall(widenconst(x)) isconstType(x) && return Const(nfields(x.parameters[1])) - if isa(x, DataType) && !x.abstract + if isa(x, DataType) && !x.name.abstract if !(x.name === Tuple.name && isvatuple(x)) && !(x.name === _NAMEDTUPLE_NAME && !isconcretetype(x)) return Const(isdefined(x, :types) ? length(x.types) : length(x.name.names)) @@ -529,7 +531,7 @@ function typeof_tfunc(@nospecialize(t)) return typeof_tfunc(t.ub) elseif isa(t, UnionAll) u = unwrap_unionall(t) - if isa(u, DataType) && !u.abstract + if isa(u, DataType) && !u.name.abstract if u.name === Tuple.name uu = typeof_concrete_vararg(u) if uu !== nothing @@ -612,10 +614,9 @@ is_dt_const_field(fld::Int) = ( fld == DATATYPE_PARAMETERS_FIELDINDEX || fld == DATATYPE_TYPES_FIELDINDEX || fld == DATATYPE_SUPER_FIELDINDEX || - fld == DATATYPE_MUTABLE_FIELDINDEX || fld == DATATYPE_INSTANCE_FIELDINDEX || fld == DATATYPE_NAMES_FIELDINDEX || - fld == DATATYPE_ABSTRACT_FIELDINDEX + fld == DATATYPE_HASH_FIELDINDEX ) function const_datatype_getfield_tfunc(@nospecialize(sv), fld::Int) if fld == DATATYPE_INSTANCE_FIELDINDEX @@ -649,7 +650,7 @@ function fieldcount_noerror(@nospecialize t) end abstr = true else - abstr = t.abstract || (t.name === Tuple.name && isvatuple(t)) + abstr = t.name.abstract || (t.name === Tuple.name && isvatuple(t)) end if abstr return nothing @@ -717,7 +718,7 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), @nospecialize getfield_nothrow(rewrap(s.b, s00), name, inbounds) elseif isa(s, DataType) # Can't say anything about abstract types - s.abstract && return false + s.name.abstract && return false # If all fields are always initialized, and bounds check is disabled, we can assume # we don't throw if bounds_check_disabled && !isvatuple(s) && s.name !== NamedTuple.body.body.name && fieldcount(s) == s.ninitialized @@ -775,6 +776,9 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name)) if (fld == TYPENAME_NAME_FIELDINDEX || fld == TYPENAME_MODULE_FIELDINDEX || fld == TYPENAME_WRAPPER_FIELDINDEX || + fld == TYPENAME_MUTABLE_FIELDINDEX || + fld == TYPENAME_ABSTRACT_FIELDINDEX || + fld == TYPENAME_HASH_FIELDINDEX || (fld == TYPENAME_NAMES_FIELDINDEX && isdefined(sv, fld))) return Const(getfield(sv, fld)) end @@ -799,7 +803,7 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name)) end s = widenconst(s) end - if isType(s) || !isa(s, DataType) || s.abstract + if isType(s) || !isa(s, DataType) || s.name.abstract return Any end s = s::DataType @@ -925,7 +929,7 @@ function _fieldtype_nothrow(@nospecialize(s), exact::Bool, name::Const) return exact ? (a || b) : (a && b) end u isa DataType || return false - u.abstract && return false + u.name.abstract && return false if u.name === _NAMEDTUPLE_NAME && !isconcretetype(u) # TODO: better approximate inference return false @@ -986,7 +990,7 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name)) _fieldtype_tfunc(rewrap(u.b, s), exact, name)) end u isa DataType || return Union{Type, TypeVar} - if u.abstract + if u.name.abstract # Abstract types have no fields exact && return Bottom # Type{...} without free typevars has no subtypes, so it is actually diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index 2eb2d6f542377..372989e114022 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -256,7 +256,7 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe let tPi = unwrap_unionall(tPi), cPi = unwrap_unionall(cPi) if isa(tPi, DataType) && isa(cPi, DataType) && - !tPi.abstract && !cPi.abstract && + !tPi.name.abstract && !cPi.name.abstract && sym_isless(cPi.name.name, tPi.name.name) # allow collect on (anonymous) Generators to nest, provided that their functions are appropriately ordered # TODO: is there a better way? diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 36c9c399def54..75ec753a4cd84 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -53,7 +53,7 @@ end function deepcopy_internal(@nospecialize(x), stackdict::IdDict) T = typeof(x)::DataType nf = nfields(x) - if T.mutable + if T.name.mutable if haskey(stackdict, x) return stackdict[x] end diff --git a/base/errorshow.jl b/base/errorshow.jl index 615b1ff4253df..19dc85ea52b81 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -242,7 +242,7 @@ function showerror(io::IO, ex::MethodError) if f === Base.convert && length(arg_types_param) == 2 && !is_arg_types f_is_function = true show_convert_error(io, ex, arg_types_param) - elseif isempty(methods(f)) && isa(f, DataType) && f.abstract + elseif isempty(methods(f)) && isa(f, DataType) && f.name.abstract print(io, "no constructors have been defined for ", f) elseif isempty(methods(f)) && !isa(f, Function) && !isa(f, Type) print(io, "objects of type ", ft, " are not callable") diff --git a/base/pointer.jl b/base/pointer.jl index 0813d0a0c9735..1739c89f46a0d 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -143,7 +143,7 @@ See also: [`unsafe_pointer_to_objref`](@ref). """ function pointer_from_objref(@nospecialize(x)) @_inline_meta - typeof(x).mutable || error("pointer_from_objref cannot be used on immutable objects") + typeof(x).name.mutable || error("pointer_from_objref cannot be used on immutable objects") ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x) end diff --git a/base/reflection.jl b/base/reflection.jl index 118d590321ed5..33327b64a6a2a 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -154,7 +154,7 @@ function fieldname(t::DataType, i::Integer) end throw_need_pos_int(i) = throw(ArgumentError("Field numbers must be positive integers. $i is invalid.")) - t.abstract && throw_not_def_field() + t.name.abstract && throw_not_def_field() names = _fieldnames(t) n_fields = length(names)::Int i > n_fields && throw_field_access(t, i, n_fields) @@ -471,7 +471,7 @@ true !!! compat "Julia 1.5" This function requires at least Julia 1.5. """ -ismutable(@nospecialize(x)) = (@_pure_meta; typeof(x).mutable) +ismutable(@nospecialize(x)) = (@_pure_meta; typeof(x).name.mutable) """ @@ -486,7 +486,7 @@ Determine whether type `T` was declared as a mutable type function ismutabletype(@nospecialize(t::Type)) t = unwrap_unionall(t) # TODO: what to do for `Union`? - return isa(t, DataType) && t.mutable + return isa(t, DataType) && t.name.mutable end @@ -502,7 +502,7 @@ function isstructtype(@nospecialize(t::Type)) # TODO: what to do for `Union`? isa(t, DataType) || return false hasfield = !isdefined(t, :types) || !isempty(t.types) - return hasfield || (t.size == 0 && !t.abstract) + return hasfield || (t.size == 0 && !t.name.abstract) end """ @@ -517,7 +517,7 @@ function isprimitivetype(@nospecialize(t::Type)) # TODO: what to do for `Union`? isa(t, DataType) || return false hasfield = !isdefined(t, :types) || !isempty(t.types) - return !hasfield && t.size != 0 && !t.abstract + return !hasfield && t.size != 0 && !t.name.abstract end """ @@ -623,7 +623,7 @@ function isabstracttype(@nospecialize(t)) @_pure_meta t = unwrap_unionall(t) # TODO: what to do for `Union`? - return isa(t, DataType) && t.abstract + return isa(t, DataType) && t.name.abstract end """ @@ -757,7 +757,7 @@ function fieldcount(@nospecialize t) end abstr = true else - abstr = t.abstract || (t.name === Tuple.name && isvatuple(t)) + abstr = t.name.abstract || (t.name === Tuple.name && isvatuple(t)) end if abstr throw(ArgumentError("type does not have a definite number of fields")) diff --git a/base/refpointer.jl b/base/refpointer.jl index 67cec0925ff58..725b2d05f95ee 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -117,7 +117,7 @@ convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1) function unsafe_convert(P::Union{Type{Ptr{T}},Type{Ptr{Cvoid}}}, b::RefArray{T})::P where T if allocatedinline(T) p = pointer(b.x, b.i) - elseif isconcretetype(T) && T.mutable + elseif isconcretetype(T) && T.name.mutable p = pointer_from_objref(b.x[b.i]) else # see comment on equivalent branch for RefValue diff --git a/base/refvalue.jl b/base/refvalue.jl index cf5f4e6b74d6f..69d9a31061724 100644 --- a/base/refvalue.jl +++ b/base/refvalue.jl @@ -38,7 +38,7 @@ isassigned(x::RefValue) = isdefined(x, :x) function unsafe_convert(P::Union{Type{Ptr{T}},Type{Ptr{Cvoid}}}, b::RefValue{T})::P where T if allocatedinline(T) p = pointer_from_objref(b) - elseif isconcretetype(T) && T.mutable + elseif isconcretetype(T) && T.name.mutable p = pointer_from_objref(b.x) else # If the slot is not leaf type, it could be either immutable or not. diff --git a/base/show.jl b/base/show.jl index 595af52a5fc1c..ca92c349db809 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2616,7 +2616,7 @@ function dump(io::IOContext, x::DataType, n::Int, indent) if x !== Any print(io, " <: ", supertype(x)) end - if n > 0 && !(x <: Tuple) && !x.abstract + if n > 0 && !(x <: Tuple) && !x.name.abstract tvar_io::IOContext = io for tparam in x.parameters # approximately recapture the list of tvar parameterization diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index 4d55d3d69a8de..3a0a5c25dc859 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -16,7 +16,7 @@ struct ABI_AArch64Layout : AbiLayout { Type *get_llvm_vectype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - // `!dt->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields > 0` + // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields > 0` if (dt->layout == NULL || jl_is_layout_opaque(dt->layout)) return nullptr; size_t nfields = dt->layout->nfields; @@ -62,7 +62,7 @@ Type *get_llvm_vectype(jl_datatype_t *dt) const Type *get_llvm_fptype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - // `!dt->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields == 0` + // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields == 0` Type *lltype; // Check size first since it's cheaper. switch (jl_datatype_size(dt)) { @@ -88,7 +88,7 @@ Type *get_llvm_fptype(jl_datatype_t *dt) const Type *get_llvm_fp_or_vectype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - if (dt->mutabl || dt->layout->npointers || dt->layout->haspadding) + if (dt->name->mutabl || dt->layout->npointers || dt->layout->haspadding) return nullptr; return dt->layout->nfields ? get_llvm_vectype(dt) : get_llvm_fptype(dt); } diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index 1a5d3d0651368..b0ae29a623abb 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -33,7 +33,7 @@ bool needPassByRef(jl_datatype_t *dt, AttrBuilder &ab) override Type *get_llvm_fptype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - if (dt->mutabl || jl_datatype_nfields(dt) != 0) + if (dt->name->mutabl || jl_datatype_nfields(dt) != 0) return NULL; Type *lltype; // Check size first since it's cheaper. diff --git a/src/builtins.c b/src/builtins.c index c6abe4b8e602d..75e3f87151672 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -183,7 +183,7 @@ static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env, int tvar_ } if (dt == jl_symbol_type) return 0; - assert(!dt->mutabl); + assert(!dt->name->mutabl); return jl_egal__bits(a, b, dt); } @@ -324,7 +324,7 @@ static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) JL_NOTSAFEPOIN } if (tv == jl_symbol_type) return ((jl_sym_t*)v)->hash; - assert(!tv->mutabl); + assert(!tv->name->mutabl); return immut_id_(tv, v, tv->hash); } @@ -358,7 +358,7 @@ static uintptr_t immut_id_(jl_datatype_t *dt, jl_value_t *v, uintptr_t h) JL_NOT uint8_t sel = ((uint8_t*)vo)[jl_field_size(dt, f) - 1]; fieldtype = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)fieldtype, sel); } - assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl); + assert(jl_is_datatype(fieldtype) && !fieldtype->name->abstract && !fieldtype->name->mutabl); int32_t first_ptr = fieldtype->layout->first_ptr; if (first_ptr >= 0 && ((jl_value_t**)vo)[first_ptr] == NULL) { // If the field is a inline immutable that can be can be undef @@ -391,7 +391,7 @@ static uintptr_t NOINLINE jl_object_id__cold(jl_datatype_t *dt, jl_value_t *v) J return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #endif } - if (dt->mutabl) + if (dt->name->mutabl) return inthash((uintptr_t)v); return immut_id_(dt, v, dt->hash); } @@ -451,7 +451,7 @@ JL_CALLABLE(jl_f_sizeof) if (jl_is_datatype(x)) { jl_datatype_t *dx = (jl_datatype_t*)x; if (dx->layout == NULL) { - if (dx->abstract) + if (dx->name->abstract) jl_errorf("Abstract type %s does not have a definite size.", jl_symbol_name(dx->name->name)); else jl_errorf("Argument is an incomplete %s type and does not have a definite size.", jl_symbol_name(dx->name->name)); @@ -473,7 +473,7 @@ JL_CALLABLE(jl_f_sizeof) return jl_box_long((1+jl_svec_len(x))*sizeof(void*)); jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(x); assert(jl_is_datatype(dt)); - assert(!dt->abstract); + assert(!dt->name->abstract); return jl_box_long(jl_datatype_size(dt)); } @@ -840,7 +840,7 @@ JL_CALLABLE(jl_f_setfield) assert(jl_is_datatype(st)); if (st == jl_module_type) jl_error("cannot assign variables in other modules"); - if (!st->mutabl) + if (!st->name->mutabl) jl_errorf("setfield! immutable struct of type %s cannot be changed", jl_symbol_name(st->name->name)); size_t idx; if (jl_is_long(args[1])) { @@ -1337,6 +1337,32 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft) return 1; } +static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout) JL_NOTSAFEPOINT +{ + if (jl_is_uniontype(p)) + return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) || + references_name(((jl_uniontype_t*)p)->b, name, affects_layout); + if (jl_is_unionall(p)) + return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0) || + references_name(((jl_unionall_t*)p)->body, name, affects_layout); + if (jl_is_typevar(p)) + return references_name(((jl_tvar_t*)p)->ub, name, 0) || + references_name(((jl_tvar_t*)p)->lb, name, 0); + if (jl_is_datatype(p)) { + jl_datatype_t *dp = (jl_datatype_t*)p; + if (affects_layout && dp->name == name) + return 1; + affects_layout = dp->types == NULL || jl_svec_len(dp->types) != 0; + size_t i, l = jl_nparams(p); + for (i = 0; i < l; i++) { + if (references_name(jl_tparam(p, i), name, affects_layout)) + return 1; + } + } + return 0; +} + + JL_CALLABLE(jl_f__typebody) { JL_NARGS(_typebody!, 1, 2); @@ -1361,6 +1387,14 @@ JL_CALLABLE(jl_f__typebody) else { dt->types = (jl_svec_t*)ft; jl_gc_wb(dt, ft); + size_t i, nf = jl_svec_len(ft); + for (i = 0; i < nf; i++) { + jl_value_t *fld = jl_svecref(ft, i); + if (references_name(fld, dt->name, 1)) { + dt->name->references_self = 1; + break; + } + } } } @@ -1386,8 +1420,6 @@ static int equiv_type(jl_value_t *ta, jl_value_t *tb) jl_datatype_t *dtb = (jl_datatype_t*)jl_unwrap_unionall(tb); if (!(jl_typeof(dta) == jl_typeof(dtb) && dta->name->name == dtb->name->name && - dta->abstract == dtb->abstract && - dta->mutabl == dtb->mutabl && (jl_svec_len(jl_field_names(dta)) != 0 || dta->size == dtb->size) && dta->ninitialized == dtb->ninitialized && jl_egal((jl_value_t*)jl_field_names(dta), (jl_value_t*)jl_field_names(dtb)) && diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 652b0a8791aae..c3f14299a133e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -982,10 +982,13 @@ static Value *emit_sizeof(jl_codectx_t &ctx, const jl_cgval_t &p) static Value *emit_datatype_mutabl(jl_codectx_t &ctx, Value *dt) { - Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), T_pint8); - Value *Idx = ConstantInt::get(T_size, offsetof(jl_datatype_t, mutabl)); + Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), T_ppint8); + Value *Idx = ConstantInt::get(T_size, offsetof(jl_datatype_t, name)); + Value *Nam = tbaa_decorate(tbaa_const, + ctx.builder.CreateAlignedLoad(T_pint8, ctx.builder.CreateInBoundsGEP(T_pint8, Ptr, Idx), Align(sizeof(int8_t*)))); + Value *Idx2 = ConstantInt::get(T_size, offsetof(jl_typename_t, name)); Value *mutabl = tbaa_decorate(tbaa_const, - ctx.builder.CreateAlignedLoad(T_int8, ctx.builder.CreateInBoundsGEP(T_int8, Ptr, Idx), Align(1))); + ctx.builder.CreateAlignedLoad(T_int8, ctx.builder.CreateInBoundsGEP(T_int8, Nam, Idx2), Align(1))); return ctx.builder.CreateTrunc(mutabl, T_int1); } @@ -1111,7 +1114,7 @@ static bool _can_optimize_isa(jl_value_t *type, int &counter) if (jl_is_concrete_type(type)) return true; jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(type); - if (jl_is_datatype(dt) && !dt->abstract && jl_subtype(dt->name->wrapper, type)) + if (jl_is_datatype(dt) && !dt->name->abstract && jl_subtype(dt->name->wrapper, type)) return true; return false; } @@ -1227,7 +1230,7 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, track_pjlvalue(ctx, literal_pointer_val(ctx, intersected_type))), false); } jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(intersected_type); - if (jl_is_datatype(dt) && !dt->abstract && jl_subtype(dt->name->wrapper, type)) { + if (jl_is_datatype(dt) && !dt->name->abstract && jl_subtype(dt->name->wrapper, type)) { // intersection is a supertype of all instances of its constructor, // so the isa test reduces to a comparison of the typename by pointer return std::make_pair( @@ -1713,7 +1716,7 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, assert(jl_is_concrete_type(jft)); idx = idx0(); Value *ptr = maybe_decay_tracked(ctx, data_pointer(ctx, strct)); - if (!stt->mutabl && !(maybe_null && (jft == (jl_value_t*)jl_bool_type || + if (!stt->name->mutabl && !(maybe_null && (jft == (jl_value_t*)jl_bool_type || ((jl_datatype_t*)jft)->layout->npointers))) { // just compute the pointer and let user load it when necessary Type *fty = julia_type_to_llvm(ctx, jft); @@ -1806,7 +1809,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st // ConstantAsMetadata::get(ConstantInt::get(T_int8, 0)), // ConstantAsMetadata::get(ConstantInt::get(T_int8, union_max)) })); Value *tindex = ctx.builder.CreateNUWAdd(ConstantInt::get(T_int8, 1), tindex0); - if (jt->mutabl) { + if (jt->name->mutabl) { // move value to an immutable stack slot (excluding tindex) Type *ET = IntegerType::get(jl_LLVMContext, 8 * al); AllocaInst *lv = emit_static_alloca(ctx, ET); @@ -1817,7 +1820,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st return mark_julia_slot(addr, jfty, tindex, tbaa); } assert(jl_is_concrete_type(jfty)); - if (!jt->mutabl && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type || + if (!jt->name->mutabl && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type || ((jl_datatype_t*)jfty)->layout->npointers))) { // just compute the pointer and let user load it when necessary return mark_julia_slot(addr, jfty, NULL, tbaa); @@ -2432,7 +2435,7 @@ static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t v = ctx.builder.CreateExtractValue(v, makeArrayRef(&zero, 1)); box = call_with_attrs(ctx, box_ssavalue_func, v); } - else if (!jb->abstract && jl_datatype_nbits(jb) == 0) { + else if (!jb->name->abstract && jl_datatype_nbits(jb) == 0) { // singleton assert(jb->instance != NULL); return track_pjlvalue(ctx, literal_pointer_val(ctx, jb->instance)); @@ -2836,7 +2839,7 @@ static void emit_setfield(jl_codectx_t &ctx, jl_datatype_t *sty, const jl_cgval_t &strct, size_t idx0, const jl_cgval_t &rhs, bool checked, bool wb) { - if (sty->mutabl || !checked) { + if (sty->name->mutabl || !checked) { assert(strct.ispointer()); size_t byte_offset = jl_field_offset(sty, idx0); Value *addr = data_pointer(ctx, strct); @@ -2892,7 +2895,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg assert(jl_is_concrete_type(ty)); jl_datatype_t *sty = (jl_datatype_t*)ty; size_t nf = jl_datatype_nfields(sty); - if (nf > 0 || sty->mutabl) { + if (nf > 0 || sty->name->mutabl) { if (deserves_stack(ty)) { Type *lt = julia_type_to_llvm(ctx, ty); unsigned na = nargs < nf ? nargs : nf; diff --git a/src/codegen.cpp b/src/codegen.cpp index 63d9946b2b673..1a2837737d203 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1362,7 +1362,7 @@ static inline jl_cgval_t update_julia_type(jl_codectx_t &ctx, const jl_cgval_t & if (jl_is_concrete_type(utyp)) alwaysboxed = !jl_is_pointerfree(utyp); else - alwaysboxed = !((jl_datatype_t*)utyp)->abstract && ((jl_datatype_t*)utyp)->mutabl; + alwaysboxed = !((jl_datatype_t*)utyp)->name->abstract && ((jl_datatype_t*)utyp)->name->mutabl; if (alwaysboxed) { // discovered that this union-split type must actually be isboxed if (v.Vboxed) { @@ -3149,7 +3149,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, else if (f == jl_builtin_sizeof && nargs == 1) { const jl_cgval_t &obj = argv[1]; jl_datatype_t *sty = (jl_datatype_t*)jl_unwrap_unionall(obj.typ); - assert(jl_string_type->mutabl); + assert(jl_string_type->name->mutabl); if (sty == jl_string_type || sty == jl_simplevector_type) { if (obj.constant) { size_t sz; diff --git a/src/datatype.c b/src/datatype.c index 86ad3170a701e..8c9bae6f09f2f 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -60,7 +60,7 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo return mt; } -JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *module) +JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *module, int abstract, int mutabl) { jl_ptls_t ptls = jl_get_ptls_states(); jl_typename_t *tn = @@ -73,6 +73,9 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu tn->linearcache = jl_emptysvec; tn->names = NULL; tn->hash = bitmix(bitmix(module ? module->build_id : 0, name->hash), 0xa1ada1da); + tn->abstract = abstract; + tn->mutabl = mutabl; + tn->references_self = 0; tn->mt = NULL; tn->partial = NULL; return tn; @@ -220,8 +223,8 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t) STATIC_INLINE int jl_is_datatype_make_singleton(jl_datatype_t *d) { - return (!d->abstract && jl_datatype_size(d) == 0 && d != jl_symbol_type && d->name != jl_array_typename && - d->isconcretetype && !d->mutabl); + return (!d->name->abstract && jl_datatype_size(d) == 0 && d != jl_symbol_type && d->name != jl_array_typename && + d->isconcretetype && !d->name->mutabl); } STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st) @@ -314,31 +317,6 @@ int jl_pointer_egal(jl_value_t *t) return 0; } -static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout) JL_NOTSAFEPOINT -{ - if (jl_is_uniontype(p)) - return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) || - references_name(((jl_uniontype_t*)p)->b, name, affects_layout); - if (jl_is_unionall(p)) - return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0) || - references_name(((jl_unionall_t*)p)->body, name, affects_layout); - if (jl_is_typevar(p)) - return references_name(((jl_tvar_t*)p)->ub, name, 0) || - references_name(((jl_tvar_t*)p)->lb, name, 0); - if (jl_is_datatype(p)) { - jl_datatype_t *dp = (jl_datatype_t*)p; - if (affects_layout && dp->name == name) - return 1; - affects_layout = dp->types == NULL || jl_svec_len(dp->types) != 0; - size_t i, l = jl_nparams(p); - for (i = 0; i < l; i++) { - if (references_name(jl_tparam(p, i), name, affects_layout)) - return 1; - } - } - return 0; -} - static void throw_ovf(int should_malloc, void *desc, jl_datatype_t* st, int offset) { if (should_malloc) @@ -359,8 +337,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) if (w->types == NULL) // we got called too early--we'll be back return; size_t i, nfields = jl_svec_len(st->types); - int isinlinealloc = st->isconcretetype && !st->mutabl; - int isbitstype = isinlinealloc; + int isinlinealloc = st->isconcretetype && !st->name->mutabl && !st->name->references_self; assert(st->ninitialized <= nfields); if (st == w && st->layout) { // this check allows us to force re-computation of the layout for some types during init @@ -419,22 +396,10 @@ void jl_compute_field_offsets(jl_datatype_t *st) } } - // compute whether this type may ever be inlined - // based solely on whether its definition is self-referential - if (isinlinealloc) { - size_t i, nf = jl_svec_len(w->types); - for (i = 0; i < nf; i++) { - jl_value_t *fld = jl_svecref(w->types, i); - if (references_name(fld, w->name, 1)) { - isinlinealloc = 0; - isbitstype = 0; - break; - } - } - for (i = 0; isbitstype && i < nfields; i++) { - jl_value_t *fld = jl_field_type(st, i); - isbitstype = jl_isbits(fld); - } + int isbitstype = isinlinealloc; + for (i = 0; isbitstype && i < nfields; i++) { + jl_value_t *fld = jl_field_type(st, i); + isbitstype = jl_isbits(fld); } // if we didn't reuse the layout above, compute it now @@ -592,8 +557,6 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype( jl_gc_wb(t, t->parameters); t->types = ftypes; if (ftypes != NULL) jl_gc_wb(t, t->types); - t->abstract = abstract; - t->mutabl = mutabl; t->ninitialized = ninitialized; t->size = 0; @@ -601,9 +564,11 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype( if (jl_is_typename(name)) { // This code-path is used by the Serialization module to by-pass normal expectations tn = (jl_typename_t*)name; + tn->abstract = abstract; + tn->mutabl = mutabl; } else { - tn = jl_new_typename_in((jl_sym_t*)name, module); + tn = jl_new_typename_in((jl_sym_t*)name, module, abstract, mutabl); if (super == jl_function_type || super == jl_builtin_type || is_anonfn_typename(jl_symbol_name(name))) { // Callable objects (including compiler-generated closures) get independent method tables // as an optimization diff --git a/src/dump.c b/src/dump.c index 2a6c8318c2095..fc34417123025 100644 --- a/src/dump.c +++ b/src/dump.c @@ -270,7 +270,7 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_ write_int32(s->s, dt->size); int has_instance = (dt->instance != NULL); int has_layout = (dt->layout != NULL); - write_uint8(s->s, dt->abstract | (dt->mutabl << 1) | (has_layout << 2) | (has_instance << 3)); + write_uint8(s->s, dt->name->abstract | (has_layout << 1) | (has_instance << 2)); write_uint8(s->s, dt->hasfreetypevars | (dt->isconcretetype << 1) | (dt->isdispatchtuple << 2) @@ -279,7 +279,7 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_ | (dt->isinlinealloc << 5) | (dt->has_concrete_subtype << 6) | (dt->cached_by_hash << 7)); - if (!dt->abstract) { + if (!dt->name->abstract) { write_uint16(s->s, dt->ninitialized); } write_int32(s->s, dt->hash); @@ -815,6 +815,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, tn->wrapper); jl_serialize_value(s, tn->mt); ios_write(s->s, (char*)&tn->hash, sizeof(tn->hash)); + write_uint8(s->s, tn->abstract | (tn->mutabl << 1) | (tn->references_self << 2)); } return; } @@ -833,7 +834,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li ios_write(s->s, last, prevptr - last); jl_value_t *e = *(jl_value_t**)prevptr; JL_GC_PROMISE_ROOTED(e); - if (t->mutabl && e && jl_field_isptr(t, i - 1) && jl_is_cpointer(e) && + if (t->name->mutabl && e && jl_field_isptr(t, i - 1) && jl_is_cpointer(e) && jl_unbox_voidpointer(e) != (void*)-1 && jl_unbox_voidpointer(e) != NULL) // reset Ptr fields to C_NULL (but keep MAP_FAILED / INVALID_HANDLE) jl_serialize_cnull(s, jl_typeof(e)); @@ -849,7 +850,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } if (i == nf) break; - if (t->mutabl && jl_is_cpointer_type(jl_field_type(t, i)) && *(void**)ptr != (void*)-1) { + if (t->name->mutabl && jl_is_cpointer_type(jl_field_type(t, i)) && *(void**)ptr != (void*)-1) { if (ptr > last) ios_write(s->s, last, ptr - last); char *n = NULL; @@ -1263,10 +1264,9 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v uint8_t flags = read_uint8(s->s); uint8_t memflags = read_uint8(s->s); dt->size = size; - dt->abstract = flags & 1; - dt->mutabl = (flags >> 1) & 1; - int has_layout = (flags >> 2) & 1; - int has_instance = (flags >> 3) & 1; + int abstract = flags & 1; + int has_layout = (flags >> 1) & 1; + int has_instance = (flags >> 2) & 1; dt->hasfreetypevars = memflags & 1; dt->isconcretetype = (memflags >> 1) & 1; dt->isdispatchtuple = (memflags >> 2) & 1; @@ -1275,10 +1275,10 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v dt->isinlinealloc = (memflags >> 5) & 1; dt->has_concrete_subtype = (memflags >> 6) & 1; dt->cached_by_hash = (memflags >> 7) & 1; - if (!dt->abstract) - dt->ninitialized = read_uint16(s->s); - else + if (abstract) dt->ninitialized = 0; + else + dt->ninitialized = read_uint16(s->s); dt->hash = read_int32(s->s); if (has_layout) { @@ -1728,6 +1728,10 @@ static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, tn->mt = (jl_methtable_t*)jl_deserialize_value(s, (jl_value_t**)&tn->mt); jl_gc_wb(tn, tn->mt); ios_read(s->s, (char*)&tn->hash, sizeof(tn->hash)); + int8_t flags = read_int8(s->s); + tn->abstract = flags & 1; + tn->mutabl = (flags>>1) & 1; + tn->references_self = (flags>>2) & 1; } else { jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(jl_get_global(m, sym)); diff --git a/src/jltypes.c b/src/jltypes.c index 2ba69caf1991e..f759173f2051c 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -62,9 +62,8 @@ static int has_free_typevars(jl_value_t *v, jl_typeenv_t *env) JL_NOTSAFEPOINT if (expect == 0 || env == NULL) return expect; size_t i; - for (i=0; i < jl_nparams(v); i++) { - if (has_free_typevars(jl_tparam(v,i), env)) { - assert(expect); + for (i = 0; i < jl_nparams(v); i++) { + if (has_free_typevars(jl_tparam(v, i), env)) { return 1; } } @@ -1082,7 +1081,7 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt, int cacheable) { int istuple = (dt->name == jl_tuple_typename); dt->hasfreetypevars = 0; - dt->isconcretetype = !dt->abstract; + dt->isconcretetype = !dt->name->abstract; dt->isdispatchtuple = istuple; size_t i, l = jl_nparams(dt); for (i = 0; i < l; i++) { @@ -1398,8 +1397,6 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value ndt->types = jl_emptysvec; } } - ndt->mutabl = dt->mutabl; - ndt->abstract = dt->abstract; ndt->size = 0; jl_precompute_memoized_dt(ndt, cacheable); if (istuple) @@ -1437,7 +1434,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value } else if (!isnamedtuple && !istuple) { assert(ftypes != jl_emptysvec || jl_field_names(ndt) == jl_emptysvec); - assert(ftypes == jl_emptysvec || !ndt->abstract); + assert(ftypes == jl_emptysvec || !ndt->name->abstract); if (ftypes == jl_emptysvec) { ndt->types = ftypes; } @@ -1453,7 +1450,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value // now publish the finished result if (cacheable) { - if (!jl_is_primitivetype(dt) && ndt->types != NULL && !ndt->abstract) { + if (!jl_is_primitivetype(dt) && ndt->types != NULL && !ndt->name->abstract) { jl_compute_field_offsets(ndt); } jl_cache_type_(ndt); @@ -1884,11 +1881,12 @@ void jl_init_types(void) JL_GC_DISABLED jl_type_typename->mt = jl_type_type_mt; // initialize them. lots of cycles. - jl_datatype_type->name = jl_new_typename_in(jl_symbol("DataType"), core); + // NOTE: types are not actually mutable, but we want to ensure they are heap-allocated with stable addresses + jl_datatype_type->name = jl_new_typename_in(jl_symbol("DataType"), core, 0, 1); jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->names = jl_perm_symsvec(20, + jl_datatype_type->name->names = jl_perm_symsvec(18, "name", "super", "parameters", @@ -1899,8 +1897,6 @@ void jl_init_types(void) JL_GC_DISABLED "size", "ninitialized", "hash", - "abstract", - "mutable", "hasfreetypevars", "isconcretetype", "isdispatchtuple", @@ -1909,7 +1905,7 @@ void jl_init_types(void) JL_GC_DISABLED "isinlinealloc", "has_concrete_subtype", "cached_by_hash"); - jl_datatype_type->types = jl_svec(20, + jl_datatype_type->types = jl_svec(18, jl_typename_type, jl_datatype_type, jl_simplevector_type, @@ -1917,32 +1913,28 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, // instance jl_any_type, jl_any_type, jl_any_type, jl_any_type, // properties jl_any_type, jl_any_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type); - jl_datatype_type->abstract = 0; - // NOTE: types are not actually mutable, but we want to ensure they are heap-allocated with stable addresses - jl_datatype_type->mutabl = 1; + jl_any_type, jl_any_type, jl_any_type, jl_any_type); jl_datatype_type->ninitialized = 3; jl_precompute_memoized_dt(jl_datatype_type, 1); - jl_typename_type->name = jl_new_typename_in(jl_symbol("TypeName"), core); + jl_typename_type->name = jl_new_typename_in(jl_symbol("TypeName"), core, 0, 1); jl_typename_type->name->wrapper = (jl_value_t*)jl_typename_type; jl_typename_type->name->mt = jl_nonfunction_mt; jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; - jl_typename_type->name->names = jl_perm_symsvec(9, "name", "module", + jl_typename_type->name->names = jl_perm_symsvec(12, "name", "module", "names", "wrapper", "cache", "linearcache", - "hash", "mt", "partial"); - jl_typename_type->types = jl_svec(9, jl_symbol_type, jl_any_type, jl_simplevector_type, + "hash", "abstract", "mutable", "references_self", + "mt", "partial"); + jl_typename_type->types = jl_svec(12, jl_symbol_type, jl_any_type, jl_simplevector_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, - jl_any_type, jl_methtable_type, jl_any_type); - jl_typename_type->abstract = 0; - jl_typename_type->mutabl = 1; + jl_any_type, jl_any_type, jl_any_type, jl_any_type, + jl_methtable_type, jl_any_type); jl_typename_type->ninitialized = 2; jl_precompute_memoized_dt(jl_typename_type, 1); - jl_methtable_type->name = jl_new_typename_in(jl_symbol("MethodTable"), core); + jl_methtable_type->name = jl_new_typename_in(jl_symbol("MethodTable"), core, 0, 1); jl_methtable_type->name->wrapper = (jl_value_t*)jl_methtable_type; jl_methtable_type->name->mt = jl_nonfunction_mt; jl_methtable_type->super = jl_any_type; @@ -1956,12 +1948,10 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_any_type/*module*/, jl_any_type/*any vector*/, jl_any_type/*long*/, jl_any_type/*int32*/, jl_any_type/*uint8*/, jl_any_type/*uint8*/); - jl_methtable_type->abstract = 0; - jl_methtable_type->mutabl = 1; jl_methtable_type->ninitialized = 5; jl_precompute_memoized_dt(jl_methtable_type, 1); - jl_symbol_type->name = jl_new_typename_in(jl_symbol("Symbol"), core); + jl_symbol_type->name = jl_new_typename_in(jl_symbol("Symbol"), core, 0, 1); jl_symbol_type->name->wrapper = (jl_value_t*)jl_symbol_type; jl_symbol_type->name->mt = jl_nonfunction_mt; jl_symbol_type->super = jl_any_type; @@ -1969,20 +1959,16 @@ void jl_init_types(void) JL_GC_DISABLED jl_symbol_type->name->names = jl_emptysvec; jl_symbol_type->types = jl_emptysvec; jl_symbol_type->size = 0; - jl_symbol_type->abstract = 0; - jl_symbol_type->mutabl = 1; jl_symbol_type->ninitialized = 0; jl_precompute_memoized_dt(jl_symbol_type, 1); - jl_simplevector_type->name = jl_new_typename_in(jl_symbol("SimpleVector"), core); + jl_simplevector_type->name = jl_new_typename_in(jl_symbol("SimpleVector"), core, 0, 1); jl_simplevector_type->name->wrapper = (jl_value_t*)jl_simplevector_type; jl_simplevector_type->name->mt = jl_nonfunction_mt; jl_simplevector_type->super = jl_any_type; jl_simplevector_type->parameters = jl_emptysvec; jl_simplevector_type->name->names = jl_emptysvec; jl_simplevector_type->types = jl_emptysvec; - jl_simplevector_type->abstract = 0; - jl_simplevector_type->mutabl = 1; jl_simplevector_type->ninitialized = 0; jl_precompute_memoized_dt(jl_simplevector_type, 1); @@ -2518,11 +2504,12 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_datatype_type->types, 15, jl_bool_type); jl_svecset(jl_datatype_type->types, 16, jl_bool_type); jl_svecset(jl_datatype_type->types, 17, jl_bool_type); - jl_svecset(jl_datatype_type->types, 18, jl_bool_type); - jl_svecset(jl_datatype_type->types, 19, jl_bool_type); jl_svecset(jl_typename_type->types, 1, jl_module_type); - jl_svecset(jl_typename_type->types, 6, jl_long_type); jl_svecset(jl_typename_type->types, 3, jl_type_type); + jl_svecset(jl_typename_type->types, 6, jl_long_type); + jl_svecset(jl_typename_type->types, 7, jl_bool_type); + jl_svecset(jl_typename_type->types, 8, jl_bool_type); + jl_svecset(jl_typename_type->types, 9, jl_bool_type); jl_svecset(jl_methtable_type->types, 4, jl_long_type); jl_svecset(jl_methtable_type->types, 6, jl_module_type); jl_svecset(jl_methtable_type->types, 7, jl_array_any_type); diff --git a/src/julia.h b/src/julia.h index 8ec461e77126b..cd3780b9eb453 100644 --- a/src/julia.h +++ b/src/julia.h @@ -429,6 +429,9 @@ typedef struct { jl_svec_t *cache; // sorted array jl_svec_t *linearcache; // unsorted array intptr_t hash; + uint8_t abstract; + uint8_t mutabl; + uint8_t references_self; struct _jl_methtable_t *mt; jl_array_t *partial; // incomplete instantiations of this type } jl_typename_t; @@ -489,8 +492,6 @@ typedef struct _jl_datatype_t { int32_t size; // TODO: move to _jl_datatype_layout_t int32_t ninitialized; uint32_t hash; - uint8_t abstract; - uint8_t mutabl; // memoized properties uint8_t hasfreetypevars; // majority part of isconcrete computation uint8_t isconcretetype; // whether this type can have instances @@ -1136,10 +1137,10 @@ static inline int jl_is_layout_opaque(const jl_datatype_layout_t *l) JL_NOTSAFEP #define jl_is_svec(v) jl_typeis(v,jl_simplevector_type) #define jl_is_simplevector(v) jl_is_svec(v) #define jl_is_datatype(v) jl_typeis(v,jl_datatype_type) -#define jl_is_mutable(t) (((jl_datatype_t*)t)->mutabl) -#define jl_is_mutable_datatype(t) (jl_is_datatype(t) && (((jl_datatype_t*)t)->mutabl)) -#define jl_is_immutable(t) (!((jl_datatype_t*)t)->mutabl) -#define jl_is_immutable_datatype(t) (jl_is_datatype(t) && (!((jl_datatype_t*)t)->mutabl)) +#define jl_is_mutable(t) (((jl_datatype_t*)t)->name->mutabl) +#define jl_is_mutable_datatype(t) (jl_is_datatype(t) && (((jl_datatype_t*)t)->name->mutabl)) +#define jl_is_immutable(t) (!((jl_datatype_t*)t)->name->mutabl) +#define jl_is_immutable_datatype(t) (jl_is_datatype(t) && (!((jl_datatype_t*)t)->name->mutabl)) #define jl_is_uniontype(v) jl_typeis(v,jl_uniontype_type) #define jl_is_typevar(v) jl_typeis(v,jl_tvar_type) #define jl_is_unionall(v) jl_typeis(v,jl_unionall_type) @@ -1208,7 +1209,7 @@ STATIC_INLINE int jl_is_primitivetype(void *v) JL_NOTSAFEPOINT STATIC_INLINE int jl_is_structtype(void *v) JL_NOTSAFEPOINT { return (jl_is_datatype(v) && - !((jl_datatype_t*)(v))->abstract && + !((jl_datatype_t*)(v))->name->abstract && !jl_is_primitivetype(v)); } @@ -1224,7 +1225,7 @@ STATIC_INLINE int jl_is_datatype_singleton(jl_datatype_t *d) JL_NOTSAFEPOINT STATIC_INLINE int jl_is_abstracttype(void *v) JL_NOTSAFEPOINT { - return (jl_is_datatype(v) && ((jl_datatype_t*)(v))->abstract); + return (jl_is_datatype(v) && ((jl_datatype_t*)(v))->name->abstract); } STATIC_INLINE int jl_is_array_type(void *t) JL_NOTSAFEPOINT @@ -1315,7 +1316,7 @@ STATIC_INLINE int jl_egal_(jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAY jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(a); if (dt != (jl_datatype_t*)jl_typeof(b)) return 0; - if (dt->mutabl) { + if (dt->name->mutabl) { if (dt == jl_simplevector_type || dt == jl_string_type || dt == jl_datatype_type) return jl_egal__special(a, b, dt); return 0; @@ -1355,7 +1356,7 @@ STATIC_INLINE int jl_is_concrete_type(jl_value_t *v) JL_NOTSAFEPOINT JL_DLLEXPORT int jl_isa_compileable_sig(jl_tupletype_t *type, jl_method_t *definition); // type constructors -JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *inmodule); +JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *inmodule, int abstract, int mutabl); JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub); JL_DLLEXPORT jl_value_t *jl_instantiate_unionall(jl_unionall_t *u, jl_value_t *p); JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n); diff --git a/src/rtutils.c b/src/rtutils.c index 99fce51128345..98dc68dfa02f3 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -354,7 +354,7 @@ JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a) JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t idx0, jl_value_t *rhs) { jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); - if (!st->mutabl) + if (!st->name->mutabl) jl_errorf("setfield! immutable struct of type %s cannot be changed", jl_symbol_name(st->name->name)); if (idx0 >= jl_datatype_nfields(st)) jl_bounds_error_int(v, idx0 + 1); diff --git a/src/staticdata.c b/src/staticdata.c index 44b6f33d05e7a..1fc1797f35fdd 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -901,7 +901,7 @@ static void jl_write_values(jl_serializer_state *s) write_padding(s->s, offset - tot); tot = offset; size_t fsz = jl_field_size(t, i); - if (t->mutabl && jl_is_cpointer_type(jl_field_type(t, i))) { + if (t->name->mutabl && jl_is_cpointer_type(jl_field_type(t, i))) { // reset Ptr fields to C_NULL assert(!jl_field_isptr(t, i)); write_pointer(s->s); diff --git a/src/subtype.c b/src/subtype.c index 90f5438cfd1b6..0d87532e73c39 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -646,7 +646,7 @@ static int is_leaf_bound(jl_value_t *v) JL_NOTSAFEPOINT if (v == jl_bottom_type) return 1; if (jl_is_datatype(v)) { - if (((jl_datatype_t*)v)->abstract) { + if (((jl_datatype_t*)v)->name->abstract) { if (jl_is_type_type(v)) return 1;//!jl_has_free_typevars(jl_tparam0(v)); return 0; diff --git a/src/typemap.c b/src/typemap.c index 8714e4699d855..b546aadee77ac 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -65,7 +65,7 @@ static int jl_type_extract_name_precise(jl_value_t *t1, int invariant) } else if (jl_is_datatype(t1)) { jl_datatype_t *dt = (jl_datatype_t*)t1; - if ((invariant || !dt->abstract) && !jl_is_kind(t1)) + if ((invariant || !dt->name->abstract) && !jl_is_kind(t1)) return 1; return 0; } diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index db87e9e5cba04..459cad76e7d60 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -303,7 +303,7 @@ end function dumptype(io::IO, @nospecialize(x), n::Int, indent) print(io, x) n == 0 && return # too deeply nested - isa(x, DataType) && x.abstract && dumpsubtypes(io, x, Main, n, indent) + isa(x, DataType) && x.name.abstract && dumpsubtypes(io, x, Main, n, indent) nothing end diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index cfb554f6cae32..2ff223beff4b2 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -272,14 +272,14 @@ function summarize(io::IO, TT::Type, binding::Binding) if T isa DataType println(io, "```") print(io, - T.abstract ? "abstract type " : - T.mutable ? "mutable struct " : + T.name.abstract ? "abstract type " : + T.name.mutable ? "mutable struct " : Base.isstructtype(T) ? "struct " : "primitive type ") supert = supertype(T) println(io, T) println(io, "```") - if !T.abstract && T.name !== Tuple.name && !isempty(fieldnames(T)) + if !T.name.abstract && T.name !== Tuple.name && !isempty(fieldnames(T)) println(io, "# Fields") println(io, "```") pad = maximum(length(string(f)) for f in fieldnames(T)) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 060dbb2bc011f..22782eff99816 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -507,8 +507,8 @@ function serialize_typename(s::AbstractSerializer, t::Core.TypeName) serialize(s, primary.parameters) serialize(s, primary.types) serialize(s, isdefined(primary, :instance)) - serialize(s, primary.abstract) - serialize(s, primary.mutable) + serialize(s, t.abstract) + serialize(s, t.mutable) serialize(s, primary.ninitialized) if isdefined(t, :mt) && t.mt !== Symbol.name.mt serialize(s, t.mt.name) @@ -660,7 +660,7 @@ function serialize_any(s::AbstractSerializer, @nospecialize(x)) serialize_type(s, t) write(s.io, x) else - if t.mutable + if t.name.mutable serialize_cycle(s, x) && return serialize_type(s, t, true) else @@ -937,7 +937,7 @@ function handle_deserialize(s::AbstractSerializer, b::Int32) return deserialize_dict(s, t) end t = desertag(b)::DataType - if t.mutable && length(t.types) > 0 # manual specialization of fieldcount + if t.name.mutable && length(t.types) > 0 # manual specialization of fieldcount slot = s.counter; s.counter += 1 push!(s.pending_refs, slot) end @@ -1253,8 +1253,8 @@ function deserialize_typename(s::AbstractSerializer, number) else # reuse the same name for the type, if possible, for nicer debugging tn_name = isdefined(__deserialized_types__, name) ? gensym() : name - tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any), - tn_name, __deserialized_types__) + tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any, Cint, Cint), + tn_name, __deserialized_types__, false, false) makenew = true end remember_object(s, tn, number) @@ -1270,7 +1270,7 @@ function deserialize_typename(s::AbstractSerializer, number) ninitialized = deserialize(s)::Int32 if makenew - tn.names = names + Core.setfield!(tn, :names, names) # TODO: there's an unhanded cycle in the dependency graph at this point: # while deserializing super and/or types, we may have encountered # tn.wrapper and throw UndefRefException before we get to this point @@ -1422,7 +1422,7 @@ function deserialize(s::AbstractSerializer, t::DataType) if nf == 0 && t.size > 0 # bits type return read(s.io, t) - elseif t.mutable + elseif t.name.mutable x = ccall(:jl_new_struct_uninit, Any, (Any,), t) deserialize_cycle(s, x) for i in 1:nf diff --git a/sysimage.mk b/sysimage.mk index de5c3e22f253a..57479da366583 100644 --- a/sysimage.mk +++ b/sysimage.mk @@ -60,7 +60,7 @@ RELBUILDROOT := $(call rel_path,$(JULIAHOME)/base,$(BUILDROOT)/base)/ # <-- make $(build_private_libdir)/corecompiler.ji: $(COMPILER_SRCS) @$(call PRINT_JULIA, cd $(JULIAHOME)/base && \ $(call spawn,$(JULIA_EXECUTABLE)) -C "$(JULIA_CPU_TARGET)" --output-ji $(call cygpath_w,$@).tmp \ - --startup-file=no --warn-overwrite=yes -g0 -O0 compiler/compiler.jl) + --startup-file=no --warn-overwrite=yes -g1 -O0 compiler/compiler.jl) @mv $@.tmp $@ $(build_private_libdir)/sys.ji: $(build_private_libdir)/corecompiler.ji $(JULIAHOME)/VERSION $(BASE_SRCS) $(STDLIB_SRCS) diff --git a/test/ccall.jl b/test/ccall.jl index b7367c96549a5..77e17c6843db1 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -906,7 +906,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), global function $fname(s::$t) verbose && println("B: ", s) @test s == $v - if($(t).mutable) + if $(t).name.mutable @test !(s === $a) end global c = s @@ -934,7 +934,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), end verbose && println("C: ",b) @test b == $v - if ($(t).mutable) + if $(t).name.mutable @test !(b === c) @test !(b === a) end @@ -943,7 +943,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), end verbose && println("C: ",b) @test b == $v - if ($(t).mutable) + if $(t).name.mutable @test !(b === c) @test !(b === a) end @@ -953,7 +953,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), verbose && println("C: ",b) @test b == $v @test b === c - if ($(t).mutable) + if $(t).name.mutable @test !(b === a) end let cf = @cfunction($fname, Any, (Ref{$t},)) @@ -962,7 +962,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), verbose && println("C: ",b) @test b == $v @test b === c - if ($(t).mutable) + if $(t).name.mutable @test !(b === a) end let cf = @cfunction($fname, Any, (Ref{Any},)) @@ -970,7 +970,7 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), end @test b == $v @test b === c - if ($(t).mutable) + if $(t).name.mutable @test !(b === a) end let cf = @cfunction($fname, Ref{AbstractString}, (Ref{Any},)) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 96ab411c654a0..ff48b428852af 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -1551,9 +1551,9 @@ f_pure_add() = (1 + 1 == 2) ? true : "FAIL" @test @inferred f_pure_add() # inference of `T.mutable` -@test Core.Compiler.getfield_tfunc(Const(Int), Const(:mutable)) == Const(false) -@test Core.Compiler.getfield_tfunc(Const(Vector{Int}), Const(:mutable)) == Const(true) -@test Core.Compiler.getfield_tfunc(DataType, Const(:mutable)) == Bool +@test Core.Compiler.getfield_tfunc(Const(Int.name), Const(:mutable)) == Const(false) +@test Core.Compiler.getfield_tfunc(Const(Vector{Int}.name), Const(:mutable)) == Const(true) +@test Core.Compiler.getfield_tfunc(Core.TypeName, Const(:mutable)) == Bool # getfield on abstract named tuples. issue #32698 import Core.Compiler.getfield_tfunc diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 42839d4d954e6..ea0761320e700 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -162,8 +162,8 @@ function fully_eliminated(f, args, retval) end end -# check that type.mutable can be fully eliminated -f_mutable_nothrow(s::String) = Val{typeof(s).mutable} +# check that ismutabletype(type) can be fully eliminated +f_mutable_nothrow(s::String) = Val{typeof(s).name.mutable} @test fully_eliminated(f_mutable_nothrow, (String,)) # check that ifelse can be fully eliminated From 7c39836f7290ccb800b29cf23a459e35a75efe3d Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Mon, 24 May 2021 21:25:32 -0600 Subject: [PATCH 396/439] Fix ryu tests from doing @show to @test --- test/ryu.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/ryu.jl b/test/ryu.jl index d5a8df24bd03b..cf60e4867e236 100644 --- a/test/ryu.jl +++ b/test/ryu.jl @@ -549,9 +549,9 @@ end # Float16 @test Ryu.writefixed(1.0, 1, false, false, false, UInt8('.'), true) == "1" @test Ryu.writefixed(2.0, 1, false, false, false, UInt8('.'), true) == "2" - @show Ryu.writefixed(1.25e+5, 0, false, false, false, UInt8('.'), true) == "125000" - @show Ryu.writefixed(1.25e+5, 1, false, false, false, UInt8('.'), true) == "125000" - @show Ryu.writefixed(1.25e+5, 2, false, false, false, UInt8('.'), true) == "125000" + @test Ryu.writefixed(1.25e+5, 0, false, false, false, UInt8('.'), true) == "125000" + @test Ryu.writefixed(1.25e+5, 1, false, false, false, UInt8('.'), true) == "125000" + @test Ryu.writefixed(1.25e+5, 2, false, false, false, UInt8('.'), true) == "125000" end end # fixed From ff85419254b736d4da404164b85325761bfd8afe Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 25 May 2021 08:19:57 +0400 Subject: [PATCH 397/439] Add type assertion in deepcopy_internal for Arrays (#40909) Add type assertion in deepcopy_internal for Arrays --- base/deepcopy.jl | 2 +- test/copy.jl | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 75ec753a4cd84..abe8a07fc9a3e 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -87,7 +87,7 @@ end function deepcopy_internal(x::Array, stackdict::IdDict) if haskey(stackdict, x) - return stackdict[x] + return stackdict[x]::typeof(x) end _deepcopy_array_t(x, eltype(x), stackdict) end diff --git a/test/copy.jl b/test/copy.jl index 34d1c20c5f4fa..28d34e4756a6b 100644 --- a/test/copy.jl +++ b/test/copy.jl @@ -233,4 +233,8 @@ end @test copyto!(s, view(Int[],Int[])) == [1, 2] @test copyto!(s, Float64[]) == [1, 2] @test copyto!(s, String[]) == [1, 2] # No error -end \ No newline at end of file +end + +@testset "deepcopy_internal arrays" begin + @test (@inferred Base.deepcopy_internal(zeros(), IdDict())) == zeros() +end From 46527efd55f27898a343f0fc0f67b87c69ee750c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 25 May 2021 15:34:30 +0200 Subject: [PATCH 398/439] remove explicit inline annotation on expm functions (#40939) --- base/special/exp.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/special/exp.jl b/base/special/exp.jl index c9d53ed8aa695..09f4b211d40dc 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -387,7 +387,7 @@ end return fma(x, p2[1], x*p2[2]) end -@inline function expm1(x::Float64) +function expm1(x::Float64) T = Float64 if -0.2876820724517809 <= x <= 0.22314355131420976 return expm1_small(x) @@ -413,7 +413,7 @@ end return twopk*((jU-twopnk) + fma(jU, p, jL)) end -@inline function expm1(x::Float32) +function expm1(x::Float32) if -0.2876821f0 <=x <= 0.22314355f0 return expm1_small(x) end From 835f65d9b9f54e0a8dd856fc940a188f87a48cda Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 25 May 2021 09:51:23 -0400 Subject: [PATCH 399/439] Remove confusion between libsuitesparse the C library and SuiteSparse the stdlib (#40920) * Fix #40854 * SUITESPARSE -> LIBSUITESPARSE * Fix stdlib Co-authored-by: Elliot Saba --- Make.inc | 10 +-- Makefile | 2 +- base/Makefile | 16 ++-- contrib/refresh_checksums.mk | 2 +- deps/Makefile | 18 ++-- deps/Versions.make | 4 +- deps/libsuitesparse.mk | 156 +++++++++++++++++++++++++++++++++++ deps/suitesparse.mk | 156 ----------------------------------- stdlib/Makefile | 2 +- 9 files changed, 183 insertions(+), 183 deletions(-) create mode 100644 deps/libsuitesparse.mk delete mode 100644 deps/suitesparse.mk diff --git a/Make.inc b/Make.inc index 207308b34b82a..10f1b471fe7a6 100644 --- a/Make.inc +++ b/Make.inc @@ -45,7 +45,7 @@ USE_SYSTEM_BLAS:=0 USE_SYSTEM_LAPACK:=0 USE_SYSTEM_GMP:=0 USE_SYSTEM_MPFR:=0 -USE_SYSTEM_SUITESPARSE:=0 +USE_SYSTEM_LIBSUITESPARSE:=0 USE_SYSTEM_LIBUV:=0 USE_SYSTEM_UTF8PROC:=0 USE_SYSTEM_MBEDTLS:=0 @@ -1168,7 +1168,7 @@ BB_TRIPLET := $(subst $(SPACE),-,$(filter-out cxx%,$(filter-out libgfortran%,$(s LIBGFORTRAN_VERSION := $(subst libgfortran,,$(filter libgfortran%,$(subst -,$(SPACE),$(BB_TRIPLET_LIBGFORTRAN)))) # This is the set of projects that BinaryBuilder dependencies are hooked up for. -BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM SUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP CSL +BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP CSL define SET_BB_DEFAULT # First, check to see if BB is disabled on a global setting ifeq ($$(USE_BINARYBUILDER),0) @@ -1187,7 +1187,7 @@ $(foreach proj,$(BB_PROJECTS),$(eval $(call SET_BB_DEFAULT,$(proj)))) # Warn if the user tries to build something that requires `gfortran` but they don't have it installed. ifeq ($(FC_VERSION),) -ifneq ($(USE_BINARYBUILDER_OPENBLAS)$(USE_BINARYBUILDER_SUITESPARSE),11) +ifneq ($(USE_BINARYBUILDER_OPENBLAS)$(USE_BINARYBUILDER_LIBSUITESPARSE),11) $(error "Attempting to build OpenBLAS or SuiteSparse without a functioning fortran compiler!") endif endif @@ -1374,8 +1374,8 @@ endif ifeq ($(USE_SYSTEM_BLAS),1) # Since the names don't line up (`BLAS` vs. `OPENBLAS`), manually gate: USE_BINARYBUILDER_OPENBLAS := 0 -# Disable BB SuiteSparse if we're using system BLAS -USE_BINARYBUILDER_SUITESPARSE := 0 +# Disable BB LIBSUITESPARSE if we're using system BLAS +USE_BINARYBUILDER_LIBSUITESPARSE := 0 endif ifeq ($(USE_SYSTEM_LIBM),1) diff --git a/Makefile b/Makefile index 4bd51f2af495e..f4207c1719021 100644 --- a/Makefile +++ b/Makefile @@ -171,7 +171,7 @@ JL_PRIVATE_LIBS-0 += libjulia-internal-debug endif ifeq ($(USE_GPL_LIBS), 1) JL_PRIVATE_LIBS-0 += libsuitesparse_wrapper -JL_PRIVATE_LIBS-$(USE_SYSTEM_SUITESPARSE) += libamd libbtf libcamd libccolamd libcholmod libcolamd libklu libldl librbio libspqr libsuitesparseconfig libumfpack +JL_PRIVATE_LIBS-$(USE_SYSTEM_LIBSUITESPARSE) += libamd libbtf libcamd libccolamd libcholmod libcolamd libklu libldl librbio libspqr libsuitesparseconfig libumfpack endif JL_PRIVATE_LIBS-$(USE_SYSTEM_PCRE) += libpcre2-8 JL_PRIVATE_LIBS-$(USE_SYSTEM_DSFMT) += libdSFMT diff --git a/base/Makefile b/base/Makefile index 5c6540331a880..56e1cbebf21bf 100644 --- a/base/Makefile +++ b/base/Makefile @@ -218,14 +218,14 @@ $(eval $(call symlink_system_library,LIBSSH2,libssh2)) $(eval $(call symlink_system_library,NGHTTP2,libnghttp2)) $(eval $(call symlink_system_library,CURL,libcurl)) $(eval $(call symlink_system_library,LIBGIT2,libgit2)) -$(eval $(call symlink_system_library,SUITESPARSE,libamd)) -$(eval $(call symlink_system_library,SUITESPARSE,libcamd)) -$(eval $(call symlink_system_library,SUITESPARSE,libccolamd)) -$(eval $(call symlink_system_library,SUITESPARSE,libcholmod)) -$(eval $(call symlink_system_library,SUITESPARSE,libcolamd)) -$(eval $(call symlink_system_library,SUITESPARSE,libumfpack)) -$(eval $(call symlink_system_library,SUITESPARSE,libspqr)) -$(eval $(call symlink_system_library,SUITESPARSE,libsuitesparseconfig)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libamd)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libcamd)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libccolamd)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libcholmod)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libcolamd)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libumfpack)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libspqr)) +$(eval $(call symlink_system_library,LIBSUITESPARSE,libsuitesparseconfig)) # EXCLUDED LIBRARIES (installed/used, but not vendored for use with dlopen): # libunwind endif # WINNT diff --git a/contrib/refresh_checksums.mk b/contrib/refresh_checksums.mk index c6c358daa699e..b1921488dd98f 100644 --- a/contrib/refresh_checksums.mk +++ b/contrib/refresh_checksums.mk @@ -19,7 +19,7 @@ CLANG_TRIPLETS=$(filter %-darwin %-freebsd,$(TRIPLETS)) NON_CLANG_TRIPLETS=$(filter-out %-darwin %-freebsd,$(TRIPLETS)) # These are the projects currently using BinaryBuilder; both GCC-expanded and non-GCC-expanded: -BB_PROJECTS=mbedtls libssh2 nghttp2 mpfr curl libgit2 pcre libuv unwind llvmunwind dsfmt objconv p7zip zlib suitesparse openlibm blastrampoline +BB_PROJECTS=mbedtls libssh2 nghttp2 mpfr curl libgit2 pcre libuv unwind llvmunwind dsfmt objconv p7zip zlib libsuitesparse openlibm blastrampoline BB_GCC_EXPANDED_PROJECTS=openblas csl BB_CXX_EXPANDED_PROJECTS=gmp llvm clang llvm-tools # These are non-BB source-only deps diff --git a/deps/Makefile b/deps/Makefile index 3a1099df4d2e9..35c30d5930bd1 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -24,7 +24,7 @@ BUILDDIR := $(BUILDDIR)$(MAYBE_HOST) # if you are adding a new target, it can help to copy an similar, existing target # # autoconf configure-driven scripts: pcre unwind gmp mpfr patchelf libuv curl -# custom Makefile rules: openlibm dsfmt suitesparse-wrapper suitesparse lapack blastrampoline openblas utf8proc objconv libwhich +# custom Makefile rules: openlibm dsfmt libsuitesparse-wrapper libsuitesparse lapack blastrampoline openblas utf8proc objconv libwhich # CMake libs: llvm llvmunwind libgit2 libssh2 mbedtls # # downloadable via git: llvm-svn, libuv, libopenlibm, utf8proc, libgit2, libssh2 @@ -47,7 +47,7 @@ DEP_LIBS += csl endif ifeq ($(USE_GPL_LIBS), 1) -DEP_LIBS += suitesparse-wrapper +DEP_LIBS += libsuitesparse-wrapper endif ifeq ($(USE_SYSTEM_LIBUV), 0) @@ -134,8 +134,8 @@ DEP_LIBS += mpfr endif ifeq ($(USE_GPL_LIBS), 1) -ifeq ($(USE_SYSTEM_SUITESPARSE), 0) -DEP_LIBS += suitesparse +ifeq ($(USE_SYSTEM_LIBSUITESPARSE), 0) +DEP_LIBS += libsuitesparse endif endif @@ -166,13 +166,13 @@ ifneq ($(OS), WINNT) DEP_LIBS += libwhich endif -DEP_LIBS_STAGED := $(filter-out suitesparse-wrapper,$(DEP_LIBS)) +DEP_LIBS_STAGED := $(filter-out libsuitesparse-wrapper,$(DEP_LIBS)) # list all targets DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ - suitesparse suitesparse-wrapper + libsuitesparse libsuitesparse-wrapper DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) @@ -183,8 +183,8 @@ ifeq ($(USE_BINARYBUILDER_LLVM),0) DEP_LIBS_ALL := $(filter-out clang llvm-tools,$(DEP_LIBS_ALL)) endif -ifeq ($(USE_BINARYBUILDER_SUITESPARSE),0) -DEP_LIBS_STAGED := $(filter-out suitesparse,$(DEP_LIBS_STAGED)) +ifeq ($(USE_BINARYBUILDER_LIBSUITESPARSE),0) +DEP_LIBS_STAGED := $(filter-out libsuitesparse,$(DEP_LIBS_STAGED)) endif ## Common build target prefixes @@ -216,7 +216,7 @@ include $(SRCDIR)/objconv.mk include $(SRCDIR)/blastrampoline.mk include $(SRCDIR)/openblas.mk include $(SRCDIR)/utf8proc.mk -include $(SRCDIR)/suitesparse.mk +include $(SRCDIR)/libsuitesparse.mk include $(SRCDIR)/unwind.mk include $(SRCDIR)/gmp.mk include $(SRCDIR)/mpfr.mk diff --git a/deps/Versions.make b/deps/Versions.make index f2e4a821eb94e..56014d8b052b0 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -98,8 +98,8 @@ PCRE_VER := 10.36 PCRE_JLL_NAME := PCRE2 # SuiteSparse -SUITESPARSE_VER := 5.8.1 -SUITESPARSE_JLL_NAME := SuiteSparse +LIBSUITESPARSE_VER := 5.8.1 +LIBSUITESPARSE_JLL_NAME := SuiteSparse # unwind UNWIND_VER := 1.3.2 diff --git a/deps/libsuitesparse.mk b/deps/libsuitesparse.mk new file mode 100644 index 0000000000000..a7bf592ccc9ea --- /dev/null +++ b/deps/libsuitesparse.mk @@ -0,0 +1,156 @@ +## LIBSUITESPARSE ## + +ifeq ($(USE_BLAS64), 1) +UMFPACK_CONFIG := -DLONGBLAS='long long' +CHOLMOD_CONFIG := -DLONGBLAS='long long' +SPQR_CONFIG := -DLONGBLAS='long long' +UMFPACK_CONFIG += -DSUN64 +CHOLMOD_CONFIG += -DSUN64 +SPQR_CONFIG += -DSUN64 +endif + +# Disable linking to libmetis +CHOLMOD_CONFIG += -DNPARTITION + +ifneq ($(USE_BINARYBUILDER_LIBSUITESPARSE), 1) + +LIBSUITESPARSE_PROJECTS := AMD BTF CAMD CCOLAMD COLAMD CHOLMOD LDL KLU UMFPACK RBio SPQR +LIBSUITESPARSE_LIBS := $(addsuffix .*$(SHLIB_EXT)*,suitesparseconfig amd btf camd ccolamd colamd cholmod klu ldl umfpack rbio spqr) + +SUITE_SPARSE_LIB := $(LDFLAGS) -L"$(abspath $(BUILDDIR))/SuiteSparse-$(LIBSUITESPARSE_VER)/lib" +ifeq ($(OS), Darwin) +SUITE_SPARSE_LIB += $(RPATH_ESCAPED_ORIGIN) +endif +LIBSUITESPARSE_MFLAGS := CC="$(CC)" CXX="$(CXX)" F77="$(FC)" AR="$(AR)" RANLIB="$(RANLIB)" BLAS="-L$(build_shlibdir) -lblastrampoline" LAPACK="-L$(build_shlibdir) -lblastrampoline" \ + LDFLAGS="$(SUITE_SPARSE_LIB)" CFOPENMP="" CUDA=no CUDA_PATH="" \ + UMFPACK_CONFIG="$(UMFPACK_CONFIG)" CHOLMOD_CONFIG="$(CHOLMOD_CONFIG)" SPQR_CONFIG="$(SPQR_CONFIG)" +ifeq ($(OS),WINNT) +LIBSUITESPARSE_MFLAGS += UNAME=Windows +else +LIBSUITESPARSE_MFLAGS += UNAME=$(OS) +endif + +$(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz: | $(SRCCACHE) + $(JLDOWNLOAD) $@ https://github.com/DrTimothyAldenDavis/SuiteSparse/archive/v$(LIBSUITESPARSE_VER).tar.gz + +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted: $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz + $(JLCHECKSUM) $< + mkdir -p $(dir $@) + $(TAR) -C $(dir $@) --strip-components 1 -zxf $< + echo 1 > $@ + +checksum-libsuitesparse: $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz + $(JLCHECKSUM) $< + +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-winclang.patch-applied: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted + cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-winclang.patch + echo 1 > $@ +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-shlib.patch-applied: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted + cd $(dir $@) && patch -p1 < $(SRCDIR)/patches/SuiteSparse-shlib.patch + echo 1 > $@ +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-winclang.patch-applied +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-shlib.patch-applied + +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/blastrampoline + +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted + $(MAKE) -C $(dir $<)SuiteSparse_config library config $(LIBSUITESPARSE_MFLAGS) + $(INSTALL_NAME_CMD)libsuitesparseconfig.$(SHLIB_EXT) $(dir $<)lib/libsuitesparseconfig.$(SHLIB_EXT) + for PROJ in $(LIBSUITESPARSE_PROJECTS); do \ + $(MAKE) -C $(dir $<)$${PROJ} library $(LIBSUITESPARSE_MFLAGS) || exit 1; \ + $(INSTALL_NAME_CMD)lib`echo $${PROJ} | tr A-Z a-z`.$(SHLIB_EXT) $(dir $<)lib/lib`echo $${PROJ} | tr A-Z a-z`.$(SHLIB_EXT) || exit 1; \ + done + echo 1 > $@ + +ifeq ($(OS),WINNT) +LIBSUITESPARSE_SHLIB_ENV:=PATH="$(abspath $(dir $<))lib:$(build_bindir):$(PATH)" +else +LIBSUITESPARSE_SHLIB_ENV:=LD_LIBRARY_PATH="$(build_shlibdir)" +endif +$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-checked: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled + for PROJ in $(LIBSUITESPARSE_PROJECTS); do \ + $(LIBSUITESPARSE_SHLIB_ENV) $(MAKE) -C $(dir $<)$${PROJ} default $(LIBSUITESPARSE_MFLAGS) || exit 1; \ + done + echo 1 > $@ + +UNINSTALL_suitesparse := $(LIBSUITESPARSE_VER) manual_suitesparse $(LIBSUITESPARSE_LIBS) + +$(build_prefix)/manifest/libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled | $(build_prefix)/manifest $(build_shlibdir) + for lib in $(LIBSUITESPARSE_LIBS); do \ + cp -a $(dir $<)lib/lib$${lib} $(build_shlibdir) || exit 1; \ + done + #cp -a $(dir $<)lib/* $(build_shlibdir) + #cp -a $(dir $<)include/* $(build_includedir) + echo $(UNINSTALL_libsuitesparse) > $@ + +clean-libsuitesparse: clean-suitesparse-wrapper uninstall-libsuitesparse + -rm $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled + -rm -fr $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/lib + -rm -fr $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/include + -$(MAKE) -C $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER) clean + +distclean-libsuitesparse: clean-libsuitesparse-wrapper + -rm -rf $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz \ + $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER) + +get-libsuitesparse: $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz +extract-libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted +configure-libsuitesparse: extract-libsuitesparse +compile-libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled +fastcheck-libsuitesparse: #none +check-libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-checked +install-libsuitesparse: $(build_prefix)/manifest/libsuitesparse install-libsuitesparse-wrapper + +# LIBSUITESPARSE WRAPPER + +ifeq ($(USE_SYSTEM_LIBSUITESPARSE), 1) +LIBSUITESPARSE_INC := -I $(LOCALBASE)/include/suitesparse +LIBSUITESPARSE_LIB := -lumfpack -lcholmod -lamd -lcamd -lcolamd -lspqr +else +LIBSUITESPARSE_INC := -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/CHOLMOD/Include -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse_config -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SPQR/Include +LIBSUITESPARSE_LIB := -L$(build_shlibdir) -lcholmod -lumfpack -lspqr $(RPATH_ORIGIN) +$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(build_prefix)/manifest/libsuitesparse +endif + +$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(SRCDIR)/SuiteSparse_wrapper.c + mkdir -p $(build_shlibdir) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(LIBSUITESPARSE_INC) $< -o $@ $(LIBSUITESPARSE_LIB) + $(INSTALL_NAME_CMD)libsuitesparse_wrapper.$(SHLIB_EXT) $@ + touch -c $@ + +clean-libsuitesparse-wrapper: + -rm -f $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) + +distclean-libsuitesparse-wrapper: clean-suitesparse-wrapper + +get-libsuitesparse-wrapper: +extract-libsuitesparse-wrapper: +configure-libsuitesparse-wrapper: +compile-libsuitesparse-wrapper: +fastcheck-libsuitesparse-wrapper: #none +check-libsuitesparse-wrapper: +install-libsuitesparse-wrapper: $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) + +else # USE_BINARYBUILDER_LIBSUITESPARSE + +$(eval $(call bb-install,libsuitesparse,LIBSUITESPARSE,false)) + +get-libsuitesparse-wrapper: get-libsuitesparse +extract-libsuitesparse-wrapper: extract-libsuitesparse +configure-libsuitesparse-wrapper: configure-libsuitesparse +compile-libsuitesparse-wrapper: compile-libsuitesparse +fastcheck-libsuitesparse-wrapper: fastcheck-libsuitesparse +check-libsuitesparse-wrapper: check-libsuitesparse +clean-libsuitesparse-wrapper: clean-libsuitesparse +distclean-libsuitesparse-wrapper: distclean-libsuitesparse +install-libsuitesparse-wrapper: install-libsuitesparse + +# libsuitesparse depends on blastrampoline +compile-libsuitesparse: | $(build_prefix)/manifest/blastrampoline +endif + +define manual_libsuitesparse +uninstall-libsuitesparse: + -rm $(build_prefix)/manifest/libsuitesparse + -rm $(addprefix $(build_shlibdir)/lib,$3) +endef diff --git a/deps/suitesparse.mk b/deps/suitesparse.mk deleted file mode 100644 index 8bc179ef76b00..0000000000000 --- a/deps/suitesparse.mk +++ /dev/null @@ -1,156 +0,0 @@ -## SUITESPARSE ## - -ifeq ($(USE_BLAS64), 1) -UMFPACK_CONFIG := -DLONGBLAS='long long' -CHOLMOD_CONFIG := -DLONGBLAS='long long' -SPQR_CONFIG := -DLONGBLAS='long long' -UMFPACK_CONFIG += -DSUN64 -CHOLMOD_CONFIG += -DSUN64 -SPQR_CONFIG += -DSUN64 -endif - -# Disable linking to libmetis -CHOLMOD_CONFIG += -DNPARTITION - -ifneq ($(USE_BINARYBUILDER_SUITESPARSE), 1) - -SUITESPARSE_PROJECTS := AMD BTF CAMD CCOLAMD COLAMD CHOLMOD LDL KLU UMFPACK RBio SPQR -SUITESPARSE_LIBS := $(addsuffix .*$(SHLIB_EXT)*,suitesparseconfig amd btf camd ccolamd colamd cholmod klu ldl umfpack rbio spqr) - -SUITE_SPARSE_LIB := $(LDFLAGS) -L"$(abspath $(BUILDDIR))/SuiteSparse-$(SUITESPARSE_VER)/lib" -ifeq ($(OS), Darwin) -SUITE_SPARSE_LIB += $(RPATH_ESCAPED_ORIGIN) -endif -SUITESPARSE_MFLAGS := CC="$(CC)" CXX="$(CXX)" F77="$(FC)" AR="$(AR)" RANLIB="$(RANLIB)" BLAS="-L$(build_shlibdir) -lblastrampoline" LAPACK="-L$(build_shlibdir) -lblastrampoline" \ - LDFLAGS="$(SUITE_SPARSE_LIB)" CFOPENMP="" CUDA=no CUDA_PATH="" \ - UMFPACK_CONFIG="$(UMFPACK_CONFIG)" CHOLMOD_CONFIG="$(CHOLMOD_CONFIG)" SPQR_CONFIG="$(SPQR_CONFIG)" -ifeq ($(OS),WINNT) -SUITESPARSE_MFLAGS += UNAME=Windows -else -SUITESPARSE_MFLAGS += UNAME=$(OS) -endif - -$(SRCCACHE)/SuiteSparse-$(SUITESPARSE_VER).tar.gz: | $(SRCCACHE) - $(JLDOWNLOAD) $@ https://github.com/DrTimothyAldenDavis/SuiteSparse/archive/v$(SUITESPARSE_VER).tar.gz - -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted: $(SRCCACHE)/SuiteSparse-$(SUITESPARSE_VER).tar.gz - $(JLCHECKSUM) $< - mkdir -p $(dir $@) - $(TAR) -C $(dir $@) --strip-components 1 -zxf $< - echo 1 > $@ - -checksum-suitesparse: $(SRCCACHE)/SuiteSparse-$(SUITESPARSE_VER).tar.gz - $(JLCHECKSUM) $< - -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted - cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-winclang.patch - echo 1 > $@ -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-shlib.patch-applied: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted - cd $(dir $@) && patch -p1 < $(SRCDIR)/patches/SuiteSparse-shlib.patch - echo 1 > $@ -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-shlib.patch-applied - -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/blastrampoline - -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted - $(MAKE) -C $(dir $<)SuiteSparse_config library config $(SUITESPARSE_MFLAGS) - $(INSTALL_NAME_CMD)libsuitesparseconfig.$(SHLIB_EXT) $(dir $<)lib/libsuitesparseconfig.$(SHLIB_EXT) - for PROJ in $(SUITESPARSE_PROJECTS); do \ - $(MAKE) -C $(dir $<)$${PROJ} library $(SUITESPARSE_MFLAGS) || exit 1; \ - $(INSTALL_NAME_CMD)lib`echo $${PROJ} | tr A-Z a-z`.$(SHLIB_EXT) $(dir $<)lib/lib`echo $${PROJ} | tr A-Z a-z`.$(SHLIB_EXT) || exit 1; \ - done - echo 1 > $@ - -ifeq ($(OS),WINNT) -SUITESPARSE_SHLIB_ENV:=PATH="$(abspath $(dir $<))lib:$(build_bindir):$(PATH)" -else -SUITESPARSE_SHLIB_ENV:=LD_LIBRARY_PATH="$(build_shlibdir)" -endif -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-checked: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled - for PROJ in $(SUITESPARSE_PROJECTS); do \ - $(SUITESPARSE_SHLIB_ENV) $(MAKE) -C $(dir $<)$${PROJ} default $(SUITESPARSE_MFLAGS) || exit 1; \ - done - echo 1 > $@ - -UNINSTALL_suitesparse := $(SUITESPARSE_VER) manual_suitesparse $(SUITESPARSE_LIBS) - -$(build_prefix)/manifest/suitesparse: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled | $(build_prefix)/manifest $(build_shlibdir) - for lib in $(SUITESPARSE_LIBS); do \ - cp -a $(dir $<)lib/lib$${lib} $(build_shlibdir) || exit 1; \ - done - #cp -a $(dir $<)lib/* $(build_shlibdir) - #cp -a $(dir $<)include/* $(build_includedir) - echo $(UNINSTALL_suitesparse) > $@ - -clean-suitesparse: clean-suitesparse-wrapper uninstall-suitesparse - -rm $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled - -rm -fr $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/lib - -rm -fr $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/include - -$(MAKE) -C $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER) clean - -distclean-suitesparse: clean-suitesparse-wrapper - -rm -rf $(SRCCACHE)/SuiteSparse-$(SUITESPARSE_VER).tar.gz \ - $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER) - -get-suitesparse: $(SRCCACHE)/SuiteSparse-$(SUITESPARSE_VER).tar.gz -extract-suitesparse: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted -configure-suitesparse: extract-suitesparse -compile-suitesparse: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled -fastcheck-suitesparse: #none -check-suitesparse: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-checked -install-suitesparse: $(build_prefix)/manifest/suitesparse install-suitesparse-wrapper - -# SUITESPARSE WRAPPER - -ifeq ($(USE_SYSTEM_SUITESPARSE), 1) -SUITESPARSE_INC := -I $(LOCALBASE)/include/suitesparse -SUITESPARSE_LIB := -lumfpack -lcholmod -lamd -lcamd -lcolamd -lspqr -else -SUITESPARSE_INC := -I $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/CHOLMOD/Include -I $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse_config -I $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SPQR/Include -SUITESPARSE_LIB := -L$(build_shlibdir) -lcholmod -lumfpack -lspqr $(RPATH_ORIGIN) -$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(build_prefix)/manifest/suitesparse -endif - -$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(SRCDIR)/SuiteSparse_wrapper.c - mkdir -p $(build_shlibdir) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(SUITESPARSE_INC) $< -o $@ $(SUITESPARSE_LIB) - $(INSTALL_NAME_CMD)libsuitesparse_wrapper.$(SHLIB_EXT) $@ - touch -c $@ - -clean-suitesparse-wrapper: - -rm -f $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) - -distclean-suitesparse-wrapper: clean-suitesparse-wrapper - -get-suitesparse-wrapper: -extract-suitesparse-wrapper: -configure-suitesparse-wrapper: -compile-suitesparse-wrapper: -fastcheck-suitesparse-wrapper: #none -check-suitesparse-wrapper: -install-suitesparse-wrapper: $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) - -else # USE_BINARYBUILDER_SUITESPARSE - -$(eval $(call bb-install,suitesparse,SUITESPARSE,false)) - -get-suitesparse-wrapper: get-suitesparse -extract-suitesparse-wrapper: extract-suitesparse -configure-suitesparse-wrapper: configure-suitesparse -compile-suitesparse-wrapper: compile-suitesparse -fastcheck-suitesparse-wrapper: fastcheck-suitesparse -check-suitesparse-wrapper: check-suitesparse -clean-suitesparse-wrapper: clean-suitesparse -distclean-suitesparse-wrapper: distclean-suitesparse -install-suitesparse-wrapper: install-suitesparse - -# suitesparse depends on blastrampoline -compile-suitesparse: | $(build_prefix)/manifest/blastrampoline -endif - -define manual_suitesparse -uninstall-suitesparse: - -rm $(build_prefix)/manifest/suitesparse - -rm $(addprefix $(build_shlibdir)/lib,$3) -endef diff --git a/stdlib/Makefile b/stdlib/Makefile index 8dfa1e2f40fc3..38c8c45ac8975 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -16,7 +16,7 @@ $(build_datarootdir)/julia/stdlib/$(VERSDIR): mkdir -p $@ JLLS = DSFMT GMP CURL LIBGIT2 LLVM LIBSSH2 LIBUV MBEDTLS MPFR NGHTTP2 \ - BLASTRAMPOLINE OPENBLAS OPENLIBM P7ZIP PCRE SUITESPARSE ZLIB \ + BLASTRAMPOLINE OPENBLAS OPENLIBM P7ZIP PCRE LIBSUITESPARSE ZLIB \ LLVMUNWIND CSL UNWIND # Initialize this with JLLs that aren't in deps/Versions.make From 7bba3672a820e3f287756639f35cb80c8415b844 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 25 May 2021 21:02:45 +0200 Subject: [PATCH 400/439] fix `-Inf16 < typemin(Int)` (#40871) fix `-Inf16 < typemin(Int)` A new method was added in 3851ac55 which was seemingly violating the stated assumption that `typemin(Int)` can be exactly represented by `Float16`. And a more corrected method was shadowed. Idem for `Int128`. add test for `Float16(typemin(Int), RoundUp) == nextfloat(-Inf16)` --- base/float.jl | 2 +- test/float16.jl | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/base/float.jl b/base/float.jl index 560016d9400f5..06603940f8f19 100644 --- a/base/float.jl +++ b/base/float.jl @@ -467,7 +467,7 @@ end # b. unsafe_convert undefined behaviour if fy == Tf(typemax(Ti)) # (but consequently x == fy > y) for Ti in (Int64,UInt64,Int128,UInt128) - for Tf in (Float16,Float32,Float64) + for Tf in (Float32,Float64) @eval begin function ==(x::$Tf, y::$Ti) fy = ($Tf)(y) diff --git a/test/float16.jl b/test/float16.jl index 5ac9582f900c4..916032131bf5d 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -21,6 +21,20 @@ g = Float16(1.) @test isequal(Float16(0.0), Float16(0.0)) @test !isequal(Float16(-0.0), Float16(0.0)) @test !isequal(Float16(0.0), Float16(-0.0)) + + for T = Base.BitInteger_types + @test -Inf16 < typemin(T) + @test -Inf16 <= typemin(T) + @test typemin(T) > -Inf16 + @test typemin(T) >= -Inf16 + @test typemin(T) != -Inf16 + + @test Inf16 > typemax(T) + @test Inf16 >= typemax(T) + @test typemax(T) < Inf16 + @test typemax(T) <= Inf16 + @test typemax(T) != Inf16 + end end @testset "convert" begin @@ -157,6 +171,10 @@ end # halfway between and last bit is 0 ff = reinterpret(Float32, 0b00111110101010100001000000000000) @test Float32(Float16(ff)) === reinterpret(Float32, 0b00111110101010100000000000000000) + + for x = (typemin(Int64), typemin(Int128)), R = (RoundUp, RoundToZero) + @test Float16(x, R) == nextfloat(-Inf16) + end end # issue #5948 From 55be343c774adfd81f5b6f85cdf934dd204423bd Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 25 May 2021 21:04:57 +0200 Subject: [PATCH 401/439] Refuse to serialize instances of foreign types (#40852) This will simply not work; those types are foreign, after all, so we know nothing about how to serialize them. --- src/datatype.c | 6 ++++++ src/dump.c | 5 +++++ src/julia_gcext.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/datatype.c b/src/datatype.c index 8c9bae6f09f2f..cfa4b368b825c 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -650,6 +650,12 @@ JL_DLLEXPORT jl_datatype_t * jl_new_foreign_type(jl_sym_t *name, return bt; } +JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt) +{ + return jl_is_datatype(dt) && dt->layout && dt->layout->fielddesc_type == 3; +} + + // bits constructors ---------------------------------------------------------- JL_DLLEXPORT jl_value_t *jl_new_bits(jl_value_t *dt, void *data) diff --git a/src/dump.c b/src/dump.c index fc34417123025..8ce42de6f5f18 100644 --- a/src/dump.c +++ b/src/dump.c @@ -8,6 +8,7 @@ #include "julia.h" #include "julia_internal.h" +#include "julia_gcext.h" #include "builtin_proto.h" #include "serialize.h" @@ -820,6 +821,10 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li return; } + if (jl_is_foreign_type(t)) { + jl_error("Cannot serialize instances of foreign datatypes"); + } + char *data = (char*)jl_data_ptr(v); size_t i, j, np = t->layout->npointers; uint32_t nf = t->layout->nfields; diff --git a/src/julia_gcext.h b/src/julia_gcext.h index 3ca729e722dba..6787dafb4b7ee 100644 --- a/src/julia_gcext.h +++ b/src/julia_gcext.h @@ -49,6 +49,8 @@ JL_DLLEXPORT jl_datatype_t *jl_new_foreign_type( int haspointers, int large); +JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt); + JL_DLLEXPORT size_t jl_gc_max_internal_obj_size(void); JL_DLLEXPORT size_t jl_gc_external_obj_hdr_size(void); From 829d7e090f2cadfe1b1d506394f416b2938b3e7e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 25 May 2021 21:05:37 +0200 Subject: [PATCH 402/439] Restore some ABI compatibility with Julia 1.6 (#40851) In Julia <= 1.6, the C API function `jl_init` and `jl_init_with_image` were exported on the ABI level under the names `jl_init__threading` and `jl_init_with_image__threading`. This was changed during development of Julia 1.7, but unfortunately that broke ABI compatibility with binaries build against Julia <= 1.6. Add back and export two simple wrapper functions to restore this aspect of ABI compatibility. --- src/jl_exported_funcs.inc | 2 ++ src/jlapi.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 07f783d36439c..d37dd43bfb04a 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -275,6 +275,8 @@ XX(jl_init_restored_modules) \ XX(jl_init) \ XX(jl_init_with_image) \ + XX(jl_init__threading) \ + XX(jl_init_with_image__threading) \ XX(jl_install_sigint_handler) \ XX(jl_instantiate_type_in_env) \ XX(jl_instantiate_unionall) \ diff --git a/src/jlapi.c b/src/jlapi.c index a0ca896aa0ed0..669cce270c2d7 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -91,6 +91,19 @@ JL_DLLEXPORT void jl_init(void) free(libbindir); } +// HACK: remove this for Julia 1.8 (see ) +JL_DLLEXPORT void jl_init__threading(void) +{ + jl_init(); +} + +// HACK: remove this for Julia 1.8 (see ) +JL_DLLEXPORT void jl_init_with_image__threading(const char *julia_bindir, + const char *image_relative_path) +{ + jl_init_with_image(julia_bindir, image_relative_path); +} + JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str) { jl_value_t *r; From 3159a81977d611ac3c0591ab634f0da9c570a5e6 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 26 May 2021 03:50:16 +0200 Subject: [PATCH 403/439] docs: Dynamic documentation: clearer example (#40940) * docs: Dynamic documentation: clearer example * Update doc/src/manual/documentation.md Co-authored-by: Simeon Schaub Co-authored-by: Simeon Schaub --- doc/src/manual/documentation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 8a3d41ffc8171..ab52536e01cb9 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -343,17 +343,17 @@ for your custom type that returns the documentation on a per-instance basis. For ```julia struct MyType - value::String + value::Int end Docs.getdoc(t::MyType) = "Documentation for MyType with value $(t.value)" -x = MyType("x") -y = MyType("y") +x = MyType(1) +y = MyType(2) ``` -`?x` will display "Documentation for MyType with value x" while `?y` will display -"Documentation for MyType with value y". +`?x` will display "Documentation for MyType with value 1" while `?y` will display +"Documentation for MyType with value 2". ## Syntax Guide From 71d3be52e397aabfbeb756909623ba2aebac89d5 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 26 May 2021 09:13:49 +0200 Subject: [PATCH 404/439] bump SuiteSparse version (#40844) --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/SuiteSparse.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 delete mode 100644 deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 create mode 100644 deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/md5 create mode 100644 deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/sha512 diff --git a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 deleted file mode 100644 index f7c002884f412..0000000000000 --- a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -80b2f04e722a97261755e6d0a7ab83e5 diff --git a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 b/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 deleted file mode 100644 index fd802a1117072..0000000000000 --- a/deps/checksums/SuiteSparse-9cfdbbd33d2d52b83b2459f670162244cc95460c.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8547896fc8a1296f5efe1a9a05b7f7ebd5905d8e8a3d444b94e64e672565869eb540d7fba28ad6d6634e2a6b1220b7c1c67c61a5b0735de7ad37157bd841d1b9 diff --git a/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/md5 b/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/md5 new file mode 100644 index 0000000000000..234424096e008 --- /dev/null +++ b/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/md5 @@ -0,0 +1 @@ +62c5d890b62dc8825ff449dd229452b2 diff --git a/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/sha512 b/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/sha512 new file mode 100644 index 0000000000000..7833dea8238d1 --- /dev/null +++ b/deps/checksums/SuiteSparse-ec4b40ad9c0490ebf0969a41d4f880620db3f6f9.tar.gz/sha512 @@ -0,0 +1 @@ +b822f84edaab9dce301803510ac6e597fd135620685544aa9e8fbc0bbb140784fb00012e5ccfe4836b4dc39bd75f8be54c4e1fffc29696991e3d78855bc7617c diff --git a/stdlib/SuiteSparse.version b/stdlib/SuiteSparse.version index 1283d47e9ea52..da54441dc4041 100644 --- a/stdlib/SuiteSparse.version +++ b/stdlib/SuiteSparse.version @@ -1,2 +1,2 @@ SUITESPARSE_BRANCH = master -SUITESPARSE_SHA1 = 9cfdbbd33d2d52b83b2459f670162244cc95460c +SUITESPARSE_SHA1 = ec4b40ad9c0490ebf0969a41d4f880620db3f6f9 From 2d92749cfb0d5ea12f9f56a80b5b18b67dda5c17 Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Wed, 26 May 2021 22:31:09 +0930 Subject: [PATCH 405/439] doc/manual: fix grammar (#40949) Number agreement should be with the subject of the sentence, "Using", which is singular. --- doc/src/manual/complex-and-rational-numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index 99e4a677e2724..ac48e5b420f5e 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -8,7 +8,7 @@ behave as expected. ## Complex Numbers The global constant [`im`](@ref) is bound to the complex number *i*, representing the principal -square root of -1. (Using mathematicians' `i` or engineers' `j` for this global constant were rejected since they are such popular index variable names.) Since Julia allows numeric literals to be [juxtaposed with identifiers as coefficients](@ref man-numeric-literal-coefficients), +square root of -1. (Using mathematicians' `i` or engineers' `j` for this global constant was rejected since they are such popular index variable names.) Since Julia allows numeric literals to be [juxtaposed with identifiers as coefficients](@ref man-numeric-literal-coefficients), this binding suffices to provide convenient syntax for complex numbers, similar to the traditional mathematical notation: From e5d7ef01b06f44cb75c871e54c81eb92eceae738 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Wed, 26 May 2021 10:17:52 -0400 Subject: [PATCH 406/439] put CITATION.bib back with one entry (#40956) With a link to https://julialang.org/research for more papers to cite. --- CITATION.bib | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 CITATION.bib diff --git a/CITATION.bib b/CITATION.bib new file mode 100644 index 0000000000000..f1361a1eea0b8 --- /dev/null +++ b/CITATION.bib @@ -0,0 +1,15 @@ +% This article is the definitive citation for Julia. +@article{Julia-2017, + title={Julia: A fresh approach to numerical computing}, + author={Bezanson, Jeff and Edelman, Alan and Karpinski, Stefan and Shah, Viral B}, + journal={SIAM {R}eview}, + volume={59}, + number={1}, + pages={65--98}, + year={2017}, + publisher={SIAM}, + doi={10.1137/141000671}, + url={https://epubs.siam.org/doi/10.1137/141000671} +} + +% For more details on research related to Julia, see https://julialang.org/research From d0a6b3a814dd1f92a69daf09ab7c6318250801be Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Wed, 26 May 2021 19:20:22 +0000 Subject: [PATCH 407/439] [automated] Bump the Pkg stdlib from edfe2943 to 9f672535 (#40961) Co-authored-by: Dilum Aluthge --- .../Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 | 1 + .../Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 | 1 + .../Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 | 1 - .../Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 create mode 100644 deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 diff --git a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 new file mode 100644 index 0000000000000..79e70ab448180 --- /dev/null +++ b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 @@ -0,0 +1 @@ +1e1bd065364becaf2ca4e4015a770a61 diff --git a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 new file mode 100644 index 0000000000000..59744b851b27f --- /dev/null +++ b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 @@ -0,0 +1 @@ +33df67087d1f9423aedf6c5c0b79b78b6bdffae1caf39cdd7f0d07e24097054fced547f284f34b8210d3726a7f964a906113dcee7062703f1dadfe6da2a3640d diff --git a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 deleted file mode 100644 index c704b9f08d0b1..0000000000000 --- a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -65ec1044bb9815844f239b7e2b3d2e7a diff --git a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 b/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 deleted file mode 100644 index bfa5cd447f375..0000000000000 --- a/deps/checksums/Pkg-edfe2943a7867ea6b1292877a94131ac2a29b848.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -65209c1461075cc58098650abdef5814295490693f4cf11fda957e7f1304d99fc76e7ab38a9a5c041503c7acdeb512ff405fb804b589536d3fcc24fd8379b48e diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 1c8f4efa425b8..329a2a83f85d3 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = edfe2943a7867ea6b1292877a94131ac2a29b848 +PKG_SHA1 = 9f67253529c72753cbfbb0078a80717f6c9bd90f From 20dc9e4b1d886826968714061586cff20313bebd Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 27 May 2021 05:05:27 +0900 Subject: [PATCH 408/439] inference: Relax constprop recursion detection (#40561) At the moment, we restrict const prop whenever we see a cycle in methods being called. However, I think this condition can be relaxed slightly: In particular, if the type complexity limiting did not decide to limit the growth of the type in question, I think it should be fine to constant prop as long as there is no cycle in *method instances* (rather than just methods). Fixes #39915, replaces #39918 Co-authored-by: Keno Fisher --- base/compiler/abstractinterpretation.jl | 32 +++++++++++++++---------- test/compiler/inference.jl | 22 +++++++++++++++++ 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 465948c610c42..553344bbde0f0 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -137,12 +137,12 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), if splitunions splitsigs = switchtupleunion(sig) for sig_n in splitsigs - rt, edgecycle, edge = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv) + rt, edgecycle, edgelimited, edge = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv) if edge !== nothing push!(edges, edge) end this_argtypes = applicable_argtypes === nothing ? argtypes : applicable_argtypes[i] - const_rt, const_result = abstract_call_method_with_const_args(interp, rt, f, this_argtypes, match, sv, edgecycle, false) + const_rt, const_result = abstract_call_method_with_const_args(interp, rt, f, this_argtypes, match, sv, edgecycle, edgelimited, false) if const_rt !== rt && const_rt ⊑ rt rt = const_rt end @@ -156,14 +156,14 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end end else - this_rt, edgecycle, edge = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv) + this_rt, edgecycle, edgelimited, edge = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv) if edge !== nothing push!(edges, edge) end # try constant propagation with argtypes for this match # this is in preparation for inlining, or improving the return result this_argtypes = applicable_argtypes === nothing ? argtypes : applicable_argtypes[i] - const_this_rt, const_result = abstract_call_method_with_const_args(interp, this_rt, f, this_argtypes, match, sv, edgecycle, false) + const_this_rt, const_result = abstract_call_method_with_const_args(interp, this_rt, f, this_argtypes, match, sv, edgecycle, edgelimited, false) if const_this_rt !== this_rt && const_this_rt ⊑ this_rt this_rt = const_this_rt end @@ -312,7 +312,7 @@ const RECURSION_MSG = "Bounded recursion detected. Call was widened to force con function abstract_call_method(interp::AbstractInterpreter, method::Method, @nospecialize(sig), sparams::SimpleVector, hardlimit::Bool, sv::InferenceState) if method.name === :depwarn && isdefined(Main, :Base) && method.module === Main.Base add_remark!(interp, sv, "Refusing to infer into `depwarn`") - return Any, false, nothing + return Any, false, false, nothing end topmost = nothing # Limit argument type tuple growth of functions: @@ -320,6 +320,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp # and from the same method. # Returns the topmost occurrence of that repeated edge. edgecycle = false + edgelimited = false # The `method_for_inference_heuristics` will expand the given method's generator if # necessary in order to retrieve this field from the generated `CodeInfo`, if it exists. # The other `CodeInfo`s we inspect will already have this field inflated, so we just @@ -380,7 +381,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp # we have a self-cycle in the call-graph, but not in the inference graph (typically): # break this edge now (before we record it) by returning early # (non-typically, this means that we lose the ability to detect a guaranteed StackOverflow in some cases) - return Any, true, nothing + return Any, true, true, nothing end topmost = nothing edgecycle = true @@ -429,7 +430,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp # since it's very unlikely that we'll try to inline this, # or want make an invoke edge to its calling convention return type. # (non-typically, this means that we lose the ability to detect a guaranteed StackOverflow in some cases) - return Any, true, nothing + return Any, true, true, nothing end add_remark!(interp, sv, RECURSION_MSG) topmost = topmost::InferenceState @@ -437,6 +438,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp poison_callstack(sv, parentframe === nothing ? topmost : parentframe) sig = newsig sparams = svec() + edgelimited = true end end @@ -468,14 +470,14 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp rt, edge = typeinf_edge(interp, method, sig, sparams, sv) if edge === nothing - edgecycle = true + edgecycle = edgelimited = true end - return rt, edgecycle, edge + return rt, edgecycle, edgelimited, edge end function abstract_call_method_with_const_args(interp::AbstractInterpreter, @nospecialize(rettype), @nospecialize(f), argtypes::Vector{Any}, match::MethodMatch, - sv::InferenceState, edgecycle::Bool, + sv::InferenceState, edgecycle::Bool, edgelimited::Bool, va_override::Bool) mi = maybe_get_const_prop_profitable(interp, rettype, f, argtypes, match, sv, edgecycle) mi === nothing && return Any, nothing @@ -486,7 +488,11 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, @nosp # if there might be a cycle, check to make sure we don't end up # calling ourselves here. if edgecycle && _any(InfStackUnwind(sv)) do infstate - return match.method === infstate.linfo.def && any(infstate.result.overridden_by_const) + # if the type complexity limiting didn't decide to limit the call signature (`edgelimited = false`) + # we can relax the cycle detection by comparing `MethodInstance`s and allow inference to + # propagate different constant elements if the recursion is finite over the lattice + return (edgelimited ? match.method === infstate.linfo.def : mi === infstate.linfo) && + any(infstate.result.overridden_by_const) end add_remark!(interp, sv, "[constprop] Edge cycle encountered") return Any, nothing @@ -1228,7 +1234,7 @@ end function abstract_call_opaque_closure(interp::AbstractInterpreter, closure::PartialOpaque, argtypes::Vector{Any}, sv::InferenceState) pushfirst!(argtypes, closure.env) sig = argtypes_to_type(argtypes) - rt, edgecycle, edge = abstract_call_method(interp, closure.source::Method, sig, Core.svec(), false, sv) + rt, edgecycle, edgelimited, edge = abstract_call_method(interp, closure.source::Method, sig, Core.svec(), false, sv) edge !== nothing && add_backedge!(edge, sv) tt = closure.typ sigT = unwrap_unionall(tt).parameters[1] @@ -1236,7 +1242,7 @@ function abstract_call_opaque_closure(interp::AbstractInterpreter, closure::Part info = OpaqueClosureCallInfo(match) if !edgecycle const_rettype, result = abstract_call_method_with_const_args(interp, rt, closure, argtypes, - match, sv, edgecycle, closure.isva) + match, sv, edgecycle, edgelimited, closure.isva) if const_rettype ⊑ rt rt = const_rettype end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index ff48b428852af..8cb247bf958eb 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -3288,3 +3288,25 @@ end == [Union{Some{Float64}, Some{Int}, Some{UInt8}}] true end end + +# Make sure that const prop doesn't fall into cycles that aren't problematic +# in the type domain +f_recurse(x) = x > 1000000 ? x : f_recurse(x+1) +@test Base.return_types() do + f_recurse(1) +end |> first === Int + +# issue #39915 +function f33915(a_tuple, which_ones) + rest = f33915(Base.tail(a_tuple), Base.tail(which_ones)) + if first(which_ones) + (first(a_tuple), rest...) + else + rest + end +end +f33915(a_tuple::Tuple{}, which_ones::Tuple{}) = () +g39915(a_tuple) = f33915(a_tuple, (true, false, true, false)) +@test Base.return_types() do + g39915((1, 1.0, "a", :a)) +end |> first === Tuple{Int, String} From 2d1f16e624a3d15cf83172b865c2b191f0a4919e Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Wed, 26 May 2021 15:10:07 -0500 Subject: [PATCH 409/439] Add expm1(::Float16) (#40867) add expm1(::Float16) and tests for expm1(-floatmax(T)) Co-authored-by: Mustafa M Co-authored-by: Kristoffer Carlsson --- base/special/exp.jl | 37 +++++++++++++++++++++++++++++-------- test/math.jl | 13 +++++++++++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/base/special/exp.jl b/base/special/exp.jl index 09f4b211d40dc..fd88eee3fc638 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -363,22 +363,20 @@ exp10(x) end end -# min and max arguments by base and type +# min and max arguments for expm1 by type MAX_EXP(::Type{Float64}) = 709.7827128933845 # log 2^1023*(2-2^-52) MIN_EXP(::Type{Float64}) = -37.42994775023705 # log 2^-54 MAX_EXP(::Type{Float32}) = 88.72284f0 # log 2^127 *(2-2^-23) MIN_EXP(::Type{Float32}) = -17.32868f0 # log 2^-25 +MAX_EXP(::Type{Float16}) = Float16(11.09) # log 2^15 *(2-2^-10) +MIN_EXP(::Type{Float16}) = -Float16(8.32) # log 2^-12 Ln2INV(::Type{Float64}) = 1.4426950408889634 Ln2(::Type{Float64}) = -0.6931471805599453 +Ln2INV(::Type{Float32}) = 1.442695f0 +Ln2(::Type{Float32}) = -0.6931472f0 # log(.75) <= x <= log(1.25) -function expm1_small(x::Float32) - p = evalpoly(x, (0.16666666f0, 0.041666627f0, 0.008333682f0, - 0.0013908712f0, 0.0001933096f0)) - p2 = exthorner(x, (1f0, .5f0, p)) - return fma(x, p2[1], x*p2[2]) -end @inline function expm1_small(x::Float64) p = evalpoly(x, (0.16666666666666632, 0.04166666666666556, 0.008333333333401227, 0.001388888889068783, 0.00019841269447671544, 2.480157691845342e-5, @@ -386,6 +384,12 @@ end p2 = exthorner(x, (1.0, .5, p)) return fma(x, p2[1], x*p2[2]) end +@inline function expm1_small(x::Float32) + p = evalpoly(x, (0.16666666f0, 0.041666627f0, 0.008333682f0, + 0.0013908712f0, 0.0001933096f0)) + p2 = exthorner(x, (1f0, .5f0, p)) + return fma(x, p2[1], x*p2[2]) +end function expm1(x::Float64) T = Float64 @@ -414,6 +418,8 @@ function expm1(x::Float64) end function expm1(x::Float32) + x > MAX_EXP(Float32) && return Inf32 + x < MIN_EXP(Float32) && return -1f0 if -0.2876821f0 <=x <= 0.22314355f0 return expm1_small(x) end @@ -425,10 +431,25 @@ function expm1(x::Float32) 0.008332997481506921, 0.0013966479175977883, 0.0002004037059220124)) small_part = r*hi twopk = reinterpret(Float64, (N+1023) << 52) - x > MAX_EXP(Float32) && return Inf32 return Float32(muladd(twopk, small_part, twopk-1.0)) end +function expm1(x::Float16) + x > MAX_EXP(Float16) && return Inf16 + x < MIN_EXP(Float16) && return Float16(-1.0) + x = Float32(x) + if -0.2876821f0 <=x <= 0.22314355f0 + return Float16(x*evalpoly(x, (1f0, .5f0, 0.16666628f0, 0.04166785f0, 0.008351848f0, 0.0013675707f0))) + end + N_float = round(x*Ln2INV(Float32)) + N = unsafe_trunc(UInt32, N_float) + r = muladd(N_float, Ln2(Float32), x) + hi = evalpoly(r, (1f0, .5f0, 0.16666667f0, 0.041665863f0, 0.008333111f0, 0.0013981499f0, 0.00019983904f0)) + small_part = r*hi + twopk = reinterpret(Float32, (N+Int32(127)) << Int32(23)) + return Float16(muladd(twopk, small_part, twopk-1f0)) +end + """ expm1(x) diff --git a/test/math.jl b/test/math.jl index 120f1075e0818..67522b9be4c7b 100644 --- a/test/math.jl +++ b/test/math.jl @@ -196,11 +196,13 @@ end @test isequal(cos(T(0)), T(1)) @test cos(T(pi)/2) ≈ T(0) atol=eps(T) @test isequal(cos(T(pi)), T(-1)) - @test exp(T(1)) ≈ T(ℯ) atol=10*eps(T) + @test exp(T(1)) ≈ T(ℯ) atol=2*eps(T) @test isequal(exp10(T(1)), T(10)) @test isequal(exp2(T(1)), T(2)) @test isequal(expm1(T(0)), T(0)) - @test expm1(T(1)) ≈ T(ℯ)-1 atol=10*eps(T) + @test isequal(expm1(-floatmax(T)), -one(T)) + @test isequal(expm1(floatmax(T)), T(Inf)) + @test expm1(T(1)) ≈ T(ℯ)-1 atol=2*eps(T) @test isequal(hypot(T(3),T(4)), T(5)) @test isequal(hypot(floatmax(T),T(1)),floatmax(T)) @test isequal(hypot(floatmin(T)*sqrt(eps(T)),T(0)),floatmin(T)*sqrt(eps(T))) @@ -286,6 +288,13 @@ end @test tanh(T(Inf)) === T(1) end end + @testset "Float16 expm1" begin + T=Float16 + @test isequal(expm1(T(0)), T(0)) + @test isequal(expm1(-floatmax(T)), -one(T)) + @test isequal(expm1(floatmax(T)), T(Inf)) + @test expm1(T(1)) ≈ T(ℯ)-1 atol=2*eps(T) + end end @testset "exp function" for T in (Float64, Float32) From ed5cc4ec674a2900f7a1d2f0937726bd61e694ca Mon Sep 17 00:00:00 2001 From: bsilvereagle Date: Wed, 26 May 2021 14:06:50 -0700 Subject: [PATCH 410/439] [doc] updated stale links to inference blog posts (#40953) --- doc/src/devdocs/inference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/devdocs/inference.md b/doc/src/devdocs/inference.md index 6181a1f64c846..a9c4ec5c726ed 100644 --- a/doc/src/devdocs/inference.md +++ b/doc/src/devdocs/inference.md @@ -6,8 +6,8 @@ to the process of deducing the types of later values from the types of input values. Julia's approach to inference has been described in blog posts -([1](https://juliacomputing.com/blog/2016/04/04/inference-convergence.html), -[2](https://juliacomputing.com/blog/2017/05/15/inference-converage2.html)). +([1](https://juliacomputing.com/blog/2016/04/inference-convergence/), +[2](https://juliacomputing.com/blog/2017/05/inference-converage2/)). ## Debugging compiler.jl From 7edd1904b9be0088c65dfd4e8520a976db6ee5a3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 27 May 2021 14:11:18 -0400 Subject: [PATCH 411/439] Revert "change setup_stdio default method to support any IO (#40780)" (#40971) This reverts commit 59a9df1ba42c0d01ec6c0039793b7a7e1db02e6e. --- base/cmd.jl | 1 - base/filesystem.jl | 3 +-- base/process.jl | 66 ++++++++++++++++++++++++---------------------- base/stream.jl | 1 - test/spawn.jl | 8 ------ 5 files changed, 36 insertions(+), 43 deletions(-) diff --git a/base/cmd.jl b/base/cmd.jl index 93138ed6b459b..0d66cb932a04a 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -165,7 +165,6 @@ rawhandle(x::OS_HANDLE) = x if OS_HANDLE !== RawFD rawhandle(x::RawFD) = Libc._get_osfhandle(x) end -setup_stdio(stdio::Union{DevNull,OS_HANDLE,RawFD}, ::Bool) = (stdio, false) const Redirectable = Union{IO, FileRedirect, RawFD, OS_HANDLE} const StdIOSet = NTuple{3, Redirectable} diff --git a/base/filesystem.jl b/base/filesystem.jl index 35703132cae86..191f6537d8041 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -42,7 +42,7 @@ import .Base: IOError, _UVError, _sizeof_uv_fs, check_open, close, eof, eventloop, fd, isopen, bytesavailable, position, read, read!, readavailable, seek, seekend, show, skip, stat, unsafe_read, unsafe_write, write, transcode, uv_error, - setup_stdio, rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize + rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize import .Base.RefValue @@ -76,7 +76,6 @@ if OS_HANDLE !== RawFD end rawhandle(file::File) = file.handle -setup_stdio(file::File, ::Bool) = (file, false) # Filesystem.open, not Base.open function open(path::AbstractString, flags::Integer, mode::Integer=0) diff --git a/base/process.jl b/base/process.jl index 0a2caccad30d4..e7a460b0e8ead 100644 --- a/base/process.jl +++ b/base/process.jl @@ -74,28 +74,26 @@ const SpawnIOs = Vector{Any} # convenience name for readability # handle marshalling of `Cmd` arguments from Julia to C @noinline function _spawn_primitive(file, cmd::Cmd, stdio::SpawnIOs) loop = eventloop() - GC.@preserve stdio begin - iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout - let h = rawhandle(io) - h === C_NULL ? (0x00, UInt(0)) : - h isa OS_HANDLE ? (0x02, UInt(cconvert(@static(Sys.iswindows() ? Ptr{Cvoid} : Cint), h))) : - h isa Ptr{Cvoid} ? (0x04, UInt(h)) : - error("invalid spawn handle $h from $io") - end - for io in stdio] - handle = Libc.malloc(_sizeof_uv_process) - disassociate_julia_struct(handle) # ensure that data field is set to C_NULL - err = ccall(:jl_spawn, Int32, - (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, - Ptr{Tuple{Cint, UInt}}, Int, - UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}), - file, cmd.exec, loop, handle, - iohandles, length(iohandles), - cmd.flags, - cmd.env === nothing ? C_NULL : cmd.env, - isempty(cmd.dir) ? C_NULL : cmd.dir, - @cfunction(uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32))) - end + iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout + let h = rawhandle(io) + h === C_NULL ? (0x00, UInt(0)) : + h isa OS_HANDLE ? (0x02, UInt(cconvert(@static(Sys.iswindows() ? Ptr{Cvoid} : Cint), h))) : + h isa Ptr{Cvoid} ? (0x04, UInt(h)) : + error("invalid spawn handle $h from $io") + end + for io in stdio] + handle = Libc.malloc(_sizeof_uv_process) + disassociate_julia_struct(handle) # ensure that data field is set to C_NULL + err = ccall(:jl_spawn, Int32, + (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, + Ptr{Tuple{Cint, UInt}}, Int, + UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}), + file, cmd.exec, loop, handle, + iohandles, length(iohandles), + cmd.flags, + cmd.env === nothing ? C_NULL : cmd.env, + isempty(cmd.dir) ? C_NULL : cmd.dir, + @cfunction(uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32))) if err != 0 ccall(:jl_forceclose_uv, Cvoid, (Ptr{Cvoid},), handle) # will call free on handle eventually throw(_UVError("could not spawn " * repr(cmd), err)) @@ -211,10 +209,10 @@ function setup_stdio(stdio::PipeEndpoint, child_readable::Bool) rd, wr = link_pipe(!child_readable, child_readable) try open_pipe!(stdio, child_readable ? wr : rd) - catch + catch ex close_pipe_sync(rd) close_pipe_sync(wr) - rethrow() + rethrow(ex) end child = child_readable ? rd : wr return (child, true) @@ -253,18 +251,18 @@ function setup_stdio(stdio::FileRedirect, child_readable::Bool) return (io, true) end -# incrementally move data between an arbitrary IO and a system Pipe +# incrementally move data between an IOBuffer and a system Pipe # TODO: probably more efficient (when valid) to use `stdio` directly as the # PipeEndpoint buffer field in some cases -function setup_stdio(stdio::IO, child_readable::Bool) +function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool) parent = PipeEndpoint() rd, wr = link_pipe(!child_readable, child_readable) try open_pipe!(parent, child_readable ? wr : rd) - catch + catch ex close_pipe_sync(rd) close_pipe_sync(wr) - rethrow() + rethrow(ex) end child = child_readable ? rd : wr try @@ -273,18 +271,24 @@ function setup_stdio(stdio::IO, child_readable::Bool) @async try write(in, out) catch ex - @warn "Process I/O error" exception=(ex, catch_backtrace()) + @warn "Process error" exception=(ex, catch_backtrace()) finally close(parent) end end - catch + catch ex close_pipe_sync(child) - rethrow() + rethrow(ex) end return (child, true) end +function setup_stdio(io, child_readable::Bool) + # if there is no specialization, + # assume that rawhandle is defined for it + return (io, false) +end + close_stdio(stdio::OS_HANDLE) = close_pipe_sync(stdio) close_stdio(stdio) = close(stdio) diff --git a/base/stream.jl b/base/stream.jl index 2a23e97b4652c..509bc9953add6 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -282,7 +282,6 @@ end lock(s::LibuvStream) = lock(s.lock) unlock(s::LibuvStream) = unlock(s.lock) -setup_stdio(stream::LibuvStream) = (stream, false) rawhandle(stream::LibuvStream) = stream.handle unsafe_convert(::Type{Ptr{Cvoid}}, s::Union{LibuvStream, LibuvServer}) = s.handle diff --git a/test/spawn.jl b/test/spawn.jl index e6dae394cbd2b..75c7252ab673e 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -697,15 +697,7 @@ let text = "input-test-text" @test read(proc, String) == string(length(text), '\n') @test success(proc) @test String(take!(b)) == text - - out = PipeBuffer() - proc = run(catcmd, IOBuffer(SubString(text)), out) - @test success(proc) - @test proc.out === proc.err === proc.in === devnull - @test String(take!(out)) == text end - - @test repr(Base.CmdRedirect(``, devnull, 0, false)) == "pipeline(``, stdin>Base.DevNull())" @test repr(Base.CmdRedirect(``, devnull, 1, true)) == "pipeline(``, stdout Date: Thu, 27 May 2021 20:25:01 +0200 Subject: [PATCH 412/439] make \minus equivalent to - operator #26193 (#40948) * make \minus equivalent to - operator #26193 --- NEWS.md | 1 + doc/src/manual/variables.md | 1 + src/flisp/julia_charmap.h | 1 + src/julia-parser.scm | 14 +++++++++----- test/syntax.jl | 13 ++++++++++++- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 27074440b3b49..f36e8bff553d0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -22,6 +22,7 @@ Language changes * `macroexpand`, `@macroexpand`, and `@macroexpand1` no longer wrap errors in a `LoadError`. To reduce breakage, `@test_throws` has been modified so that many affected tests will still pass ([#38379]]. * The middle dot `·` (`\cdotp` U+00b7) and the Greek interpunct `·` (U+0387) are now treated as equivalent to the dot operator `⋅` (`\cdot` U+22c5) (#25157). +* The minus sign `−` (`\minus` U+2212) is now treated as equivalent to the hyphen-minus sign `-` (U+002d). Compiler/Runtime improvements ----------------------------- diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 4461ee5c32afe..004efb92dc0e5 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -143,6 +143,7 @@ are treated as equivalent to the corresponding Greek letters. The middle dot `·` (U+00B7) and the Greek [interpunct](https://en.wikipedia.org/wiki/Interpunct) `·` (U+0387) are both treated as the mathematical dot operator `⋅` (U+22C5). +The minus sign `−` (U+2212) is treated as equivalent to the hyphen-minus sign `-` (U+002D). ## Stylistic Conventions diff --git a/src/flisp/julia_charmap.h b/src/flisp/julia_charmap.h index 7384df0c7f506..59f408ce012c9 100644 --- a/src/flisp/julia_charmap.h +++ b/src/flisp/julia_charmap.h @@ -6,4 +6,5 @@ static const uint32_t charmap[][2] = { { 0x00B5, 0x03BC }, // micro sign -> greek small letter mu { 0x00B7, 0x22C5 }, // middot char -> dot operator (#25098) { 0x0387, 0x22C5 }, // Greek interpunct -> dot operator (#25098) + { 0x2212, 0x002D }, // minus -> hyphen-minus (#26193) }; diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 1f594ff0a1414..f68e0d2c4ebb5 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -4,7 +4,7 @@ (define (add-dots ops) (append! ops (map (lambda (op) (symbol (string "." op))) ops))) (define prec-assignment - (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕)) + (append! (add-dots '(= += -= −= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕)) (add-dots '(~)) '(:= $=))) ;; comma - higher than assignment outside parentheses, lower when inside @@ -20,7 +20,7 @@ (define prec-pipe> '(|.\|>| |\|>|)) (define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) (define prec-plus (append! '($) - (add-dots '(+ - ¦ |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) + (add-dots '(+ - − ¦ |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) (define prec-times (add-dots '(* / ⌿ ÷ % & · · ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ ⨟))) (define prec-rational (add-dots '(//))) (define prec-bitshift (add-dots '(<< >> >>>))) @@ -377,13 +377,17 @@ (and (eq? pred char-hex?) ispP) (memv c '(#\e #\E #\f))) (begin (read-char port) - (let ((d (peek-char port))) + (let* ((d (peek-char port)) + (is-minus-sign (or (eqv? d #\-) (eqv? d #\u2212)))) (if (and (not (eof-object? d)) - (or (char-numeric? d) (eqv? d #\+) (eqv? d #\-))) + (or (char-numeric? d) (eqv? d #\+) is-minus-sign)) (begin (set! is-float32-literal (eqv? c #\f)) (set! is-hex-float-literal ispP) (write-char c str) - (write-char (read-char port) str) + (if is-minus-sign + (begin (read-char port) + (write-char #\- str)) + (write-char (read-char port) str)) (read-digs #t #f) (disallow-dot)) (io.ungetc port c))))) diff --git a/test/syntax.jl b/test/syntax.jl index d7e136f92dfcc..5771fcee00e6c 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -819,7 +819,7 @@ let f = function (x; kw...) end # normalization of Unicode symbols (#19464) -let ε=1, μ=2, x=3, î=4, ⋅=5 +let ε=1, μ=2, x=3, î=4, ⋅=5, (-)=6 # issue #5434 (mu vs micro): @test Meta.parse("\u00b5") === Meta.parse("\u03bc") @test µ == μ == 2 @@ -832,6 +832,17 @@ let ε=1, μ=2, x=3, î=4, ⋅=5 # middot char · or · vs math dot operator ⋅ (#25098) @test Meta.parse("\u00b7") === Meta.parse("\u0387") === Meta.parse("\u22c5") @test (·) == (·) == (⋅) == 5 + # minus − vs hyphen-minus - (#26193) + @test Meta.parse("\u2212") === Meta.parse("-") + @test Meta.parse("\u221242") === Meta.parse("-42") + @test Meta.parse("\u2212 42") == Meta.parse("- 42") + @test Meta.parse("\u2212x") == Meta.parse("-x") + @test Meta.parse("x \u2212 42") == Meta.parse("x - 42") + @test Meta.parse("x \u2212= 42") == Meta.parse("x -= 42") + @test Meta.parse("100.0e\u22122") === Meta.parse("100.0E\u22122") === Meta.parse("100.0e-2") + @test Meta.parse("100.0f\u22122") === Meta.parse("100.0f-2") + @test Meta.parse("0x100p\u22128") === Meta.parse("0x100P\u22128") === Meta.parse("0x100p-8") + @test (−) == (-) == 6 end # issue #8925 From c509eff2b1e3ecf4b14c2ea4b0a376f02787b2d1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 27 May 2021 14:30:02 -0400 Subject: [PATCH 413/439] docs: add `and` docs suggestions (#40545) Co-authored-by: Jerry Ling Co-authored-by: Jerry Ling --- base/errorshow.jl | 1 + stdlib/REPL/src/REPLCompletions.jl | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/base/errorshow.jl b/base/errorshow.jl index 19dc85ea52b81..1d2745f63b297 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -878,6 +878,7 @@ end # the instance of a number (probably missing the operator) # eg: (1 + 2)(3 + 4) function noncallable_number_hint_handler(io, ex, arg_types, kwargs) + @nospecialize if ex.f isa Number print(io, "\nMaybe you forgot to use an operator such as ") printstyled(io, "*, ^, %, / etc. ", color=:cyan) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 5d857dbe10407..44b3e6a3a4158 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -825,4 +825,18 @@ function shell_completions(string, pos) return Completion[], 0:-1, false end +function UndefVarError_hint(io::IO, ex::UndefVarError) + var = ex.var + if var === :or + print("\nsuggestion: Use `||` for short-circuiting boolean OR.") + elseif var === :and + print("\nsuggestion: Use `&&` for short-circuiting boolean AND.") + end +end + +function __init__() + Base.Experimental.register_error_hint(UndefVarError_hint, UndefVarError) + nothing +end + end # module From e73a2a09a9cb0421b3f305f8b96c1450bc68c2e7 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Thu, 27 May 2021 14:51:38 -0400 Subject: [PATCH 414/439] print LineNumberNode in light_black (#40937) --- base/show.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/show.jl b/base/show.jl index ca92c349db809..fa69913ee1c3c 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1477,8 +1477,8 @@ emphasize(io, str::AbstractString, col = Base.error_color()) = get(io, :color, f printstyled(io, str; color=col, bold=true) : print(io, uppercase(str)) -show_linenumber(io::IO, line) = print(io, "#= line ", line, " =#") -show_linenumber(io::IO, line, file) = print(io, "#= ", file, ":", line, " =#") +show_linenumber(io::IO, line) = printstyled(io, "#= line ", line, " =#", color=:light_black) +show_linenumber(io::IO, line, file) = printstyled(io, "#= ", file, ":", line, " =#", color=:light_black) show_linenumber(io::IO, line, file::Nothing) = show_linenumber(io, line) # show a block, e g if/for/etc From d2b2b8c5b7dd598d9dbc7c6c4df2a26a01d2d4e5 Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Thu, 27 May 2021 15:28:03 -0400 Subject: [PATCH 415/439] Fix #39798 by using one(start) rather than 1 for _linrange (#40467) * Fix #39798 by using one(start) rather than 1 for _linrange * Expand tests for #39798 --- base/twiceprecision.jl | 10 +++++++++- test/ranges.jl | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 4df9c072f78ee..55cdc59371674 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -214,6 +214,14 @@ function TwicePrecision{T}(nd::Tuple{I,I}, nb::Integer) where {T,I} twiceprecision(TwicePrecision{T}(nd), nb) end +# Fix #39798 +# See steprangelen_hp(::Type{Float64}, ref::Tuple{Integer,Integer}, +# step::Tuple{Integer,Integer}, nb::Integer, +# len::Integer, offset::Integer) +function TwicePrecision{T}(nd::Tuple{Integer,Integer}, nb::Integer) where T + twiceprecision(TwicePrecision{T}(nd), nb) +end + # Truncating constructors. Useful for generating values that can be # exactly multiplied by small integers. function twiceprecision(val::T, nb::Integer) where {T<:IEEEFloat} @@ -673,7 +681,7 @@ end # range for rational numbers, start = start_n/den, stop = stop_n/den # Note this returns a StepRangeLen -_linspace(::Type{T}, start::Integer, stop::Integer, len::Integer) where {T<:IEEEFloat} = _linspace(T, start, stop, len, 1) +_linspace(::Type{T}, start::Integer, stop::Integer, len::Integer) where {T<:IEEEFloat} = _linspace(T, start, stop, len, one(start)) function _linspace(::Type{T}, start_n::Integer, stop_n::Integer, len::Integer, den::Integer) where T<:IEEEFloat len < 2 && return _linspace1(T, start_n/den, stop_n/den, len) start_n == stop_n && return steprangelen_hp(T, (start_n, den), (zero(start_n), den), 0, len, 1) diff --git a/test/ranges.jl b/test/ranges.jl index 8dcff017c4556..eb4fadfac6253 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1908,7 +1908,20 @@ end @test_throws BoundsError r[true:true:false] @test_throws BoundsError r[true:true:true] end - +@testset "Non-Int64 endpoints that are identical (#39798)" begin + for T in DataType[Float16,Float32,Float64,Bool,Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128], + r in [ LinRange(1, 1, 10), StepRangeLen(7, 0, 5) ] + if first(r) > typemax(T) + continue + end + let start=T(first(r)), stop=T(last(r)), step=T(step(r)), length=length(r) + @test range( start, stop, length) == r + @test range( start, stop; length) == r + @test range( start; stop, length) == r + @test range(; start, stop, length) == r + end + end +end @testset "PR 40320 fixes" begin # found by nanosoldier @test 0.2 * (-2:2) == -0.4:0.2:0.4 # from tests of AbstractFFTs, needs Base.TwicePrecision From 97d5f6afc450e93859e447ebdf5493339d446884 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 28 May 2021 04:40:52 +0900 Subject: [PATCH 416/439] Show raw machine code along with disassembled code (#40220) For code_native with binary=true --- src/disasm.cpp | 50 ++++++++++++++++++++++-- src/jitlayers.cpp | 6 +-- src/julia_internal.h | 4 +- stdlib/InteractiveUtils/src/codeview.jl | 23 +++++------ stdlib/InteractiveUtils/test/runtests.jl | 21 ++++++++-- test/reflection.jl | 1 + 6 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/disasm.cpp b/src/disasm.cpp index 778a090598016..28e0178e11654 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -470,7 +470,8 @@ static void jl_dump_asm_internal( DIContext *di_ctx, raw_ostream &rstream, const char* asm_variant, - const char* debuginfo); + const char* debuginfo, + bool binary); // This isn't particularly fast, but neither is printing assembly, and they're only used for interactive mode static uint64_t compute_obj_symsize(object::SectionRef Section, uint64_t offset) @@ -506,7 +507,7 @@ static uint64_t compute_obj_symsize(object::SectionRef Section, uint64_t offset) // print a native disassembly for the function starting at fptr extern "C" JL_DLLEXPORT -jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant, const char *debuginfo) +jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant, const char *debuginfo, char binary) { assert(fptr != 0); jl_ptls_t ptls = jl_get_ptls_states(); @@ -543,7 +544,8 @@ jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant, Section, context, stream, asm_variant, - debuginfo); + debuginfo, + binary); jl_gc_safe_leave(ptls, gc_state); return jl_pchar_to_string(stream.str().data(), stream.str().size()); @@ -739,6 +741,33 @@ static int OpInfoLookup(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Si } } // namespace +// Stringify raw bytes as a comment string. +std::string rawCodeComment(const llvm::ArrayRef& Memory, const llvm::Triple& Triple) +{ + std::string Buffer{"; "}; + llvm::raw_string_ostream Stream{Buffer}; + auto Address = reinterpret_cast(Memory.data()); + // write abbreviated address + llvm::write_hex(Stream, Address & 0xffff, HexPrintStyle::Lower, 4); + Stream << ":"; + auto Arch = Triple.getArch(); + bool FixedLength = !(Arch == Triple::x86 || Arch == Triple::x86_64); + if (FixedLength) + Stream << " "; + if (FixedLength && Triple.isLittleEndian()) { + for (auto Iter = Memory.rbegin(); Iter != Memory.rend(); ++Iter) + llvm::write_hex(Stream, *Iter, HexPrintStyle::Lower, 2); + } + else { + // variable-length or (fixed-length) big-endian format + for (auto Byte : Memory) { + if (!FixedLength) + Stream << " "; + llvm::write_hex(Stream, Byte, HexPrintStyle::Lower, 2); + } + } + return Stream.str(); +} static void jl_dump_asm_internal( uintptr_t Fptr, size_t Fsize, int64_t slide, @@ -746,7 +775,8 @@ static void jl_dump_asm_internal( DIContext *di_ctx, raw_ostream &rstream, const char* asm_variant, - const char* debuginfo) + const char* debuginfo, + bool binary) { // GC safe // Get the host information @@ -842,6 +872,16 @@ static void jl_dump_asm_internal( } } + if (binary) { + // Print the complete address and the size at the top (instruction addresses are abbreviated) + std::string Buffer{"; code origin: "}; + llvm::raw_string_ostream Stream{Buffer}; + auto Address = reinterpret_cast(memoryObject.data()); + llvm::write_hex(Stream, Address, HexPrintStyle::Lower, 16); + Stream << ", code size: " << memoryObject.size(); + Streamer->emitRawText(Stream.str()); + } + // Take two passes: In the first pass we record all branch labels, // in the second we actually perform the output for (int pass = 0; pass < 2; ++ pass) { @@ -984,6 +1024,8 @@ static void jl_dump_asm_internal( } } } + if (binary) + Streamer->emitRawText(rawCodeComment(memoryObject.slice(Index, insSize), TheTriple)); Streamer->emitInstruction(Inst, *STI); } break; diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index eb9c91e301184..d24c26812b3d3 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -409,14 +409,14 @@ void jl_generate_fptr_for_unspecialized(jl_code_instance_t *unspec) // get a native disassembly for a compiled method extern "C" JL_DLLEXPORT jl_value_t *jl_dump_method_asm(jl_method_instance_t *mi, size_t world, - int raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo) + int raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary) { // printing via disassembly jl_code_instance_t *codeinst = jl_generate_fptr(mi, world); if (codeinst) { uintptr_t fptr = (uintptr_t)codeinst->invoke; if (getwrapper) - return jl_dump_fptr_asm(fptr, raw_mc, asm_variant, debuginfo); + return jl_dump_fptr_asm(fptr, raw_mc, asm_variant, debuginfo, binary); uintptr_t specfptr = (uintptr_t)codeinst->specptr.fptr; if (fptr == (uintptr_t)&jl_fptr_const_return && specfptr == 0) { // normally we prevent native code from being generated for these functions, @@ -455,7 +455,7 @@ jl_value_t *jl_dump_method_asm(jl_method_instance_t *mi, size_t world, JL_UNLOCK(&codegen_lock); } if (specfptr != 0) - return jl_dump_fptr_asm(specfptr, raw_mc, asm_variant, debuginfo); + return jl_dump_fptr_asm(specfptr, raw_mc, asm_variant, debuginfo, binary); } // whatever, that didn't work - use the assembler output instead diff --git a/src/julia_internal.h b/src/julia_internal.h index d6170a9d56719..826d37fd6888e 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -743,9 +743,9 @@ static inline void jl_set_gc_and_wait(void) void jl_gc_set_permalloc_region(void *start, void *end); JL_DLLEXPORT jl_value_t *jl_dump_method_asm(jl_method_instance_t *linfo, size_t world, - int raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo); + int raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary); JL_DLLEXPORT void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, char getwrapper, char optimize, const jl_cgparams_t params); -JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant, const char *debuginfo); +JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant, const char *debuginfo, char binary); JL_DLLEXPORT jl_value_t *jl_dump_llvm_asm(void *F, const char* asm_variant, const char *debuginfo); JL_DLLEXPORT jl_value_t *jl_dump_function_ir(void *f, char strip_ir_metadata, char dump_module, const char *debuginfo); diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index e11a8d1ec6433..3cb792c75b9b4 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -141,7 +141,7 @@ import Base.CodegenParams # Printing code representations in IR and assembly function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrapper::Bool, strip_ir_metadata::Bool, dump_module::Bool, syntax::Symbol, - optimize::Bool, debuginfo::Symbol, + optimize::Bool, debuginfo::Symbol, binary::Bool, params::CodegenParams=CodegenParams()) ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions") if isa(f, Core.Builtin) @@ -153,7 +153,7 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe linfo = Core.Compiler.specialize_method(match) # get the code for it if native - str = _dump_function_linfo_native(linfo, world, wrapper, syntax, debuginfo) + str = _dump_function_linfo_native(linfo, world, wrapper, syntax, debuginfo, binary) else str = _dump_function_linfo_llvm(linfo, world, wrapper, strip_ir_metadata, dump_module, optimize, debuginfo, params) end @@ -162,7 +162,7 @@ function _dump_function(@nospecialize(f), @nospecialize(t), native::Bool, wrappe return str end -function _dump_function_linfo_native(linfo::Core.MethodInstance, world::UInt, wrapper::Bool, syntax::Symbol, debuginfo::Symbol) +function _dump_function_linfo_native(linfo::Core.MethodInstance, world::UInt, wrapper::Bool, syntax::Symbol, debuginfo::Symbol, binary::Bool) if syntax !== :att && syntax !== :intel throw(ArgumentError("'syntax' must be either :intel or :att")) end @@ -172,8 +172,8 @@ function _dump_function_linfo_native(linfo::Core.MethodInstance, world::UInt, wr throw(ArgumentError("'debuginfo' must be either :source or :none")) end str = ccall(:jl_dump_method_asm, Ref{String}, - (Any, UInt, Cint, Bool, Ptr{UInt8}, Ptr{UInt8}), - linfo, world, 0, wrapper, syntax, debuginfo) + (Any, UInt, Cint, Bool, Ptr{UInt8}, Ptr{UInt8}, Bool), + linfo, world, 0, wrapper, syntax, debuginfo, binary) return str end @@ -208,7 +208,7 @@ Keyword argument `debuginfo` may be one of source (default) or none, to specify """ function code_llvm(io::IO, @nospecialize(f), @nospecialize(types), raw::Bool, dump_module::Bool=false, optimize::Bool=true, debuginfo::Symbol=:default) - d = _dump_function(f, types, false, false, !raw, dump_module, :att, optimize, debuginfo) + d = _dump_function(f, types, false, false, !raw, dump_module, :att, optimize, debuginfo, false) if highlighting[:llvm] && get(io, :color, false) print_llvm(io, d) else @@ -222,24 +222,25 @@ code_llvm(@nospecialize(f), @nospecialize(types=Tuple); raw=false, dump_module=f """ - code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default) + code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default, binary=false) Prints the native assembly instructions generated for running the method matching the given generic function and type signature to `io`. Switch assembly syntax using `syntax` symbol parameter set to `:att` for AT&T syntax or `:intel` for Intel syntax. Keyword argument `debuginfo` may be one of source (default) or none, to specify the verbosity of code comments. +If `binary` is `true`, it also prints the binary machine code for each instruction precedented by an abbreviated address. """ function code_native(io::IO, @nospecialize(f), @nospecialize(types=Tuple); - syntax::Symbol=:att, debuginfo::Symbol=:default) - d = _dump_function(f, types, true, false, false, false, syntax, true, debuginfo) + syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false) + d = _dump_function(f, types, true, false, false, false, syntax, true, debuginfo, binary) if highlighting[:native] && get(io, :color, false) print_native(io, d) else print(io, d) end end -code_native(@nospecialize(f), @nospecialize(types=Tuple); syntax::Symbol=:att, debuginfo::Symbol=:default) = - code_native(stdout, f, types; syntax=syntax, debuginfo=debuginfo) +code_native(@nospecialize(f), @nospecialize(types=Tuple); syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false) = + code_native(stdout, f, types; syntax=syntax, debuginfo=debuginfo, binary=binary) code_native(::IO, ::Any, ::Symbol) = error("illegal code_native call") # resolve ambiguous call ## colorized IR and assembly printing diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index 046d5d7bc85f5..bf32ea0eb6159 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -442,23 +442,36 @@ if Sys.ARCH === :x86_64 || occursin(ix86, string(Sys.ARCH)) rgx = r"%" buf = IOBuffer() - output = "" #test that the string output is at&t syntax by checking for occurrences of '%'s code_native(buf, linear_foo, (), syntax = :att, debuginfo = :none) output = String(take!(buf)) - @test occursin(rgx, output) #test that the code output is intel syntax by checking it has no occurrences of '%' code_native(buf, linear_foo, (), syntax = :intel, debuginfo = :none) output = String(take!(buf)) - @test !occursin(rgx, output) code_native(buf, linear_foo, ()) output = String(take!(buf)) - @test occursin(rgx, output) + + @testset "binary" begin + # check the RET instruction (opcode: C3) + ret = r"^; [0-9a-f]{4}: c3$"m + + # without binary flag (default) + code_native(buf, linear_foo, ()) + output = String(take!(buf)) + @test !occursin(ret, output) + + # with binary flag + for binary in false:true + code_native(buf, linear_foo, (), binary = binary) + output = String(take!(buf)) + @test occursin(ret, output) == binary + end + end end @testset "error message" begin diff --git a/test/reflection.jl b/test/reflection.jl index be0a53beae61f..2e0ad68cf8aa1 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -883,6 +883,7 @@ _test_at_locals2(1,1,0.5f0) _dump_function(f31687_parent, Tuple{}, #=native=#false, #=wrapper=#false, #=strip=#false, #=dump_module=#true, #=syntax=#:att, #=optimize=#false, :none, + #=binary=#false, params) end From b89a2c10a53145fdf190a6050abe75d56204c7b4 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 27 May 2021 13:05:08 -0700 Subject: [PATCH 417/439] Reenable some errorshow tests on FreeBSD It seems that issue 30233 has been fixed at some point, as I can no longer reproduce it. --- test/errorshow.jl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/errorshow.jl b/test/errorshow.jl index 3bcf3df514c64..24d0241049da0 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -653,13 +653,8 @@ backtrace() @test occursin("g28442", output[3]) @test lstrip(output[5])[1:3] == "[2]" @test occursin("f28442", output[5]) - # Issue #30233 - # Note that we can't use @test_broken on FreeBSD here, because the tests actually do - # pass with some compilation options, e.g. with assertions enabled - if !Sys.isfreebsd() - @test occursin("the last 2 lines are repeated 5000 more times", output[7]) - @test lstrip(output[8])[1:7] == "[10003]" - end + @test occursin("the last 2 lines are repeated 5000 more times", output[7]) + @test lstrip(output[8])[1:7] == "[10003]" end @testset "Line number correction" begin From 4cdcdb860ce447480e6712505dfabd31ab4c37be Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 27 May 2021 22:13:41 +0200 Subject: [PATCH 418/439] add keepat! (the opposite of deleteat!) (#36229) --- NEWS.md | 2 ++ base/abstractarray.jl | 43 +++++++++++++++++++++++++++++++++++++ base/exports.jl | 1 + doc/src/base/collections.md | 1 + test/abstractarray.jl | 21 ++++++++++++++++++ 5 files changed, 68 insertions(+) diff --git a/NEWS.md b/NEWS.md index f36e8bff553d0..3f9a7c582b7ef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -47,6 +47,8 @@ New library functions * Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]). * `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`. +* New `keepat!(vector, inds)` function which is the inplace equivalent of `vector[inds]` + for a list `inds` of integers ([#36229]). * New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971]) * Two arguments method `lock(f, lck)` now accepts a `Channel` as the second argument. ([#39312]) * New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 33c549d060273..c5dd8ae3660b4 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2918,3 +2918,46 @@ function rest(a::AbstractArray{T}, state...) where {T} sizehint!(v, length(a)) return foldl(push!, Iterators.rest(a, state...), init=v) end + + +## keepat! ## + +""" + keepat!(a::AbstractVector, inds) + +Remove the items at all the indices which are not given by `inds`, +and return the modified `a`. +Items which are kept are shifted to fill the resulting gaps. + +`inds` must be an iterator of sorted and unique integer indices. +See also [`deleteat!`](@ref). + +!!! compat "Julia 1.7" + This function is available as of Julia 1.7. + +# Examples +```jldoctest +julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5) +3-element Array{Int64,1}: + 6 + 4 + 2 +``` +""" +function keepat!(a::AbstractVector, inds) + local prev + i = firstindex(a) + for k in inds + if @isdefined(prev) + prev < k || throw(ArgumentError("indices must be unique and sorted")) + end + ak = a[k] # must happen even when i==k for bounds checking + if i != k + @inbounds a[i] = ak # k > i, so a[i] is inbounds + end + prev = k + i = nextind(a, i) + end + deleteat!(a, i:lastindex(a)) + return a +end diff --git a/base/exports.jl b/base/exports.jl index 36a78c544acae..8b699e7e86af4 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -504,6 +504,7 @@ export count, delete!, deleteat!, + keepat!, eltype, empty!, empty, diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index fe4d8f80b1cd0..f8ef12071171a 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -273,6 +273,7 @@ Base.pushfirst! Base.popfirst! Base.insert! Base.deleteat! +Base.keepat! Base.splice! Base.resize! Base.append! diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 4e5e92881d601..9af20b8047701 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1364,3 +1364,24 @@ end @test [v v;;; fill(v, 1, 2)] == fill(v, 1, 2, 2) end end + +@testset "keepat!" begin + a = [1:6;] + @test a === keepat!(a, 1:5) + @test a == 1:5 + @test keepat!(a, [2, 4]) == [2, 4] + @test isempty(keepat!(a, [])) + + a = [1:6;] + @test_throws BoundsError keepat!(a, 1:10) # make sure this is not a no-op + @test_throws BoundsError keepat!(a, 2:10) + @test_throws ArgumentError keepat!(a, [2, 4, 3]) + + b = BitVector([1, 1, 1, 0, 0]) + @test b === keepat!(b, 1:5) + @test b == [1, 1, 1, 0, 0] + @test keepat!(b, 2:4) == [1, 1, 0] + @test_throws BoundsError keepat!(a, -1:10) + @test_throws ArgumentError keepat!(a, [2, 1]) + @test isempty(keepat!(a, [])) +end From 559520cd0cddc577c10615c86db8c63f22750223 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 28 May 2021 05:45:55 +0900 Subject: [PATCH 419/439] export spawn macro from Threads (#40965) --- base/threadingconstructs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 179bc3170fa52..e66af69b3e82f 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -export threadid, nthreads, @threads +export threadid, nthreads, @threads, @spawn """ Threads.threadid() From 19133821c6cfcd7f02b78b0729aa01dce3f906bb Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 27 May 2021 17:21:29 -0400 Subject: [PATCH 420/439] fix keepat! doctest (#40976) --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c5dd8ae3660b4..bcce1363e4516 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2938,7 +2938,7 @@ See also [`deleteat!`](@ref). # Examples ```jldoctest julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5) -3-element Array{Int64,1}: +3-element Vector{Int64}: 6 4 2 From 523cc3f259c777fe3b076d5f105a230a28f7e307 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 16 Mar 2021 15:40:21 -0400 Subject: [PATCH 421/439] fix unsoundness in fieldtype of Tuple with non-Type params --- base/compiler/tfuncs.jl | 24 +++++++++++++++++++----- test/compiler/inference.jl | 12 ++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 25631d9594c98..5ae32d31ec189 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -960,8 +960,8 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name)) end if s0 === Any || s0 === Type || DataType ⊑ s0 || UnionAll ⊑ s0 # For a generic DataType, one of the fields could still be a TypeVar - # which is not a Type - return Union{Type, TypeVar} + # which is not a Type. Tuple{...} can also contain Symbols etc. + return Any end # fieldtype only accepts Types if isa(s0, Const) && !(isa(s0.val, DataType) || isa(s0.val, UnionAll) || isa(s0.val, Union)) @@ -989,14 +989,14 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name)) return tmerge(_fieldtype_tfunc(rewrap(u.a, s), exact, name), _fieldtype_tfunc(rewrap(u.b, s), exact, name)) end - u isa DataType || return Union{Type, TypeVar} + u isa DataType || return Any if u.name.abstract # Abstract types have no fields exact && return Bottom # Type{...} without free typevars has no subtypes, so it is actually # exact, even if `exact` is false. isType(u) && !has_free_typevars(u.parameters[1]) && return Bottom - return Union{Type, TypeVar} + return Any end if u.name === _NAMEDTUPLE_NAME && !isconcretetype(u) # TODO: better approximate inference @@ -1023,8 +1023,15 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name)) else ft1 = Type{ft1} end + elseif ft1 isa Type || ft1 isa TypeVar + if ft1 === Any && u.name === Tuple.name + # Tuple{:x} is possible in this case + ft1 = Any + else + ft1 = Type{ft} where ft<:ft1 + end else - ft1 = Type{ft} where ft<:ft1 + ft1 = Const(ft1) end t = tmerge(t, ft1) t === Any && break @@ -1047,6 +1054,9 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name)) else ft = ftypes[fld] end + if !isa(ft, Type) && !isa(ft, TypeVar) + return Const(ft) + end exactft = exact || (!has_free_typevars(ft) && u.name !== Tuple.name) ft = rewrap_unionall(ft, s) @@ -1056,6 +1066,10 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name)) end return Type{ft} end + if u.name === Tuple.name && ft === Any + # Tuple{:x} is possible + return Any + end return Type{<:ft} end add_tfunc(fieldtype, 2, 3, fieldtype_tfunc, 0) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 8cb247bf958eb..f74b23cfe640b 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -677,8 +677,8 @@ let fieldtype_tfunc = Core.Compiler.fieldtype_tfunc, @test fieldtype_tfunc(Union{Type{Base.RefValue{<:Real}}, Type{Int32}}, Const(:x)) == Const(Real) @test fieldtype_tfunc(Const(Union{Base.RefValue{<:Real}, Type{Int32}}), Const(:x)) == Const(Real) @test fieldtype_tfunc(Type{Union{Base.RefValue{T}, Type{Int32}}} where {T<:Real}, Const(:x)) == Type{<:Real} - @test fieldtype_tfunc(Type{<:Tuple}, Const(1)) == Type - @test fieldtype_tfunc(Type{<:Tuple}, Any) == Type + @test fieldtype_tfunc(Type{<:Tuple}, Const(1)) == Any + @test fieldtype_tfunc(Type{<:Tuple}, Any) == Any @test fieldtype_nothrow(Type{Base.RefValue{<:Real}}, Const(:x)) @test !fieldtype_nothrow(Type{Union{}}, Const(:x)) @test !fieldtype_nothrow(Union{Type{Base.RefValue{T}}, Int32} where {T<:Real}, Const(:x)) @@ -2965,10 +2965,10 @@ end @test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Tuple{Int}, Any, Vararg}) == Int @test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Tuple{Int}, Any, Any, Vararg}) == Int @test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Any, Any, Any, Any, Vararg}) == Union{} -@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Vararg}) == Union{Type, TypeVar} -@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Vararg}) == Union{Type, TypeVar} -@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Vararg}) == Union{Type, TypeVar} -@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Any, Vararg}) == Union{Type, TypeVar} +@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Vararg}) == Any +@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Vararg}) == Any +@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Vararg}) == Any +@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Any, Vararg}) == Any @test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Any, Any, Vararg}) == Union{} @test Core.Compiler.return_type(apply26826, Tuple{typeof(Core.apply_type), Vararg}) == Any @test Core.Compiler.return_type(apply26826, Tuple{typeof(Core.apply_type), Any, Vararg}) == Any From 920992c834314cf944cc48e4b1299b7129645a01 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 19 May 2021 15:37:57 -0400 Subject: [PATCH 422/439] fix #40742, unset `has_concrete_subtype` for types like `Tuple{:x}` --- src/jltypes.c | 7 +++++++ test/compiler/inference.jl | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/jltypes.c b/src/jltypes.c index f759173f2051c..273976e57d7ed 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1098,6 +1098,13 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt, int cacheable) ((!jl_is_kind(p) && ((jl_datatype_t*)p)->isconcretetype) || (((jl_datatype_t*)p)->name == jl_type_typename && !((jl_datatype_t*)p)->hasfreetypevars)); } + if (istuple && dt->has_concrete_subtype) { + if (jl_is_vararg(p)) + p = ((jl_vararg_t*)p)->T; + // tuple types like Tuple{:x} cannot have instances + if (p && !jl_is_type(p) && !jl_is_typevar(p)) + dt->has_concrete_subtype = 0; + } } if (dt->name == jl_type_typename) cacheable = 0; // the cache for Type ignores parameter normalization, so it can't be used as a regular hash diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index f74b23cfe640b..5cbd39d8468a6 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -3310,3 +3310,6 @@ g39915(a_tuple) = f33915(a_tuple, (true, false, true, false)) @test Base.return_types() do g39915((1, 1.0, "a", :a)) end |> first === Tuple{Int, String} + +# issue #40742 +@test Base.return_types(string, (Vector{Tuple{:x}},)) == Any[String] From d692b897be0afca7939f325b46bbd7007bd7503b Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Fri, 28 May 2021 09:35:15 +0200 Subject: [PATCH 423/439] don't mutate lhs while destructuring (#40737) Jeff was a bit sceptical about this in #40574, but I think this is worth doing since it seems strictly more useful than the current behavior and we already go out of our way in cases like `x, y = y, x` to only assign to the lhs after the rhs has been evaluated, so I think handling `x[2], x[1] = x` in a similar way would only be consistent. As a general rule that assignment will always happen after destructuring does not seem much less obvious than the current behavior to me. This might technically be slightly breaking, but I would be surprised if people relied on the current behavior here. Nevertheless, it would probably be good to run PkgEval if we decide to go with this change. closes #40574 --- NEWS.md | 3 +++ src/julia-syntax.scm | 38 ++++++++++++++++++++++++++++---------- test/syntax.jl | 11 +++++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3f9a7c582b7ef..515fc4c236ead 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,6 +23,9 @@ Language changes * `macroexpand`, `@macroexpand`, and `@macroexpand1` no longer wrap errors in a `LoadError`. To reduce breakage, `@test_throws` has been modified so that many affected tests will still pass ([#38379]]. * The middle dot `·` (`\cdotp` U+00b7) and the Greek interpunct `·` (U+0387) are now treated as equivalent to the dot operator `⋅` (`\cdot` U+22c5) (#25157). * The minus sign `−` (`\minus` U+2212) is now treated as equivalent to the hyphen-minus sign `-` (U+002d). +* Destructuring will no longer mutate values on the left hand side while iterating through values on the right hand side. In the example + of an array `x`, `x[2], x[1] = x` will now swap the first and second entry of `x`, whereas it used to fill both entries with `x[1]` + because `x[2]` was mutated during the iteration of `x`. ([#40737]) Compiler/Runtime improvements ----------------------------- diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 6bc8401c9b3dd..d4d6711f2577f 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2143,22 +2143,40 @@ (- n 1) n)) n)) - (st (gensy))) + (st (gensy)) + (end '())) `(block ,@(if (> n 0) `((local ,st)) '()) ,@ini ,@(map (lambda (i lhs) - (expand-forms - (if (vararg? lhs) - `(= ,(cadr lhs) (call (top rest) ,xx ,@(if (eq? i 0) '() `(,st)))) - (lower-tuple-assignment - (if (= i (- n 1)) - (list lhs) - (list lhs st)) - `(call (top indexed_iterate) - ,xx ,(+ i 1) ,@(if (eq? i 0) '() `(,st))))))) + (let ((lhs- (cond ((or (symbol? lhs) (ssavalue? lhs)) + lhs) + ((vararg? lhs) + (let ((lhs- (cadr lhs))) + (if (or (symbol? lhs-) (ssavalue? lhs-)) + lhs + `(|...| ,(if (eventually-call? lhs-) + (gensy) + (make-ssavalue)))))) + ;; can't use ssavalues if it's a function definition + ((eventually-call? lhs) (gensy)) + (else (make-ssavalue))))) + (if (not (eq? lhs lhs-)) + (if (vararg? lhs) + (set! end (cons (expand-forms `(= ,(cadr lhs) ,(cadr lhs-))) end)) + (set! end (cons (expand-forms `(= ,lhs ,lhs-)) end)))) + (expand-forms + (if (vararg? lhs-) + `(= ,(cadr lhs-) (call (top rest) ,xx ,@(if (eq? i 0) '() `(,st)))) + (lower-tuple-assignment + (if (= i (- n 1)) + (list lhs-) + (list lhs- st)) + `(call (top indexed_iterate) + ,xx ,(+ i 1) ,@(if (eq? i 0) '() `(,st)))))))) (iota n) lhss) + ,@(reverse end) (unnecessary ,xx)))))) ;; move an assignment into the last statement of a block to keep more statements at top level diff --git a/test/syntax.jl b/test/syntax.jl index 5771fcee00e6c..5a3af3b1863cb 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2819,3 +2819,14 @@ macro m_nospecialize_unnamed_hygiene() end @test @m_nospecialize_unnamed_hygiene()(1) === Any + +# https://github.com/JuliaLang/julia/issues/40574 +@testset "no mutation while destructuring" begin + x = [1, 2] + x[2], x[1] = x + @test x == [2, 1] + + x = [1, 2, 3] + x[3], x[1:2]... = x + @test x == [2, 3, 1] +end From 61701d7a84be62beaf129b2178ede42882a7a46a Mon Sep 17 00:00:00 2001 From: Mason Protter Date: Fri, 28 May 2021 03:53:25 -0600 Subject: [PATCH 424/439] Explicit test that `shuffle!` behaves correct on `BitArray`s (#40558) --- stdlib/Random/Project.toml | 3 ++- stdlib/Random/test/runtests.jl | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/stdlib/Random/Project.toml b/stdlib/Random/Project.toml index 6aa9f65374539..6958e618d3ea8 100644 --- a/stdlib/Random/Project.toml +++ b/stdlib/Random/Project.toml @@ -9,6 +9,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Future = "9fa8497b-333b-5362-9e8d-4d0656e87820" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [targets] -test = ["Test", "SparseArrays", "LinearAlgebra", "Future"] +test = ["Test", "SparseArrays", "LinearAlgebra", "Future", "Statistics"] diff --git a/stdlib/Random/test/runtests.jl b/stdlib/Random/test/runtests.jl index c502b14bc3a7f..639a2bbed60c2 100644 --- a/stdlib/Random/test/runtests.jl +++ b/stdlib/Random/test/runtests.jl @@ -2,6 +2,7 @@ using Test, SparseArrays using Test: guardseed +using Statistics: mean const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl")) @@ -898,3 +899,15 @@ end x = BigFloat() @test_throws ArgumentError rand!(rng, x, s) # incompatible precision end + +@testset "shuffle! for BitArray" begin + # Test that shuffle! is uniformly random on BitArrays + rng = MersenneTwister(123) + a = (reshape(1:(4*5), 4, 5) .<= 2) # 4x5 BitMatrix whose first two elements are true, rest are false + m = mean(1:50_000) do _ + shuffle!(rng, a) + end # mean result of shuffle!-ing a 50_000 times. If the shuffle! is uniform, then each index has a + # 10% chance of having a true in it, so each value should converge to 0.1. + @test minimum(m) >= 0.094 + @test maximum(m) <= 0.106 +end From ecea238e5577c1b4a83de4c3ec4de1a13cdf56a1 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 28 May 2021 15:24:08 +0200 Subject: [PATCH 425/439] more ergonomic stream redirection (#37978) Co-authored-by: Jeff Bezanson Co-authored-by: Fredrik Ekre Co-authored-by: Kristoffer Carlsson --- NEWS.md | 1 + base/exports.jl | 1 + base/stream.jl | 138 ++++++++++++++++++++++++++++++++++--- doc/src/base/io-network.md | 1 + test/spawn.jl | 68 ++++++++++++++++++ 5 files changed, 200 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index 515fc4c236ead..bf9b0ceb6b61c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -57,6 +57,7 @@ New library functions * New functor `Returns(value)`, which returns `value` for any arguments ([#39794]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438]) * New macros `@something` and `@coalesce` which are short-circuiting versions of `something` and `coalesce`, respectively ([#40729]) +* New function `redirect_stdio` for redirecting `stdin`, `stdout` and `stderr` ([#37978]). New library features -------------------- diff --git a/base/exports.jl b/base/exports.jl index 8b699e7e86af4..f27ac7f96c883 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -833,6 +833,7 @@ export readline, readlines, readuntil, + redirect_stdio, redirect_stderr, redirect_stdin, redirect_stdout, diff --git a/base/stream.jl b/base/stream.jl index 509bc9953add6..6cbd1d3b86a28 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1127,7 +1127,7 @@ function _fd(x::Union{LibuvStream, LibuvServer}) return fd[] end -struct redirect_stdio <: Function +struct RedirectStdStream <: Function unix_fd::Int writable::Bool end @@ -1135,7 +1135,7 @@ for (f, writable, unix_fd) in ((:redirect_stdin, false, 0), (:redirect_stdout, true, 1), (:redirect_stderr, true, 2)) - @eval const ($f) = redirect_stdio($unix_fd, $writable) + @eval const ($f) = RedirectStdStream($unix_fd, $writable) end function _redirect_io_libc(stream, unix_fd::Int) posix_fd = _fd(stream) @@ -1154,7 +1154,7 @@ function _redirect_io_global(io, unix_fd::Int) unix_fd == 2 && (global stderr = io) nothing end -function (f::redirect_stdio)(handle::Union{LibuvStream, IOStream}) +function (f::RedirectStdStream)(handle::Union{LibuvStream, IOStream}) _redirect_io_libc(handle, f.unix_fd) c_sym = f.unix_fd == 0 ? cglobal(:jl_uv_stdin, Ptr{Cvoid}) : f.unix_fd == 1 ? cglobal(:jl_uv_stdout, Ptr{Cvoid}) : @@ -1164,7 +1164,7 @@ function (f::redirect_stdio)(handle::Union{LibuvStream, IOStream}) _redirect_io_global(handle, f.unix_fd) return handle end -function (f::redirect_stdio)(::DevNull) +function (f::RedirectStdStream)(::DevNull) nulldev = @static Sys.iswindows() ? "NUL" : "/dev/null" handle = open(nulldev, write=f.writable) _redirect_io_libc(handle, f.unix_fd) @@ -1172,13 +1172,13 @@ function (f::redirect_stdio)(::DevNull) _redirect_io_global(devnull, f.unix_fd) return devnull end -function (f::redirect_stdio)(io::AbstractPipe) +function (f::RedirectStdStream)(io::AbstractPipe) io2 = (f.writable ? pipe_writer : pipe_reader)(io) f(io2) _redirect_io_global(io, f.unix_fd) return io end -function (f::redirect_stdio)(p::Pipe) +function (f::RedirectStdStream)(p::Pipe) if p.in.status == StatusInit && p.out.status == StatusInit link_pipe!(p) end @@ -1186,9 +1186,9 @@ function (f::redirect_stdio)(p::Pipe) f(io2) return p end -(f::redirect_stdio)() = f(Pipe()) +(f::RedirectStdStream)() = f(Pipe()) -# Deprecate these in v2 (redirect_stdio support) +# Deprecate these in v2 (RedirectStdStream support) iterate(p::Pipe) = (p.out, 1) iterate(p::Pipe, i::Int) = i == 1 ? (p.in, 2) : nothing getindex(p::Pipe, key::Int) = key == 1 ? p.out : key == 2 ? p.in : throw(KeyError(key)) @@ -1204,6 +1204,8 @@ the pipe. !!! note `stream` must be a compatible objects, such as an `IOStream`, `TTY`, `Pipe`, socket, or `devnull`. + +See also [`redirect_stdio`](@ref). """ redirect_stdout @@ -1215,6 +1217,8 @@ Like [`redirect_stdout`](@ref), but for [`stderr`](@ref). !!! note `stream` must be a compatible objects, such as an `IOStream`, `TTY`, `Pipe`, socket, or `devnull`. + +See also [`redirect_stdio`](@ref). """ redirect_stderr @@ -1227,10 +1231,125 @@ Note that the direction of the stream is reversed. !!! note `stream` must be a compatible objects, such as an `IOStream`, `TTY`, `Pipe`, socket, or `devnull`. + +See also [`redirect_stdio`](@ref). """ redirect_stdin -function (f::redirect_stdio)(thunk::Function, stream) +""" + redirect_stdio(;stdin=stdin, stderr=stderr, stdout=stdout) + +Redirect a subset of the streams `stdin`, `stderr`, `stdout`. +Each argument must be an `IOStream`, `TTY`, `Pipe`, socket, or `devnull`. + +!!! compat "Julia 1.7" + `redirect_stdio` requires Julia 1.7 or later. +""" +function redirect_stdio(;stdin=nothing, stderr=nothing, stdout=nothing) + stdin === nothing || redirect_stdin(stdin) + stderr === nothing || redirect_stderr(stderr) + stdout === nothing || redirect_stdout(stdout) +end + +""" + redirect_stdio(f; stdin=nothing, stderr=nothing, stdout=nothing) + +Redirect a subset of the streams `stdin`, `stderr`, `stdout`, +call `f()` and restore each stream. + +Possible values for each stream are: +* `nothing` indicating the stream should not be redirected. +* `path::AbstractString` redirecting the stream to the file at `path`. +* `io` an `IOStream`, `TTY`, `Pipe`, socket, or `devnull`. + +# Examples +```julia +julia> redirect_stdio(stdout="stdout.txt", stderr="stderr.txt") do + print("hello stdout") + print(stderr, "hello stderr") + end + +julia> read("stdout.txt", String) +"hello stdout" + +julia> read("stderr.txt", String) +"hello stderr" +``` + +# Edge cases + +It is possible to pass the same argument to `stdout` and `stderr`: +```julia +julia> redirect_stdio(stdout="log.txt", stderr="log.txt", stdin=devnull) do + ... +end +``` + +However it is not supported to pass two distinct descriptors of the same file. +```julia +julia> io1 = open("same/path", "w") + +julia> io2 = open("same/path", "w") + +julia> redirect_stdio(f, stdout=io1, stderr=io2) # not suppored +``` +Also the `stdin` argument may not be the same descriptor as `stdout` or `stderr`. +```julia +julia> io = open(...) + +julia> redirect_stdio(f, stdout=io, stdin=io) # not supported +``` + +!!! compat "Julia 1.7" + `redirect_stdio` requires Julia 1.7 or later. +""" +function redirect_stdio(f; stdin=nothing, stderr=nothing, stdout=nothing) + + function resolve(new::Nothing, oldstream, mode) + (new=nothing, close=false, old=nothing) + end + function resolve(path::AbstractString, oldstream,mode) + (new=open(path, mode), close=true, old=oldstream) + end + function resolve(new, oldstream, mode) + (new=new, close=false, old=oldstream) + end + + same_path(x, y) = false + function same_path(x::AbstractString, y::AbstractString) + # if x = y = "does_not_yet_exist.txt" then samefile will return false + (abspath(x) == abspath(y)) || samefile(x,y) + end + if same_path(stderr, stdin) + throw(ArgumentError("stdin and stderr cannot be the same path")) + end + if same_path(stdout, stdin) + throw(ArgumentError("stdin and stdout cannot be the same path")) + end + + new_in , close_in , old_in = resolve(stdin , Base.stdin , "r") + new_out, close_out, old_out = resolve(stdout, Base.stdout, "w") + if same_path(stderr, stdout) + # make sure that in case stderr = stdout = "same/path" + # only a single io is used instead of opening the same file twice + new_err, close_err, old_err = new_out, false, Base.stderr + else + new_err, close_err, old_err = resolve(stderr, Base.stderr, "w") + end + + redirect_stdio(; stderr=new_err, stdin=new_in, stdout=new_out) + + try + return f() + finally + redirect_stdio(;stderr=old_err, stdin=old_in, stdout=old_out) + close_err && close(new_err) + close_in && close(new_in ) + close_out && close(new_out) + end +end + +function (f::RedirectStdStream)(thunk::Function, stream) stdold = f.unix_fd == 0 ? stdin : f.unix_fd == 1 ? stdout : f.unix_fd == 2 ? stderr : @@ -1243,6 +1362,7 @@ function (f::redirect_stdio)(thunk::Function, stream) end end + """ redirect_stdout(f::Function, stream) diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index b798a708f22b2..2d6a462400813 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -36,6 +36,7 @@ Base.iswritable Base.isreadable Base.isopen Base.fd +Base.redirect_stdio Base.redirect_stdout Base.redirect_stdout(::Function, ::Any) Base.redirect_stderr diff --git a/test/spawn.jl b/test/spawn.jl index 75c7252ab673e..fe6912faf0447 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -261,6 +261,74 @@ end end end +@testset "redirect_stdio" begin + + function hello_err_out() + println(stderr, "hello from stderr") + println(stdout, "hello from stdout") + end + @testset "same path for multiple streams" begin + @test_throws ArgumentError redirect_stdio(hello_err_out, + stdin="samepath.txt", stdout="samepath.txt") + @test_throws ArgumentError redirect_stdio(hello_err_out, + stdin="samepath.txt", stderr="samepath.txt") + + @test_throws ArgumentError redirect_stdio(hello_err_out, + stdin=joinpath("tricky", "..", "samepath.txt"), + stderr="samepath.txt") + mktempdir() do dir + path = joinpath(dir, "stdouterr.txt") + redirect_stdio(hello_err_out, stdout=path, stderr=path) + @test read(path, String) == """ + hello from stderr + hello from stdout + """ + end + end + + mktempdir() do dir + path_stdout = joinpath(dir, "stdout.txt") + path_stderr = joinpath(dir, "stderr.txt") + redirect_stdio(hello_err_out, stderr=devnull, stdout=path_stdout) + @test read(path_stdout, String) == "hello from stdout\n" + + open(path_stderr, "w") do ioerr + redirect_stdio(hello_err_out, stderr=ioerr, stdout=devnull) + end + @test read(path_stderr, String) == "hello from stderr\n" + end + + mktempdir() do dir + path_stderr = joinpath(dir, "stderr.txt") + path_stdin = joinpath(dir, "stdin.txt") + path_stdout = joinpath(dir, "stdout.txt") + + content_stderr = randstring() + content_stdout = randstring() + + redirect_stdio(stdout=path_stdout, stderr=path_stderr) do + print(content_stdout) + print(stderr, content_stderr) + end + + @test read(path_stderr, String) == content_stderr + @test read(path_stdout, String) == content_stdout + end + + # stdin is unavailable on the workers. Run test on master. + ret = Core.eval(Main, + quote + remotecall_fetch(1) do + mktempdir() do dir + path = joinpath(dir, "stdin.txt") + write(path, "hello from stdin\n") + redirect_stdio(readline, stdin=path) + end + end + end) + @test ret == "hello from stdin" +end + # issue #36136 @testset "redirect to devnull" begin @test redirect_stdout(devnull) do; println("Hello") end === nothing From e0ecc557a24eb3338b8dc672d02c98e8b31111fa Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Fri, 28 May 2021 18:07:45 +0200 Subject: [PATCH 426/439] Replace Val-types by singleton types in `lu` and `qr` (#40623) Co-authored-by: Andreas Noack --- NEWS.md | 4 ++ stdlib/LinearAlgebra/src/LinearAlgebra.jl | 7 +++ stdlib/LinearAlgebra/src/dense.jl | 2 +- stdlib/LinearAlgebra/src/factorization.jl | 6 +-- stdlib/LinearAlgebra/src/generic.jl | 2 +- stdlib/LinearAlgebra/src/lu.jl | 52 +++++++++++++-------- stdlib/LinearAlgebra/src/qr.jl | 29 +++++++----- stdlib/LinearAlgebra/test/diagonal.jl | 2 +- stdlib/LinearAlgebra/test/generic.jl | 4 +- stdlib/LinearAlgebra/test/lq.jl | 2 +- stdlib/LinearAlgebra/test/lu.jl | 24 +++++----- stdlib/LinearAlgebra/test/qr.jl | 22 ++++----- stdlib/LinearAlgebra/test/special.jl | 4 +- stdlib/LinearAlgebra/test/uniformscaling.jl | 2 +- 14 files changed, 95 insertions(+), 67 deletions(-) diff --git a/NEWS.md b/NEWS.md index bf9b0ceb6b61c..fcd5168dd9514 100644 --- a/NEWS.md +++ b/NEWS.md @@ -115,6 +115,10 @@ Standard library changes * The shape of an `UpperHessenberg` matrix is preserved under certain arithmetic operations, e.g. when multiplying or dividing by an `UpperTriangular` matrix. ([#40039]) * `cis(A)` now supports matrix arguments ([#40194]). * `dot` now supports `UniformScaling` with `AbstractMatrix` ([#40250]). +* `qr[!]` and `lu[!]` now support `LinearAlgebra.PivotingStrategy` (singleton type) values + as their optional `pivot` argument: defaults are `qr(A, NoPivot())` (vs. + `qr(A, ColumnNorm())` for pivoting) and `lu(A, RowMaximum())` (vs. `lu(A, NoPivot())` + without pivoting); the former `Val{true/false}`-based calls are deprecated. ([#40623]) * `det(M::AbstractMatrix{BigInt})` now calls `det_bareiss(M)`, which uses the [Bareiss](https://en.wikipedia.org/wiki/Bareiss_algorithm) algorithm to calculate precise values.([#40868]). #### Markdown diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 855e49265af2d..d5a2a64467f93 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -35,6 +35,7 @@ export BunchKaufman, Cholesky, CholeskyPivoted, + ColumnNorm, Eigen, GeneralizedEigen, GeneralizedSVD, @@ -42,12 +43,14 @@ export Hessenberg, LU, LDLt, + NoPivot, QR, QRPivoted, LQ, Schur, SVD, Hermitian, + RowMaximum, Symmetric, LowerTriangular, UpperTriangular, @@ -164,6 +167,10 @@ abstract type Algorithm end struct DivideAndConquer <: Algorithm end struct QRIteration <: Algorithm end +abstract type PivotingStrategy end +struct NoPivot <: PivotingStrategy end +struct RowMaximum <: PivotingStrategy end +struct ColumnNorm <: PivotingStrategy end # Check that stride of matrix/vector is 1 # Writing like this to avoid splatting penalty when called with multiple arguments, diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index ff789a9fd11b2..4159525d07679 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -1371,7 +1371,7 @@ function factorize(A::StridedMatrix{T}) where T end return lu(A) end - qr(A, Val(true)) + qr(A, ColumnNorm()) end factorize(A::Adjoint) = adjoint(factorize(parent(A))) factorize(A::Transpose) = transpose(factorize(parent(A))) diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index 3e335ed391ad6..5ff215a3eb665 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -16,9 +16,9 @@ size(F::Adjoint{<:Any,<:Factorization}) = reverse(size(parent(F))) size(F::Transpose{<:Any,<:Factorization}) = reverse(size(parent(F))) checkpositivedefinite(info) = info == 0 || throw(PosDefException(info)) -checknonsingular(info, pivoted::Val{true}) = info == 0 || throw(SingularException(info)) -checknonsingular(info, pivoted::Val{false}) = info == 0 || throw(ZeroPivotException(info)) -checknonsingular(info) = checknonsingular(info, Val{true}()) +checknonsingular(info, ::RowMaximum) = info == 0 || throw(SingularException(info)) +checknonsingular(info, ::NoPivot) = info == 0 || throw(ZeroPivotException(info)) +checknonsingular(info) = checknonsingular(info, RowMaximum()) """ issuccess(F::Factorization) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index e0e7cebe2b0e1..c9c624500e928 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1141,7 +1141,7 @@ function (\)(A::AbstractMatrix, B::AbstractVecOrMat) end return lu(A) \ B end - return qr(A,Val(true)) \ B + return qr(A, ColumnNorm()) \ B end (\)(a::AbstractVector, b::AbstractArray) = pinv(a) * b diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 2d915680d5381..e55508db6b397 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -76,22 +76,26 @@ adjoint(F::LU) = Adjoint(F) transpose(F::LU) = Transpose(F) # StridedMatrix -function lu!(A::StridedMatrix{T}, pivot::Union{Val{false}, Val{true}} = Val(true); - check::Bool = true) where T<:BlasFloat - if pivot === Val(false) - return generic_lufact!(A, pivot; check = check) - end +lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true) = lu!(A, RowMaximum(); check=check) +function lu!(A::StridedMatrix{T}, ::RowMaximum; check::Bool = true) where {T<:BlasFloat} lpt = LAPACK.getrf!(A) check && checknonsingular(lpt[3]) return LU{T,typeof(A)}(lpt[1], lpt[2], lpt[3]) end -function lu!(A::HermOrSym, pivot::Union{Val{false}, Val{true}} = Val(true); check::Bool = true) +function lu!(A::StridedMatrix{<:BlasFloat}, pivot::NoPivot; check::Bool = true) + return generic_lufact!(A, pivot; check = check) +end +function lu!(A::HermOrSym, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) copytri!(A.data, A.uplo, isa(A, Hermitian)) lu!(A.data, pivot; check = check) end +# for backward compatibility +# TODO: remove towards Julia v2 +@deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{true}; check::Bool = true) lu!(A, RowMaximum(); check=check) +@deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{false}; check::Bool = true) lu!(A, NoPivot(); check=check) """ - lu!(A, pivot=Val(true); check = true) -> LU + lu!(A, pivot = RowMaximum(); check = true) -> LU `lu!` is the same as [`lu`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) @@ -127,19 +131,22 @@ Stacktrace: [...] ``` """ -lu!(A::StridedMatrix, pivot::Union{Val{false}, Val{true}} = Val(true); check::Bool = true) = +lu!(A::StridedMatrix, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) = generic_lufact!(A, pivot; check = check) -function generic_lufact!(A::StridedMatrix{T}, ::Val{Pivot} = Val(true); - check::Bool = true) where {T,Pivot} +function generic_lufact!(A::StridedMatrix{T}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); + check::Bool = true) where {T} + # Extract values m, n = size(A) minmn = min(m,n) + + # Initialize variables info = 0 ipiv = Vector{BlasInt}(undef, minmn) @inbounds begin for k = 1:minmn # find index max kp = k - if Pivot && k < m + if pivot === RowMaximum() && k < m amax = abs(A[k, k]) for i = k+1:m absi = abs(A[i,k]) @@ -175,7 +182,7 @@ function generic_lufact!(A::StridedMatrix{T}, ::Val{Pivot} = Val(true); end end end - check && checknonsingular(info, Val{Pivot}()) + check && checknonsingular(info, pivot) return LU{T,typeof(A)}(A, ipiv, convert(BlasInt, info)) end @@ -200,7 +207,7 @@ end # for all other types we must promote to a type which is stable under division """ - lu(A, pivot=Val(true); check = true) -> F::LU + lu(A, pivot = RowMaximum(); check = true) -> F::LU Compute the LU factorization of `A`. @@ -211,7 +218,7 @@ validity (via [`issuccess`](@ref)) lies with the user. In most cases, if `A` is a subtype `S` of `AbstractMatrix{T}` with an element type `T` supporting `+`, `-`, `*` and `/`, the return type is `LU{T,S{T}}`. If pivoting is chosen (default) the element type should also support [`abs`](@ref) and -[`<`](@ref). +[`<`](@ref). Pivoting can be turned off by passing `pivot = NoPivot()`. The individual components of the factorization `F` can be accessed via [`getproperty`](@ref): @@ -267,11 +274,14 @@ julia> l == F.L && u == F.U && p == F.p true ``` """ -function lu(A::AbstractMatrix{T}, pivot::Union{Val{false}, Val{true}}=Val(true); - check::Bool = true) where T +function lu(A::AbstractMatrix{T}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T} S = lutype(T) lu!(copy_oftype(A, S), pivot; check = check) end +# TODO: remove for Julia v2.0 +@deprecate lu(A::AbstractMatrix, ::Val{true}; check::Bool = true) lu(A, RowMaximum(); check=check) +@deprecate lu(A::AbstractMatrix, ::Val{false}; check::Bool = true) lu(A, NoPivot(); check=check) + lu(S::LU) = S function lu(x::Number; check::Bool=true) @@ -481,9 +491,11 @@ inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(copy(A)) # Tridiagonal # See dgttrf.f -function lu!(A::Tridiagonal{T,V}, pivot::Union{Val{false}, Val{true}} = Val(true); - check::Bool = true) where {T,V} +function lu!(A::Tridiagonal{T,V}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T,V} + # Extract values n = size(A, 1) + + # Initialize variables info = 0 ipiv = Vector{BlasInt}(undef, n) dl = A.dl @@ -500,7 +512,7 @@ function lu!(A::Tridiagonal{T,V}, pivot::Union{Val{false}, Val{true}} = Val(true end for i = 1:n-2 # pivot or not? - if pivot === Val(false) || abs(d[i]) >= abs(dl[i]) + if pivot === NoPivot() || abs(d[i]) >= abs(dl[i]) # No interchange if d[i] != 0 fact = dl[i]/d[i] @@ -523,7 +535,7 @@ function lu!(A::Tridiagonal{T,V}, pivot::Union{Val{false}, Val{true}} = Val(true end if n > 1 i = n-1 - if pivot === Val(false) || abs(d[i]) >= abs(dl[i]) + if pivot === NoPivot() || abs(d[i]) >= abs(dl[i]) if d[i] != 0 fact = dl[i]/d[i] dl[i] = fact diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index cd5d17565fa3f..390c8a5875773 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -246,17 +246,17 @@ function qrfactPivotedUnblocked!(A::AbstractMatrix) end # LAPACK version -qr!(A::StridedMatrix{<:BlasFloat}, ::Val{false} = Val(false); blocksize=36) = +qr!(A::StridedMatrix{<:BlasFloat}, ::NoPivot; blocksize=36) = QRCompactWY(LAPACK.geqrt!(A, min(min(size(A)...), blocksize))...) -qr!(A::StridedMatrix{<:BlasFloat}, ::Val{true}) = QRPivoted(LAPACK.geqp3!(A)...) +qr!(A::StridedMatrix{<:BlasFloat}, ::ColumnNorm) = QRPivoted(LAPACK.geqp3!(A)...) # Generic fallbacks """ - qr!(A, pivot=Val(false); blocksize) + qr!(A, pivot = NoPivot(); blocksize) -`qr!` is the same as [`qr`](@ref) when `A` is a subtype of -[`StridedMatrix`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. +`qr!` is the same as [`qr`](@ref) when `A` is a subtype of [`StridedMatrix`](@ref), +but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorization produces a number not representable by the element type of `A`, e.g. for integer types. @@ -292,14 +292,17 @@ Stacktrace: [...] ``` """ -qr!(A::AbstractMatrix, ::Val{false}) = qrfactUnblocked!(A) -qr!(A::AbstractMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A) -qr!(A::AbstractMatrix) = qr!(A, Val(false)) +qr!(A::AbstractMatrix, ::NoPivot) = qrfactUnblocked!(A) +qr!(A::AbstractMatrix, ::ColumnNorm) = qrfactPivotedUnblocked!(A) +qr!(A::AbstractMatrix) = qr!(A, NoPivot()) +# TODO: Remove in Julia v2.0 +@deprecate qr!(A::AbstractMatrix, ::Val{true}) qr!(A, ColumnNorm()) +@deprecate qr!(A::AbstractMatrix, ::Val{false}) qr!(A, NoPivot()) _qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T)))) """ - qr(A, pivot=Val(false); blocksize) -> F + qr(A, pivot = NoPivot(); blocksize) -> F Compute the QR factorization of the matrix `A`: an orthogonal (or unitary if `A` is complex-valued) matrix `Q`, and an upper triangular matrix `R` such that @@ -310,7 +313,7 @@ A = Q R The returned object `F` stores the factorization in a packed format: - - if `pivot == Val(true)` then `F` is a [`QRPivoted`](@ref) object, + - if `pivot == ColumnNorm()` then `F` is a [`QRPivoted`](@ref) object, - otherwise if the element type of `A` is a BLAS type ([`Float32`](@ref), [`Float64`](@ref), `ComplexF32` or `ComplexF64`), then `F` is a [`QRCompactWY`](@ref) object, @@ -340,7 +343,7 @@ and `F.Q*A` are supported. A `Q` matrix can be converted into a regular matrix w orthogonal matrix. The block size for QR decomposition can be specified by keyword argument -`blocksize :: Integer` when `pivot == Val(false)` and `A isa StridedMatrix{<:BlasFloat}`. +`blocksize :: Integer` when `pivot == NoPivot()` and `A isa StridedMatrix{<:BlasFloat}`. It is ignored when `blocksize > minimum(size(A))`. See [`QRCompactWY`](@ref). !!! compat "Julia 1.4" @@ -382,6 +385,10 @@ function qr(A::AbstractMatrix{T}, arg...; kwargs...) where T copyto!(AA, A) return qr!(AA, arg...; kwargs...) end +# TODO: remove in Julia v2.0 +@deprecate qr(A::AbstractMatrix, ::Val{false}; kwargs...) qr(A, NoPivot(); kwargs...) +@deprecate qr(A::AbstractMatrix, ::Val{true}; kwargs...) qr(A, ColumnNorm(); kwargs...) + qr(x::Number) = qr(fill(x,1,1)) function qr(v::AbstractVector) require_one_based_indexing(v) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index b6b52c0a0770c..dcd82618c4968 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -565,7 +565,7 @@ end D = Diagonal(randn(5)) Q = qr(randn(5, 5)).Q @test D * Q' == Array(D) * Q' - Q = qr(randn(5, 5), Val(true)).Q + Q = qr(randn(5, 5), ColumnNorm()).Q @test_throws ArgumentError lmul!(Q, D) end diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index cde16288f8f67..489b96be56019 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -387,13 +387,13 @@ LinearAlgebra.Transpose(a::ModInt{n}) where {n} = transpose(a) A = [ModInt{2}(1) ModInt{2}(0); ModInt{2}(1) ModInt{2}(1)] b = [ModInt{2}(1), ModInt{2}(0)] - @test A*(lu(A, Val(false))\b) == b + @test A*(lu(A, NoPivot())\b) == b # Needed for pivoting: Base.abs(a::ModInt{n}) where {n} = a Base.:<(a::ModInt{n}, b::ModInt{n}) where {n} = a.k < b.k - @test A*(lu(A, Val(true))\b) == b + @test A*(lu(A, RowMaximum())\b) == b end @testset "Issue 18742" begin diff --git a/stdlib/LinearAlgebra/test/lq.jl b/stdlib/LinearAlgebra/test/lq.jl index 883793c55d4dd..8915324af9461 100644 --- a/stdlib/LinearAlgebra/test/lq.jl +++ b/stdlib/LinearAlgebra/test/lq.jl @@ -40,7 +40,7 @@ rectangularQ(Q::LinearAlgebra.LQPackedQ) = convert(Array, Q) lqa = lq(a) x = lqa\b l,q = lqa.L, lqa.Q - qra = qr(a, Val(true)) + qra = qr(a, ColumnNorm()) @testset "Basic ops" begin @test size(lqa,1) == size(a,1) @test size(lqa,3) == 1 diff --git a/stdlib/LinearAlgebra/test/lu.jl b/stdlib/LinearAlgebra/test/lu.jl index 8e6c06cdbd12e..6a1c34e511c2e 100644 --- a/stdlib/LinearAlgebra/test/lu.jl +++ b/stdlib/LinearAlgebra/test/lu.jl @@ -61,7 +61,7 @@ dimg = randn(n)/2 lua = factorize(a) @test_throws ErrorException lua.Z l,u,p = lua.L, lua.U, lua.p - ll,ul,pl = lu(a) + ll,ul,pl = @inferred lu(a) @test ll * ul ≈ a[pl,:] @test l*u ≈ a[p,:] @test (l*u)[invperm(p),:] ≈ a @@ -85,9 +85,9 @@ dimg = randn(n)/2 end κd = cond(Array(d),1) @testset "Tridiagonal LU" begin - lud = lu(d) + lud = @inferred lu(d) @test LinearAlgebra.issuccess(lud) - @test lu(lud) == lud + @test @inferred(lu(lud)) == lud @test_throws ErrorException lud.Z @test lud.L*lud.U ≈ lud.P*Array(d) @test lud.L*lud.U ≈ Array(d)[lud.p,:] @@ -199,14 +199,14 @@ dimg = randn(n)/2 @test lua.L*lua.U ≈ lua.P*a[:,1:n1] end @testset "Fat LU" begin - lua = lu(a[1:n1,:]) + lua = @inferred lu(a[1:n1,:]) @test lua.L*lua.U ≈ lua.P*a[1:n1,:] end end @testset "LU of Symmetric/Hermitian" begin for HS in (Hermitian(a'a), Symmetric(a'a)) - luhs = lu(HS) + luhs = @inferred lu(HS) @test luhs.L*luhs.U ≈ luhs.P*Matrix(HS) end end @@ -229,12 +229,12 @@ end @test_throws SingularException lu!(copy(A); check = true) @test !issuccess(lu(A; check = false)) @test !issuccess(lu!(copy(A); check = false)) - @test_throws ZeroPivotException lu(A, Val(false)) - @test_throws ZeroPivotException lu!(copy(A), Val(false)) - @test_throws ZeroPivotException lu(A, Val(false); check = true) - @test_throws ZeroPivotException lu!(copy(A), Val(false); check = true) - @test !issuccess(lu(A, Val(false); check = false)) - @test !issuccess(lu!(copy(A), Val(false); check = false)) + @test_throws ZeroPivotException lu(A, NoPivot()) + @test_throws ZeroPivotException lu!(copy(A), NoPivot()) + @test_throws ZeroPivotException lu(A, NoPivot(); check = true) + @test_throws ZeroPivotException lu!(copy(A), NoPivot(); check = true) + @test !issuccess(lu(A, NoPivot(); check = false)) + @test !issuccess(lu!(copy(A), NoPivot(); check = false)) F = lu(A; check = false) @test sprint((io, x) -> show(io, "text/plain", x), F) == "Failed factorization of type $(typeof(F))" @@ -320,7 +320,7 @@ include("trickyarithmetic.jl") @testset "lu with type whose sum is another type" begin A = TrickyArithmetic.A[1 2; 3 4] ElT = TrickyArithmetic.D{TrickyArithmetic.C,TrickyArithmetic.C} - B = lu(A, Val(false)) + B = lu(A, NoPivot()) @test B isa LinearAlgebra.LU{ElT,Matrix{ElT}} end diff --git a/stdlib/LinearAlgebra/test/qr.jl b/stdlib/LinearAlgebra/test/qr.jl index 394b371e02eac..16f828b4f8861 100644 --- a/stdlib/LinearAlgebra/test/qr.jl +++ b/stdlib/LinearAlgebra/test/qr.jl @@ -49,7 +49,6 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = convert(Array, Q) a_1 = size(a, 1) @testset "QR decomposition (without pivoting)" begin qra = @inferred qr(a) - @inferred qr(a) q, r = qra.Q, qra.R @test_throws ErrorException qra.Z @test q'*squareQ(q) ≈ Matrix(I, a_1, a_1) @@ -78,8 +77,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = convert(Array, Q) @test Base.propertynames(qra) == (:R, :Q) end @testset "Thin QR decomposition (without pivoting)" begin - qra = @inferred qr(a[:, 1:n1], Val(false)) - @inferred qr(a[:, 1:n1], Val(false)) + qra = @inferred qr(a[:, 1:n1], NoPivot()) q,r = qra.Q, qra.R @test_throws ErrorException qra.Z @test q'*squareQ(q) ≈ Matrix(I, a_1, a_1) @@ -104,7 +102,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = convert(Array, Q) @test Base.propertynames(qra) == (:R, :Q) end @testset "(Automatic) Fat (pivoted) QR decomposition" begin - @inferred qr(a, Val(true)) + @inferred qr(a, ColumnNorm()) qrpa = factorize(a[1:n1,:]) q,r = qrpa.Q, qrpa.R @@ -190,7 +188,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = convert(Array, Q) @test mul!(c, b, q') ≈ b*q' @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n), q, b) - qra = qr(a[:,1:n1], Val(false)) + qra = qr(a[:,1:n1], NoPivot()) q, r = qra.Q, qra.R @test rmul!(copy(squareQ(q)'), q) ≈ Matrix(I, n, n) @test_throws DimensionMismatch rmul!(Matrix{eltya}(I, n+1, n+1),q) @@ -215,8 +213,8 @@ end @testset "transpose errors" begin @test_throws MethodError transpose(qr(randn(3,3))) @test_throws MethodError adjoint(qr(randn(3,3))) - @test_throws MethodError transpose(qr(randn(3,3), Val(false))) - @test_throws MethodError adjoint(qr(randn(3,3), Val(false))) + @test_throws MethodError transpose(qr(randn(3,3), NoPivot())) + @test_throws MethodError adjoint(qr(randn(3,3), NoPivot())) @test_throws MethodError transpose(qr(big.(randn(3,3)))) @test_throws MethodError adjoint(qr(big.(randn(3,3)))) end @@ -256,7 +254,7 @@ end A = zeros(1, 2) B = zeros(1, 1) @test A \ B == zeros(2, 1) - @test qr(A, Val(true)) \ B == zeros(2, 1) + @test qr(A, ColumnNorm()) \ B == zeros(2, 1) end @testset "Issue 24107" begin @@ -278,7 +276,7 @@ end @test A \b ≈ ldiv!(c, qr(A ), b) @test b == b0 c0 = copy(c) - @test Ac\c ≈ ldiv!(b, qr(Ac, Val(true)), c) + @test Ac\c ≈ ldiv!(b, qr(Ac, ColumnNorm()), c) @test c0 == c end @@ -295,11 +293,11 @@ end @testset "det(Q::Union{QRCompactWYQ, QRPackedQ})" begin # 40 is the number larger than the default block size 36 of QRCompactWY - @testset for n in [1:3; 40], m in [1:3; 40], pivot in [false, true] + @testset for n in [1:3; 40], m in [1:3; 40], pivot in (NoPivot(), ColumnNorm()) @testset "real" begin @testset for k in 0:min(n, m, 5) A = cat(Array(I(k)), randn(n - k, m - k); dims=(1, 2)) - Q, = qr(A, Val(pivot)) + Q, = qr(A, pivot) @test det(Q) ≈ det(collect(Q)) @test abs(det(Q)) ≈ 1 end @@ -307,7 +305,7 @@ end @testset "complex" begin @testset for k in 0:min(n, m, 5) A = cat(Array(I(k)), randn(ComplexF64, n - k, m - k); dims=(1, 2)) - Q, = qr(A, Val(pivot)) + Q, = qr(A, pivot) @test det(Q) ≈ det(collect(Q)) @test abs(det(Q)) ≈ 1 end diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index c23371f3d072e..48cb65e33eb74 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -192,10 +192,10 @@ end a = rand(n,n) atri = typ(a) b = rand(n,n) - qrb = qr(b,Val(true)) + qrb = qr(b, ColumnNorm()) @test *(atri, adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' @test rmul!(copy(atri), adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' - qrb = qr(b,Val(false)) + qrb = qr(b, NoPivot()) @test *(atri, adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' @test rmul!(copy(atri), adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' end diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index b7b2e5c81cf88..8c69308d06ce8 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -500,7 +500,7 @@ end @testset "Factorization solutions" begin J = complex(randn(),randn()) * I - qrp = A -> qr(A, Val(true)) + qrp = A -> qr(A, ColumnNorm()) # thin matrices X = randn(3,2) From 5dbf45a2997acd26e0f72abaa320c9d0d54956a1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 28 May 2021 12:47:46 -0400 Subject: [PATCH 427/439] compute mayinlinealloc more accurately (for ccall) (#40947) This allows code to assume that `->layout` will be assigned when analyzing a type in codegen if the type is mapped to C. The ABI code often assumes this, and it is also just much generally easier that the jl_struct_to_llvm code can share the jl_compute_field_offsets results. --- src/builtins.c | 2 + src/ccall.cpp | 8 +-- src/cgutils.cpp | 65 ++++++++---------------- src/codegen.cpp | 16 +++--- src/datatype.c | 55 +++++++++++---------- src/dump.c | 13 +++-- src/intrinsics.cpp | 2 +- src/jitlayers.cpp | 4 +- src/jltypes.c | 98 +++++++++++++++++++++++++++++++------ src/julia.h | 3 +- src/julia_internal.h | 3 ++ src/method.c | 29 ++++++++--- stdlib/LibGit2/src/types.jl | 34 ++++++------- test/ccall.jl | 50 ++++++++++++------- 14 files changed, 228 insertions(+), 154 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 75e3f87151672..37471bbb7a718 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1395,6 +1395,8 @@ JL_CALLABLE(jl_f__typebody) break; } } + if (!dt->name->mutabl && !dt->name->references_self) + dt->name->mayinlinealloc = 1; } } diff --git a/src/ccall.cpp b/src/ccall.cpp index c66e86867dc87..00a6403d6434b 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -493,7 +493,7 @@ static Value *julia_to_native( assert(!byRef); // don't expect any ABI to pass pointers by pointer return boxed(ctx, jvinfo); } - assert(jl_is_datatype(jlto) && julia_struct_has_layout((jl_datatype_t*)jlto, jlto_env)); + assert(jl_is_datatype(jlto) && julia_struct_has_layout((jl_datatype_t*)jlto)); typeassert_input(ctx, jvinfo, jlto, jlto_env, argn); if (!byRef) @@ -1065,7 +1065,7 @@ std::string generate_func_sig(const char *fname) } } - t = _julia_struct_to_llvm(ctx, tti, unionall_env, &isboxed, llvmcall); + t = _julia_struct_to_llvm(ctx, tti, &isboxed, llvmcall); if (t == NULL || t == T_void) { return make_errmsg(fname, i + 1, " doesn't correspond to a C type"); } @@ -1211,7 +1211,7 @@ static const std::string verify_ccall_sig(jl_value_t *&rt, jl_value_t *at, rt = (jl_value_t*)jl_any_type; } - lrt = _julia_struct_to_llvm(ctx, rt, unionall_env, &retboxed, llvmcall); + lrt = _julia_struct_to_llvm(ctx, rt, &retboxed, llvmcall); if (lrt == NULL) return "return type doesn't correspond to a C type"; @@ -1405,7 +1405,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) isboxed = false; } else { - largty = _julia_struct_to_llvm(&ctx.emission_context, tti, unionall, &isboxed, llvmcall); + largty = _julia_struct_to_llvm(&ctx.emission_context, tti, &isboxed, llvmcall); } if (isboxed) { ary = boxed(ctx, argv[0]); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index c3f14299a133e..7f88d2d2fff4b 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -475,7 +475,7 @@ static Value *emit_struct_gep(jl_codectx_t &ctx, Type *lty, Value *base, unsigne return ctx.builder.CreateConstInBoundsGEP2_32(lty, base, 0, idx); } -static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_unionall_t *ua, bool *isboxed, bool llvmcall=false); +static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, bool *isboxed, bool llvmcall=false); static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, bool *isboxed) { @@ -486,7 +486,7 @@ static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, bool if (jl_is_concrete_immutable(jt)) { if (jl_datatype_nbits(jt) == 0) return T_void; - Type *t = _julia_struct_to_llvm(ctx, jt, NULL, isboxed); + Type *t = _julia_struct_to_llvm(ctx, jt, isboxed); assert(t != NULL); return t; } @@ -542,23 +542,10 @@ static bool jl_type_hasptr(jl_value_t* typ) return jl_is_datatype(typ) && ((jl_datatype_t*)typ)->layout->npointers > 0; } -// compute whether all concrete subtypes of this type have the same layout -// (which is conservatively approximated here by asking whether the types of any of the -// fields depend on any of the parameters of the containing type) -static bool julia_struct_has_layout(jl_datatype_t *dt, jl_unionall_t *ua) +// return whether all concrete subtypes of this type have the same layout +static bool julia_struct_has_layout(jl_datatype_t *dt) { - if (dt->layout) - return true; - if (ua) { - jl_svec_t *types = jl_get_fieldtypes(dt); - size_t i, ntypes = jl_svec_len(types); - for (i = 0; i < ntypes; i++) { - jl_value_t *ty = jl_svecref(types, i); - if (jl_has_typevar_from_unionall(ty, ua)) - return false; - } - } - return true; + return dt->layout || jl_has_fixed_layout(dt); } static unsigned jl_field_align(jl_datatype_t *dt, size_t i) @@ -569,7 +556,7 @@ static unsigned jl_field_align(jl_datatype_t *dt, size_t i) return std::min({al, (unsigned)jl_datatype_align(dt), (unsigned)JL_HEAP_ALIGNMENT}); } -static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_unionall_t *ua_env, bool *isboxed, bool llvmcall) +static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, bool *isboxed, bool llvmcall) { // this function converts a Julia Type into the equivalent LLVM struct // use this where C-compatible (unboxed) structs are desired @@ -584,7 +571,12 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ bool isTuple = jl_is_tuple_type(jt); jl_svec_t *ftypes = jl_get_fieldtypes(jst); size_t i, ntypes = jl_svec_len(ftypes); - if (ntypes == 0 || (jst->layout && jl_datatype_nbits(jst) == 0)) + if (!julia_struct_has_layout(jst)) + return NULL; // caller should have checked jl_type_mappable_to_c already, but we'll be nice + if (jst->layout == NULL) + jl_compute_field_offsets(jst); + assert(jst->layout); + if (ntypes == 0 || jl_datatype_nbits(jst) == 0) return T_void; Type *_struct_decl = NULL; // TODO: we should probably make a temporary root for `jst` somewhere @@ -592,8 +584,6 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ Type *&struct_decl = (ctx && !llvmcall ? ctx->llvmtypes[jst] : _struct_decl); if (struct_decl) return struct_decl; - if (!julia_struct_has_layout(jst, ua_env)) - return NULL; std::vector latypes(0); bool isarray = true; bool isvector = true; @@ -605,17 +595,8 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ if (jlasttype != NULL && ty != jlasttype) isvector = false; jlasttype = ty; - size_t fsz = 0, al = 0; - bool isptr = !jl_islayout_inline(ty, &fsz, &al); - if (jst->layout) { - // NOTE: jl_field_isptr can disagree with jl_islayout_inline here if the - // struct decided this field must be a pointer due to a type circularity. - // Example from issue #40050: `struct B <: Ref{Tuple{B}}; end` - isptr = jl_field_isptr(jst, i); - assert((isptr ? sizeof(void*) : fsz + jl_is_uniontype(ty)) == jl_field_size(jst, i)); - } Type *lty; - if (isptr) { + if (jl_field_isptr(jst, i)) { lty = T_prjlvalue; isvector = false; } @@ -626,13 +607,15 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ // pick an Integer type size such that alignment will generally be correct, // and always end with an Int8 (selector byte). // We may need to insert padding first to get to the right offset + size_t fsz = 0, al = 0; + bool isptr = !jl_islayout_inline(ty, &fsz, &al); + assert(!isptr && fsz == jl_field_size(jst, i) - 1); (void)isptr; if (al > MAX_ALIGN) { Type *AlignmentType; AlignmentType = ArrayType::get(FixedVectorType::get(T_int8, al), 0); latypes.push_back(AlignmentType); al = MAX_ALIGN; } - assert(al <= jl_field_align(jst, i)); Type *AlignmentType = IntegerType::get(jl_LLVMContext, 8 * al); unsigned NumATy = fsz / al; unsigned remainder = fsz % al; @@ -647,8 +630,9 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ continue; } else { - lty = _julia_struct_to_llvm(ctx, ty, NULL, &isptr, llvmcall); - assert(!isptr); + bool isptr; + lty = _julia_struct_to_llvm(ctx, ty, &isptr, llvmcall); + assert(lty && !isptr); } if (lasttype != NULL && lasttype != lty) isarray = false; @@ -703,16 +687,9 @@ static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, jl_value_t *jt, jl_ return T_prjlvalue; } -static Type *julia_struct_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, jl_unionall_t *ua, bool *isboxed) -{ - return _julia_struct_to_llvm(&ctx.emission_context, jt, ua, isboxed); -} - -bool jl_type_mappable_to_c(jl_value_t *ty) +static Type *julia_struct_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed) { - jl_codegen_params_t params; - bool toboxed; - return _julia_struct_to_llvm(¶ms, ty, NULL, &toboxed) != NULL; + return _julia_struct_to_llvm(&ctx.emission_context, jt, isboxed); } static bool is_datatype_all_pointers(jl_datatype_t *dt) diff --git a/src/codegen.cpp b/src/codegen.cpp index 1a2837737d203..4944356a73dbb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -920,11 +920,11 @@ static bool jl_is_pointerfree(jl_value_t* t) // these queries are usually related, but we split them out here // for convenience and clarity (and because it changes the calling convention) -static bool deserves_stack(jl_value_t* t, bool pointerfree=false) +static bool deserves_stack(jl_value_t* t) { if (!jl_is_concrete_immutable(t)) return false; - return ((jl_datatype_t*)t)->isinlinealloc; + return jl_datatype_isinlinealloc((jl_datatype_t*)t, 0); } static bool deserves_argbox(jl_value_t* t) { @@ -3042,6 +3042,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, jl_value_t *jt = jl_tparam0(utt); if (jl_is_vararg(jt)) jt = jl_unwrap_vararg(jt); + assert(jl_is_datatype(jt)); Value *vidx = emit_unbox(ctx, T_size, fld, (jl_value_t*)jl_long_type); // This is not necessary for correctness, but allows to omit // the extra code for getting the length of the tuple @@ -3053,7 +3054,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, emit_datatype_nfields(ctx, emit_typeof_boxed(ctx, obj)), jl_true); } - bool isboxed = !jl_datatype_isinlinealloc(jt); + bool isboxed = !jl_datatype_isinlinealloc((jl_datatype_t*)jt, 0); Value *ptr = maybe_decay_tracked(ctx, data_pointer(ctx, obj)); *ret = typed_load(ctx, ptr, vidx, isboxed ? (jl_value_t*)jl_any_type : jt, @@ -5424,10 +5425,7 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con // some sanity checking and check whether there's a vararg size_t nargt = jl_svec_len(argt); bool isVa = (nargt > 0 && jl_is_vararg(jl_svecref(argt, nargt - 1))); - if (isVa) { - emit_error(ctx, "cfunction: Vararg syntax not allowed for argument list"); - return jl_cgval_t(); - } + assert(!isVa); jl_array_t *closure_types = NULL; jl_value_t *sigt = NULL; // dispatch-sig = type signature with Ref{} annotations removed and applied to the env @@ -5576,7 +5574,7 @@ const char *jl_generate_ccallable(void *llvmmod, void *sysimg_handle, jl_value_t crt = (jl_value_t*)jl_any_type; } bool toboxed; - Type *lcrt = _julia_struct_to_llvm(¶ms, crt, NULL, &toboxed); + Type *lcrt = _julia_struct_to_llvm(¶ms, crt, &toboxed); if (toboxed) lcrt = T_prjlvalue; size_t nargs = jl_nparams(sigt)-1; @@ -6325,7 +6323,7 @@ static std::pair, jl_llvm_functions_t> if (allunbox) return; } - else if (deserves_stack(jt, true)) { + else if (deserves_stack(jt)) { bool isboxed; Type *vtype = julia_type_to_llvm(ctx, jt, &isboxed); assert(!isboxed); diff --git a/src/datatype.c b/src/datatype.c index cfa4b368b825c..b65c8a602bfcf 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -76,6 +76,7 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu tn->abstract = abstract; tn->mutabl = mutabl; tn->references_self = 0; + tn->mayinlinealloc = 0; tn->mt = NULL; tn->partial = NULL; return tn; @@ -97,7 +98,6 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) t->isdispatchtuple = 0; t->isbitstype = 0; t->zeroinit = 0; - t->isinlinealloc = 0; t->has_concrete_subtype = 1; t->cached_by_hash = 0; t->name = NULL; @@ -238,6 +238,22 @@ STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st) } } +int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree) JL_NOTSAFEPOINT +{ + if (ty->name->mayinlinealloc && ty->layout) { + if (ty->layout->npointers > 0) { + if (pointerfree) + return 0; + if (ty->ninitialized != jl_svec_len(ty->types)) + return 0; + if (ty->layout->fielddesc_type > 1) // GC only implements support for 8 and 16 (not array32) + return 0; + } + return 1; + } + return 0; +} + static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield) JL_NOTSAFEPOINT { if (jl_is_uniontype(ty)) { @@ -249,7 +265,7 @@ static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbyte return 0; return na + nb; } - if (jl_is_datatype(ty) && jl_datatype_isinlinealloc(ty) && (!pointerfree || ((jl_datatype_t*)ty)->layout->npointers == 0)) { + if (jl_is_datatype(ty) && jl_datatype_isinlinealloc((jl_datatype_t*)ty, pointerfree)) { size_t sz = jl_datatype_size(ty); size_t al = jl_datatype_align(ty); // primitive types in struct slots need their sizes aligned. issue #37974 @@ -329,15 +345,11 @@ void jl_compute_field_offsets(jl_datatype_t *st) const uint64_t max_offset = (((uint64_t)1) << 32) - 1; const uint64_t max_size = max_offset >> 1; - if (st->types == NULL || st->name->wrapper == NULL) - return; - if ((jl_is_tuple_type(st) || jl_is_namedtuple_type(st)) && !jl_is_concrete_type((jl_value_t*)st)) - return; + if (st->name->wrapper == NULL) + return; // we got called too early--we'll be back jl_datatype_t *w = (jl_datatype_t*)jl_unwrap_unionall(st->name->wrapper); - if (w->types == NULL) // we got called too early--we'll be back - return; + assert(st->types && w->types); size_t i, nfields = jl_svec_len(st->types); - int isinlinealloc = st->isconcretetype && !st->name->mutabl && !st->name->references_self; assert(st->ninitialized <= nfields); if (st == w && st->layout) { // this check allows us to force re-computation of the layout for some types during init @@ -386,17 +398,13 @@ void jl_compute_field_offsets(jl_datatype_t *st) st->has_concrete_subtype = !jl_is_datatype(fld) || ((jl_datatype_t *)fld)->has_concrete_subtype; } // compute layout for the wrapper object if the field types have no free variables - if (!st->isconcretetype) { - if (st != w) - return; // otherwise we would leak memory - for (i = 0; i < nfields; i++) { - if (jl_has_free_typevars(jl_field_type(st, i))) - return; // not worthwhile computing the rest - } + if (!st->isconcretetype && !jl_has_fixed_layout(st)) { + assert(st == w); // otherwise caller should not have requested this layout + return; } } - int isbitstype = isinlinealloc; + int isbitstype = st->isconcretetype && st->name->mayinlinealloc; for (i = 0; isbitstype && i < nfields; i++) { jl_value_t *fld = jl_field_type(st, i); isbitstype = jl_isbits(fld); @@ -513,14 +521,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) } // now finish deciding if this instantiation qualifies for special properties assert(!isbitstype || st->layout->npointers == 0); // the definition of isbits - if (isinlinealloc && st->layout->npointers > 0) { - if (st->ninitialized != nfields) - isinlinealloc = 0; - else if (st->layout->fielddesc_type > 1) // GC only implements support for 8 and 16 (not array32) - isinlinealloc = 0; - } st->isbitstype = isbitstype; - st->isinlinealloc = isinlinealloc; jl_maybe_allocate_singleton_instance(st); return; } @@ -595,10 +596,12 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype( t->name->wrapper = jl_new_struct(jl_unionall_type, jl_svecref(parameters, i), t->name->wrapper); jl_gc_wb(t->name, t->name->wrapper); } + if (!mutabl && !abstract && ftypes != NULL) + tn->mayinlinealloc = 1; } jl_precompute_memoized_dt(t, 0); - if (!abstract) + if (!abstract && t->types != NULL) jl_compute_field_offsets(t); JL_GC_POP(); @@ -615,7 +618,7 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t * uint32_t alignm = next_power_of_two(nbytes); if (alignm > MAX_ALIGN) alignm = MAX_ALIGN; - bt->isbitstype = bt->isinlinealloc = (parameters == jl_emptysvec); + bt->isbitstype = (parameters == jl_emptysvec); bt->size = nbytes; bt->layout = jl_get_layout(0, 0, alignm, 0, NULL, NULL); bt->instance = NULL; diff --git a/src/dump.c b/src/dump.c index 8ce42de6f5f18..5d9924497a7c4 100644 --- a/src/dump.c +++ b/src/dump.c @@ -277,9 +277,8 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_ | (dt->isdispatchtuple << 2) | (dt->isbitstype << 3) | (dt->zeroinit << 4) - | (dt->isinlinealloc << 5) - | (dt->has_concrete_subtype << 6) - | (dt->cached_by_hash << 7)); + | (dt->has_concrete_subtype << 5) + | (dt->cached_by_hash << 6)); if (!dt->name->abstract) { write_uint16(s->s, dt->ninitialized); } @@ -816,7 +815,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, tn->wrapper); jl_serialize_value(s, tn->mt); ios_write(s->s, (char*)&tn->hash, sizeof(tn->hash)); - write_uint8(s->s, tn->abstract | (tn->mutabl << 1) | (tn->references_self << 2)); + write_uint8(s->s, tn->abstract | (tn->mutabl << 1) | (tn->references_self << 2) | (tn->mayinlinealloc << 3)); } return; } @@ -1277,9 +1276,8 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v dt->isdispatchtuple = (memflags >> 2) & 1; dt->isbitstype = (memflags >> 3) & 1; dt->zeroinit = (memflags >> 4) & 1; - dt->isinlinealloc = (memflags >> 5) & 1; - dt->has_concrete_subtype = (memflags >> 6) & 1; - dt->cached_by_hash = (memflags >> 7) & 1; + dt->has_concrete_subtype = (memflags >> 5) & 1; + dt->cached_by_hash = (memflags >> 6) & 1; if (abstract) dt->ninitialized = 0; else @@ -1737,6 +1735,7 @@ static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, tn->abstract = flags & 1; tn->mutabl = (flags>>1) & 1; tn->references_self = (flags>>2) & 1; + tn->mayinlinealloc = (flags>>3) & 1; } else { jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(jl_get_global(m, sym)); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index deb174f700c77..173a9bb429c08 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -149,7 +149,7 @@ static Constant *julia_const_to_llvm(jl_codectx_t &ctx, const void *ptr, jl_data if (bt == jl_bool_type) return ConstantInt::get(T_int8, (*(const uint8_t*)ptr) ? 1 : 0); - Type *lt = julia_struct_to_llvm(ctx, (jl_value_t*)bt, NULL, NULL); + Type *lt = julia_struct_to_llvm(ctx, (jl_value_t*)bt, NULL); if (jl_is_vecelement_type((jl_value_t*)bt) && !jl_is_uniontype(jl_tparam0(bt))) bt = (jl_datatype_t*)jl_tparam0(bt); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index d24c26812b3d3..e86d6109ff427 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -264,8 +264,6 @@ int jl_compile_extern_c(void *llvmmod, void *p, void *sysimg, jl_value_t *declrt return success; } -bool jl_type_mappable_to_c(jl_value_t *ty); - // declare a C-callable entry point; called during code loading from the toplevel extern "C" JL_DLLEXPORT void jl_extern_c(jl_value_t *declrt, jl_tupletype_t *sigt) @@ -292,7 +290,7 @@ void jl_extern_c(jl_value_t *declrt, jl_tupletype_t *sigt) size_t i, nargs = jl_nparams(sigt); for (i = 1; i < nargs; i++) { jl_value_t *ati = jl_tparam(sigt, i); - if (!jl_is_concrete_type(ati) || jl_is_kind(ati)) + if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati)) jl_error("@ccallable: argument types must be concrete"); } diff --git a/src/jltypes.c b/src/jltypes.c index f759173f2051c..b445a6ddff0d6 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -35,6 +35,45 @@ static int typeenv_has(jl_typeenv_t *env, jl_tvar_t *v) JL_NOTSAFEPOINT return 0; } +static int layout_uses_free_typevars(jl_value_t *v, jl_typeenv_t *env) +{ + if (jl_typeis(v, jl_tvar_type)) + return !typeenv_has(env, (jl_tvar_t*)v); + if (jl_is_uniontype(v)) + return layout_uses_free_typevars(((jl_uniontype_t*)v)->a, env) || + layout_uses_free_typevars(((jl_uniontype_t*)v)->b, env); + if (jl_is_vararg(v)) { + jl_vararg_t *vm = (jl_vararg_t*)v; + if (vm->T) { + if (layout_uses_free_typevars(vm->T, env)) + return 1; + if (vm->N && layout_uses_free_typevars(vm->N, env)) + return 1; + } + return 0; + } + if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + jl_typeenv_t newenv = { ua->var, NULL, env }; + return layout_uses_free_typevars(ua->body, &newenv); + } + if (jl_is_datatype(v)) { + jl_datatype_t *dt = (jl_datatype_t*)v; + if (dt->layout || dt->isconcretetype || !dt->name->mayinlinealloc) + return 0; + jl_svec_t *types = jl_get_fieldtypes(dt); + size_t i, l = jl_svec_len(types); + for (i = 0; i < l; i++) { + jl_value_t *ft = jl_svecref(types, i); + if (layout_uses_free_typevars(ft, env)) { + // This might be inline-alloc, but we don't know the layout + return 1; + } + } + } + return 0; +} + static int has_free_typevars(jl_value_t *v, jl_typeenv_t *env) JL_NOTSAFEPOINT { if (jl_typeis(v, jl_tvar_type)) { @@ -180,6 +219,35 @@ JL_DLLEXPORT int jl_has_typevar_from_unionall(jl_value_t *t, jl_unionall_t *ua) return _jl_has_typevar_from_ua(t, ua, NULL); } +int jl_has_fixed_layout(jl_datatype_t *dt) +{ + if (dt->layout || dt->isconcretetype) + return 1; + if (jl_is_tuple_type(dt)) + return 0; // TODO: relax more? + jl_svec_t *types = jl_get_fieldtypes(dt); + size_t i, l = jl_svec_len(types); + for (i = 0; i < l; i++) { + jl_value_t *ft = jl_svecref(types, i); + if (layout_uses_free_typevars(ft, NULL)) { + // This might be inline-alloc, but we don't know the layout + return 0; + } + } + return 1; +} + +int jl_type_mappable_to_c(jl_value_t *ty) +{ + assert(!jl_is_typevar(ty) && jl_is_type(ty)); + if (jl_is_structtype(ty)) { + jl_datatype_t *jst = (jl_datatype_t*)ty; + return jst->layout || jl_has_fixed_layout(jst); + } + if (jl_is_tuple_type(jl_unwrap_unionall(ty))) + return 0; // TODO: relax some? + return 1; // as boxed or primitive +} // Return true for any type (Integer or Unsigned) that can fit in a // size_t and pass back value, else return false @@ -1409,7 +1477,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value if (jl_is_primitivetype(dt)) { ndt->size = dt->size; ndt->layout = dt->layout; - ndt->isbitstype = ndt->isinlinealloc = ndt->isconcretetype; + ndt->isbitstype = ndt->isconcretetype; } jl_datatype_t *primarydt = ((jl_datatype_t*)jl_unwrap_unionall(tn->wrapper)); @@ -1449,8 +1517,11 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value } // now publish the finished result + // XXX: if the stack was used, this will publish in the wrong order, + // leading to incorrect layouts and data races (#40050: the A{T} should be + // an isbitstype singleton of size 0) if (cacheable) { - if (!jl_is_primitivetype(dt) && ndt->types != NULL && !ndt->name->abstract) { + if (!jl_is_primitivetype(dt) && ndt->types != NULL && ndt->isconcretetype) { jl_compute_field_offsets(ndt); } jl_cache_type_(ndt); @@ -1886,7 +1957,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->names = jl_perm_symsvec(18, + jl_datatype_type->name->names = jl_perm_symsvec(17, "name", "super", "parameters", @@ -1902,10 +1973,9 @@ void jl_init_types(void) JL_GC_DISABLED "isdispatchtuple", "isbitstype", "zeroinit", - "isinlinealloc", "has_concrete_subtype", "cached_by_hash"); - jl_datatype_type->types = jl_svec(18, + jl_datatype_type->types = jl_svec(17, jl_typename_type, jl_datatype_type, jl_simplevector_type, @@ -1913,7 +1983,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, // instance jl_any_type, jl_any_type, jl_any_type, jl_any_type, // properties jl_any_type, jl_any_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type, jl_any_type, jl_any_type); + jl_any_type, jl_any_type, jl_any_type); jl_datatype_type->ninitialized = 3; jl_precompute_memoized_dt(jl_datatype_type, 1); @@ -1922,14 +1992,14 @@ void jl_init_types(void) JL_GC_DISABLED jl_typename_type->name->mt = jl_nonfunction_mt; jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; - jl_typename_type->name->names = jl_perm_symsvec(12, "name", "module", + jl_typename_type->name->names = jl_perm_symsvec(13, "name", "module", "names", "wrapper", "cache", "linearcache", - "hash", "abstract", "mutable", "references_self", + "hash", "abstract", "mutable", "references_self", "mayinlinealloc", "mt", "partial"); - jl_typename_type->types = jl_svec(12, jl_symbol_type, jl_any_type, jl_simplevector_type, + jl_typename_type->types = jl_svec(13, jl_symbol_type, jl_any_type, jl_simplevector_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, - jl_any_type, jl_any_type, jl_any_type, jl_any_type, + jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_methtable_type, jl_any_type); jl_typename_type->ninitialized = 2; jl_precompute_memoized_dt(jl_typename_type, 1); @@ -2503,13 +2573,13 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_datatype_type->types, 14, jl_bool_type); jl_svecset(jl_datatype_type->types, 15, jl_bool_type); jl_svecset(jl_datatype_type->types, 16, jl_bool_type); - jl_svecset(jl_datatype_type->types, 17, jl_bool_type); jl_svecset(jl_typename_type->types, 1, jl_module_type); jl_svecset(jl_typename_type->types, 3, jl_type_type); jl_svecset(jl_typename_type->types, 6, jl_long_type); jl_svecset(jl_typename_type->types, 7, jl_bool_type); jl_svecset(jl_typename_type->types, 8, jl_bool_type); jl_svecset(jl_typename_type->types, 9, jl_bool_type); + jl_svecset(jl_typename_type->types, 10, jl_bool_type); jl_svecset(jl_methtable_type->types, 4, jl_long_type); jl_svecset(jl_methtable_type->types, 6, jl_module_type); jl_svecset(jl_methtable_type->types, 7, jl_array_any_type); @@ -2540,10 +2610,10 @@ void jl_init_types(void) JL_GC_DISABLED jl_compute_field_offsets(jl_symbol_type); // override the preferred layout for a couple types - jl_lineinfonode_type->isinlinealloc = 0; // FIXME: assumed to be a pointer by codegen + jl_lineinfonode_type->name->mayinlinealloc = 0; // FIXME: assumed to be a pointer by codegen // It seems like we probably usually end up needing the box for kinds (used in an Any context)--but is that true? - jl_uniontype_type->isinlinealloc = 0; - jl_unionall_type->isinlinealloc = 0; + jl_uniontype_type->name->mayinlinealloc = 0; + jl_unionall_type->name->mayinlinealloc = 0; } #ifdef __cplusplus diff --git a/src/julia.h b/src/julia.h index cd3780b9eb453..1d9d735c10d06 100644 --- a/src/julia.h +++ b/src/julia.h @@ -432,6 +432,7 @@ typedef struct { uint8_t abstract; uint8_t mutabl; uint8_t references_self; + uint8_t mayinlinealloc; struct _jl_methtable_t *mt; jl_array_t *partial; // incomplete instantiations of this type } jl_typename_t; @@ -498,7 +499,6 @@ typedef struct _jl_datatype_t { uint8_t isdispatchtuple; // aka isleaftupletype uint8_t isbitstype; // relevant query for C-api and type-parameters uint8_t zeroinit; // if one or more fields requires zero-initialization - uint8_t isinlinealloc; // if this is allocated inline uint8_t has_concrete_subtype; // If clear, no value will have this datatype uint8_t cached_by_hash; // stored in hash-based set cache (instead of linear cache) } jl_datatype_t; @@ -1048,7 +1048,6 @@ STATIC_INLINE jl_value_t *jl_field_type_concrete(jl_datatype_t *st JL_PROPAGATES #define jl_datatype_align(t) (((jl_datatype_t*)t)->layout->alignment) #define jl_datatype_nbits(t) ((((jl_datatype_t*)t)->size)*8) #define jl_datatype_nfields(t) (((jl_datatype_t*)(t))->layout->nfields) -#define jl_datatype_isinlinealloc(t) (((jl_datatype_t *)(t))->isinlinealloc) JL_DLLEXPORT void *jl_symbol_name(jl_sym_t *s); // inline version with strong type check to detect typos in a `->name` chain diff --git a/src/julia_internal.h b/src/julia_internal.h index 826d37fd6888e..a07c8e8568ab6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -499,6 +499,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED; int jl_obviously_unequal(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_array_t *jl_find_free_typevars(jl_value_t *v); +int jl_has_fixed_layout(jl_datatype_t *t); +int jl_type_mappable_to_c(jl_value_t *ty); jl_svec_t *jl_outer_unionall_vars(jl_value_t *u); jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty); jl_value_t *jl_type_intersection_env(jl_value_t *a, jl_value_t *b, jl_svec_t **penv); @@ -532,6 +534,7 @@ void jl_foreach_reachable_mtable(void (*visit)(jl_methtable_t *mt, void *env), v void jl_init_main_module(void); int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT; jl_array_t *jl_get_loaded_modules(void); +int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree); jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded); diff --git a/src/method.c b/src/method.c index 1d3a593e638ed..b972d98ef1260 100644 --- a/src/method.c +++ b/src/method.c @@ -21,6 +21,25 @@ extern jl_value_t *jl_builtin_tuple; jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name, jl_value_t *nargs, jl_value_t *functionloc, jl_code_info_t *ci); +static void check_c_types(const char *where, jl_value_t *rt, jl_value_t *at) +{ + if (jl_is_svec(rt)) + jl_errorf("%s: missing return type", where); + JL_TYPECHKS(where, type, rt); + if (!jl_type_mappable_to_c(rt)) + jl_errorf("%s: return type doesn't correspond to a C type", where); + JL_TYPECHKS(where, simplevector, at); + int i, l = jl_svec_len(at); + for (i = 0; i < l; i++) { + jl_value_t *ati = jl_svecref(at, i); + if (jl_is_vararg(ati)) + jl_errorf("%s: Vararg not allowed for argument list", where); + JL_TYPECHKS(where, type, ati); + if (!jl_type_mappable_to_c(ati)) + jl_errorf("%s: argument %d type doesn't correspond to a C type", where, i + 1); + } +} + // Resolve references to non-locally-defined variables to become references to global // variables in `module` (unless the rvalue is one of the type parameters in `sparam_vals`). static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t *sparam_vals, @@ -120,10 +139,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_sve } jl_exprargset(e, 3, at); } - if (jl_is_svec(rt)) - jl_error("cfunction: missing return type"); - JL_TYPECHK(cfunction method definition, type, rt); - JL_TYPECHK(cfunction method definition, simplevector, at); + check_c_types("cfunction method definition", rt, at); JL_TYPECHK(cfunction method definition, quotenode, jl_exprarg(e, 4)); JL_TYPECHK(cfunction method definition, symbol, *(jl_value_t**)jl_exprarg(e, 4)); return expr; @@ -156,10 +172,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_sve } jl_exprargset(e, 2, at); } - if (jl_is_svec(rt)) - jl_error("ccall: missing return type"); - JL_TYPECHK(ccall method definition, type, rt); - JL_TYPECHK(ccall method definition, simplevector, at); + check_c_types("ccall method definition", rt, at); JL_TYPECHK(ccall method definition, long, jl_exprarg(e, 3)); JL_TYPECHK(ccall method definition, quotenode, jl_exprarg(e, 4)); JL_TYPECHK(ccall method definition, symbol, *(jl_value_t**)jl_exprarg(e, 4)); diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 129f526812926..9ffcaa3646127 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -192,7 +192,7 @@ The fields represent: perfdata_cb::Ptr{Cvoid} = C_NULL perfdata_payload::Any = Nothing end -@assert CheckoutOptions.isinlinealloc +@assert Base.allocatedinline(CheckoutOptions) """ LibGit2.TransferProgress @@ -209,7 +209,7 @@ Matches the [`git_indexer_progress`](https://libgit2.org/libgit2/#HEAD/type/git_ indexed_deltas::Cuint = Cuint(0) received_bytes::Csize_t = Csize_t(0) end -@assert TransferProgress.isinlinealloc +@assert Base.allocatedinline(TransferProgress) """ LibGit2.RemoteCallbacks @@ -235,7 +235,7 @@ Matches the [`git_remote_callbacks`](https://libgit2.org/libgit2/#HEAD/type/git_ resolve_url::Ptr{Cvoid} = C_NULL end end -@assert RemoteCallbacks.isinlinealloc +@assert Base.allocatedinline(RemoteCallbacks) """ LibGit2.Callbacks @@ -313,7 +313,7 @@ julia> fetch(remote, "master", options=fo) certificate_cb::Ptr{Cvoid} = certificate_cb() payload::Any = nothing end -@assert ProxyOptions.isinlinealloc +@assert Base.allocatedinline(ProxyOptions) """ LibGit2.FetchOptions @@ -347,7 +347,7 @@ The fields represent: custom_headers::StrArrayStruct = StrArrayStruct() end end -@assert FetchOptions.isinlinealloc +@assert Base.allocatedinline(FetchOptions) """ @@ -384,7 +384,7 @@ The fields represent: remote_cb::Ptr{Cvoid} = C_NULL remote_cb_payload::Any = nothing end -@assert CloneOptions.isinlinealloc +@assert Base.allocatedinline(CloneOptions) """ LibGit2.DiffOptionsStruct @@ -438,7 +438,7 @@ The fields represent: old_prefix::Cstring = Cstring(C_NULL) new_prefix::Cstring = Cstring(C_NULL) end -@assert DiffOptionsStruct.isinlinealloc +@assert Base.allocatedinline(DiffOptionsStruct) """ LibGit2.DescribeOptions @@ -468,7 +468,7 @@ The fields represent: only_follow_first_parent::Cint = Cint(0) show_commit_oid_as_fallback::Cint = Cint(0) end -@assert DescribeOptions.isinlinealloc +@assert Base.allocatedinline(DescribeOptions) """ LibGit2.DescribeFormatOptions @@ -487,7 +487,7 @@ The fields represent: always_use_long_format::Cint = Cint(0) dirty_suffix::Cstring = Cstring(C_NULL) end -@assert DescribeFormatOptions.isinlinealloc +@assert Base.allocatedinline(DescribeFormatOptions) """ LibGit2.DiffFile @@ -617,7 +617,7 @@ The fields represent: file_favor::GIT_MERGE_FILE_FAVOR = Consts.MERGE_FILE_FAVOR_NORMAL file_flags::GIT_MERGE_FILE = Consts.MERGE_FILE_DEFAULT end -@assert MergeOptions.isinlinealloc +@assert Base.allocatedinline(MergeOptions) """ LibGit2.BlameOptions @@ -647,7 +647,7 @@ The fields represent: min_line::Csize_t = Csize_t(1) max_line::Csize_t = Csize_t(0) end -@assert BlameOptions.isinlinealloc +@assert Base.allocatedinline(BlameOptions) """ @@ -678,7 +678,7 @@ The fields represent: custom_headers::StrArrayStruct = StrArrayStruct() end end -@assert PushOptions.isinlinealloc +@assert Base.allocatedinline(PushOptions) """ @@ -701,7 +701,7 @@ The fields represent: merge_opts::MergeOptions = MergeOptions() checkout_opts::CheckoutOptions = CheckoutOptions() end -@assert CherrypickOptions.isinlinealloc +@assert Base.allocatedinline(CherrypickOptions) """ @@ -771,7 +771,7 @@ The fields represent: end checkout_opts::CheckoutOptions = CheckoutOptions() end -@assert RebaseOptions.isinlinealloc +@assert Base.allocatedinline(RebaseOptions) """ LibGit2.RebaseOperation @@ -834,7 +834,7 @@ The fields represent: baseline::Ptr{Cvoid} = C_NULL end end -@assert StatusOptions.isinlinealloc +@assert Base.allocatedinline(StatusOptions) """ LibGit2.StatusEntry @@ -902,7 +902,7 @@ Matches the [`git_config_entry`](https://libgit2.org/libgit2/#HEAD/type/git_conf free::Ptr{Cvoid} = C_NULL payload::Any = nothing end -@assert ConfigEntry.isinlinealloc +@assert Base.allocatedinline(ConfigEntry) function Base.show(io::IO, ce::ConfigEntry) print(io, "ConfigEntry(\"", unsafe_string(ce.name), "\", \"", unsafe_string(ce.value), "\")") @@ -1136,7 +1136,7 @@ The fields represent: boundary::Char = '\0' end -@assert BlameHunk.isinlinealloc +@assert Base.allocatedinline(BlameHunk) """ with(f::Function, obj) diff --git a/test/ccall.jl b/test/ccall.jl index 77e17c6843db1..ae29b40784eb6 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1443,15 +1443,28 @@ end eval(:(f20835(x) = ccall(:fn, Cvoid, (Ptr{typeof(x)},), x)))) @test_throws(UndefVarError(:Something_not_defined_20835), eval(:(f20835(x) = ccall(:fn, Something_not_defined_20835, (Ptr{typeof(x)},), x)))) - -@noinline f21104at(::Type{T}) where {T} = ccall(:fn, Cvoid, (Some{T},), Some(0)) -@noinline f21104rt(::Type{T}) where {T} = ccall(:fn, Some{T}, ()) -@test code_llvm(devnull, f21104at, (Type{Float64},)) === nothing -@test code_llvm(devnull, f21104rt, (Type{Float64},)) === nothing -@test_throws(ErrorException("ccall argument 1 doesn't correspond to a C type"), - f21104at(Float64)) -@test_throws(ErrorException("ccall return type doesn't correspond to a C type"), - f21104rt(Float64)) +@test isempty(methods(f20835)) + +@test_throws(ErrorException("ccall method definition: argument 1 type doesn't correspond to a C type"), + @eval f21104(::Type{T}) where {T} = ccall(:fn, Cvoid, (Some{T},), Some(0))) +@test_throws(ErrorException("ccall method definition: return type doesn't correspond to a C type"), + @eval f21104(::Type{T}) where {T} = ccall(:fn, Some{T}, ())) +@test isempty(methods(f21104)) +@test_throws(ErrorException("ccall method definition: argument 1 type doesn't correspond to a C type"), + @eval if false; ccall(:fn, Cvoid, (Some.body,), Some(0)); end) +@test_throws(ErrorException("ccall method definition: return type doesn't correspond to a C type"), + @eval if false; ccall(:fn, Some.body, ()); end) +@test_throws(ErrorException("ccall method definition: return type doesn't correspond to a C type"), + @eval if false; ccall(:fn, Tuple, ()); end) +## TODO: lowering is broken on this (throws "syntax: ssavalue with no def") +#@test_throws(ErrorException("ccall method definition: return type doesn't correspond to a C type"), +# @eval if false; ccall(:fn, Tuple{Val{T}} where T, ()); end) +@test_throws(ErrorException("ccall method definition: return type doesn't correspond to a C type"), + @eval if false; ccall(:fn, Tuple{Val}, ()); end) +@test_throws(TypeError, @eval if false; ccall(:fn, Some.var, ()); end) +@test_throws(TypeError, @eval if false; ccall(:fn, Cvoid, (Some.var,), Some(0)); end) +@test_throws(ErrorException("ccall method definition: Vararg not allowed for argument list"), + @eval ccall(+, Int, (Vararg{Int},), 1)) # test for malformed syntax errors @test Expr(:error, "more arguments than types for ccall") == Meta.lower(@__MODULE__, :(ccall(:fn, A, (), x))) @@ -1482,21 +1495,20 @@ end evalf_callback_19805(ci::callinfos_19805{FUNC_FT}) where {FUNC_FT} = ci.f(0.5)::Float64 -evalf_callback_c_19805(ci::callinfos_19805{FUNC_FT}) where {FUNC_FT} = @cfunction( - evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},)) - -@test_throws(ErrorException("cfunction argument 1 doesn't correspond to a C type"), - evalf_callback_c_19805( callinfos_19805(sin) )) -@test_throws(ErrorException("cfunction argument 2 doesn't correspond to a C type"), - @cfunction(+, Int, (Int, Nothing))) -@test_throws(ErrorException("cfunction: Vararg syntax not allowed for argument list"), - @cfunction(+, Int, (Vararg{Int},))) +@test_throws(ErrorException("cfunction method definition: argument 1 type doesn't correspond to a C type"), + @eval evalf_callback_c_19805(ci::callinfos_19805{FUNC_FT}) where {FUNC_FT} = + @cfunction(evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},))) +@test isempty(methods(evalf_callback_c_19805)) +@test_throws(ErrorException("cfunction method definition: Vararg not allowed for argument list"), + @eval if false; @cfunction(+, Int, (Vararg{Int},)); end) @test_throws(ErrorException("could not evaluate cfunction argument type (it might depend on a local variable)"), @eval () -> @cfunction(+, Int, (Ref{T}, Ref{T})) where T) @test_throws(ErrorException("could not evaluate cfunction return type (it might depend on a local variable)"), @eval () -> @cfunction(+, Ref{T}, (Int, Int)) where T) +@test_throws(ErrorException("cfunction argument 2 doesn't correspond to a C type"), + @eval @cfunction(+, Int, (Int, Nothing))) @test_throws(ErrorException("cfunction return type Ref{Any} is invalid. Use Any or Ptr{Any} instead."), - @cfunction(+, Ref{Any}, (Int, Int))) + @eval @cfunction(+, Ref{Any}, (Int, Int))) # test Ref{abstract_type} calling parameter passes a heap box abstract type Abstract22734 end From 93d375cb021379a7a57aad05df86c5925cfaebcf Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 28 May 2021 15:19:14 -0400 Subject: [PATCH 428/439] doc: drop colon from "See also" sentences (#40401) We generally seem to prefer sentences over keyword lists (which feel a bit too much like Javadoc to me), so this changes the documentation to use a more free-form sentence for "see also," including an ending period (we seem to have intuitively preferred this already, by a ratio of 5:2). --- base/abstractarray.jl | 2 +- base/array.jl | 2 +- base/char.jl | 10 ++++++---- base/div.jl | 6 +++--- base/initdefs.jl | 5 ++--- base/intfuncs.jl | 10 ++++------ base/io.jl | 2 +- base/iterators.jl | 4 ++-- base/libc.jl | 2 +- base/mpfr.jl | 10 +++++----- base/operators.jl | 10 ++++++---- base/pair.jl | 2 +- base/path.jl | 4 ++-- base/permuteddimsarray.jl | 4 ++-- base/pointer.jl | 4 ++-- base/range.jl | 2 +- base/shell.jl | 4 ++-- base/sort.jl | 7 ++++--- base/stat.jl | 4 ++-- base/strings/basic.jl | 26 ++++++++++++------------- base/strings/io.jl | 16 +++++++-------- base/strings/search.jl | 2 +- base/strings/unicode.jl | 20 +++++++++---------- base/sysinfo.jl | 4 ++-- base/threads_overloads.jl | 2 +- doc/src/manual/documentation.md | 4 ++-- stdlib/InteractiveUtils/src/editless.jl | 2 +- stdlib/LinearAlgebra/src/dense.jl | 2 +- stdlib/LinearAlgebra/src/givens.jl | 8 ++++---- stdlib/Printf/src/Printf.jl | 2 +- stdlib/Sockets/src/addrinfo.jl | 4 ++-- stdlib/SparseArrays/src/sparsematrix.jl | 4 ++-- stdlib/TOML/src/TOML.jl | 8 ++++---- 33 files changed, 99 insertions(+), 99 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index bcce1363e4516..88947e582fda5 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2740,7 +2740,7 @@ mapany(f, itr) = Any[f(x) for x in itr] Transform collection `c` by applying `f` to each element. For multiple collection arguments, apply `f` elementwise, and stop when when any of them is exhausted. -See also: [`map!`](@ref), [`foreach`](@ref), [`mapreduce`](@ref), [`mapslices`](@ref), [`zip`](@ref), [`Iterators.map`](@ref). +See also [`map!`](@ref), [`foreach`](@ref), [`mapreduce`](@ref), [`mapslices`](@ref), [`zip`](@ref), [`Iterators.map`](@ref). # Examples ```jldoctest diff --git a/base/array.jl b/base/array.jl index 9c522855957fe..33c1b7f268562 100644 --- a/base/array.jl +++ b/base/array.jl @@ -499,7 +499,7 @@ function zeros end ones([T=Float64,] dims...) Create an `Array`, with element type `T`, of all ones with size specified by `dims`. -See also: [`fill`](@ref), [`zeros`](@ref). +See also [`fill`](@ref), [`zeros`](@ref). # Examples ```jldoctest diff --git a/base/char.jl b/base/char.jl index a4071d37e41b2..0584471cb6a33 100644 --- a/base/char.jl +++ b/base/char.jl @@ -108,8 +108,9 @@ end ismalformed(c::AbstractChar) -> Bool Return `true` if `c` represents malformed (non-Unicode) data according to the -encoding used by `c`. Defaults to `false` for non-`Char` types. See also -[`show_invalid`](@ref). +encoding used by `c`. Defaults to `false` for non-`Char` types. + +See also [`show_invalid`](@ref). """ ismalformed(c::AbstractChar) = false @@ -117,8 +118,9 @@ ismalformed(c::AbstractChar) = false isoverlong(c::AbstractChar) -> Bool Return `true` if `c` represents an overlong UTF-8 sequence. Defaults -to `false` for non-`Char` types. See also [`decode_overlong`](@ref) -and [`show_invalid`](@ref). +to `false` for non-`Char` types. + +See also [`decode_overlong`](@ref) and [`show_invalid`](@ref). """ isoverlong(c::AbstractChar) = false diff --git a/base/div.jl b/base/div.jl index 8b8361c4150ed..226d155a7bc01 100644 --- a/base/div.jl +++ b/base/div.jl @@ -12,7 +12,7 @@ an integer according to the rounding mode `r`. In other words, the quantity without any intermediate rounding. -See also: [`fld`](@ref), [`cld`](@ref) which are special cases of this function +See also [`fld`](@ref) and [`cld`](@ref), which are special cases of this function. # Examples: ```jldoctest @@ -88,7 +88,7 @@ rem(x::Integer, y::Integer, r::RoundingMode{:Nearest}) = divrem(x, y, r)[2] Largest integer less than or equal to `x/y`. Equivalent to `div(x, y, RoundDown)`. -See also: [`div`](@ref), [`cld`](@ref), [`fld1`](@ref). +See also [`div`](@ref), [`cld`](@ref), [`fld1`](@ref). # Examples ```jldoctest @@ -122,7 +122,7 @@ fld(a, b) = div(a, b, RoundDown) Smallest integer larger than or equal to `x/y`. Equivalent to `div(x, y, RoundUp)`. -See also: [`div`](@ref), [`fld`](@ref). +See also [`div`](@ref), [`fld`](@ref). # Examples ```jldoctest diff --git a/base/initdefs.jl b/base/initdefs.jl index 4c73cfb65dc60..eee4b9ef4f325 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -81,8 +81,7 @@ Here is an overview of some of the subdirectories that may exist in a depot: * `packages`: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by `Pkg.jl`. * `registries`: Contains package registries. By default only `General`. Maintained by `Pkg.jl`. -See also: -[`JULIA_DEPOT_PATH`](@ref JULIA_DEPOT_PATH), and +See also [`JULIA_DEPOT_PATH`](@ref JULIA_DEPOT_PATH), and [Code Loading](@ref code-loading). """ const DEPOT_PATH = String[] @@ -161,7 +160,7 @@ have special meanings: The fully expanded value of `LOAD_PATH` that is searched for projects and packages can be seen by calling the `Base.load_path()` function. -See also: +See also [`JULIA_LOAD_PATH`](@ref JULIA_LOAD_PATH), [`JULIA_PROJECT`](@ref JULIA_PROJECT), [`JULIA_DEPOT_PATH`](@ref JULIA_DEPOT_PATH), and diff --git a/base/intfuncs.jl b/base/intfuncs.jl index d3ab6f2842386..3082b05cdd005 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -953,6 +953,8 @@ Factorial of `n`. If `n` is an [`Integer`](@ref), the factorial is computed as a integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision. +See also [`binomial`](@ref). + # Examples ```jldoctest julia> factorial(6) @@ -967,9 +969,6 @@ julia> factorial(big(21)) 51090942171709440000 ``` -# See also -* [`binomial`](@ref) - # External links * [Factorial](https://en.wikipedia.org/wiki/Factorial) on Wikipedia. """ @@ -999,6 +998,8 @@ If ``n`` is negative, then it is defined in terms of the identity \\binom{n}{k} = (-1)^k \\binom{k-n-1}{k} ``` +See also [`factorial`](@ref). + # Examples ```jldoctest julia> binomial(5, 3) @@ -1011,9 +1012,6 @@ julia> binomial(-5, 3) -35 ``` -# See also -* [`factorial`](@ref) - # External links * [Binomial coefficient](https://en.wikipedia.org/wiki/Binomial_coefficient) on Wikipedia. """ diff --git a/base/io.jl b/base/io.jl index 44fe54ff1df37..aa9ef22c9d306 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1034,7 +1034,7 @@ end Return an iterable object yielding [`read(io, T)`](@ref). -See also: [`skipchars`](@ref), [`eachline`](@ref), [`readuntil`](@ref) +See also [`skipchars`](@ref), [`eachline`](@ref), [`readuntil`](@ref). !!! compat "Julia 1.6" `readeach` requires Julia 1.6 or later. diff --git a/base/iterators.jl b/base/iterators.jl index 2ae6347a4b849..8bbd39d689cce 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -221,7 +221,7 @@ CartesianIndex(1, 2) d CartesianIndex(2, 2) e ``` -See also: [`IndexStyle`](@ref), [`axes`](@ref). +See also [`IndexStyle`](@ref), [`axes`](@ref). """ pairs(::IndexLinear, A::AbstractArray) = Pairs(A, LinearIndices(A)) pairs(::IndexCartesian, A::AbstractArray) = Pairs(A, CartesianIndices(axes(A))) @@ -1338,7 +1338,7 @@ length(s::Stateful) = length(s.itr) - s.taken Returns the one and only element of collection `x`, and throws an `ArgumentError` if the collection has zero or multiple elements. -See also: [`first`](@ref), [`last`](@ref). +See also [`first`](@ref), [`last`](@ref). !!! compat "Julia 1.4" This method requires at least Julia 1.4. diff --git a/base/libc.jl b/base/libc.jl index 547561ac964ba..cb0f05f1dec7b 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -131,7 +131,7 @@ Suspends execution for `s` seconds. This function does not yield to Julia's scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time. -See also: [`sleep`](@ref) +See also [`sleep`](@ref). """ systemsleep diff --git a/base/mpfr.jl b/base/mpfr.jl index 40990df4c9c8f..8f24cd8c0ab38 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -151,6 +151,11 @@ global precision; `convert` will always return `x`. convenience since decimal literals are converted to `Float64` when parsed, so `BigFloat(2.1)` may not yield what you expect. +See also: +- [`@big_str`](@ref) +- [`rounding`](@ref) and [`setrounding`](@ref) +- [`precision`](@ref) and [`setprecision`](@ref) + !!! compat "Julia 1.1" `precision` as a keyword argument requires at least Julia 1.1. In Julia 1.0 `precision` is the second positional argument (`BigFloat(x, precision)`). @@ -169,11 +174,6 @@ julia> BigFloat("2.1", RoundUp) julia> BigFloat("2.1", RoundUp, precision=128) 2.100000000000000000000000000000000000007 ``` - -# See also -- [`@big_str`](@ref) -- [`rounding`](@ref) and [`setrounding`](@ref) -- [`precision`](@ref) and [`setprecision`](@ref) """ BigFloat(x, r::RoundingMode) diff --git a/base/operators.jl b/base/operators.jl index 303fc915e978c..3292ab8f7abe6 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -508,7 +508,9 @@ min(x,y) = ifelse(isless(y, x), y, x) """ minmax(x, y) -Return `(min(x,y), max(x,y))`. See also: [`extrema`](@ref) that returns `(minimum(x), maximum(x))`. +Return `(min(x,y), max(x,y))`. + +See also [`extrema`](@ref) that returns `(minimum(x), maximum(x))`. # Examples ```jldoctest @@ -873,7 +875,7 @@ const ÷ = div Modulus after flooring division, returning a value `r` such that `mod(r, y) == mod(x, y)` in the range ``(0, y]`` for positive `y` and in the range ``[y,0)`` for negative `y`. -See also: [`fld1`](@ref), [`fldmod1`](@ref). +See also [`fld1`](@ref), [`fldmod1`](@ref). # Examples ```jldoctest @@ -892,7 +894,7 @@ mod1(x::T, y::T) where {T<:Real} = (m = mod(x, y); ifelse(m == 0, y, m)) Flooring division, returning a value consistent with `mod1(x,y)` -See also: [`mod1`](@ref), [`fldmod1`](@ref). +See also [`mod1`](@ref), [`fldmod1`](@ref). # Examples ```jldoctest @@ -919,7 +921,7 @@ end Return `(fld1(x,y), mod1(x,y))`. -See also: [`fld1`](@ref), [`mod1`](@ref). +See also [`fld1`](@ref), [`mod1`](@ref). """ fldmod1(x, y) = (fld1(x, y), mod1(x, y)) diff --git a/base/pair.jl b/base/pair.jl index 30fd91892ce4b..7481d50b7458b 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -23,7 +23,7 @@ Construct a `Pair` object with type `Pair{typeof(x), typeof(y)}`. The elements are stored in the fields `first` and `second`. They can also be accessed via iteration (but a `Pair` is treated as a single "scalar" for broadcasting operations). -See also: [`Dict`](@ref) +See also [`Dict`](@ref). # Examples ```jldoctest diff --git a/base/path.jl b/base/path.jl index 2278bb4731948..013ed5db26a5a 100644 --- a/base/path.jl +++ b/base/path.jl @@ -159,7 +159,7 @@ julia> dirname("/home/myuser/") "/home/myuser" ``` -See also: [`basename`](@ref) +See also [`basename`](@ref). """ dirname(path::AbstractString) = splitdir(path)[1] @@ -181,7 +181,7 @@ julia> basename("/home/myuser/") "" ``` -See also: [`dirname`](@ref) +See also [`dirname`](@ref). """ basename(path::AbstractString) = splitdir(path)[2] diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 9c12616e5f265..ea966c44efc38 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -24,7 +24,7 @@ Given an AbstractArray `A`, create a view `B` such that the dimensions appear to be permuted. Similar to `permutedims`, except that no copying occurs (`B` shares storage with `A`). -See also: [`permutedims`](@ref), [`invperm`](@ref). +See also [`permutedims`](@ref), [`invperm`](@ref). # Examples ```jldoctest @@ -86,7 +86,7 @@ end Permute the dimensions of array `A`. `perm` is a vector or a tuple of length `ndims(A)` specifying the permutation. -See also: [`permutedims!`](@ref), [`PermutedDimsArray`](@ref), [`transpose`](@ref), [`invperm`](@ref). +See also [`permutedims!`](@ref), [`PermutedDimsArray`](@ref), [`transpose`](@ref), [`invperm`](@ref). # Examples ```jldoctest diff --git a/base/pointer.jl b/base/pointer.jl index 1739c89f46a0d..d5b4972cc7875 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -125,7 +125,7 @@ Convert a `Ptr` to an object reference. Assumes the pointer refers to a valid he Julia object. If this is not the case, undefined behavior results, hence this function is considered "unsafe" and should be used with care. -See also: [`pointer_from_objref`](@ref). +See also [`pointer_from_objref`](@ref). """ unsafe_pointer_to_objref(x::Ptr) = ccall(:jl_value_ptr, Any, (Ptr{Cvoid},), x) @@ -139,7 +139,7 @@ remains referenced for the whole time that the `Ptr` will be used. This function may not be called on immutable objects, since they do not have stable memory addresses. -See also: [`unsafe_pointer_to_objref`](@ref). +See also [`unsafe_pointer_to_objref`](@ref). """ function pointer_from_objref(@nospecialize(x)) @_inline_meta diff --git a/base/range.jl b/base/range.jl index ca1f577ecf00a..8051b0cdb7ccb 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1282,7 +1282,7 @@ end Find `y` in the range `r` such that ``x ≡ y (mod n)``, where `n = length(r)`, i.e. `y = mod(x - first(r), n) + first(r)`. -See also: [`mod1`](@ref). +See also [`mod1`](@ref). # Examples ```jldoctest diff --git a/base/shell.jl b/base/shell.jl index 48fcb4079bda0..99866c8010b0f 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -322,7 +322,7 @@ run(setenv(`cmd /C echo %cmdargs%`, "cmdargs" => cmdargs)) With an I/O stream parameter `io`, the result will be written there, rather than returned as a string. -See also: [`escape_microsoft_c_args`](@ref), [`shell_escape_posixly`](@ref) +See also [`escape_microsoft_c_args`](@ref), [`shell_escape_posixly`](@ref). # Example ```jldoctest @@ -376,7 +376,7 @@ It joins command-line arguments to be passed to a Windows C/C++/Julia application into a command line, escaping or quoting the meta characters space, TAB, double quote and backslash where needed. -See also: [`shell_escape_wincmd`](@ref), [`escape_raw_string`](@ref) +See also [`shell_escape_wincmd`](@ref), [`escape_raw_string`](@ref). """ function escape_microsoft_c_args(io::IO, args::AbstractString...) # http://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES diff --git a/base/sort.jl b/base/sort.jl index d16de5904c8dd..0946eec516ef7 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -383,13 +383,14 @@ julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start """ searchsortedlast """ - insorted(a, x; by=, lt=, rev=false) + insorted(a, x; by=, lt=, rev=false) -> Bool Determine whether an item is in the given sorted collection, in the sense that it is [`==`](@ref) to one of the values of the collection according to the order specified by the `by`, `lt` and `rev` keywords, assuming that `a` is already -sorted in that order, see [`sort`](@ref) for the keywords. See also -[`in`](@ref). Returns a `Bool` value. +sorted in that order, see [`sort`](@ref) for the keywords. + +See also [`in`](@ref). # Examples ```jldoctest diff --git a/base/stat.jl b/base/stat.jl index d3612b23a0fd1..e6adda11fef6f 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -187,7 +187,7 @@ julia> isdir("not/a/directory") false ``` -See also: [`isfile`](@ref) and [`ispath`](@ref). +See also [`isfile`](@ref) and [`ispath`](@ref). """ isdir(st::StatStruct) = filemode(st) & 0xf000 == 0x4000 @@ -216,7 +216,7 @@ true julia> close(f); rm("test_file.txt") ``` -See also: [`isdir`](@ref) and [`ispath`](@ref). +See also [`isdir`](@ref) and [`ispath`](@ref). """ isfile(st::StatStruct) = filemode(st) & 0xf000 == 0x8000 diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 0b7a4ae8345e6..52c8f6591874f 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -35,8 +35,8 @@ model allows index arithmetic to work with out-of- bounds indices as intermediate values so long as one never uses them to retrieve a character, which often helps avoid needing to code around edge cases. -See also: [`codeunit`](@ref), [`ncodeunits`](@ref), [`thisind`](@ref), -[`nextind`](@ref), [`prevind`](@ref) +See also [`codeunit`](@ref), [`ncodeunits`](@ref), [`thisind`](@ref), +[`nextind`](@ref), [`prevind`](@ref). """ AbstractString @@ -62,8 +62,8 @@ julia> ncodeunits('∫'), ncodeunits('e'), ncodeunits('ˣ') (3, 1, 2) ``` -See also: [`codeunit`](@ref), [`checkbounds`](@ref), [`sizeof`](@ref), -[`length`](@ref), [`lastindex`](@ref) +See also [`codeunit`](@ref), [`checkbounds`](@ref), [`sizeof`](@ref), +[`length`](@ref), [`lastindex`](@ref). """ ncodeunits(s::AbstractString) @@ -77,7 +77,7 @@ limited to these three types, but it's hard to think of widely used string encodings that don't use one of these units. `codeunit(s)` is the same as `typeof(codeunit(s,1))` when `s` is a non-empty string. -See also: [`ncodeunits`](@ref) +See also [`ncodeunits`](@ref). """ codeunit(s::AbstractString) @@ -102,7 +102,7 @@ julia> typeof(a) UInt8 ``` -See also: [`ncodeunits`](@ref), [`checkbounds`](@ref) +See also [`ncodeunits`](@ref), [`checkbounds`](@ref). """ @propagate_inbounds codeunit(s::AbstractString, i::Integer) = typeof(i) === Int ? throw(MethodError(codeunit, (s, i))) : codeunit(s, Int(i)) @@ -118,8 +118,8 @@ In order for `isvalid(s, i)` to be an O(1) function, the encoding of `s` must be [self-synchronizing](https://en.wikipedia.org/wiki/Self-synchronizing_code). This is a basic assumption of Julia's generic string support. -See also: [`getindex`](@ref), [`iterate`](@ref), [`thisind`](@ref), -[`nextind`](@ref), [`prevind`](@ref), [`length`](@ref) +See also [`getindex`](@ref), [`iterate`](@ref), [`thisind`](@ref), +[`nextind`](@ref), [`prevind`](@ref), [`length`](@ref). # Examples ```jldoctest @@ -152,7 +152,7 @@ be iterated, yielding a sequences of characters. If `i` is out of bounds in `s` then a bounds error is raised. The `iterate` function, as part of the iteration protocol may assume that `i` is the start of a character in `s`. -See also: [`getindex`](@ref), [`checkbounds`](@ref) +See also [`getindex`](@ref), [`checkbounds`](@ref). """ @propagate_inbounds iterate(s::AbstractString, i::Integer) = typeof(i) === Int ? throw(MethodError(iterate, (s, i))) : iterate(s, Int(i)) @@ -375,8 +375,8 @@ value `0`. the string because it counts the value on the fly. This is in contrast to the method for arrays, which is a constant-time operation. -See also: [`isvalid`](@ref), [`ncodeunits`](@ref), [`lastindex`](@ref), -[`thisind`](@ref), [`nextind`](@ref), [`prevind`](@ref) +See also [`isvalid`](@ref), [`ncodeunits`](@ref), [`lastindex`](@ref), +[`thisind`](@ref), [`nextind`](@ref), [`prevind`](@ref). # Examples ```jldoctest @@ -695,7 +695,7 @@ reverseind(s::AbstractString, i::Integer) = thisind(s, ncodeunits(s)-i+1) Repeat a string `r` times. This can be written as `s^r`. -See also: [`^`](@ref :^(::Union{AbstractString, AbstractChar}, ::Integer)) +See also [`^`](@ref :^(::Union{AbstractString, AbstractChar}, ::Integer)). # Examples ```jldoctest @@ -710,7 +710,7 @@ repeat(s::AbstractString, r::Integer) = repeat(String(s), r) Repeat a string or character `n` times. This can also be written as `repeat(s, n)`. -See also: [`repeat`](@ref) +See also [`repeat`](@ref). # Examples ```jldoctest diff --git a/base/strings/io.jl b/base/strings/io.jl index 8b6bc21723ced..4ed55f9f0a2bf 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -370,6 +370,8 @@ escaped by a prepending backslash (`\"` is also escaped by default in the first The argument `keep` specifies a collection of characters which are to be kept as they are. Notice that `esc` has precedence here. +See also [`unescape_string`](@ref) for the reverse operation. + !!! compat "Julia 1.7" The `keep` argument is available as of Julia 1.7. @@ -390,9 +392,6 @@ julia> escape_string(string('\\u2135','\\0')) # unambiguous julia> escape_string(string('\\u2135','\\0','0')) # \\0 would be ambiguous "ℵ\\\\x000" ``` - -## See also -[`unescape_string`](@ref) for the reverse operation. """ function escape_string(io::IO, s::AbstractString, esc=""; keep = ()) a = Iterators.Stateful(s) @@ -453,6 +452,8 @@ The following escape sequences are recognised: - Hex bytes (`\\x` with 1-2 trailing hex digits) - Octal bytes (`\\` with 1-3 trailing octal digits) +See also [`escape_string`](@ref). + # Examples ```jldoctest julia> unescape_string("aaa\\\\nbbb") # C escape sequence @@ -467,9 +468,6 @@ julia> unescape_string("\\\\101") # octal julia> unescape_string("aaa \\\\g \\\\n", ['g']) # using `keep` argument "aaa \\\\g \\n" ``` - -## See also -[`escape_string`](@ref). """ function unescape_string(io::IO, s::AbstractString, keep = ()) a = Iterators.Stateful(s) @@ -597,7 +595,7 @@ string literals. (It also happens to be the escaping convention expected by the Microsoft C/C++ compiler runtime when it parses a command-line string into the argv[] array.) -See also: [`escape_string`](@ref) +See also [`escape_string`](@ref). """ function escape_raw_string(io, str::AbstractString) escapes = 0 @@ -669,6 +667,8 @@ end Remove leading indentation from string. +See also `indent` from the [`MultilineStrings` package](https://github.com/invenia/MultilineStrings.jl). + # Examples ```jldoctest julia> Base.unindent(" a\\n b", 2) @@ -677,8 +677,6 @@ julia> Base.unindent(" a\\n b", 2) julia> Base.unindent("\\ta\\n\\tb", 2, tabwidth=8) " a\\n b" ``` - -See also `indent` from the [`MultilineStrings` package](https://github.com/invenia/MultilineStrings.jl). """ function unindent(str::AbstractString, indent::Int; tabwidth=8) indent == 0 && return str diff --git a/base/strings/search.jl b/base/strings/search.jl index 51b23705671f7..ed5758aa68307 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -616,7 +616,7 @@ julia> occursin(r"a.a", "abba") false ``` -See also: [`contains`](@ref). +See also [`contains`](@ref). """ occursin(needle::Union{AbstractString,AbstractChar}, haystack::AbstractString) = _searchindex(haystack, needle, firstindex(haystack)) != 0 diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index 38ffacd8aa572..cf215849ab08c 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -283,7 +283,7 @@ isassigned(c) = UTF8PROC_CATEGORY_CN < category_code(c) <= UTF8PROC_CATEGORY_CO Tests whether a character is a lowercase letter (according to the Unicode standard's `Lowercase` derived property). -See also: [`isuppercase`](@ref). +See also [`isuppercase`](@ref). # Examples ```jldoctest @@ -307,7 +307,7 @@ islowercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isl Tests whether a character is an uppercase letter (according to the Unicode standard's `Uppercase` derived property). -See also: [`islowercase`](@ref). +See also [`islowercase`](@ref). # Examples ```jldoctest @@ -328,7 +328,7 @@ isuppercase(c::AbstractChar) = ismalformed(c) ? false : Bool(ccall(:utf8proc_isu Tests whether a character is cased, i.e. is lower-, upper- or title-cased. -See also: [`islowercase`](@ref), [`isuppercase`](@ref). +See also [`islowercase`](@ref), [`isuppercase`](@ref). """ function iscased(c::AbstractChar) cat = category_code(c) @@ -514,7 +514,7 @@ isxdigit(c::AbstractChar) = '0'<=c<='9' || 'a'<=c<='f' || 'A'<=c<='F' Return `s` with all characters converted to uppercase. -See also: [`lowercase`](@ref), [`titlecase`](@ref), [`uppercasefirst`](@ref). +See also [`lowercase`](@ref), [`titlecase`](@ref), [`uppercasefirst`](@ref). # Examples ```jldoctest @@ -529,7 +529,7 @@ uppercase(s::AbstractString) = map(uppercase, s) Return `s` with all characters converted to lowercase. -See also: [`uppercase`](@ref), [`titlecase`](@ref), [`lowercasefirst`](@ref). +See also [`uppercase`](@ref), [`titlecase`](@ref), [`lowercasefirst`](@ref). # Examples ```jldoctest @@ -551,7 +551,7 @@ which characters should be considered as word separators. See also [`uppercasefirst`](@ref) to capitalize only the first character in `s`. -See also: [`uppercase`](@ref), [`lowercase`](@ref), [`uppercasefirst`](@ref). +See also [`uppercase`](@ref), [`lowercase`](@ref), [`uppercasefirst`](@ref). # Examples ```jldoctest @@ -593,8 +593,8 @@ Return `s` with the first character converted to uppercase (technically "title case" for Unicode). See also [`titlecase`](@ref) to capitalize the first character of every word in `s`. -See also: [`lowercasefirst`](@ref), [`uppercase`](@ref), [`lowercase`](@ref), -[`titlecase`](@ref) +See also [`lowercasefirst`](@ref), [`uppercase`](@ref), [`lowercase`](@ref), +[`titlecase`](@ref). # Examples ```jldoctest @@ -615,8 +615,8 @@ end Return `s` with the first character converted to lowercase. -See also: [`uppercasefirst`](@ref), [`uppercase`](@ref), [`lowercase`](@ref), -[`titlecase`](@ref) +See also [`uppercasefirst`](@ref), [`uppercase`](@ref), [`lowercase`](@ref), +[`titlecase`](@ref). # Examples ```jldoctest diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 01e7866c50d19..cdcb304271b5d 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -286,8 +286,8 @@ end Get the maximum resident set size utilized in bytes. See also: - - man page of getrusage(2) on Linux and FreeBSD. - - windows api `GetProcessMemoryInfo` + - man page of `getrusage`(2) on Linux and FreeBSD. + - Windows API `GetProcessMemoryInfo`. """ maxrss() = ccall(:jl_maxrss, Csize_t, ()) diff --git a/base/threads_overloads.jl b/base/threads_overloads.jl index 3e6ad06760747..a0d4bbeda2288 100644 --- a/base/threads_overloads.jl +++ b/base/threads_overloads.jl @@ -35,7 +35,7 @@ function Threads.foreach(f, channel::Channel; # do `stop[] && break` after `f(item)` to avoid losing `item`. # this isn't super comprehensive since a task could still get # stuck on `take!` at `for item in channel`. We should think - # about a more robust mechanism to avoid dropping items. See also: + # about a more robust mechanism to avoid dropping items. See also # https://github.com/JuliaLang/julia/pull/34543#discussion_r422695217 stop[] && break end diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index ab52536e01cb9..8c68e409b7b5b 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -91,10 +91,10 @@ As in the example above, we recommend following some simple conventions when wri 5. Provide hints to related functions. Sometimes there are functions of related functionality. To increase discoverability please provide - a short list of these in a `See also:` paragraph. + a short list of these in a `See also` paragraph. ``` - See also: [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref) + See also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref). ``` 6. Include any code examples in an `# Examples` section. diff --git a/stdlib/InteractiveUtils/src/editless.jl b/stdlib/InteractiveUtils/src/editless.jl index e9ff7cdd21101..cc3de27e9a4d9 100644 --- a/stdlib/InteractiveUtils/src/editless.jl +++ b/stdlib/InteractiveUtils/src/editless.jl @@ -192,7 +192,7 @@ Edit a file or directory optionally providing a line number to edit the file at. Return to the `julia` prompt when you quit the editor. The editor can be changed by setting `JULIA_EDITOR`, `VISUAL` or `EDITOR` as an environment variable. -See also: [`define_editor`](@ref) +See also [`define_editor`](@ref). """ function edit(path::AbstractString, line::Integer=0) path isa String || (path = convert(String, path)) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 4159525d07679..6be5ac1bb0c56 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -230,7 +230,7 @@ end The `k`th diagonal of a matrix, as a vector. -See also: [`diagm`](@ref), [`diagind`](@ref), [`Diagonal`](@ref), [`isdiag`](@ref). +See also [`diagm`](@ref), [`diagind`](@ref), [`Diagonal`](@ref), [`isdiag`](@ref). # Examples ```jldoctest diff --git a/stdlib/LinearAlgebra/src/givens.jl b/stdlib/LinearAlgebra/src/givens.jl index 4270994018811..d892720a7a1f3 100644 --- a/stdlib/LinearAlgebra/src/givens.jl +++ b/stdlib/LinearAlgebra/src/givens.jl @@ -31,7 +31,7 @@ conjugated transpose right multiplication `A*G'`. The type doesn't have a `size` therefore be multiplied with matrices of arbitrary size as long as `i2<=size(A,2)` for `G*A` or `i2<=size(A,1)` for `A*G'`. -See also: [`givens`](@ref) +See also [`givens`](@ref). """ struct Givens{T} <: AbstractRotation{T} i1::Int @@ -282,7 +282,7 @@ y[i1] = r y[i2] = 0 ``` -See also: [`LinearAlgebra.Givens`](@ref) +See also [`LinearAlgebra.Givens`](@ref). """ function givens(f::T, g::T, i1::Integer, i2::Integer) where T if i1 == i2 @@ -308,7 +308,7 @@ B[i1,j] = r B[i2,j] = 0 ``` -See also: [`LinearAlgebra.Givens`](@ref) +See also [`LinearAlgebra.Givens`](@ref). """ givens(A::AbstractMatrix, i1::Integer, i2::Integer, j::Integer) = givens(A[i1,j], A[i2,j],i1,i2) @@ -327,7 +327,7 @@ B[i1] = r B[i2] = 0 ``` -See also: [`LinearAlgebra.Givens`](@ref) +See also [`LinearAlgebra.Givens`](@ref). """ givens(x::AbstractVector, i1::Integer, i2::Integer) = givens(x[i1], x[i2], i1, i2) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index b40ce3406f212..5f42df50b80de 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -843,7 +843,7 @@ Use shorter of decimal or scientific 1.23 1.23e+07 ``` For a systematic specification of the format, see [here](https://www.cplusplus.com/reference/cstdio/printf/). -See also: [`@sprintf`](@ref). +See also [`@sprintf`](@ref). # Caveats `Inf` and `NaN` are printed consistently as `Inf` and `NaN` for flags `%a`, `%A`, diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl index a4eed4d16d6fa..586463ba0fa21 100644 --- a/stdlib/Sockets/src/addrinfo.jl +++ b/stdlib/Sockets/src/addrinfo.jl @@ -260,7 +260,7 @@ julia> getipaddr(IPv6) ip"fe80::9731:35af:e1c5:6e49" ``` -See also: [`getipaddrs`](@ref) +See also [`getipaddrs`](@ref). """ function getipaddr(addr_type::Type{T}) where T<:IPAddr addrs = getipaddrs(addr_type) @@ -305,7 +305,7 @@ julia> getipaddrs(IPv6) ip"fe80::445e:5fff:fe5d:5500" ``` -See also: [`islinklocaladdr`](@ref), `split(ENV["SSH_CONNECTION"], ' ')[3]` +See also [`islinklocaladdr`](@ref). """ function getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr addresses = T[] diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index ffecaaeaf20c0..4065b783de8b4 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -1103,7 +1103,7 @@ avoids an unnecessary length-`nnz(A)` array-sweep and associated recomputation o pointers. See [`halfperm!`](:func:SparseArrays.halfperm!) for additional algorithmic information. -See also: `unchecked_aliasing_permute!` +See also `unchecked_aliasing_permute!`. """ function unchecked_noalias_permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, @@ -1280,7 +1280,7 @@ For additional (algorithmic) information, and for versions of these methods that argument checking, see (unexported) parent methods `unchecked_noalias_permute!` and `unchecked_aliasing_permute!`. -See also: [`permute`](@ref). +See also [`permute`](@ref). """ function permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} diff --git a/stdlib/TOML/src/TOML.jl b/stdlib/TOML/src/TOML.jl index a8ad706d0b8b4..4765a05c05f52 100644 --- a/stdlib/TOML/src/TOML.jl +++ b/stdlib/TOML/src/TOML.jl @@ -38,7 +38,7 @@ const Parser = Internals.Parser Parse file `f` and return the resulting table (dictionary). Throw a [`ParserError`](@ref) upon failure. -See also: [`TOML.tryparsefile`](@ref) +See also [`TOML.tryparsefile`](@ref). """ parsefile(f::AbstractString) = Internals.parse(Parser(readstring(f); filepath=abspath(f))) @@ -52,7 +52,7 @@ parsefile(p::Parser, f::AbstractString) = Parse file `f` and return the resulting table (dictionary). Return a [`ParserError`](@ref) upon failure. -See also: [`TOML.parsefile`](@ref) +See also [`TOML.parsefile`](@ref). """ tryparsefile(f::AbstractString) = Internals.tryparse(Parser(readstring(f); filepath=abspath(f))) @@ -66,7 +66,7 @@ tryparsefile(p::Parser, f::AbstractString) = Parse the string or stream `x`, and return the resulting table (dictionary). Throw a [`ParserError`](@ref) upon failure. -See also: [`TOML.tryparse`](@ref) +See also [`TOML.tryparse`](@ref). """ parse(str::AbstractString) = Internals.parse(Parser(String(str))) @@ -82,7 +82,7 @@ parse(p::Parser, io::IO) = parse(p, read(io, String)) Parse the string or stream `x`, and return the resulting table (dictionary). Return a [`ParserError`](@ref) upon failure. -See also: [`TOML.parse`](@ref) +See also [`TOML.parse`](@ref). """ tryparse(str::AbstractString) = Internals.tryparse(Parser(String(str))) From a5889a8d3493c42024d11c09bd9ad7433abc9da4 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Fri, 28 May 2021 20:47:46 -0700 Subject: [PATCH 429/439] Fix suitesparse checksum refresh naming mismatch (#40943) Without this change, suitesparse checksum files don't get packed properly. --- contrib/refresh_checksums.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/refresh_checksums.mk b/contrib/refresh_checksums.mk index b1921488dd98f..1ccbb16a9ba4f 100644 --- a/contrib/refresh_checksums.mk +++ b/contrib/refresh_checksums.mk @@ -103,6 +103,11 @@ pack-checksum-llvm: | checksum-llvm-tools pack-checksum-csl: | pack-checksum-compilersupportlibraries pack-checksum-compilersupportlibraries: | checksum-csl +# We need to adjust to the fact that the checksum files are called `suitesparse` +pack-checksum-libsuitesparse: | pack-checksum-suitesparse + @# nothing to do but disable the prefix rule +pack-checksum-suitesparse: | checksum-libsuitesparse + # define how to pack parallel checksums into a single file format pack-checksum-%: FORCE @echo making "$(JULIAHOME)/deps/checksums/$*" From fb42ea57c24eb87d08d3021313d471359763cc62 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Sat, 29 May 2021 05:53:44 +0200 Subject: [PATCH 430/439] gcd and lcm fixed for one negative argument (#40968) --- base/intfuncs.jl | 5 +++-- test/intfuncs.jl | 5 ++++- test/rational.jl | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 3082b05cdd005..e312000ac39f1 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -117,8 +117,9 @@ function lcm(a::T, b::T) where T<:Integer end end -gcd(a::Union{Integer,Rational}) = a -lcm(a::Union{Integer,Rational}) = a +gcd(a::Integer) = checked_abs(a) +gcd(a::Rational) = checked_abs(a.num) // a.den +lcm(a::Union{Integer,Rational}) = gcd(a) gcd(a::Unsigned, b::Signed) = gcd(promote(a, abs(b))...) gcd(a::Signed, b::Unsigned) = gcd(promote(abs(a), b)...) gcd(a::Real, b::Real) = gcd(promote(a,b)...) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 24505935a2fed..8a8f046310622 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -12,6 +12,7 @@ using Random @test gcd(T(0), T(15)) === T(15) @test gcd(T(15), T(0)) === T(15) if T <: Signed + @test gcd(T(-12)) === T(12) @test gcd(T(0), T(-15)) === T(15) @test gcd(T(-15), T(0)) === T(15) @test gcd(T(3), T(-15)) === T(3) @@ -78,6 +79,7 @@ using Random @test lcm(T(0), T(3)) === T(0) @test lcm(T(0), T(0)) === T(0) if T <: Signed + @test lcm(T(-12)) === T(12) @test lcm(T(0), T(-4)) === T(0) @test lcm(T(-4), T(0)) === T(0) @test lcm(T(4), T(-6)) === T(12) @@ -154,6 +156,7 @@ end @test gcd(T[3, 15]) === T(3) @test gcd(T[0, 15]) === T(15) if T <: Signed + @test gcd(T[-12]) === T(12) @test gcd(T[3,-15]) === T(3) @test gcd(T[-3,-15]) === T(3) end @@ -163,12 +166,12 @@ end @test gcd(T[2, 4, 3, 5]) === T(1) @test lcm(T[]) === T(1) - @test lcm(T[2]) === T(2) @test lcm(T[2, 3]) === T(6) @test lcm(T[4, 6]) === T(12) @test lcm(T[3, 0]) === T(0) @test lcm(T[0, 0]) === T(0) if T <: Signed + @test lcm(T[-2]) === T(2) @test lcm(T[4, -6]) === T(12) @test lcm(T[-4, -6]) === T(12) end diff --git a/test/rational.jl b/test/rational.jl index 07e312543318f..aa7d48fb52513 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -488,6 +488,8 @@ end @test gcd(b, a) === T(2)//T(105) @test lcm(a, b) === T(30)//T(7) if T <: Signed + @test gcd(-a) === a + @test lcm(-b) === b @test gcdx(a, b) === (T(2)//T(105), T(-11), T(4)) @test gcd(-a, b) === T(2)//T(105) @test gcd(a, -b) === T(2)//T(105) From 6b10500786c6ecc0eb5c0a3e21f9ee93acd4e0f8 Mon Sep 17 00:00:00 2001 From: Mal Miller <59854849+mmiller-max@users.noreply.github.com> Date: Sat, 29 May 2021 14:01:07 +1000 Subject: [PATCH 431/439] Test: Add information to passing tests (#36879) Closes #25483 --- stdlib/Test/docs/src/index.md | 9 +++++++++ stdlib/Test/src/Test.jl | 21 +++++++++++++++++---- stdlib/Test/src/logging.jl | 2 +- stdlib/Test/test/runtests.jl | 30 ++++++++++++++++++++++++++++-- test/runtests.jl | 2 +- 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index 510654c69ecd1..98fdf45706bf7 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -42,9 +42,13 @@ If the condition is true, a `Pass` is returned: ```jldoctest testfoo julia> @test foo("bar") == 9 Test Passed + Expression: foo("bar") == 9 + Evaluated: 9 == 9 julia> @test foo("fizz") >= 10 Test Passed + Expression: foo("fizz") >= 10 + Evaluated: 16 >= 10 ``` If the condition is false, then a `Fail` is returned and an exception is thrown: @@ -83,6 +87,7 @@ to check that this occurs: ```jldoctest testfoo julia> @test_throws MethodError foo(:cat) Test Passed + Expression: foo(:cat) Thrown: MethodError ``` @@ -194,6 +199,8 @@ checks using either `@test a ≈ b` (where `≈`, typed via tab completion of `\ ```jldoctest julia> @test 1 ≈ 0.999999999 Test Passed + Expression: 1 ≈ 0.999999999 + Evaluated: 1 ≈ 0.999999999 julia> @test 1 ≈ 0.999999 Test Failed at none:1 @@ -206,6 +213,8 @@ after the `≈` comparison: ```jldoctest julia> @test 1 ≈ 0.999999 rtol=1e-5 Test Passed + Expression: ≈(1, 0.999999, rtol = 1.0e-5) + Evaluated: ≈(1, 0.999999; rtol = 1.0e-5) ``` Note that this is not a specific feature of the `≈` but rather a general feature of the `@test` macro: `@test a b key=val` is transformed by the macro into `@test op(a, b, key=val)`. It is, however, particularly useful for `≈` tests. diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 9a16d3d25c9be..62d084bdcad58 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -85,8 +85,9 @@ struct Pass <: Result orig_expr data value - function Pass(test_type::Symbol, orig_expr, data, thrown) - return new(test_type, orig_expr, data, thrown isa String ? "String" : thrown) + source::Union{Nothing,LineNumberNode} + function Pass(test_type::Symbol, orig_expr, data, thrown, source) + return new(test_type, orig_expr, data, thrown isa String ? "String" : thrown, source) end end @@ -236,6 +237,7 @@ function Serialization.serialize(s::Serialization.AbstractSerializer, t::Pass) Serialization.serialize(s, t.orig_expr === nothing ? nothing : string(t.orig_expr)) Serialization.serialize(s, t.data === nothing ? nothing : string(t.data)) Serialization.serialize(s, string(t.value)) + Serialization.serialize(s, t.source === nothing ? nothing : t.source) nothing end @@ -353,9 +355,12 @@ Returns a `Pass` `Result` if it does, a `Fail` `Result` if it is ```jldoctest julia> @test true Test Passed + Expression: true julia> @test [1, 2] + [2, 1] == [3, 3] Test Passed + Expression: [1, 2] + [2, 1] == [3, 3] + Evaluated: [3, 3] == [3, 3] ``` The `@test f(args...) key=val...` form is equivalent to writing @@ -365,6 +370,8 @@ is a call using infix syntax such as approximate comparisons: ```jldoctest julia> @test π ≈ 3.14 atol=0.01 Test Passed + Expression: ≈(π, 3.14, atol = 0.01) + Evaluated: ≈(π, 3.14; atol = 0.01) ``` This is equivalent to the uglier test `@test ≈(π, 3.14, atol=0.01)`. @@ -393,6 +400,8 @@ Test Broken julia> @test 2 + 2 ≈ 5 atol=1 broken=false Test Passed + Expression: ≈(2 + 2, 5, atol = 1) + Evaluated: ≈(4, 5; atol = 1) julia> @test 2 + 2 == 5 skip=true Test Broken @@ -400,6 +409,8 @@ Test Broken julia> @test 2 + 2 == 4 skip=false Test Passed + Expression: 2 + 2 == 4 + Evaluated: 4 == 4 ``` !!! compat "Julia 1.7" @@ -610,7 +621,7 @@ function do_test(result::ExecutionResult, orig_expr) value = result.value testres = if isa(value, Bool) # a true value Passes - value ? Pass(:test, nothing, nothing, value) : + value ? Pass(:test, orig_expr, result.data, value, result.source) : Fail(:test, orig_expr, result.data, value, result.source) else # If the result is non-Boolean, this counts as an Error @@ -652,10 +663,12 @@ Note that `@test_throws` does not support a trailing keyword form. ```jldoctest julia> @test_throws BoundsError [1, 2, 3][4] Test Passed + Expression: ([1, 2, 3])[4] Thrown: BoundsError julia> @test_throws DimensionMismatch [1, 2, 3] + [1, 2] Test Passed + Expression: [1, 2, 3] + [1, 2] Thrown: DimensionMismatch ``` """ @@ -713,7 +726,7 @@ function do_test_throws(result::ExecutionResult, orig_expr, extype) end end if success - testres = Pass(:test_throws, nothing, nothing, exc) + testres = Pass(:test_throws, orig_expr, extype, exc, result.source) else testres = Fail(:test_throws_wrong, orig_expr, extype, exc, result.source) end diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index d333f40b11428..71309944fd9d0 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -178,7 +178,7 @@ macro test_logs(exs...) $(esc(expression)) end if didmatch - testres = Pass(:test, nothing, nothing, value) + testres = Pass(:test, $orig_expr, nothing, value, $sourceloc) else testres = LogTestFailure($orig_expr, $sourceloc, $(QuoteNode(exs[1:end-1])), logs) diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 22bc815e0019b..ff8ba13841aaa 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -288,7 +288,7 @@ end let retval_tests = @testset NoThrowTestSet begin ts = Test.DefaultTestSet("Mock for testing retval of record(::DefaultTestSet, ::T <: Result) methods") - pass_mock = Test.Pass(:test, 1, 2, LineNumberNode(0, "A Pass Mock")) + pass_mock = Test.Pass(:test, 1, 2, 3, LineNumberNode(0, "A Pass Mock")) @test Test.record(ts, pass_mock) isa Test.Pass error_mock = Test.Error(:test, 1, 2, 3, LineNumberNode(0, "An Error Mock")) @test Test.record(ts, error_mock) isa Test.Error @@ -988,7 +988,7 @@ end let ex = :(something_complex + [1, 2, 3]) b = PipeBuffer() - let t = Test.Pass(:test, (ex, 1), (ex, 2), (ex, 3)) + let t = Test.Pass(:test, (ex, 1), (ex, 2), (ex, 3), LineNumberNode(@__LINE__, @__FILE__)) serialize(b, t) @test string(t) == string(deserialize(b)) @test eof(b) @@ -1177,3 +1177,29 @@ end # Decorated LoadErrors are not unwrapped if a LoadError was thrown. @test_throws LoadError("file", 111, ErrorException("Real error")) @macroexpand @test_macro_throw_2 end + +# Issue 25483 +mutable struct PassInformationTestSet <: Test.AbstractTestSet + results::Vector + PassInformationTestSet(desc) = new([]) +end +Test.record(ts::PassInformationTestSet, t::Test.Result) = (push!(ts.results, t); t) +Test.finish(ts::PassInformationTestSet) = ts +@testset "Information in Pass result (Issue 25483)" begin + ts = @testset PassInformationTestSet begin + @test 1 == 1 + @test_throws ErrorException throw(ErrorException("Msg")) + end + test_line_number = (@__LINE__) - 3 + test_throws_line_number = (@__LINE__) - 3 + @test ts.results[1].test_type == :test + @test ts.results[1].orig_expr == :(1 == 1) + @test ts.results[1].data == Expr(:comparison, 1, :(==), 1) + @test ts.results[1].value == true + @test ts.results[1].source == LineNumberNode(test_line_number, @__FILE__) + @test ts.results[2].test_type == :test_throws + @test ts.results[2].orig_expr == :(throw(ErrorException("Msg"))) + @test ts.results[2].data == ErrorException + @test ts.results[2].value == ErrorException("Msg") + @test ts.results[2].source == LineNumberNode(test_throws_line_number, @__FILE__) +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index ec4427d99b197..ea94fca877057 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -363,7 +363,7 @@ cd(@__DIR__) do elseif isa(resp, Test.TestSetException) fake = Test.DefaultTestSet(testname) for i in 1:resp.pass - Test.record(fake, Test.Pass(:test, nothing, nothing, nothing)) + Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, LineNumberNode(@__LINE__, @__FILE__))) end for i in 1:resp.broken Test.record(fake, Test.Broken(:test, nothing)) From 8402463c9364a14aed7d2639d1d5e8d6b74b5392 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 29 May 2021 00:28:03 -0400 Subject: [PATCH 432/439] handle kwarg lowering for vararg with default value (#40977) Fixes #40964 --- src/julia-syntax.scm | 4 +++- test/keywordargs.jl | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index d4d6711f2577f..49404891267da 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -431,7 +431,9 @@ (body (blockify body)) (ftype (decl-type (car pargl))) ;; 1-element list of vararg argument, or empty if none - (vararg (let ((l (if (null? pargl) '() (last pargl)))) + (vararg (let* ((l (if (null? pargl) '() (last pargl))) + ;; handle vararg with default value + (l (if (kwarg? l) (cadr l) l))) (if (or (vararg? l) (varargexpr? l)) (list l) '()))) ;; positional args with vararg diff --git a/test/keywordargs.jl b/test/keywordargs.jl index f9be8edd80dc0..348eaea2ee4c3 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -374,3 +374,9 @@ using InteractiveUtils no_kw_args(x::Int) = 0 @test_throws MethodError no_kw_args(1, k=1) @test_throws MethodError no_kw_args("", k=1) + +# issue #40964 +f40964(xs::Int...=1; k = 2) = (xs, k) +@test f40964() === ((1,), 2) +@test f40964(7, 8) === ((7,8), 2) +@test f40964(7, 8, k=0) === ((7,8), 0) From d6b5bf962a27d854b16d3de97dbdf26e8dc12396 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sat, 29 May 2021 15:39:40 -0400 Subject: [PATCH 433/439] Remove SuiteSparse_wrapper and winclang patch (#40998) * Remove SuiteSparse_wrapper and winclang patch Fix https://github.com/JuliaLang/SuiteSparse.jl/issues/11 Fix https://github.com/JuliaLang/julia/issues/37322 * Update SuiteSparse version to 5.10.1 * Update libsuitesparse checksums for 5.10.1 * Remove more wrapper stuff --- Makefile | 1 - deps/Makefile | 10 +- deps/SuiteSparse_wrapper.c | 156 ------------------ deps/Versions.make | 2 +- deps/checksums/suitesparse | 68 ++++---- deps/libsuitesparse.mk | 50 +----- deps/patches/SuiteSparse-winclang.patch | 14 -- stdlib/SuiteSparse_jll/Project.toml | 2 +- stdlib/SuiteSparse_jll/src/SuiteSparse_jll.jl | 12 +- stdlib/SuiteSparse_jll/test/runtests.jl | 2 +- 10 files changed, 43 insertions(+), 274 deletions(-) delete mode 100644 deps/SuiteSparse_wrapper.c delete mode 100644 deps/patches/SuiteSparse-winclang.patch diff --git a/Makefile b/Makefile index f4207c1719021..51bb09b094f1c 100644 --- a/Makefile +++ b/Makefile @@ -170,7 +170,6 @@ ifeq ($(BUNDLE_DEBUG_LIBS),1) JL_PRIVATE_LIBS-0 += libjulia-internal-debug endif ifeq ($(USE_GPL_LIBS), 1) -JL_PRIVATE_LIBS-0 += libsuitesparse_wrapper JL_PRIVATE_LIBS-$(USE_SYSTEM_LIBSUITESPARSE) += libamd libbtf libcamd libccolamd libcholmod libcolamd libklu libldl librbio libspqr libsuitesparseconfig libumfpack endif JL_PRIVATE_LIBS-$(USE_SYSTEM_PCRE) += libpcre2-8 diff --git a/deps/Makefile b/deps/Makefile index 35c30d5930bd1..27b93f444580f 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -24,7 +24,7 @@ BUILDDIR := $(BUILDDIR)$(MAYBE_HOST) # if you are adding a new target, it can help to copy an similar, existing target # # autoconf configure-driven scripts: pcre unwind gmp mpfr patchelf libuv curl -# custom Makefile rules: openlibm dsfmt libsuitesparse-wrapper libsuitesparse lapack blastrampoline openblas utf8proc objconv libwhich +# custom Makefile rules: openlibm dsfmt libsuitesparse lapack blastrampoline openblas utf8proc objconv libwhich # CMake libs: llvm llvmunwind libgit2 libssh2 mbedtls # # downloadable via git: llvm-svn, libuv, libopenlibm, utf8proc, libgit2, libssh2 @@ -46,10 +46,6 @@ ifeq ($(USE_SYSTEM_CSL), 0) DEP_LIBS += csl endif -ifeq ($(USE_GPL_LIBS), 1) -DEP_LIBS += libsuitesparse-wrapper -endif - ifeq ($(USE_SYSTEM_LIBUV), 0) DEP_LIBS += libuv endif @@ -166,13 +162,11 @@ ifneq ($(OS), WINNT) DEP_LIBS += libwhich endif -DEP_LIBS_STAGED := $(filter-out libsuitesparse-wrapper,$(DEP_LIBS)) - # list all targets DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ - libsuitesparse libsuitesparse-wrapper + libsuitesparse DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) diff --git a/deps/SuiteSparse_wrapper.c b/deps/SuiteSparse_wrapper.c deleted file mode 100644 index 63204ac80a665..0000000000000 --- a/deps/SuiteSparse_wrapper.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - SuiteSparse_wrapper.c: Changes made to this file in the Julia repo - in deps/SuiteSparse_wrapper.c should be also made in - Yggdrasil/S/SuiteSparse and vice versa. -*/ - -#include -#include - -extern size_t jl_cholmod_sizeof_long(void) { - return sizeof(SuiteSparse_long); -} - -extern int jl_cholmod_version(int *ver) { - if (ver != (int*) NULL) { - ver[0] = CHOLMOD_MAIN_VERSION; - ver[1] = CHOLMOD_SUB_VERSION; - ver[2] = CHOLMOD_SUBSUB_VERSION; - } - return CHOLMOD_VERSION; -} - -// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl -extern void jl_cholmod_method_offsets(size_t *v) { - size_t offset = offsetof(cholmod_common, method[0]); - v[ 0] = offsetof(cholmod_common, method[0].lnz) - offset; - v[ 1] = offsetof(cholmod_common, method[0].fl) - offset; - v[ 2] = offsetof(cholmod_common, method[0].prune_dense) - offset; - v[ 3] = offsetof(cholmod_common, method[0].prune_dense2) - offset; - v[ 4] = offsetof(cholmod_common, method[0].nd_oksep) - offset; - v[ 5] = offsetof(cholmod_common, method[0].other_1) - offset; - v[ 6] = offsetof(cholmod_common, method[0].nd_small) - offset; - v[ 7] = offsetof(cholmod_common, method[0].other_2) - offset; - v[ 8] = offsetof(cholmod_common, method[0].aggressive) - offset; - v[ 9] = offsetof(cholmod_common, method[0].order_for_lu) - offset; - v[10] = offsetof(cholmod_common, method[0].nd_compress) - offset; - v[11] = offsetof(cholmod_common, method[0].nd_camd) - offset; - v[12] = offsetof(cholmod_common, method[0].nd_components) - offset; - v[13] = offsetof(cholmod_common, method[0].ordering) - offset; - v[14] = offsetof(cholmod_common, method[0].other_3) - offset; -} - -// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl -extern void jl_cholmod_common_offsets(size_t *v) { - v[ 0] = offsetof(cholmod_common, dbound); - v[ 1] = offsetof(cholmod_common, grow0); - v[ 2] = offsetof(cholmod_common, grow1); - v[ 3] = offsetof(cholmod_common, grow2); - v[ 4] = offsetof(cholmod_common, maxrank); - v[ 5] = offsetof(cholmod_common, supernodal_switch); - v[ 6] = offsetof(cholmod_common, supernodal); - v[ 7] = offsetof(cholmod_common, final_asis); - v[ 8] = offsetof(cholmod_common, final_super); - v[ 9] = offsetof(cholmod_common, final_ll); - v[ 10] = offsetof(cholmod_common, final_pack); - v[ 11] = offsetof(cholmod_common, final_monotonic); - v[ 12] = offsetof(cholmod_common, final_resymbol); - v[ 13] = offsetof(cholmod_common, zrelax); - v[ 14] = offsetof(cholmod_common, nrelax); - v[ 15] = offsetof(cholmod_common, prefer_zomplex); - v[ 16] = offsetof(cholmod_common, prefer_upper); - v[ 17] = offsetof(cholmod_common, quick_return_if_not_posdef); - v[ 18] = offsetof(cholmod_common, prefer_binary); - v[ 19] = offsetof(cholmod_common, print); - v[ 20] = offsetof(cholmod_common, precise); - v[ 21] = offsetof(cholmod_common, try_catch); - v[ 22] = offsetof(cholmod_common, error_handler); - v[ 23] = offsetof(cholmod_common, nmethods); - v[ 24] = offsetof(cholmod_common, current); - v[ 25] = offsetof(cholmod_common, selected); - v[ 26] = offsetof(cholmod_common, method); - v[ 27] = offsetof(cholmod_common, postorder); - v[ 28] = offsetof(cholmod_common, default_nesdis); - v[ 29] = offsetof(cholmod_common, metis_memory); - v[ 30] = offsetof(cholmod_common, metis_dswitch); - v[ 31] = offsetof(cholmod_common, metis_nswitch); - v[ 32] = offsetof(cholmod_common, nrow); - v[ 33] = offsetof(cholmod_common, mark); - v[ 34] = offsetof(cholmod_common, iworksize); - v[ 35] = offsetof(cholmod_common, xworksize); - v[ 36] = offsetof(cholmod_common, Flag); - v[ 37] = offsetof(cholmod_common, Head); - v[ 38] = offsetof(cholmod_common, Xwork); - v[ 39] = offsetof(cholmod_common, Iwork); - v[ 40] = offsetof(cholmod_common, itype); - v[ 41] = offsetof(cholmod_common, dtype); - v[ 42] = offsetof(cholmod_common, no_workspace_reallocate); - v[ 43] = offsetof(cholmod_common, status); - v[ 44] = offsetof(cholmod_common, fl); - v[ 45] = offsetof(cholmod_common, lnz); - v[ 46] = offsetof(cholmod_common, anz); - v[ 47] = offsetof(cholmod_common, modfl); - v[ 48] = offsetof(cholmod_common, malloc_count); - v[ 49] = offsetof(cholmod_common, memory_usage); - v[ 50] = offsetof(cholmod_common, memory_inuse); - v[ 51] = offsetof(cholmod_common, nrealloc_col); - v[ 52] = offsetof(cholmod_common, nrealloc_factor); - v[ 53] = offsetof(cholmod_common, ndbounds_hit); - v[ 54] = offsetof(cholmod_common, rowfacfl); - v[ 55] = offsetof(cholmod_common, aatfl); - v[ 56] = offsetof(cholmod_common, called_nd); - v[ 57] = offsetof(cholmod_common, blas_ok); - v[ 58] = offsetof(cholmod_common, SPQR_grain); - v[ 59] = offsetof(cholmod_common, SPQR_small); - v[ 60] = offsetof(cholmod_common, SPQR_shrink); - v[ 61] = offsetof(cholmod_common, SPQR_nthreads); - v[ 62] = offsetof(cholmod_common, SPQR_flopcount); - v[ 63] = offsetof(cholmod_common, SPQR_analyze_time); - v[ 64] = offsetof(cholmod_common, SPQR_factorize_time); - v[ 65] = offsetof(cholmod_common, SPQR_solve_time); - v[ 66] = offsetof(cholmod_common, SPQR_flopcount_bound); - v[ 67] = offsetof(cholmod_common, SPQR_tol_used); - v[ 68] = offsetof(cholmod_common, SPQR_norm_E_fro); - v[ 69] = offsetof(cholmod_common, SPQR_istat); - v[ 70] = offsetof(cholmod_common, useGPU); - v[ 71] = offsetof(cholmod_common, maxGpuMemBytes); - v[ 72] = offsetof(cholmod_common, maxGpuMemFraction); - v[ 73] = offsetof(cholmod_common, gpuMemorySize); - v[ 74] = offsetof(cholmod_common, gpuKernelTime); - v[ 75] = offsetof(cholmod_common, gpuFlops); - v[ 76] = offsetof(cholmod_common, gpuNumKernelLaunches); - v[ 77] = offsetof(cholmod_common, cublasHandle); - v[ 78] = offsetof(cholmod_common, gpuStream); - v[ 79] = offsetof(cholmod_common, cublasEventPotrf); - v[ 80] = offsetof(cholmod_common, updateCKernelsComplete); - v[ 81] = offsetof(cholmod_common, updateCBuffersFree); - v[ 82] = offsetof(cholmod_common, dev_mempool); - v[ 83] = offsetof(cholmod_common, dev_mempool_size); - v[ 84] = offsetof(cholmod_common, host_pinned_mempool); - v[ 85] = offsetof(cholmod_common, host_pinned_mempool_size); - v[ 86] = offsetof(cholmod_common, devBuffSize); - v[ 87] = offsetof(cholmod_common, ibuffer); - v[ 88] = offsetof(cholmod_common, syrkStart); - v[ 89] = offsetof(cholmod_common, cholmod_cpu_gemm_time); - v[ 90] = offsetof(cholmod_common, cholmod_cpu_syrk_time); - v[ 91] = offsetof(cholmod_common, cholmod_cpu_trsm_time); - v[ 92] = offsetof(cholmod_common, cholmod_cpu_potrf_time); - v[ 93] = offsetof(cholmod_common, cholmod_gpu_gemm_time); - v[ 94] = offsetof(cholmod_common, cholmod_gpu_syrk_time); - v[ 95] = offsetof(cholmod_common, cholmod_gpu_trsm_time); - v[ 96] = offsetof(cholmod_common, cholmod_gpu_potrf_time); - v[ 97] = offsetof(cholmod_common, cholmod_assemble_time); - v[ 98] = offsetof(cholmod_common, cholmod_assemble_time2); - v[ 99] = offsetof(cholmod_common, cholmod_cpu_gemm_calls); - v[100] = offsetof(cholmod_common, cholmod_cpu_syrk_calls); - v[101] = offsetof(cholmod_common, cholmod_cpu_trsm_calls); - v[102] = offsetof(cholmod_common, cholmod_cpu_potrf_calls); - v[103] = offsetof(cholmod_common, cholmod_gpu_gemm_calls); - v[104] = offsetof(cholmod_common, cholmod_gpu_syrk_calls); - v[105] = offsetof(cholmod_common, cholmod_gpu_trsm_calls); - v[106] = offsetof(cholmod_common, cholmod_gpu_potrf_calls); -} - -extern size_t jl_cholmod_common_size() { - return sizeof(cholmod_common); -} diff --git a/deps/Versions.make b/deps/Versions.make index 56014d8b052b0..cb41d43622aed 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -98,7 +98,7 @@ PCRE_VER := 10.36 PCRE_JLL_NAME := PCRE2 # SuiteSparse -LIBSUITESPARSE_VER := 5.8.1 +LIBSUITESPARSE_VER := 5.10.1 LIBSUITESPARSE_JLL_NAME := SuiteSparse # unwind diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 7b4975e4ca709..25123ba015294 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,34 +1,34 @@ -SuiteSparse-5.8.1.tar.gz/md5/c414679bbc9432a3def01b31ad921140 -SuiteSparse-5.8.1.tar.gz/sha512/3d986157acd39968216880c2de30c54d72e0addd7318a04948c1b842ad9c876bcde32f292504d4540a4baa998a368dfc0db000606a2d00f61760a92d5b8c1cb8 -SuiteSparse.v5.8.1+2.aarch64-apple-darwin.tar.gz/md5/949a6cd6ac04e41f89cef401d7e5ca74 -SuiteSparse.v5.8.1+2.aarch64-apple-darwin.tar.gz/sha512/60612bd0bfeb1e00a452aea8024454110838eb20889be3f82fa6ee25884f791d7fd21c156aaca68e94561f084ab83b44f71c7740486d8233c5451ff267e85d9a -SuiteSparse.v5.8.1+2.aarch64-linux-gnu.tar.gz/md5/241344499b65b88a967fecae692e314c -SuiteSparse.v5.8.1+2.aarch64-linux-gnu.tar.gz/sha512/5ab6f4df36a56c2ebc880a10889071bbf0846d6231ffe750a1427108a5ae3c7e1dcd0e994dcd4264908a420cc6534b8f58912baaafd1cdc83d5c38f5f44fb217 -SuiteSparse.v5.8.1+2.aarch64-linux-musl.tar.gz/md5/d0cbfe923083718235a6ef878a36dd7d -SuiteSparse.v5.8.1+2.aarch64-linux-musl.tar.gz/sha512/e1e0b4c9408ae966c429a81c22089077f137cd44fdd6a8ee228122ac3dfe79dd163277657fcce69c916d071b46b82f6cc445b1b2a778691c2a7fc4178eaeae0c -SuiteSparse.v5.8.1+2.armv6l-linux-gnueabihf.tar.gz/md5/5c690a16f2a176e3d7369ef52aaf0dcc -SuiteSparse.v5.8.1+2.armv6l-linux-gnueabihf.tar.gz/sha512/ce018e09df64f63b728a6f3fd6b256859b1f6ff76750858192083b19acd25813512ae50755d5cfd716fa62dc17ef160bad1ed4c65a46268801df9504482e2c04 -SuiteSparse.v5.8.1+2.armv6l-linux-musleabihf.tar.gz/md5/4b51607d9d6c332b5c86adc9ab6887e6 -SuiteSparse.v5.8.1+2.armv6l-linux-musleabihf.tar.gz/sha512/9fac97308c3109d4a6c365393c8077f9717b2cdd3dd483e0a0aed82ed4e70cd321aeb18e3eaa764bdb1c3b24e378eb687eeb0c48b91e1d0de55a08301b50c6d6 -SuiteSparse.v5.8.1+2.armv7l-linux-gnueabihf.tar.gz/md5/f40fdd991ef0cf9d556d1ae2ae079cd1 -SuiteSparse.v5.8.1+2.armv7l-linux-gnueabihf.tar.gz/sha512/1d1b81b8f6f82d09f53bff5ade45d3183cb903fee0b279d69fbb7cfa737aeff72279d3e151d4094ed56dfa4b8affe1f4bda443c982c5fc8aa881c2ce9f88dafc -SuiteSparse.v5.8.1+2.armv7l-linux-musleabihf.tar.gz/md5/4a87fc57bc380220abc7422f9f428d6f -SuiteSparse.v5.8.1+2.armv7l-linux-musleabihf.tar.gz/sha512/47cab4afd3559f67dfe54c6bc2ce9ff3c0e69334c2df99e929ff4843c7f92b6fdf7b6001e61701040a1623fc97927001b7cd0f07074d4099cd03b2d4e184d4c1 -SuiteSparse.v5.8.1+2.i686-linux-gnu.tar.gz/md5/4d3826df74a9f0c64e4dffabb6de0c7d -SuiteSparse.v5.8.1+2.i686-linux-gnu.tar.gz/sha512/2a0a10e1ba273b308aa7d11b0ace54eaef300ff4c8ddbf8ff3a721766fa5b59a43184b73f80afe8205410fa4d295ed5b38973053dcdba278d8e03aa0f47903ed -SuiteSparse.v5.8.1+2.i686-linux-musl.tar.gz/md5/72543b4dd636e4ffadb7a24eff8b5f9e -SuiteSparse.v5.8.1+2.i686-linux-musl.tar.gz/sha512/216795d8af1c2012b692d1b6ec2a4b70012331bbe9619a502c43cf1530d3170c69eb2261d6bba973ab40173f0b9a05992f4c570ff35a25018c7bff936da607ff -SuiteSparse.v5.8.1+2.i686-w64-mingw32.tar.gz/md5/29141ae2b353d4477b9d8e9fad0b8242 -SuiteSparse.v5.8.1+2.i686-w64-mingw32.tar.gz/sha512/ac80a24f60cb89ec25fddd77371cf209e43c4223756d435eb6f1a931c840bf7f2b11762de889664b98b0e0bb9b35f747c6af2365d564a164d6d92bb69c7b5108 -SuiteSparse.v5.8.1+2.powerpc64le-linux-gnu.tar.gz/md5/a776cb5742b4d00c89c445bc07ac7c3d -SuiteSparse.v5.8.1+2.powerpc64le-linux-gnu.tar.gz/sha512/314a220782be70d8267cefe4efd84439e33516c576666d8edbfa02581f0a1ebd31af97618743d461acb63f447ddff4dc282445b96782f2a73ec72b911948e443 -SuiteSparse.v5.8.1+2.x86_64-apple-darwin.tar.gz/md5/8b94288d3ec650f85f7723fc53e0acfd -SuiteSparse.v5.8.1+2.x86_64-apple-darwin.tar.gz/sha512/7a790a3bf8b3ff4402aea6d8c06eaf5d997317c85a7f109850af4f6719388b4a0a96d540c55b6ca1c2a69732307a89780c3f7282b784ce9c5d65b2fd2169a20c -SuiteSparse.v5.8.1+2.x86_64-linux-gnu.tar.gz/md5/b78f13d88b69826d6cde30cf5e7dbdf1 -SuiteSparse.v5.8.1+2.x86_64-linux-gnu.tar.gz/sha512/0e624d5f0f5f69d9e60841c90a7205bb38e0916db83752bb837b42f956389b9dfb7aca55025cb071fedeaa2acde8f7c7ad567e264f43aa49b1e8797b8bc3b4cb -SuiteSparse.v5.8.1+2.x86_64-linux-musl.tar.gz/md5/f1e7760e7de7385617c42137c042f085 -SuiteSparse.v5.8.1+2.x86_64-linux-musl.tar.gz/sha512/a7098cce4bed90133e9625908373c7c695ff03ebebec556322652d1d5485c7f9ab3543122a8950d27f0d00d751f136aa640a403fd2f326e37538cea12c199ac1 -SuiteSparse.v5.8.1+2.x86_64-unknown-freebsd.tar.gz/md5/8ebdffa4e464038f5dfa00f63776a919 -SuiteSparse.v5.8.1+2.x86_64-unknown-freebsd.tar.gz/sha512/54a93637ff01d2606726d445e8f186517da8915ef6bde549f841cd11521031c4fc19d3a8254006683db6bee04e41b43aaad72bacdf3c826d0fd9eed16feb40ab -SuiteSparse.v5.8.1+2.x86_64-w64-mingw32.tar.gz/md5/d280f92f61ce045dcf434029b32b788c -SuiteSparse.v5.8.1+2.x86_64-w64-mingw32.tar.gz/sha512/a17bfa2562fc60f3832131d72d6055c7855b10a67cccea357de6bed51ed9a310da5ccae7ed31549f4628c1af73aebd26125073d49648d194827e6cad0e421626 +SuiteSparse-5.10.1.tar.gz/md5/68bb912f3cf3d2b01f30ebafef690302 +SuiteSparse-5.10.1.tar.gz/sha512/8f85c6d63b76cba95707dfa732c51200df7794cb4c2599dbd92100475747b8d02b05089a47096e85c60b89bc852a8e768e0670f24902a82d29494a80ccf2bb5f +SuiteSparse.v5.10.1+0.aarch64-apple-darwin.tar.gz/md5/b9392f8e71c0c40d37489e7b2071c5ad +SuiteSparse.v5.10.1+0.aarch64-apple-darwin.tar.gz/sha512/109d67cb009e3b2931b94d63cbdaaee29d60dc190b731ebe3737181cd48d913b8a1333043c67be8179c73e4d3ae32ed1361ab4e34312c0f42e4b29f8a7afda3e +SuiteSparse.v5.10.1+0.aarch64-linux-gnu.tar.gz/md5/1b2651ede4a74cd57f65505a65093314 +SuiteSparse.v5.10.1+0.aarch64-linux-gnu.tar.gz/sha512/753f986a749d139f9a6baedac059d8ed8efdd716ed28eacdbf00e6ebe863b4e17467f01a9693dcb39571d38b4b5c4c1375dbb790b88a7e704116e3fe83f7ff3e +SuiteSparse.v5.10.1+0.aarch64-linux-musl.tar.gz/md5/051ff9bbbc95c57d58563df8a2c8eedd +SuiteSparse.v5.10.1+0.aarch64-linux-musl.tar.gz/sha512/855979ed8d6290c529d9c9e82944fb15c88f9d9d8da7db1fa2fc34efb0ed985fc6554312882107f26956f2a18ae985918909cd834e068b874906c21a0f53b6c9 +SuiteSparse.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/md5/dbc5fb4844077084663612af26e180ce +SuiteSparse.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/b906f7275ab58006acd52927e7e04c79eec59b5f28e9d7e5d5b8556c0eedd54cfff87e494373702c205afa2384ee6b0f2bb5e811fd440b1b50d5c9eee1b47b99 +SuiteSparse.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/md5/7770d256e76d5ce1484c3781508cc3ed +SuiteSparse.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/sha512/4f1d46cc8da5a7eff665b4bb96f9e21319f39231f98a6164d8c3d654d5b6f93c3e4477f55a39a80b7f8125a78d690cc5a1cc58f29143ba4c109a4182d7fa2110 +SuiteSparse.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/md5/ee1fa978bcfb264842749f915bbefd77 +SuiteSparse.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/9592a42f6474fd89eea1144f62ecc2a23796ad251173a9c36ccbc9bc18dd88687ce49f51528974f56b5652e2ab15f0aa41634513f2cc0b3c54259de3b68350bd +SuiteSparse.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/md5/30f708421b92158c7741c82576e9047b +SuiteSparse.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/sha512/d8793d48757dbb62aa7a21c215b6d6e63a26ce4ba740f1f7f42a3e485ad3d9628744f021ad9cc96e29c8c88bfb2f02ea92865c26b971ca739d3c05c7f28875d9 +SuiteSparse.v5.10.1+0.i686-linux-gnu.tar.gz/md5/9018b6168b9a687bab0c9a9cbf45afba +SuiteSparse.v5.10.1+0.i686-linux-gnu.tar.gz/sha512/308a92f441af6855517c40c6871b4935251677c05cc082c21fd1249e0137b635fa524f60cad61c7524026301a6de7ffea0ad1f4b9a4d9d6e3ced3f332a6719d4 +SuiteSparse.v5.10.1+0.i686-linux-musl.tar.gz/md5/99143f8d6de4f071ffa19942252b6dec +SuiteSparse.v5.10.1+0.i686-linux-musl.tar.gz/sha512/9fb719fffea03296dfac8bc221bafc3ed8f7791749eca6c4b00265994de1be5d242e7e5184693603c745b39c4538feb11ab283204e0e33df2745f904cf0c7252 +SuiteSparse.v5.10.1+0.i686-w64-mingw32.tar.gz/md5/d049c943fbda2c8380dea33e16569275 +SuiteSparse.v5.10.1+0.i686-w64-mingw32.tar.gz/sha512/174768464432b991ecff88d5e5126caca83672fb5173115de59bc2387ef8aa75a56d3e84957fce625fabaf50ba462549f2ea828aea7258be7513835b7fea2e31 +SuiteSparse.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/md5/f01f7e134f8ee77849f3a46e773c1ff2 +SuiteSparse.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/sha512/dc0339f2b35f05d49fbd1dcf1822c774a07af122fabc8e00eb7435dc53fcf82b3c1ec24e2bb41b1a58d3f8ab8903830eb7ece19dc6fce3f5e73d90a3dc3c4194 +SuiteSparse.v5.10.1+0.x86_64-apple-darwin.tar.gz/md5/02975a8670660c5e79eab0a70b051a0b +SuiteSparse.v5.10.1+0.x86_64-apple-darwin.tar.gz/sha512/e55685ed7a63318c5baa326795503f13f031e0a617c045c972d5c89252ab51e7325e2b0425ca10dfbd59e79c5b4200545f5a4944fddd376e7610b6ebf74ded14 +SuiteSparse.v5.10.1+0.x86_64-linux-gnu.tar.gz/md5/6c111d315fb25c529710722bd5ae6af0 +SuiteSparse.v5.10.1+0.x86_64-linux-gnu.tar.gz/sha512/c971aed91bd695a0f7f735f58ddcb075d32b9522a8a50a30ad383ba5ce2c8e572fec97644e6cb85745206f4e5da72d7865d9a9724eb63ce3c04e90a4eedc90c9 +SuiteSparse.v5.10.1+0.x86_64-linux-musl.tar.gz/md5/7c98daf0edfad31764c3078e6351b521 +SuiteSparse.v5.10.1+0.x86_64-linux-musl.tar.gz/sha512/2c4b3cae1bd8d1ce62dae6aeca3ffbf90c26a1b01c0da4fb7761d6fe4293b8fad0b6fbfd5f930cefe6ccaef7546a482022ff2f50dc59ecf17c5c0dfc6a5961f5 +SuiteSparse.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/md5/aeca88a7bc3f9d239c61084996ce9182 +SuiteSparse.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/sha512/0bee1ee07c3883fe28dd322c40195be9adb757d6dab3eb1730d7b0ff65dd4517520047696ccdda4ca618e671d898cdb45b787094594e142cb4b176549a74200b +SuiteSparse.v5.10.1+0.x86_64-w64-mingw32.tar.gz/md5/63e449554eee134757e3d50ca8b5f47d +SuiteSparse.v5.10.1+0.x86_64-w64-mingw32.tar.gz/sha512/95b58df4fe7520e2b526f9e3b199253909992789cd24ecca814ddb9a0c0bb37ff93c1de40239e5295a8503613cdb2431a87f0a70a3d657d94d4661f1778797f2 diff --git a/deps/libsuitesparse.mk b/deps/libsuitesparse.mk index a7bf592ccc9ea..42ae7807bb4ec 100644 --- a/deps/libsuitesparse.mk +++ b/deps/libsuitesparse.mk @@ -42,13 +42,9 @@ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted: $(SRCCACHE)/Suit checksum-libsuitesparse: $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz $(JLCHECKSUM) $< -$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-winclang.patch-applied: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted - cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-winclang.patch - echo 1 > $@ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-shlib.patch-applied: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-extracted cd $(dir $@) && patch -p1 < $(SRCDIR)/patches/SuiteSparse-shlib.patch echo 1 > $@ -$(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-winclang.patch-applied $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse-shlib.patch-applied $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/blastrampoline @@ -83,13 +79,13 @@ $(build_prefix)/manifest/libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARS #cp -a $(dir $<)include/* $(build_includedir) echo $(UNINSTALL_libsuitesparse) > $@ -clean-libsuitesparse: clean-suitesparse-wrapper uninstall-libsuitesparse +clean-libsuitesparse: uninstall-libsuitesparse -rm $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled -rm -fr $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/lib -rm -fr $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/include -$(MAKE) -C $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER) clean -distclean-libsuitesparse: clean-libsuitesparse-wrapper +distclean-libsuitesparse: -rm -rf $(SRCCACHE)/SuiteSparse-$(LIBSUITESPARSE_VER).tar.gz \ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER) @@ -99,52 +95,12 @@ configure-libsuitesparse: extract-libsuitesparse compile-libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled fastcheck-libsuitesparse: #none check-libsuitesparse: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-checked -install-libsuitesparse: $(build_prefix)/manifest/libsuitesparse install-libsuitesparse-wrapper - -# LIBSUITESPARSE WRAPPER - -ifeq ($(USE_SYSTEM_LIBSUITESPARSE), 1) -LIBSUITESPARSE_INC := -I $(LOCALBASE)/include/suitesparse -LIBSUITESPARSE_LIB := -lumfpack -lcholmod -lamd -lcamd -lcolamd -lspqr -else -LIBSUITESPARSE_INC := -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/CHOLMOD/Include -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SuiteSparse_config -I $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/SPQR/Include -LIBSUITESPARSE_LIB := -L$(build_shlibdir) -lcholmod -lumfpack -lspqr $(RPATH_ORIGIN) -$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(build_prefix)/manifest/libsuitesparse -endif - -$(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT): $(SRCDIR)/SuiteSparse_wrapper.c - mkdir -p $(build_shlibdir) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(LIBSUITESPARSE_INC) $< -o $@ $(LIBSUITESPARSE_LIB) - $(INSTALL_NAME_CMD)libsuitesparse_wrapper.$(SHLIB_EXT) $@ - touch -c $@ - -clean-libsuitesparse-wrapper: - -rm -f $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) - -distclean-libsuitesparse-wrapper: clean-suitesparse-wrapper - -get-libsuitesparse-wrapper: -extract-libsuitesparse-wrapper: -configure-libsuitesparse-wrapper: -compile-libsuitesparse-wrapper: -fastcheck-libsuitesparse-wrapper: #none -check-libsuitesparse-wrapper: -install-libsuitesparse-wrapper: $(build_shlibdir)/libsuitesparse_wrapper.$(SHLIB_EXT) +install-libsuitesparse: $(build_prefix)/manifest/libsuitesparse else # USE_BINARYBUILDER_LIBSUITESPARSE $(eval $(call bb-install,libsuitesparse,LIBSUITESPARSE,false)) -get-libsuitesparse-wrapper: get-libsuitesparse -extract-libsuitesparse-wrapper: extract-libsuitesparse -configure-libsuitesparse-wrapper: configure-libsuitesparse -compile-libsuitesparse-wrapper: compile-libsuitesparse -fastcheck-libsuitesparse-wrapper: fastcheck-libsuitesparse -check-libsuitesparse-wrapper: check-libsuitesparse -clean-libsuitesparse-wrapper: clean-libsuitesparse -distclean-libsuitesparse-wrapper: distclean-libsuitesparse -install-libsuitesparse-wrapper: install-libsuitesparse - # libsuitesparse depends on blastrampoline compile-libsuitesparse: | $(build_prefix)/manifest/blastrampoline endif diff --git a/deps/patches/SuiteSparse-winclang.patch b/deps/patches/SuiteSparse-winclang.patch deleted file mode 100644 index 8bfb64dc27839..0000000000000 --- a/deps/patches/SuiteSparse-winclang.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- SuiteSparse_config/SuiteSparse_config.h 2015-07-15 03:26:41.000000000 +0000 -+++ SuiteSparse_config/SuiteSparse_config.h 2016-07-01 00:55:57.157465600 +0000 -@@ -54,7 +54,11 @@ - #ifdef _WIN64 - - #define SuiteSparse_long __int64 -+#ifdef _MSVC_VER - #define SuiteSparse_long_max _I64_MAX -+#else -+#define SuiteSparse_long_max LLONG_MAX -+#endif - #define SuiteSparse_long_idd "I64d" - - #else diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index 436f919a60976..c360967a2acc1 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.8.1+2" +version = "5.10.1+0" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93" diff --git a/stdlib/SuiteSparse_jll/src/SuiteSparse_jll.jl b/stdlib/SuiteSparse_jll/src/SuiteSparse_jll.jl index 19cf398feec25..2940970ceff9f 100644 --- a/stdlib/SuiteSparse_jll/src/SuiteSparse_jll.jl +++ b/stdlib/SuiteSparse_jll/src/SuiteSparse_jll.jl @@ -8,7 +8,7 @@ Base.Experimental.@compiler_options compile=min optimize=0 infer=false const PATH_list = String[] const LIBPATH_list = String[] -export libamd, libbtf, libcamd, libccolamd, libcholmod, libcolamd, libklu, libldl, librbio, libspqr, libsuitesparse_wrapper, libsuitesparseconfig, libumfpack +export libamd, libbtf, libcamd, libccolamd, libcholmod, libcolamd, libklu, libldl, librbio, libspqr, libsuitesparseconfig, libumfpack # These get calculated in __init__() # Man I can't wait until these are automatically handled by an in-Base JLLWrappers clone. @@ -35,8 +35,6 @@ librbio_handle = C_NULL librbio_path = "" libspqr_handle = C_NULL libspqr_path = "" -libsuitesparse_wrapper_handle = C_NULL -libsuitesparse_wrapper_path = "" libsuitesparseconfig_handle = C_NULL libsuitesparseconfig_path = "" libumfpack_handle = C_NULL @@ -53,7 +51,6 @@ if Sys.iswindows() const libldl = "libldl.dll" const librbio = "librbio.dll" const libspqr = "libspqr.dll" - const libsuitesparse_wrapper = "libsuitesparse_wrapper.dll" const libsuitesparseconfig = "libsuitesparseconfig.dll" const libumfpack = "libumfpack.dll" elseif Sys.isapple() @@ -67,7 +64,6 @@ elseif Sys.isapple() const libldl = "@rpath/libldl.2.dylib" const librbio = "@rpath/librbio.2.dylib" const libspqr = "@rpath/libspqr.2.dylib" - const libsuitesparse_wrapper = "@rpath/libsuitesparse_wrapper.dylib" const libsuitesparseconfig = "@rpath/libsuitesparseconfig.5.dylib" const libumfpack = "@rpath/libumfpack.5.dylib" else @@ -81,7 +77,6 @@ else const libldl = "libldl.so.2" const librbio = "librbio.so.2" const libspqr = "libspqr.so.2" - const libsuitesparse_wrapper = "libsuitesparse_wrapper.so" const libsuitesparseconfig = "libsuitesparseconfig.so.5" const libumfpack = "libumfpack.so.5" end @@ -107,15 +102,11 @@ function __init__() global librbio_path = dlpath(librbio_handle) global libspqr_handle = dlopen(libspqr) global libspqr_path = dlpath(libspqr_handle) - global libsuitesparse_wrapper_handle = dlopen(libsuitesparse_wrapper) - global libsuitesparse_wrapper_path = dlpath(libsuitesparse_wrapper_handle) global libsuitesparseconfig_handle = dlopen(libsuitesparseconfig) global libsuitesparseconfig_path = dlpath(libsuitesparseconfig_handle) global libumfpack_handle = dlopen(libumfpack) global libumfpack_path = dlpath(libumfpack_handle) global artifact_dir = dirname(Sys.BINDIR) - LIBPATH[] = dirname(libsuitesparse_wrapper_path) - push!(LIBPATH_list, LIBPATH[]) end # JLLWrappers API compatibility shims. Note that not all of these will really make sense. @@ -135,7 +126,6 @@ get_libklu_path() = libklu_path get_libldl_path() = libldl_path get_librbio_path() = librbio_path get_libspqr_path() = libspqr_path -get_libsuitesparse_wrapper_path() = libsuitesparse_wrapper_path get_libsuitesparseconfig_path() = libsuitesparseconfig_path get_libumfpack_path() = libumfpack_path diff --git a/stdlib/SuiteSparse_jll/test/runtests.jl b/stdlib/SuiteSparse_jll/test/runtests.jl index 60e5cf74d6534..ca356951f99e2 100644 --- a/stdlib/SuiteSparse_jll/test/runtests.jl +++ b/stdlib/SuiteSparse_jll/test/runtests.jl @@ -3,5 +3,5 @@ using Test, SuiteSparse_jll @testset "SuiteSparse_jll" begin - @test ccall((:SuiteSparse_version, libsuitesparseconfig), Cint, (Ptr{Cint},), C_NULL) == 5008 + @test ccall((:SuiteSparse_version, libsuitesparseconfig), Cint, (Ptr{Cint},), C_NULL) == 5010 end From 2280efef7933af8052647aed500547a7817970e8 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sun, 30 May 2021 00:43:50 +0000 Subject: [PATCH 434/439] [automated] Bump the Pkg stdlib from 9f672535 to 6cf6b95e (#41004) Co-authored-by: Dilum Aluthge --- .../Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/md5 | 1 + .../Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/sha512 | 1 + .../Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 | 1 - .../Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/md5 create mode 100644 deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 diff --git a/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/md5 b/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/md5 new file mode 100644 index 0000000000000..bf3e63240bbb4 --- /dev/null +++ b/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/md5 @@ -0,0 +1 @@ +1cf54106737f6481a64f8311ff32c822 diff --git a/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/sha512 b/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/sha512 new file mode 100644 index 0000000000000..060de26b7c765 --- /dev/null +++ b/deps/checksums/Pkg-6cf6b95e051d8ecde0424ff8bac022fee197c690.tar.gz/sha512 @@ -0,0 +1 @@ +aa4276a579852468db725748a05783fe81e2bb63c519e74eb0e0fc90fb1403f5d55e43e55878b52cb6a75bb6f930c409e9e5220907b007ec674fa00b86b2de85 diff --git a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 deleted file mode 100644 index 79e70ab448180..0000000000000 --- a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -1e1bd065364becaf2ca4e4015a770a61 diff --git a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 b/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 deleted file mode 100644 index 59744b851b27f..0000000000000 --- a/deps/checksums/Pkg-9f67253529c72753cbfbb0078a80717f6c9bd90f.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -33df67087d1f9423aedf6c5c0b79b78b6bdffae1caf39cdd7f0d07e24097054fced547f284f34b8210d3726a7f964a906113dcee7062703f1dadfe6da2a3640d diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 329a2a83f85d3..75362ccf79bd0 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = 9f67253529c72753cbfbb0078a80717f6c9bd90f +PKG_SHA1 = 6cf6b95e051d8ecde0424ff8bac022fee197c690 From 311ff565f00e63eb192e45552d7a15bf731e3e03 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Sun, 30 May 2021 19:40:54 +0900 Subject: [PATCH 435/439] TOML: fix converted tabular data printing (#41009) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the printing pass for converted data only works for non-tabular data (like simple number literals), and it doesn't work for `Dict` or `Array`s. Rather it leads to runtime error because we don't pass over the same `by` keyword argument through recursive calls and it may not be assigned: ```julia julia> struct MyStruct a::Int end julia> data = Dict(:foo => MyStruct(1)) Dict{Symbol, MyStruct} with 1 entry: :foo => MyStruct(1) julia> TOML.print(data; softed=true) do x x isa MyStruct && return Dict(:bar => x.a) end ERROR: MethodError: no method matching print(::var"#38#39", ::Dict{Symbol, MyStruct}; softed=true) You may have intended to import Base.print Closest candidates are: print(::Union{Nothing, Function}, ::AbstractDict; sorted, by) at /Users/aviatesk/julia/julia/stdlib/TOML/src/print.jl:130 got unsupported keyword argument "softed" print(::Union{Nothing, Function}, ::IO, ::AbstractDict; sorted, by) at /Users/aviatesk/julia/julia/stdlib/TOML/src/print.jl:129 got unsupported keyword argument "softed" print(::IO, ::AbstractDict; sorted, by) at /Users/aviatesk/julia/julia/stdlib/TOML/src/print.jl:131 got unsupported keyword argument "softed" Stacktrace: [1] kwerr(::NamedTuple{(:softed,), Tuple{Bool}}, ::Function, ::Function, ::Dict{Symbol, MyStruct}) @ Base ./error.jl:163 [2] top-level scope @ none:1 ```
Originally reported by JET: julia> using JET, Pkg julia> @report_call Pkg.project() ═════ 3 possible errors found ═════ ┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/API.jl:103 Pkg.API.EnvCache() │┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/Types.jl:285 #self#(Pkg.Types.nothing) ││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/Types.jl:288 Pkg.Types.read_project(project_file) │││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/project.jl:138 Pkg.Types.sprint(Pkg.Types.showerror, e) ││││┌ @ strings/io.jl:106 Base.#sprint#412(Core.tuple(Base.nothing, 0, #self#, f), args...) │││││┌ @ strings/io.jl:112 f(Core.tuple(s), args...) ││││││┌ @ toml_parser.jl:326 Base.TOML.point_to_line(Base.getproperty(err, :str), pos, pos, io) │││││││ for 1 of union split cases, no matching method found for call signatures (Tuple{typeof(Base.TOML.point_to_line), Nothing, Int64, Int64, IOBuffer})): Base.TOML.point_to_line(Base.getproperty(err::Base.TOML.ParserError, :str::Symbol)::Union{Nothing, String}, pos::Int64, pos::Int64, io::IOBuffer) ││││││└────────────────────── │││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/project.jl:142 Pkg.Types.Project(raw) ││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/project.jl:124 Base.setproperty!(project, :targets, Pkg.Types.read_project_targets(Pkg.Types.get(raw, "targets", Pkg.Types.nothing), project)) │││││┌ @ Base.jl:35 Base.convert(Base.fieldtype(Base.typeof(x), f), v) ││││││┌ @ abstractdict.jl:523 _(x) │││││││┌ @ dict.jl:104 Base.setindex!(h, v, k) ││││││││┌ @ dict.jl:382 Base.convert(_, v0) │││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/factorization.jl:58 _(f) ││││││││││ no matching method found for call signature (Tuple{Type{Vector{String}}, LinearAlgebra.Factorization}): _::Type{Vector{String}}(f::LinearAlgebra.Factorization) │││││││││└───────────────────────────────────────────────────────────────────────────────────────────────── ││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/Types.jl:305 Pkg.Types.write_env_usage(manifest_file, "manifest_usage.toml") │││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/Types.jl:436 Pkg.Types.sprint(#35) ││││┌ @ strings/io.jl:106 Base.#sprint#412(Core.tuple(Base.nothing, 0, #self#, f), args...) │││││┌ @ strings/io.jl:112 f(Core.tuple(s), args...) ││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/Pkg/src/Types.jl:437 TOML.print(io, Pkg.Types.Dict(Pkg.Types.=>(Core.getfield(#self#, :source_file), Base.vect(Pkg.Types.Dict(Pkg.Types.=>("time", Pkg.Types.now())))))) │││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:131 TOML.Internals.Printer.#print#16(false, TOML.Internals.Printer.identity, #self#, io, a) ││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:131 Core.kwfunc(TOML.Internals.Printer._print)(Core.apply_type(Core.NamedTuple, (:sorted, :by))(Core.tuple(sorted, by)), TOML.Internals.Printer._print, TOML.Internals.Printer.nothing, io, a) │││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:76 #s848(_2, _3, f, io, a, Base.getindex(TOML.Internals.Printer.String)) ││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:76 TOML.Internals.Printer.#_print#11(indent, first_block, sorted, by, _3, f, io, a, ks) │││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:88 Core.kwfunc(TOML.Internals.Printer.printvalue)(Core.apply_type(Core.NamedTuple, (:sorted,))(Core.tuple(sorted)), TOML.Internals.Printer.printvalue, f, io, value) ││││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:25 TOML.Internals.Printer.#printvalue#1(sorted, _3, f, io, value) │││││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:29 Core.kwfunc(TOML.Internals.Printer._print)(Core.apply_type(Core.NamedTuple, (:sorted,))(Core.tuple(sorted)), TOML.Internals.Printer._print, f, io, x) ││││││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:76 #s848(_2, _3, f, io, a, Base.getindex(TOML.Internals.Printer.String)) │││││││││││││││┌ @ /Users/aviatesk/julia/julia/usr/share/julia/stdlib/v1.7/TOML/src/print.jl:76 Core.throw(Core.UndefKeywordError(:by)) ││││││││││││││││ UndefKeywordError: keyword argument by not assigned │││││││││││││││└──────────────────────────────────────────────────────────────────────────────── Pkg.API.ProjectInfo
With this PR, everything should work: > After ```julia julia> TOML.print(data; sorted=true) do x x isa MyStruct && return Dict(:bar => x.a) end [foo] bar = 1 ``` --- stdlib/TOML/src/print.jl | 69 +++++++++++++++++++++------------------ stdlib/TOML/test/print.jl | 22 +++++++++++++ 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/stdlib/TOML/src/print.jl b/stdlib/TOML/src/print.jl index 71896b7a1d717..0cbee990d8ae1 100644 --- a/stdlib/TOML/src/print.jl +++ b/stdlib/TOML/src/print.jl @@ -2,6 +2,7 @@ import Dates +import Base: @invokelatest import ..isvalid_barekey_char function printkey(io::IO, keys::Vector{String}) @@ -20,46 +21,36 @@ function printkey(io::IO, keys::Vector{String}) end const MbyFunc = Union{Function, Nothing} -const TOMLValue = Union{AbstractVector, AbstractDict, Dates.DateTime, Dates.Time, Dates.Date, Bool, Integer, AbstractFloat, String} -function printvalue(f::MbyFunc, io::IO, value::AbstractVector; sorted=false) +const TOMLValue = Union{AbstractVector, AbstractDict, Dates.DateTime, Dates.Time, Dates.Date, Bool, Integer, AbstractFloat, AbstractString} +function printvalue(f::MbyFunc, io::IO, value::AbstractVector; sorted=false, by=identity) Base.print(io, "[") for (i, x) in enumerate(value) i != 1 && Base.print(io, ", ") if isa(x, AbstractDict) - _print(f, io, x; sorted) + _print(f, io, x; sorted, by) else - printvalue(f, io, x; sorted) + printvalue(f, io, x; sorted, by) end end Base.print(io, "]") end -function printvalue(f::MbyFunc, io::IO, value; sorted) - if f === nothing - error("type `$(typeof(value))` is not a valid TOML type, pass a conversion function to `TOML.print`") - end - toml_value = f(value) - if !(toml_value isa TOMLValue) - error("TOML syntax function for type `$(typeof(value))` did not return a valid TOML type but a `$(typeof(toml_value))`") - end - Base.invokelatest(printvalue, f, io, toml_value; sorted) -end -printvalue(f::MbyFunc, io::IO, value::AbstractDict; sorted) = - _print(f, io, value; sorted) -printvalue(f::MbyFunc, io::IO, value::Dates.DateTime; sorted) = +printvalue(f::MbyFunc, io::IO, value::AbstractDict; sorted=false, by=identity) = + _print(f, io, value; sorted, by) +printvalue(f::MbyFunc, io::IO, value::Dates.DateTime; _...) = Base.print(io, Dates.format(value, Dates.dateformat"YYYY-mm-dd\THH:MM:SS.sss\Z")) -printvalue(f::MbyFunc, io::IO, value::Dates.Time; sorted) = +printvalue(f::MbyFunc, io::IO, value::Dates.Time; _...) = Base.print(io, Dates.format(value, Dates.dateformat"HH:MM:SS.sss")) -printvalue(f::MbyFunc, io::IO, value::Dates.Date; sorted) = +printvalue(f::MbyFunc, io::IO, value::Dates.Date; _...) = Base.print(io, Dates.format(value, Dates.dateformat"YYYY-mm-dd")) -printvalue(f::MbyFunc, io::IO, value::Bool; sorted) = +printvalue(f::MbyFunc, io::IO, value::Bool; _...) = Base.print(io, value ? "true" : "false") -printvalue(f::MbyFunc, io::IO, value::Integer; sorted) = +printvalue(f::MbyFunc, io::IO, value::Integer; _...) = Base.print(io, Int64(value)) # TOML specifies 64-bit signed long range for integer -printvalue(f::MbyFunc, io::IO, value::AbstractFloat; sorted) = +printvalue(f::MbyFunc, io::IO, value::AbstractFloat; _...) = Base.print(io, isnan(value) ? "nan" : isinf(value) ? string(value > 0 ? "+" : "-", "inf") : Float64(value)) # TOML specifies IEEE 754 binary64 for float -printvalue(f::MbyFunc, io::IO, value::AbstractString; sorted) = Base.print(io, "\"", escape_string(value), "\"") +printvalue(f::MbyFunc, io::IO, value::AbstractString; _...) = Base.print(io, "\"", escape_string(value), "\"") is_table(value) = isa(value, AbstractDict) is_array_of_tables(value) = isa(value, AbstractArray) && @@ -70,8 +61,8 @@ function _print(f::MbyFunc, io::IO, a::AbstractDict, ks::Vector{String} = String[]; indent::Int = 0, first_block::Bool = true, - sorted::Bool, - by::Function, + sorted::Bool = false, + by::Function = identity, ) akeys = keys(a) if sorted @@ -82,11 +73,25 @@ function _print(f::MbyFunc, io::IO, a::AbstractDict, for key in akeys value = a[key] is_tabular(value) && continue - Base.print(io, ' '^4max(0,indent-1)) - printkey(io, [String(key)]) - Base.print(io, " = ") # print separator - printvalue(f, io, value; sorted) - Base.print(io, "\n") # new line? + if !isa(value, TOMLValue) + if f === nothing + error("type `$(typeof(value))` is not a valid TOML type, pass a conversion function to `TOML.print`") + end + toml_value = f(value) + if !(toml_value isa TOMLValue) + error("TOML syntax function for type `$(typeof(value))` did not return a valid TOML type but a `$(typeof(toml_value))`") + end + value = toml_value + end + if is_tabular(value) + _print(f, io, Dict(key => value); indent, first_block, sorted, by) + else + Base.print(io, ' '^4max(0,indent-1)) + printkey(io, [String(key)]) + Base.print(io, " = ") # print separator + printvalue(f, io, value; sorted, by) + Base.print(io, "\n") # new line? + end first_block = false end @@ -105,7 +110,7 @@ function _print(f::MbyFunc, io::IO, a::AbstractDict, Base.print(io,"]\n") end # Use runtime dispatch here since the type of value seems not to be enforced other than as AbstractDict - Base.invokelatest(_print, f, io, value, ks; indent = indent + header, first_block = header, sorted, by) + @invokelatest _print(f, io, value, ks; indent = indent + header, first_block = header, sorted, by) pop!(ks) elseif is_array_of_tables(value) # print array of tables @@ -119,7 +124,7 @@ function _print(f::MbyFunc, io::IO, a::AbstractDict, Base.print(io,"]]\n") # TODO, nicer error here !isa(v, AbstractDict) && error("array should contain only tables") - Base.invokelatest(_print, f, io, v, ks; indent = indent + 1, sorted, by) + @invokelatest _print(f, io, v, ks; indent = indent + 1, sorted, by) end pop!(ks) end diff --git a/stdlib/TOML/test/print.jl b/stdlib/TOML/test/print.jl index d6bcdf10d4f17..10bb48ffae411 100644 --- a/stdlib/TOML/test/print.jl +++ b/stdlib/TOML/test/print.jl @@ -21,12 +21,34 @@ struct MyStruct a::Int end @test_throws ErrorException toml_str(Dict("foo" => MyStruct(1))) +# simple value @test toml_str(Dict("foo" => MyStruct(1))) do x x isa MyStruct && return x.a end == """ foo = 1 """ +# tabular values +@test toml_str(Dict("foo" => MyStruct(1)); sorted=true) do x + x isa MyStruct && return [x.a] + end == """ + foo = [1] + """ +@test toml_str(Dict("foo" => MyStruct(1)); sorted=true) do x + x isa MyStruct && return Dict(:bar => x.a) + end == """ + [foo] + bar = 1 + """ + +# validation against the usual case +@test toml_str(Dict("foo" => MyStruct(1)); sorted=true) do x + x isa MyStruct && return [x.a] + end == toml_str(Dict("foo" => [1]); sorted=true) +@test toml_str(Dict("foo" => MyStruct(1)); sorted=true) do x + x isa MyStruct && return Dict(:bar => x.a) + end == toml_str(Dict("foo" => Dict(:bar => 1)); sorted=true) + @test toml_str(Dict("b" => SubString("foo"))) == "b = \"foo\"\n" @testset "empty dict print" begin From acdffeb913066d93960c13e82a124e43f2e60e8e Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 30 May 2021 15:50:19 +0200 Subject: [PATCH 436/439] Make adjoint and solve work for most factorizations (#40899) * Add adjoint for Cholesky * Implement adjoint for BunchKaufman * Fix ldiv! for adjoints of Hessenbergs * Add adjoint of LDLt * Fix return for tall problems in fallback \ method for adjoint of Factorizations to make \ work for adjoint LQ. * Fix qr(A)'\b * Define adjoint for SVD * Improve promotion in fallback by defining general convert methods for Factorizations * Fix ldiv! for SVD * Restrict the general \ definition that handles over- and underdetermined systems to LAPACK factorizations * Remove redundant \ definitions in diagonal.jl * Add Factorization constructors for SVD * Disambiguate between the specialized \ for real lhs-complex rhs and then new \ for LAPACKFactorizations. * Adjustments based on review * Fixes for new pivoting syntax --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 57 +++++++++++++++++++++++ stdlib/LinearAlgebra/src/bunchkaufman.jl | 16 +++++-- stdlib/LinearAlgebra/src/cholesky.jl | 2 + stdlib/LinearAlgebra/src/diagonal.jl | 8 ---- stdlib/LinearAlgebra/src/factorization.jl | 24 +++------- stdlib/LinearAlgebra/src/hessenberg.jl | 14 +++--- stdlib/LinearAlgebra/src/ldlt.jl | 3 ++ stdlib/LinearAlgebra/src/lq.jl | 30 ++++++------ stdlib/LinearAlgebra/src/qr.jl | 45 +++++++++++------- stdlib/LinearAlgebra/src/svd.jl | 14 +++++- stdlib/LinearAlgebra/test/bunchkaufman.jl | 21 ++++++++- stdlib/LinearAlgebra/test/cholesky.jl | 8 ++++ stdlib/LinearAlgebra/test/hessenberg.jl | 11 +++++ stdlib/LinearAlgebra/test/lq.jl | 18 +++++++ stdlib/LinearAlgebra/test/qr.jl | 44 +++++++++++++++-- stdlib/LinearAlgebra/test/svd.jl | 20 ++++++++ stdlib/LinearAlgebra/test/tridiag.jl | 12 +++++ 17 files changed, 272 insertions(+), 75 deletions(-) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index d5a2a64467f93..07bb954807361 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -397,6 +397,63 @@ const ⋅ = dot const × = cross export ⋅, × +## convenience methods +## return only the solution of a least squares problem while avoiding promoting +## vectors to matrices. +_cut_B(x::AbstractVector, r::UnitRange) = length(x) > length(r) ? x[r] : x +_cut_B(X::AbstractMatrix, r::UnitRange) = size(X, 1) > length(r) ? X[r,:] : X + +## append right hand side with zeros if necessary +_zeros(::Type{T}, b::AbstractVector, n::Integer) where {T} = zeros(T, max(length(b), n)) +_zeros(::Type{T}, B::AbstractMatrix, n::Integer) where {T} = zeros(T, max(size(B, 1), n), size(B, 2)) + +# General fallback definition for handling under- and overdetermined system as well as square problems +# While this definition is pretty general, it does e.g. promote to common element type of lhs and rhs +# which is required by LAPACK but not SuiteSpase which allows real-complex solves in some cases. Hence, +# we restrict this method to only the LAPACK factorizations in LinearAlgebra. +# The definition is put here since it explicitly references all the Factorizion structs so it has +# to be located after all the files that define the structs. +const LAPACKFactorizations{T,S} = Union{ + BunchKaufman{T,S}, + Cholesky{T,S}, + LQ{T,S}, + LU{T,S}, + QR{T,S}, + QRCompactWY{T,S}, + QRPivoted{T,S}, + SVD{T,<:Real,S}} +function (\)(F::Union{<:LAPACKFactorizations,Adjoint{<:Any,<:LAPACKFactorizations}}, B::AbstractVecOrMat) + require_one_based_indexing(B) + m, n = size(F) + if m != size(B, 1) + throw(DimensionMismatch("arguments must have the same number of rows")) + end + + TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) + FF = Factorization{TFB}(F) + + # For wide problem we (often) compute a minimum norm solution. The solution + # is larger than the right hand side so we use size(F, 2). + BB = _zeros(TFB, B, n) + + if n > size(B, 1) + # Underdetermined + copyto!(view(BB, 1:m, :), B) + else + copyto!(BB, B) + end + + ldiv!(FF, BB) + + # For tall problems, we compute a least squares solution so only part + # of the rhs should be returned from \ while ldiv! uses (and returns) + # the complete rhs + return _cut_B(BB, 1:n) +end +# disambiguate +(\)(F::LAPACKFactorizations{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} = + invoke(\, Tuple{Factorization{T}, VecOrMat{Complex{T}}}, F, B) + """ LinearAlgebra.peakflops(n::Integer=2000; parallel::Bool=false) diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index 63254308799e1..75fb9ae7bf04e 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -196,16 +196,14 @@ julia> S.L*S.D*S.L' - A[S.p, S.p] bunchkaufman(A::AbstractMatrix{T}, rook::Bool=false; check::Bool = true) where {T} = bunchkaufman!(copy_oftype(A, typeof(sqrt(oneunit(T)))), rook; check = check) -convert(::Type{BunchKaufman{T}}, B::BunchKaufman{T}) where {T} = B -convert(::Type{BunchKaufman{T}}, B::BunchKaufman) where {T} = +BunchKaufman{T}(B::BunchKaufman) where {T} = BunchKaufman(convert(Matrix{T}, B.LD), B.ipiv, B.uplo, B.symmetric, B.rook, B.info) -convert(::Type{Factorization{T}}, B::BunchKaufman{T}) where {T} = B -convert(::Type{Factorization{T}}, B::BunchKaufman) where {T} = convert(BunchKaufman{T}, B) +Factorization{T}(B::BunchKaufman) where {T} = BunchKaufman{T}(B) size(B::BunchKaufman) = size(getfield(B, :LD)) size(B::BunchKaufman, d::Integer) = size(getfield(B, :LD), d) issymmetric(B::BunchKaufman) = B.symmetric -ishermitian(B::BunchKaufman) = !B.symmetric +ishermitian(B::BunchKaufman{T}) where T = T<:Real || !B.symmetric function _ipiv2perm_bk(v::AbstractVector{T}, maxi::Integer, uplo::AbstractChar, rook::Bool) where T require_one_based_indexing(v) @@ -279,6 +277,14 @@ Base.propertynames(B::BunchKaufman, private::Bool=false) = issuccess(B::BunchKaufman) = B.info == 0 +function adjoint(B::BunchKaufman) + if ishermitian(B) + return B + else + throw(ArgumentError("adjoint not implemented for complex symmetric matrices")) + end +end + function Base.show(io::IO, mime::MIME{Symbol("text/plain")}, B::BunchKaufman) if issuccess(B) summary(io, B); println(io) diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 18ee4cb5c7dd9..6e381243faf43 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -529,6 +529,8 @@ Base.propertynames(F::CholeskyPivoted, private::Bool=false) = issuccess(C::Union{Cholesky,CholeskyPivoted}) = C.info == 0 +adjoint(C::Union{Cholesky,CholeskyPivoted}) = C + function show(io::IO, mime::MIME{Symbol("text/plain")}, C::Cholesky{<:Any,<:AbstractMatrix}) if issuccess(C) summary(io, C); println(io) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 204ff56e0c443..464e85facc640 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -488,14 +488,6 @@ rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = (/)(A::Union{StridedMatrix, AbstractTriangular}, D::Diagonal) = rdiv!((typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A), D) -(\)(F::Factorization, D::Diagonal) = - ldiv!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D)) -\(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) = - (F = adjF.parent; ldiv!(adjoint(F), Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))) -(\)(A::Union{QR,QRCompactWY,QRPivoted}, B::Diagonal) = - invoke(\, Tuple{Union{QR,QRCompactWY,QRPivoted}, AbstractVecOrMat}, A, B) - - @inline function kron!(C::AbstractMatrix, A::Diagonal, B::Diagonal) valA = A.diag; nA = length(valA) valB = B.diag; nB = length(valB) diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index 5ff215a3eb665..b651e85512f6d 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -59,6 +59,9 @@ convert(::Type{T}, f::Factorization) where {T<:AbstractArray} = T(f) ### General promotion rules Factorization{T}(F::Factorization{T}) where {T} = F +# This is a bit odd since the return is not a Factorization but it works well in generic code +Factorization{T}(A::Adjoint{<:Any,<:Factorization}) where {T} = + adjoint(Factorization{T}(parent(A))) inv(F::Factorization{T}) where {T} = (n = size(F, 1); ldiv!(F, Matrix{T}(I, n, n))) Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, 1:nfields(F); init=h) @@ -96,40 +99,25 @@ function (/)(B::VecOrMat{Complex{T}}, F::Factorization{T}) where T<:BlasReal return copy(reinterpret(Complex{T}, x)) end -function \(F::Factorization, B::AbstractVecOrMat) +function \(F::Union{Factorization, Adjoint{<:Any,<:Factorization}}, B::AbstractVecOrMat) require_one_based_indexing(B) TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copyto!(BB, B) ldiv!(F, BB) end -function \(adjF::Adjoint{<:Any,<:Factorization}, B::AbstractVecOrMat) - require_one_based_indexing(B) - F = adjF.parent - TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) - BB = similar(B, TFB, size(B)) - copyto!(BB, B) - ldiv!(adjoint(F), BB) -end -function /(B::AbstractMatrix, F::Factorization) +function /(B::AbstractMatrix, F::Union{Factorization, Adjoint{<:Any,<:Factorization}}) require_one_based_indexing(B) TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copyto!(BB, B) rdiv!(BB, F) end -function /(B::AbstractMatrix, adjF::Adjoint{<:Any,<:Factorization}) - require_one_based_indexing(B) - F = adjF.parent - TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) - BB = similar(B, TFB, size(B)) - copyto!(BB, B) - rdiv!(BB, adjoint(F)) -end /(adjB::AdjointAbsVec, adjF::Adjoint{<:Any,<:Factorization}) = adjoint(adjF.parent \ adjB.parent) /(B::TransposeAbsVec, adjF::Adjoint{<:Any,<:Factorization}) = adjoint(adjF.parent \ adjoint(B)) + # support the same 3-arg idiom as in our other in-place A_*_B functions: function ldiv!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) require_one_based_indexing(Y, B) diff --git a/stdlib/LinearAlgebra/src/hessenberg.jl b/stdlib/LinearAlgebra/src/hessenberg.jl index ffd12f39eafe2..e3b5d4983b30d 100644 --- a/stdlib/LinearAlgebra/src/hessenberg.jl +++ b/stdlib/LinearAlgebra/src/hessenberg.jl @@ -564,28 +564,30 @@ function AbstractMatrix(F::Hessenberg) end end +# adjoint(Q::HessenbergQ{<:Real}) + lmul!(Q::BlasHessenbergQ{T,false}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) -rmul!(X::StridedMatrix{T}, Q::BlasHessenbergQ{T,false}) where {T<:BlasFloat} = +rmul!(X::StridedVecOrMat{T}, Q::BlasHessenbergQ{T,false}) where {T<:BlasFloat} = LAPACK.ormhr!('R', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) lmul!(adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,false}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = (Q = adjQ.parent; LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)) -rmul!(X::StridedMatrix{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,false}}) where {T<:BlasFloat} = +rmul!(X::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,false}}) where {T<:BlasFloat} = (Q = adjQ.parent; LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)) lmul!(Q::BlasHessenbergQ{T,true}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormtr!('L', Q.uplo, 'N', Q.factors, Q.τ, X) -rmul!(X::StridedMatrix{T}, Q::BlasHessenbergQ{T,true}) where {T<:BlasFloat} = +rmul!(X::StridedVecOrMat{T}, Q::BlasHessenbergQ{T,true}) where {T<:BlasFloat} = LAPACK.ormtr!('R', Q.uplo, 'N', Q.factors, Q.τ, X) lmul!(adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,true}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = (Q = adjQ.parent; LAPACK.ormtr!('L', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X)) -rmul!(X::StridedMatrix{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,true}}) where {T<:BlasFloat} = +rmul!(X::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,true}}) where {T<:BlasFloat} = (Q = adjQ.parent; LAPACK.ormtr!('R', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X)) lmul!(Q::HessenbergQ{T}, X::Adjoint{T,<:StridedVecOrMat{T}}) where {T} = rmul!(X', Q')' -rmul!(X::Adjoint{T,<:StridedMatrix{T}}, Q::HessenbergQ{T}) where {T} = lmul!(Q', X')' +rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, Q::HessenbergQ{T}) where {T} = lmul!(Q', X')' lmul!(adjQ::Adjoint{<:Any,<:HessenbergQ{T}}, X::Adjoint{T,<:StridedVecOrMat{T}}) where {T} = rmul!(X', adjQ')' -rmul!(X::Adjoint{T,<:StridedMatrix{T}}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T} = lmul!(adjQ', X')' +rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T} = lmul!(adjQ', X')' # multiply x by the entries of M in the upper-k triangle, which contains # the entries of the upper-Hessenberg matrix H for k=-1 diff --git a/stdlib/LinearAlgebra/src/ldlt.jl b/stdlib/LinearAlgebra/src/ldlt.jl index d0f59ebb9ff1b..f1ea10aa0f614 100644 --- a/stdlib/LinearAlgebra/src/ldlt.jl +++ b/stdlib/LinearAlgebra/src/ldlt.jl @@ -77,6 +77,9 @@ function getproperty(F::LDLt, d::Symbol) end end +adjoint(F::LDLt{<:Real,<:SymTridiagonal}) = F +adjoint(F::LDLt) = LDLt(copy(adjoint(F.data))) + function show(io::IO, mime::MIME{Symbol("text/plain")}, F::LDLt) summary(io, F); println(io) println(io, "L factor:") diff --git a/stdlib/LinearAlgebra/src/lq.jl b/stdlib/LinearAlgebra/src/lq.jl index 606e8c3dd006e..d9e49f3a9c1c6 100644 --- a/stdlib/LinearAlgebra/src/lq.jl +++ b/stdlib/LinearAlgebra/src/lq.jl @@ -125,8 +125,8 @@ lq_eltype(::Type{T}) where {T} = typeof(zero(T) / sqrt(abs2(one(T)))) copy(A::LQ) = LQ(copy(A.factors), copy(A.τ)) LQ{T}(A::LQ) where {T} = LQ(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -Factorization{T}(A::LQ{T}) where {T} = A Factorization{T}(A::LQ) where {T} = LQ{T}(A) + AbstractMatrix(A::LQ) = A.L*A.Q AbstractArray(A::LQ) = AbstractMatrix(A) Matrix(A::LQ) = Array(AbstractArray(A)) @@ -194,7 +194,7 @@ function lmul!(A::LQ, B::StridedVecOrMat) end function *(A::LQ{TA}, B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) - _cut_B(lmul!(Factorization{TAB}(A), copy_oftype(B, TAB)), 1:size(A,1)) + _cut_B(lmul!(convert(Factorization{TAB}, A), copy_oftype(B, TAB)), 1:size(A,1)) end ## Multiplication by Q @@ -318,17 +318,6 @@ _rightappdimmismatch(rowsorcols) = "or (2) the number of rows of that (LQPackedQ) matrix's internal representation ", "(the factorization's originating matrix's number of rows)"))) - -function (\)(A::LQ{TA},B::StridedVecOrMat{TB}) where {TA,TB} - S = promote_type(TA,TB) - m, n = size(A) - m ≤ n || throw(DimensionMismatch("LQ solver does not support overdetermined systems (more rows than columns)")) - m == size(B,1) || throw(DimensionMismatch("Both inputs should have the same number of rows")) - AA = Factorization{S}(A) - X = _zeros(S, B, n) - X[1:size(B, 1), :] = B - return ldiv!(AA, X) -end # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal @@ -342,12 +331,25 @@ function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal end -function ldiv!(A::LQ{T}, B::StridedVecOrMat{T}) where T +function ldiv!(A::LQ, B::StridedVecOrMat) require_one_based_indexing(B) + m, n = size(A) + m ≤ n || throw(DimensionMismatch("LQ solver does not support overdetermined systems (more rows than columns)")) + ldiv!(LowerTriangular(A.L), view(B, 1:size(A,1), axes(B,2))) return lmul!(adjoint(A.Q), B) end +function ldiv!(Fadj::Adjoint{<:Any,<:LQ}, B::StridedVecOrMat) + require_one_based_indexing(B) + m, n = size(Fadj) + m >= n || throw(DimensionMismatch("solver does not support underdetermined systems (more columns than rows)")) + + F = parent(Fadj) + lmul!(F.Q, B) + ldiv!(UpperTriangular(adjoint(F.L)), view(B, 1:size(F,1), axes(B,2))) + return B +end # In LQ factorization, `Q` is expressed as the product of the adjoint of the # reflectors. Thus, `det` has to be conjugated. diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 390c8a5875773..d0ec430347193 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -472,6 +472,8 @@ end Base.propertynames(F::QRPivoted, private::Bool=false) = (:R, :Q, :p, :P, (private ? fieldnames(typeof(F)) : ())...) +adjoint(F::Union{QR,QRPivoted,QRCompactWY}) = Adjoint(F) + abstract type AbstractQ{T} <: AbstractMatrix{T} end inv(Q::AbstractQ) = Q' @@ -939,28 +941,35 @@ function ldiv!(A::QRPivoted, B::StridedMatrix) B end -# convenience methods -## return only the solution of a least squares problem while avoiding promoting -## vectors to matrices. -_cut_B(x::AbstractVector, r::UnitRange) = length(x) > length(r) ? x[r] : x -_cut_B(X::AbstractMatrix, r::UnitRange) = size(X, 1) > length(r) ? X[r,:] : X - -## append right hand side with zeros if necessary -_zeros(::Type{T}, b::AbstractVector, n::Integer) where {T} = zeros(T, max(length(b), n)) -_zeros(::Type{T}, B::AbstractMatrix, n::Integer) where {T} = zeros(T, max(size(B, 1), n), size(B, 2)) +function _apply_permutation!(F::QRPivoted, B::AbstractVecOrMat) + # Apply permutation but only to the top part of the solution vector since + # it's padded with zeros for underdetermined problems + B[1:length(F.p), :] = B[F.p, :] + return B +end +_apply_permutation!(F::Factorization, B::AbstractVecOrMat) = B -function (\)(A::Union{QR{TA},QRCompactWY{TA},QRPivoted{TA}}, B::AbstractVecOrMat{TB}) where {TA,TB} +function ldiv!(Fadj::Adjoint{<:Any,<:Union{QR,QRCompactWY,QRPivoted}}, B::AbstractVecOrMat) require_one_based_indexing(B) - S = promote_type(TA,TB) - m, n = size(A) - m == size(B,1) || throw(DimensionMismatch("Both inputs should have the same number of rows")) + m, n = size(Fadj) - AA = Factorization{S}(A) + # We don't allow solutions overdetermined systems + if m > n + throw(DimensionMismatch("overdetermined systems are not supported")) + end + if n != size(B, 1) + throw(DimensionMismatch("inputs should have the same number of rows")) + end + F = parent(Fadj) - X = _zeros(S, B, n) - X[1:size(B, 1), :] = B - ldiv!(AA, X) - return _cut_B(X, 1:n) + B = _apply_permutation!(F, B) + + # For underdetermined system, the triangular solve should only be applied to the top + # part of B that contains the rhs. For square problems, the view corresponds to B itself + ldiv!(LowerTriangular(adjoint(F.R)), view(B, 1:size(F.R, 2), :)) + lmul!(F.Q, B) + + return B end # With a real lhs and complex rhs with the same precision, we can reinterpret the complex diff --git a/stdlib/LinearAlgebra/src/svd.jl b/stdlib/LinearAlgebra/src/svd.jl index 68bce4793661f..3290b4529be37 100644 --- a/stdlib/LinearAlgebra/src/svd.jl +++ b/stdlib/LinearAlgebra/src/svd.jl @@ -72,6 +72,11 @@ function SVD{T}(U::AbstractArray, S::AbstractVector{Tr}, Vt::AbstractArray) wher convert(AbstractArray{T}, Vt)) end +SVD{T}(F::SVD) where {T} = SVD( + convert(AbstractMatrix{T}, F.U), + convert(AbstractVector{real(T)}, F.S), + convert(AbstractMatrix{T}, F.Vt)) +Factorization{T}(F::SVD) where {T} = SVD{T}(F) # iteration for destructuring into components Base.iterate(S::SVD) = (S.U, Val(:S)) @@ -235,10 +240,11 @@ svdvals(A::AbstractVector{<:BlasFloat}) = [norm(A)] svdvals(x::Number) = abs(x) svdvals(S::SVD{<:Any,T}) where {T} = (S.S)::Vector{T} -# SVD least squares +### SVD least squares ### function ldiv!(A::SVD{T}, B::StridedVecOrMat) where T + m, n = size(A) k = searchsortedlast(A.S, eps(real(T))*A.S[1], rev=true) - view(A.Vt,1:k,:)' * (view(A.S,1:k) .\ (view(A.U,:,1:k)' * B)) + return mul!(view(B, 1:n, :), view(A.Vt, 1:k, :)', view(A.S, 1:k) .\ (view(A.U, :, 1:k)' * _cut_B(B, 1:m))) end function inv(F::SVD{T}) where T @@ -252,6 +258,10 @@ end size(A::SVD, dim::Integer) = dim == 1 ? size(A.U, dim) : size(A.Vt, dim) size(A::SVD) = (size(A, 1), size(A, 2)) +function adjoint(F::SVD) + return SVD(F.Vt', F.S, F.U') +end + function show(io::IO, mime::MIME{Symbol("text/plain")}, F::SVD{<:Any,<:Any,<:AbstractArray}) summary(io, F); println(io) println(io, "U factor:") diff --git a/stdlib/LinearAlgebra/test/bunchkaufman.jl b/stdlib/LinearAlgebra/test/bunchkaufman.jl index 5098f818f1804..e05592cdc1c5c 100644 --- a/stdlib/LinearAlgebra/test/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/test/bunchkaufman.jl @@ -114,7 +114,8 @@ bimg = randn(n,2)/2 @test logabsdet(bc2)[2] == sign(det(bc2)) @test inv(bc2)*apd ≈ Matrix(I, n, n) @test apd*(bc2\b) ≈ b rtol=eps(cond(apd)) - @test ishermitian(bc2) == !issymmetric(bc2) + @test ishermitian(bc2) + @test !issymmetric(bc2) || eltya <: Real end end end @@ -171,4 +172,22 @@ end end end +@testset "adjoint of BunchKaufman" begin + Ar = randn(5, 5) + Ar = Ar + Ar' + Actmp = complex.(randn(5, 5), randn(5, 5)) + Ac1 = Actmp + Actmp' + Ac2 = Actmp + transpose(Actmp) + b = ones(size(Ar, 1)) + + F = bunchkaufman(Ar) + @test F\b == F'\b + + F = bunchkaufman(Ac1) + @test F\b == F'\b + + F = bunchkaufman(Ac2) + @test_throws ArgumentError("adjoint not implemented for complex symmetric matrices") F' +end + end # module TestBunchKaufman diff --git a/stdlib/LinearAlgebra/test/cholesky.jl b/stdlib/LinearAlgebra/test/cholesky.jl index a3f780c047a29..170af59eef8c3 100644 --- a/stdlib/LinearAlgebra/test/cholesky.jl +++ b/stdlib/LinearAlgebra/test/cholesky.jl @@ -475,4 +475,12 @@ end end end +@testset "adjoint of Cholesky" begin + A = randn(5, 5) + A = A'A + F = cholesky(A) + b = ones(size(A, 1)) + @test F\b == F'\b +end + end # module TestCholesky diff --git a/stdlib/LinearAlgebra/test/hessenberg.jl b/stdlib/LinearAlgebra/test/hessenberg.jl index dd6a131a6ae1e..0f9246c722349 100644 --- a/stdlib/LinearAlgebra/test/hessenberg.jl +++ b/stdlib/LinearAlgebra/test/hessenberg.jl @@ -185,4 +185,15 @@ end @test Base.propertynames(F, true) == (:Q, :H, :μ, :τ, :factors, :uplo) end +@testset "adjoint of Hessenberg" begin + Ar = randn(5, 5) + Ac = complex.(randn(5, 5), randn(5, 5)) + b = ones(size(Ar, 1)) + + for A in (Ar, Ac) + F = hessenberg(A) + @test A'\b ≈ F'\b + end +end + end # module TestHessenberg diff --git a/stdlib/LinearAlgebra/test/lq.jl b/stdlib/LinearAlgebra/test/lq.jl index 8915324af9461..b054621e11313 100644 --- a/stdlib/LinearAlgebra/test/lq.jl +++ b/stdlib/LinearAlgebra/test/lq.jl @@ -220,4 +220,22 @@ Q factor: 0.0 0.0 0.0 1.0""" end +@testset "adjoint of LQ" begin + n = 5 + + for b in (ones(n), ones(n, 2), ones(Complex{Float64}, n, 2)) + for A in ( + randn(n, n), + # Tall problems become least squares problems similarly to QR + randn(n - 2, n), + complex.(randn(n, n), randn(n, n))) + + F = lq(A) + @test A'\b ≈ F'\b + end + @test_throws DimensionMismatch lq(randn(n, n + 2))'\b + end + +end + end # module TestLQ diff --git a/stdlib/LinearAlgebra/test/qr.jl b/stdlib/LinearAlgebra/test/qr.jl index 16f828b4f8861..dd5a0db40dd95 100644 --- a/stdlib/LinearAlgebra/test/qr.jl +++ b/stdlib/LinearAlgebra/test/qr.jl @@ -212,11 +212,8 @@ end @testset "transpose errors" begin @test_throws MethodError transpose(qr(randn(3,3))) - @test_throws MethodError adjoint(qr(randn(3,3))) @test_throws MethodError transpose(qr(randn(3,3), NoPivot())) - @test_throws MethodError adjoint(qr(randn(3,3), NoPivot())) @test_throws MethodError transpose(qr(big.(randn(3,3)))) - @test_throws MethodError adjoint(qr(big.(randn(3,3)))) end @testset "Issue 7304" begin @@ -369,4 +366,45 @@ end end end +@testset "adjoint of QR" begin + n = 5 + B = randn(5, 2) + + @testset "size(b)=$(size(b))" for b in (B[:, 1], B) + @testset "size(A)=$(size(A))" for A in ( + randn(n, n), + # Wide problems become minimum norm (in x) problems similarly to LQ + randn(n + 2, n), + complex.(randn(n, n), randn(n, n))) + + @testset "QRCompactWY" begin + F = qr(A) + x = F'\b + @test x ≈ A'\b + @test length(size(x)) == length(size(b)) + end + + @testset "QR" begin + F = LinearAlgebra.qrfactUnblocked!(copy(A)) + x = F'\b + @test x ≈ A'\b + @test length(size(x)) == length(size(b)) + end + + @testset "QRPivoted" begin + F = LinearAlgebra.qr(A, ColumnNorm()) + x = F'\b + @test x ≈ A'\b + @test length(size(x)) == length(size(b)) + end + end + @test_throws DimensionMismatch("overdetermined systems are not supported") qr(randn(n - 2, n))'\b + @test_throws DimensionMismatch("arguments must have the same number of rows") qr(randn(n, n + 1))'\b + @test_throws DimensionMismatch("overdetermined systems are not supported") LinearAlgebra.qrfactUnblocked!(randn(n - 2, n))'\b + @test_throws DimensionMismatch("arguments must have the same number of rows") LinearAlgebra.qrfactUnblocked!(randn(n, n + 1))'\b + @test_throws DimensionMismatch("overdetermined systems are not supported") qr(randn(n - 2, n), ColumnNorm())'\b + @test_throws DimensionMismatch("arguments must have the same number of rows") qr(randn(n, n + 1), ColumnNorm())'\b + end +end + end # module TestQR diff --git a/stdlib/LinearAlgebra/test/svd.jl b/stdlib/LinearAlgebra/test/svd.jl index 30dd6db300eb9..f02b8def49e82 100644 --- a/stdlib/LinearAlgebra/test/svd.jl +++ b/stdlib/LinearAlgebra/test/svd.jl @@ -217,4 +217,24 @@ end @test Uc * diagm(0=>Sc) * transpose(V) ≈ complex.(A) rtol=1e-3 end +@testset "adjoint of SVD" begin + n = 5 + B = randn(5, 2) + + @testset "size(b)=$(size(b))" for b in (B[:, 1], B) + @testset "size(A)=$(size(A))" for A in ( + randn(n, n), + # Wide problems become minimum norm (in x) problems similarly to LQ + randn(n + 2, n), + randn(n - 2, n), + complex.(randn(n, n), randn(n, n))) + + F = svd(A) + x = F'\b + @test x ≈ A'\b + @test length(size(x)) == length(size(b)) + end + end +end + end # module TestSVD diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index 8cfde8fb5067c..d4137e3738206 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -605,4 +605,16 @@ end end end +@testset "adjoint of LDLt" begin + Sr = SymTridiagonal(randn(5), randn(4)) + Sc = SymTridiagonal(complex.(randn(5)) .+ 1im, complex.(randn(4), randn(4))) + b = ones(size(Sr, 1)) + + F = ldlt(Sr) + @test F\b == F'\b + + F = ldlt(Sc) + @test copy(Sc')\b == F'\b +end + end # module TestTridiagonal From 100dc38f27d09331396a17035fc25de57212f2e5 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Sun, 21 Mar 2021 11:39:18 +0100 Subject: [PATCH 437/439] Normalize indices in promote_shape error messages. Seeing implementation like `Base.OneTo` in error messages may be confusing to some users (cf discussion in #39242, [discourse](https://discourse.julialang.org/t/promote-shape-dimension-mismatch/57529/)). This PR turns ```julia julia> ones(2, 3) + ones(3, 2) ERROR: DimensionMismatch("dimensions must match: a has dims (Base.OneTo(2), Base.OneTo(3)), b has dims (Base.OneTo(3), Base.OneTo(2)), mismatch at 1") ``` into ```julia julia> ones(2, 3) + ones(3, 2) ERROR: DimensionMismatch("dimensions must match: a has axes (1:2, 1:3), b has axes (1:3, 1:2), mismatch at 1") ``` Fixes #40118. Acked-by: Tamas K. Papp --- base/indices.jl | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 462e62c6d8883..085491a63e73f 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -106,26 +106,34 @@ IndexStyle(::IndexStyle, ::IndexStyle) = IndexCartesian() promote_shape(::Tuple{}, ::Tuple{}) = () -function promote_shape(a::Tuple{Int,}, b::Tuple{Int,}) - if a[1] != b[1] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) +# Consistent error message for promote_shape mismatch, hiding implementation details like +# OneTo. When b ≡ nothing, it is omitted; i can be supplied for an index. +function throw_promote_shape_mismatch(a, b, i = nothing) + _normalize(d) = map(x -> x isa AbstractUnitRange ? (firstindex(x):lastindex(x)) : x, d) + msg = "dimensions must match: a has dims $(_normalize(a))" + if b ≢ nothing + msg *= ", b has dims $(_normalize(b))" + end + if i ≢ nothing + msg *= ", mismatch at $(i)" end + throw(DimensionMismatch(msg)) +end + +function promote_shape(a::Tuple{Int,}, b::Tuple{Int,}) + a[1] != b[1] && throw_promote_shape_mismatch(a, b) return a end function promote_shape(a::Tuple{Int,Int}, b::Tuple{Int,}) - if a[1] != b[1] || a[2] != 1 - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) - end + (a[1] != b[1] || a[2] != 1) && throw_promote_shape_mismatch(a, b) return a end promote_shape(a::Tuple{Int,}, b::Tuple{Int,Int}) = promote_shape(b, a) function promote_shape(a::Tuple{Int, Int}, b::Tuple{Int, Int}) - if a[1] != b[1] || a[2] != b[2] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b")) - end + (a[1] != b[1] || a[2] != b[2]) && throw_promote_shape_mismatch(a, b) return a end @@ -153,14 +161,10 @@ function promote_shape(a::Dims, b::Dims) return promote_shape(b, a) end for i=1:length(b) - if a[i] != b[i] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b, mismatch at $i")) - end + a[i] != b[i] && throw_promote_shape_mismatch(a, b, i) end for i=length(b)+1:length(a) - if a[i] != 1 - throw(DimensionMismatch("dimensions must match: a has dims $a, must have singleton at dim $i")) - end + a[i] != 1 && throw_promote_shape_mismatch(a, nothing, i) end return a end @@ -174,14 +178,10 @@ function promote_shape(a::Indices, b::Indices) return promote_shape(b, a) end for i=1:length(b) - if a[i] != b[i] - throw(DimensionMismatch("dimensions must match: a has dims $a, b has dims $b, mismatch at $i")) - end + a[i] != b[i] && throw_promote_shape_mismatch(a, b, i) end for i=length(b)+1:length(a) - if a[i] != 1:1 - throw(DimensionMismatch("dimensions must match: a has dims $a, must have singleton at dim $i")) - end + a[i] != 1:1 && throw_promote_shape_mismatch(a, nothing, i) end return a end From edff7338903446e5420b2df3d39fefc44337d26b Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Mon, 22 Mar 2021 15:33:31 +0100 Subject: [PATCH 438/439] customize error message based on types --- base/indices.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 085491a63e73f..50498a53615c0 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -108,11 +108,15 @@ promote_shape(::Tuple{}, ::Tuple{}) = () # Consistent error message for promote_shape mismatch, hiding implementation details like # OneTo. When b ≡ nothing, it is omitted; i can be supplied for an index. -function throw_promote_shape_mismatch(a, b, i = nothing) - _normalize(d) = map(x -> x isa AbstractUnitRange ? (firstindex(x):lastindex(x)) : x, d) - msg = "dimensions must match: a has dims $(_normalize(a))" +function throw_promote_shape_mismatch(a::Tuple{Vararg{T}}, + b::Union{Nothing,Tuple{Vararg{T}}}, + i = nothing) where {T} + _has_axes = T <: AbstractUnitRange + _normalize(d) = map(x -> _has_axes ? (firstindex(x):lastindex(x)) : x, d) + _things = _has_axes ? "axes" : "size" + msg = "dimensions must match: a has $(_things) $(_normalize(a))" if b ≢ nothing - msg *= ", b has dims $(_normalize(b))" + msg *= ", b has $(_things) $(_normalize(b))" end if i ≢ nothing msg *= ", mismatch at $(i)" From 5ccc4ecedd39ba4c608b2904cb4bd7c783fcf562 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Thu, 3 Jun 2021 13:56:21 +0200 Subject: [PATCH 439/439] fix ambiguity --- base/indices.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 50498a53615c0..079dc067c8572 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -108,8 +108,8 @@ promote_shape(::Tuple{}, ::Tuple{}) = () # Consistent error message for promote_shape mismatch, hiding implementation details like # OneTo. When b ≡ nothing, it is omitted; i can be supplied for an index. -function throw_promote_shape_mismatch(a::Tuple{Vararg{T}}, - b::Union{Nothing,Tuple{Vararg{T}}}, +function throw_promote_shape_mismatch(a::Tuple{T,Vararg{T}}, + b::Union{Nothing,Tuple{T,Vararg{T}}}, i = nothing) where {T} _has_axes = T <: AbstractUnitRange _normalize(d) = map(x -> _has_axes ? (firstindex(x):lastindex(x)) : x, d)