Skip to content

Commit

Permalink
Backports release 1.10 (#53201)
Browse files Browse the repository at this point in the history
A few stragglers.

Backported PRs:
- [x] #53091 <!-- Ensure elision of `require_one_based_indexing` with
high-dim array views -->
- [x] #53117 <!-- Try to fix incorrect documentation of `nthreads` -->
- [x] #52855 <!-- Fix variable name in scaling an `AbstractTriangular`
with zero alpha -->
- [x] #52952 <!-- [REPLCompletions] enable completions for `using
Module.Inner|` -->
- [x] #53101 <!-- Inplace transpose for unit Triangular may skip
diagonal -->

Need manual backport:
- [ ] #52505 <!-- fix alignment of emit_unbox_store copy -->

Non-merged PRs with backport label:
- [ ] #53125 <!-- coverage: count coverage where explicitly requested by
inference only -->
- [ ] #52694 <!-- Reinstate similar for AbstractQ for backward
compatibility -->
- [ ] #51479 <!-- prevent code loading from lookin in the versioned
environment when building Julia -->
  • Loading branch information
KristofferC authored Feb 6, 2024
2 parents 1dfdf66 + 6fcff37 commit 4745ef8
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 31 deletions.
11 changes: 7 additions & 4 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,20 @@ end
has_offset_axes(A, B, ...)
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) | ...`.
If multiple arguments are passed, equivalent to `has_offset_axes(A) || has_offset_axes(B) || ...`.
See also [`require_one_based_indexing`](@ref).
"""
has_offset_axes() = false
has_offset_axes(A) = _any_tuple(x->Int(first(x))::Int != 1, false, axes(A)...)
has_offset_axes(A::AbstractVector) = Int(firstindex(A))::Int != 1 # improve performance of a common case (ranges)
# Use `_any_tuple` to avoid unneeded invoke.
# note: this could call `any` directly if the compiler can infer it
has_offset_axes(As...) = _any_tuple(has_offset_axes, false, As...)
has_offset_axes(::Colon) = false
has_offset_axes(::Array) = false
# note: this could call `any` directly if the compiler can infer it. We don't use _any_tuple
# here because it stops full elision in some cases (#49332) and we don't need handling of
# `missing` (has_offset_axes(A) always returns a Bool)
has_offset_axes(A, As...) = has_offset_axes(A) || has_offset_axes(As...)


"""
require_one_based_indexing(A::AbstractArray)
Expand Down
5 changes: 3 additions & 2 deletions base/threadingconstructs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ maxthreadid() = Int(Core.Intrinsics.atomic_pointerref(cglobal(:jl_n_threads, Cin
"""
Threads.nthreads(:default | :interactive) -> Int
Get the current number of threads within the specified thread pool. The threads in default
have id numbers `1:nthreads(:default)`.
Get the current number of threads within the specified thread pool. The threads in `:interactive`
have id numbers `1:nthreads(:interactive)`, and the threads in `:default` have id numbers in
`nthreads(:interactive) .+ (1:nthreads(:default))`.
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)
Expand Down
28 changes: 14 additions & 14 deletions stdlib/LinearAlgebra/src/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -406,13 +406,13 @@ transpose(A::UnitLowerTriangular) = UnitUpperTriangular(transpose(A.data))
transpose(A::UnitUpperTriangular) = UnitLowerTriangular(transpose(A.data))

transpose!(A::LowerTriangular) = UpperTriangular(copytri!(A.data, 'L', false, true))
transpose!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L', false, true))
transpose!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L', false, false))
transpose!(A::UpperTriangular) = LowerTriangular(copytri!(A.data, 'U', false, true))
transpose!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U', false, true))
transpose!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U', false, false))
adjoint!(A::LowerTriangular) = UpperTriangular(copytri!(A.data, 'L' , true, true))
adjoint!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L' , true, true))
adjoint!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L' , true, false))
adjoint!(A::UpperTriangular) = LowerTriangular(copytri!(A.data, 'U' , true, true))
adjoint!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U' , true, true))
adjoint!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U' , true, false))

diag(A::LowerTriangular) = diag(A.data)
diag(A::UnitLowerTriangular) = fill(oneunit(eltype(A)), size(A,1))
Expand Down Expand Up @@ -471,7 +471,7 @@ end

function _triscale!(A::UpperTriangular, B::UpperTriangular, c::Number, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
for i = 1:j
@inbounds _modify!(_add, B.data[i,j] * c, A.data, (i,j))
Expand All @@ -481,8 +481,8 @@ function _triscale!(A::UpperTriangular, B::UpperTriangular, c::Number, _add)
end
function _triscale!(A::UpperTriangular, c::Number, B::UpperTriangular, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
for j = 1:n
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
for i = 1:j
@inbounds _modify!(_add, c * B.data[i,j], A.data, (i,j))
end
Expand All @@ -491,7 +491,7 @@ function _triscale!(A::UpperTriangular, c::Number, B::UpperTriangular, _add)
end
function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Number, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
@inbounds _modify!(_add, c, A, (j,j))
for i = 1:(j - 1)
Expand All @@ -502,7 +502,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
end
function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriangular, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
@inbounds _modify!(_add, c, A, (j,j))
for i = 1:(j - 1)
Expand All @@ -513,7 +513,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
end
function _triscale!(A::LowerTriangular, B::LowerTriangular, c::Number, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
for i = j:n
@inbounds _modify!(_add, B.data[i,j] * c, A.data, (i,j))
Expand All @@ -523,8 +523,8 @@ function _triscale!(A::LowerTriangular, B::LowerTriangular, c::Number, _add)
end
function _triscale!(A::LowerTriangular, c::Number, B::LowerTriangular, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
for j = 1:n
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
for i = j:n
@inbounds _modify!(_add, c * B.data[i,j], A.data, (i,j))
end
Expand All @@ -533,7 +533,7 @@ function _triscale!(A::LowerTriangular, c::Number, B::LowerTriangular, _add)
end
function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Number, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
@inbounds _modify!(_add, c, A, (j,j))
for i = (j + 1):n
Expand All @@ -544,7 +544,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
end
function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriangular, _add)
n = checksquare(B)
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
for j = 1:n
@inbounds _modify!(_add, c, A, (j,j))
for i = (j + 1):n
Expand Down
15 changes: 14 additions & 1 deletion stdlib/LinearAlgebra/test/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ debug && println("Test basic type functionality")
@test LowerTriangular(randn(3, 3)) |> t -> [size(t, i) for i = 1:3] == [size(Matrix(t), i) for i = 1:3]

# The following test block tries to call all methods in base/linalg/triangular.jl in order for a combination of input element types. Keep the ordering when adding code.
for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFloat}, Int)
@testset for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFloat}, Int)
# Begin loop for first Triangular matrix
for (t1, uplo1) in ((UpperTriangular, :U),
(UnitUpperTriangular, :U),
Expand Down Expand Up @@ -239,6 +239,11 @@ for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFlo
A2tmp = unitt(A1)
mul!(A1tmp, cr, A2tmp)
@test A1tmp == cr * A2tmp

A1tmp .= A1
@test mul!(A1tmp, A2tmp, cr, 0, 2) == 2A1
A1tmp .= A1
@test mul!(A1tmp, cr, A2tmp, 0, 2) == 2A1
else
A1tmp = copy(A1)
rmul!(A1tmp, ci)
Expand Down Expand Up @@ -866,4 +871,12 @@ end
end
end

@testset "transpose triangular diagonal" begin
M = Matrix{BigFloat}(undef, 2, 2);
M[1,2] = 3;
U = UnitUpperTriangular(M)
Ut = transpose(U)
@test transpose!(U) == Ut
end

end # module TestTriangular
31 changes: 28 additions & 3 deletions stdlib/Mmap/src/Mmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -208,18 +208,43 @@ function mmap(io::IO,
mmaplen = (offset - offset_page) + len

file_desc = gethandle(io)
szfile = convert(Csize_t, len + offset)
requestedSizeLarger = false
if !(io isa Mmap.Anonymous)
@static if !Sys.isapple()
requestedSizeLarger = szfile > filesize(io)
end
end
# platform-specific mmapping
@static if Sys.isunix()
prot, flags, iswrite = settings(file_desc, shared)
iswrite && grow && grow!(io, offset, len)
if requestedSizeLarger
if iswrite
if grow
grow!(io, offset, len)
else
throw(ArgumentError("requested size $szfile larger than file size $(filesize(io)), but requested not to grow"))
end
else
throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
end
end
@static if Sys.isapple()
iswrite && grow && grow!(io, offset, len)
end
# mmap the file
ptr = ccall(:jl_mmap, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Cint, Cint, RawFD, Int64),
C_NULL, mmaplen, prot, flags, file_desc, offset_page)
systemerror("memory mapping failed", reinterpret(Int, ptr) == -1)
else
name, readonly, create = settings(io)
szfile = convert(Csize_t, len + offset)
readonly && szfile > filesize(io) && throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
if requestedSizeLarger
if readonly
throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
elseif !grow
throw(ArgumentError("requested size $szfile larger than file size $(filesize(io)), but requested not to grow"))
end
end
handle = create ? ccall(:CreateFileMappingW, stdcall, Ptr{Cvoid}, (OS_HANDLE, Ptr{Cvoid}, DWORD, DWORD, DWORD, Cwstring),
file_desc, C_NULL, readonly ? PAGE_READONLY : PAGE_READWRITE, szfile >> 32, szfile & typemax(UInt32), name) :
ccall(:OpenFileMappingW, stdcall, Ptr{Cvoid}, (DWORD, Cint, Cwstring),
Expand Down
53 changes: 46 additions & 7 deletions stdlib/REPL/src/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,10 @@ function project_deps_get_completion_candidates(pkgstarts::String, project_file:
return Completion[PackageCompletion(name) for name in loading_candidates]
end

function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ffunc::Function), context_module::Module, string::String, name::String, pos::Int, dotpos::Int, startpos::Int, comp_keywords=false)
function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ffunc),
context_module::Module, string::String, name::String,
pos::Int, dotpos::Int, startpos::Int;
comp_keywords=false)
ex = nothing
if comp_keywords
append!(suggestions, complete_keyword(name))
Expand Down Expand Up @@ -1022,10 +1025,41 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff
if something(findlast(in(non_identifier_chars), s), 0) < something(findlast(isequal('.'), s), 0)
lookup_name, name = rsplit(s, ".", limit=2)
name = String(name)

ex = Meta.parse(lookup_name, raise=false, depwarn=false)
end
isexpr(ex, :incomplete) && (ex = nothing)
elseif isexpr(ex, (:using, :import))
arg1 = ex.args[1]
if isexpr(arg1, :.)
# We come here for cases like:
# - `string`: "using Mod1.Mod2.M"
# - `ex`: :(using Mod1.Mod2)
# - `name`: "M"
# Now we transform `ex` to `:(Mod1.Mod2)` to allow `complete_symbol` to
# complete for inner modules whose name starts with `M`.
# Note that `ffunc` is set to `module_filter` within `completions`
ex = nothing
firstdot = true
for arg = arg1.args
if arg === :.
# override `context_module` if multiple `.` accessors are used
if firstdot
firstdot = false
else
context_module = parentmodule(context_module)
end
elseif arg isa Symbol
if ex === nothing
ex = arg
else
ex = Expr(:., out, QuoteNode(arg))
end
else # invalid expression
ex = nothing
break
end
end
end
elseif isexpr(ex, :call) && length(ex.args) > 1
isinfix = s[end] != ')'
# A complete call expression that does not finish with ')' is an infix call.
Expand Down Expand Up @@ -1106,8 +1140,9 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
ok && return ret
startpos = first(varrange) + 4
dotpos = something(findprev(isequal('.'), string, first(varrange)-1), 0)
return complete_identifiers!(Completion[], ffunc, context_module, string,
string[startpos:pos], pos, dotpos, startpos)
name = string[startpos:pos]
return complete_identifiers!(Completion[], ffunc, context_module, string, name, pos,
dotpos, startpos)
elseif inc_tag === :cmd
# TODO: should this call shell_completions instead of partially reimplementing it?
let m = match(r"[\t\n\r\"`><=*?|]| (?!\\)", reverse(partial)) # fuzzy shell_parse in reverse
Expand Down Expand Up @@ -1255,16 +1290,20 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
end
end
end
ffunc = (mod,x)->(Base.isbindingresolved(mod, x) && isdefined(mod, x) && isa(getfield(mod, x), Module))
ffunc = module_filter
comp_keywords = false
end

startpos == 0 && (pos = -1)
dotpos < startpos && (dotpos = startpos - 1)
return complete_identifiers!(suggestions, ffunc, context_module, string,
name, pos, dotpos, startpos, comp_keywords)
return complete_identifiers!(suggestions, ffunc, context_module, string, name, pos,
dotpos, startpos;
comp_keywords)
end

module_filter(mod::Module, x::Symbol) =
Base.isbindingresolved(mod, x) && isdefined(mod, x) && isa(getglobal(mod, x), Module)

function shell_completions(string, pos)
# First parse everything up to the current position
scs = string[1:pos]
Expand Down
44 changes: 44 additions & 0 deletions stdlib/REPL/test/replcompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1939,3 +1939,47 @@ let s = "@issue51827 Base.ac"
@test res
@test "acquire" in c
end

# JuliaLang/julia#52922
let s = "using Base.Th"
c, r, res = test_complete_context(s)
@test res
@test "Threads" in c
end
let s = "using Base."
c, r, res = test_complete_context(s)
@test res
@test "BinaryPlatforms" in c
end
# test cases with the `.` accessor
module Issue52922
module Inner1
module Inner12 end
end
module Inner2 end
end
let s = "using .Iss"
c, r, res = test_complete_context(s)
@test res
@test "Issue52922" in c
end
let s = "using .Issue52922.Inn"
c, r, res = test_complete_context(s)
@test res
@test "Inner1" in c
end
let s = "using .Inner1.Inn"
c, r, res = test_complete_context(s, Issue52922)
@test res
@test "Inner12" in c
end
let s = "using ..Issue52922.Inn"
c, r, res = test_complete_context(s, Issue52922.Inner1)
@test res
@test "Inner2" in c
end
let s = "using ...Issue52922.Inn"
c, r, res = test_complete_context(s, Issue52922.Inner1.Inner12)
@test res
@test "Inner2" in c
end
4 changes: 4 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1825,13 +1825,17 @@ end

@testset "type-based offset axes check" begin
a = randn(ComplexF64, 10)
b = randn(ComplexF64, 4, 4, 4, 4)
ta = reinterpret(Float64, a)
tb = reinterpret(Float64, view(a, 1:2:10))
tc = reinterpret(Float64, reshape(view(a, 1:3:10), 2, 2, 1))
td = view(b, :, :, 1, 1)
# Issue #44040
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc))
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(tc, tc))
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc, tb))
# Issue #49332
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(td, td, td))
# Ranges && CartesianIndices
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(1:10, Base.OneTo(10), 1.0:2.0, LinRange(1.0, 2.0, 2), 1:2:10, CartesianIndices((1:2:10, 1:2:10))))
# Remind us to call `any` in `Base.has_offset_axes` once our compiler is ready.
Expand Down

0 comments on commit 4745ef8

Please sign in to comment.