Skip to content

Commit

Permalink
Merge pull request #45946 from JuliaLang/backports-release-1.8
Browse files Browse the repository at this point in the history
Backports for 1.8-rc2/1.8.0
  • Loading branch information
KristofferC authored Jul 8, 2022
2 parents 381eac3 + d4abcaa commit 477324a
Show file tree
Hide file tree
Showing 20 changed files with 264 additions and 97 deletions.
28 changes: 17 additions & 11 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,11 @@ function reverseind(a::AbstractVector, i::Integer)
first(li) + last(li) - i
end

# This implementation of `midpoint` is performance-optimized but safe
# only if `lo <= hi`.
midpoint(lo::T, hi::T) where T<:Integer = lo + ((hi - lo) >>> 0x01)
midpoint(lo::Integer, hi::Integer) = midpoint(promote(lo, hi)...)

"""
reverse!(v [, start=1 [, stop=length(v) ]]) -> v
Expand Down Expand Up @@ -1861,17 +1866,18 @@ julia> A
"""
function reverse!(v::AbstractVector, start::Integer, stop::Integer=lastindex(v))
s, n = Int(start), Int(stop)
liv = LinearIndices(v)
if n <= s # empty case; ok
elseif !(first(liv) s last(liv))
throw(BoundsError(v, s))
elseif !(first(liv) n last(liv))
throw(BoundsError(v, n))
end
r = n
@inbounds for i in s:div(s+n-1, 2)
v[i], v[r] = v[r], v[i]
r -= 1
if n > s # non-empty and non-trivial
liv = LinearIndices(v)
if !(first(liv) s last(liv))
throw(BoundsError(v, s))
elseif !(first(liv) n last(liv))
throw(BoundsError(v, n))
end
r = n
@inbounds for i in s:midpoint(s, n-1)
v[i], v[r] = v[r], v[i]
r -= 1
end
end
return v
end
Expand Down
2 changes: 1 addition & 1 deletion base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1172,7 +1172,7 @@ Base.@propagate_inbounds dotview(B::BitArray, i::BitArray) = BitMaskedBitArray(B
Base.show(io::IO, B::BitMaskedBitArray) = foreach(arg->show(io, arg), (typeof(B), (B.parent, B.mask)))
# Override materialize! to prevent the BitMaskedBitArray from escaping to an overrideable method
@inline materialize!(B::BitMaskedBitArray, bc::Broadcasted{<:Any,<:Any,typeof(identity),Tuple{Bool}}) = fill!(B, bc.args[1])
@inline materialize!(B::BitMaskedBitArray, bc::Broadcasted{<:Any}) = materialize!(SubArray(B.parent, to_indices(B.parent, (B.mask,))), bc)
@inline materialize!(B::BitMaskedBitArray, bc::Broadcasted{<:Any}) = materialize!(@inbounds(view(B.parent, B.mask)), bc)
function Base.fill!(B::BitMaskedBitArray, b::Bool)
Bc = B.parent.chunks
Ic = B.mask.chunks
Expand Down
24 changes: 8 additions & 16 deletions base/reinterpretarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,15 @@ strides(a::Union{DenseArray,StridedReshapedArray,StridedReinterpretArray}) = siz
stride(A::Union{DenseArray,StridedReshapedArray,StridedReinterpretArray}, k::Integer) =
k ndims(A) ? strides(A)[k] : length(A)

function strides(a::ReshapedReinterpretArray)
ap = parent(a)
els, elp = elsize(a), elsize(ap)
stp = strides(ap)
els == elp && return stp
els < elp && return (1, _checked_strides(stp, els, elp)...)
function strides(a::ReinterpretArray{T,<:Any,S,<:AbstractArray{S},IsReshaped}) where {T,S,IsReshaped}
_checkcontiguous(Bool, a) && return size_to_strides(1, size(a))
stp = strides(parent(a))
els, elp = sizeof(T), sizeof(S)
els == elp && return stp # 0dim parent is also handled here.
IsReshaped && els < elp && return (1, _checked_strides(stp, els, elp)...)
stp[1] == 1 || throw(ArgumentError("Parent must be contiguous in the 1st dimension!"))
return _checked_strides(tail(stp), els, elp)
end

function strides(a::NonReshapedReinterpretArray)
ap = parent(a)
els, elp = elsize(a), elsize(ap)
stp = strides(ap)
els == elp && return stp
stp[1] == 1 || throw(ArgumentError("Parent must be contiguous in the 1st dimension!"))
return (1, _checked_strides(tail(stp), els, elp)...)
st′ = _checked_strides(tail(stp), els, elp)
return IsReshaped ? st′ : (1, st′...)
end

@inline function _checked_strides(stp::Tuple, els::Integer, elp::Integer)
Expand Down
49 changes: 43 additions & 6 deletions base/reshapedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -294,14 +294,51 @@ unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{Union{RangeIndex
unsafe_convert(Ptr{T}, V.parent) + (first_index(V)-1)*sizeof(T)


_checkcontiguous(::Type{Bool}, A::AbstractArray) = size_to_strides(1, size(A)...) == strides(A)
_checkcontiguous(::Type{Bool}, A::Array) = true
_checkcontiguous(::Type{Bool}, A::AbstractArray) = false
# `strides(A::DenseArray)` calls `size_to_strides` by default.
# Thus it's OK to assume all `DenseArray`s are contiguously stored.
_checkcontiguous(::Type{Bool}, A::DenseArray) = true
_checkcontiguous(::Type{Bool}, A::ReshapedArray) = _checkcontiguous(Bool, parent(A))
_checkcontiguous(::Type{Bool}, A::FastContiguousSubArray) = _checkcontiguous(Bool, parent(A))

function strides(a::ReshapedArray)
# We can handle non-contiguous parent if it's a StridedVector
ndims(parent(a)) == 1 && return size_to_strides(only(strides(parent(a))), size(a)...)
_checkcontiguous(Bool, a) || throw(ArgumentError("Parent must be contiguous."))
size_to_strides(1, size(a)...)
_checkcontiguous(Bool, a) && return size_to_strides(1, size(a)...)
apsz::Dims = size(a.parent)
apst::Dims = strides(a.parent)
msz, mst, n = merge_adjacent_dim(apsz, apst) # Try to perform "lazy" reshape
n == ndims(a.parent) && return size_to_strides(mst, size(a)...) # Parent is stridevector like
return _reshaped_strides(size(a), 1, msz, mst, n, apsz, apst)
end

function _reshaped_strides(::Dims{0}, reshaped::Int, msz::Int, ::Int, ::Int, ::Dims, ::Dims)
reshaped == msz && return ()
throw(ArgumentError("Input is not strided."))
end
function _reshaped_strides(sz::Dims, reshaped::Int, msz::Int, mst::Int, n::Int, apsz::Dims, apst::Dims)
st = reshaped * mst
reshaped = reshaped * sz[1]
if length(sz) > 1 && reshaped == msz && sz[2] != 1
msz, mst, n = merge_adjacent_dim(apsz, apst, n + 1)
reshaped = 1
end
sts = _reshaped_strides(tail(sz), reshaped, msz, mst, n, apsz, apst)
return (st, sts...)
end

merge_adjacent_dim(::Dims{0}, ::Dims{0}) = 1, 1, 0
merge_adjacent_dim(apsz::Dims{1}, apst::Dims{1}) = apsz[1], apst[1], 1
function merge_adjacent_dim(apsz::Dims{N}, apst::Dims{N}, n::Int = 1) where {N}
sz, st = apsz[n], apst[n]
while n < N
szₙ, stₙ = apsz[n+1], apst[n+1]
if sz == 1
sz, st = szₙ, stₙ
elseif stₙ == st * sz || szₙ == 1
sz *= szₙ
else
break
end
n += 1
end
return sz, st, n
end
17 changes: 6 additions & 11 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using .Base: copymutable, LinearIndices, length, (:),
AbstractMatrix, AbstractUnitRange, isless, identity, eltype, >, <, <=, >=, |, +, -, *, !,
extrema, sub_with_overflow, add_with_overflow, oneunit, div, getindex, setindex!,
length, resize!, fill, Missing, require_one_based_indexing, keytype,
UnitRange, max, min
UnitRange, max, min, midpoint

using .Base: >>>, !==

Expand Down Expand Up @@ -166,11 +166,6 @@ same thing as `partialsort!` but leaving `v` unmodified.
partialsort(v::AbstractVector, k::Union{Integer,OrdinalRange}; kws...) =
partialsort!(copymutable(v), k; kws...)

# This implementation of `midpoint` is performance-optimized but safe
# only if `lo <= hi`.
midpoint(lo::T, hi::T) where T<:Integer = lo + ((hi - lo) >>> 0x01)
midpoint(lo::Integer, hi::Integer) = midpoint(promote(lo, hi)...)

# reference on sorted binary search:
# http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary

Expand Down Expand Up @@ -505,12 +500,12 @@ function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg,
j = i
x = v[i]
while j > lo
if lt(o, x, v[j-1])
v[j] = v[j-1]
j -= 1
continue
y = v[j-1]
if !lt(o, x, y)
break
end
break
v[j] = y
j -= 1
end
v[j] = x
end
Expand Down
5 changes: 5 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ PUBLIC_HEADER_TARGETS := $(addprefix $(build_includedir)/julia/,$(notdir $(PUBLI
LLVM_LDFLAGS := $(shell $(LLVM_CONFIG_HOST) --ldflags)
LLVM_CXXFLAGS := $(shell $(LLVM_CONFIG_HOST) --cxxflags)

# llvm-config --cxxflags does not return -DNDEBUG
ifeq ($(shell $(LLVM_CONFIG_HOST) --assertion-mode),OFF)
LLVM_CXXFLAGS += -DNDEBUG
endif

ifeq ($(JULIACODEGEN),LLVM)
ifneq ($(USE_SYSTEM_LLVM),0)
CG_LLVMLINK += $(LLVM_LDFLAGS) $(shell $(LLVM_CONFIG_HOST) --libs --system-libs)
Expand Down
1 change: 1 addition & 0 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void JL_UV_LOCK(void)
}
else {
jl_atomic_fetch_add_relaxed(&jl_uv_n_waiters, 1);
jl_fence(); // [^store_buffering_2]
jl_wake_libuv();
JL_LOCK(&jl_uv_mutex);
jl_atomic_fetch_add_relaxed(&jl_uv_n_waiters, -1);
Expand Down
35 changes: 25 additions & 10 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,8 @@ static int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT

// sort singletons first, then DataTypes, then UnionAlls,
// ties broken alphabetically including module name & type parameters
static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
static int union_sort_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT
{
jl_value_t *a = *(jl_value_t**)ap;
jl_value_t *b = *(jl_value_t**)bp;
if (a == NULL)
return b == NULL ? 0 : 1;
if (b == NULL)
Expand Down Expand Up @@ -458,16 +456,33 @@ static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
}
}

static void isort_union(jl_value_t **a, size_t len) JL_NOTSAFEPOINT
{
size_t i, j;
for (i = 1; i < len; i++) {
jl_value_t *x = a[i];
for (j = i; j > 0; j--) {
jl_value_t *y = a[j - 1];
if (!(union_sort_cmp(x, y) < 0))
break;
a[j] = y;
}
a[j] = x;
}
}

JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
{
if (n == 0) return (jl_value_t*)jl_bottom_type;
if (n == 0)
return (jl_value_t*)jl_bottom_type;
size_t i;
for(i=0; i < n; i++) {
for (i = 0; i < n; i++) {
jl_value_t *pi = ts[i];
if (!(jl_is_type(pi) || jl_is_typevar(pi)))
jl_type_error("Union", (jl_value_t*)jl_type_type, pi);
}
if (n == 1) return ts[0];
if (n == 1)
return ts[0];

size_t nt = count_union_components(ts, n);
jl_value_t **temp;
Expand All @@ -476,9 +491,9 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
flatten_type_union(ts, n, temp, &count);
assert(count == nt);
size_t j;
for(i=0; i < nt; i++) {
int has_free = temp[i]!=NULL && jl_has_free_typevars(temp[i]);
for(j=0; j < nt; j++) {
for (i = 0; i < nt; i++) {
int has_free = temp[i] != NULL && jl_has_free_typevars(temp[i]);
for (j = 0; j < nt; j++) {
if (j != i && temp[i] && temp[j]) {
if (temp[i] == jl_bottom_type ||
temp[j] == (jl_value_t*)jl_any_type ||
Expand All @@ -490,7 +505,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
}
}
}
qsort(temp, nt, sizeof(jl_value_t*), union_sort_cmp);
isort_union(temp, nt);
jl_value_t **ptu = &temp[nt];
*ptu = jl_bottom_type;
int k;
Expand Down
11 changes: 9 additions & 2 deletions src/partr.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@ static const int16_t sleeping = 1;
// * 2a: `multiq_insert`
// * 2b: `jl_atomic_load_relaxed(&ptls->sleep_check_state)` in `jl_wakeup_thread` returns `not_sleeping`
// i.e., the dequeuer misses the enqueue and enqueuer misses the sleep state transition.

// [^store_buffering_2]: and also
// * Enqueuer:
// * 1a: `jl_atomic_store_relaxed(jl_uv_n_waiters, 1)` in `JL_UV_LOCK`
// * 1b: "cheap read" of `handle->pending` in `uv_async_send` (via `JL_UV_LOCK`) loads `0`
// * Dequeuer:
// * 2a: store `2` to `handle->pending` in `uv_async_send` (via `JL_UV_LOCK` in `jl_task_get_next`)
// * 2b: `jl_atomic_load_relaxed(jl_uv_n_waiters)` in `jl_task_get_next` returns `0`
// i.e., the dequeuer misses the `n_waiters` is set and enqueuer misses the `uv_stop` flag (in `signal_async`) transition to cleared

JULIA_DEBUG_SLEEPWAKE(
uint64_t wakeup_enter;
Expand Down Expand Up @@ -462,7 +469,7 @@ static int may_sleep(jl_ptls_t ptls) JL_NOTSAFEPOINT
// by the thread itself. As a result, if this returns false, it will
// continue returning false. If it returns true, we know the total
// modification order of the fences.
jl_fence(); // [^store_buffering_1]
jl_fence(); // [^store_buffering_1] [^store_buffering_2]
return jl_atomic_load_relaxed(&ptls->sleep_check_state) == sleeping;
}

Expand Down
71 changes: 52 additions & 19 deletions stdlib/LinearAlgebra/src/blas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,19 @@ end
# Level 1
# A help function to pick the pointer and inc for 1d like inputs.
@inline function vec_pointer_stride(x::AbstractArray, stride0check = nothing)
isdense(x) && return pointer(x), 1 # simpify runtime check when possibe
ndims(x) == 1 || strides(x) == Base.size_to_strides(stride(x, 1), size(x)...) ||
throw(ArgumentError("only support vector like inputs"))
st = stride(x, 1)
Base._checkcontiguous(Bool, x) && return pointer(x), 1 # simpify runtime check when possibe
st, ptr = checkedstride(x), pointer(x)
isnothing(stride0check) || (st == 0 && throw(stride0check))
ptr = st > 0 ? pointer(x) : pointer(x, lastindex(x))
ptr += min(st, 0) * sizeof(eltype(x)) * (length(x) - 1)
ptr, st
end
isdense(x) = x isa DenseArray
isdense(x::Base.FastContiguousSubArray) = isdense(parent(x))
isdense(x::Base.ReshapedArray) = isdense(parent(x))
isdense(x::Base.ReinterpretArray) = isdense(parent(x))
function checkedstride(x::AbstractArray)
szs::Dims = size(x)
sts::Dims = strides(x)
_, st, n = Base.merge_adjacent_dim(szs, sts)
n === ndims(x) && return st
throw(ArgumentError("only support vector like inputs"))
end
## copy

"""
Expand Down Expand Up @@ -1565,11 +1566,27 @@ for (mfname, elty) in ((:dsymm_,:Float64),
require_one_based_indexing(A, B, C)
m, n = size(C)
j = checksquare(A)
if j != (side == 'L' ? m : n)
throw(DimensionMismatch(lazy"A has size $(size(A)), C has size ($m,$n)"))
end
if size(B,2) != n
throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)) but needs to match second dimension of C, $n"))
M, N = size(B)
if side == 'L'
if j != m
throw(DimensionMismatch(lazy"A has first dimension $j but needs to match first dimension of C, $m"))
end
if N != n
throw(DimensionMismatch(lazy"B has second dimension $N but needs to match second dimension of C, $n"))
end
if j != M
throw(DimensionMismatch(lazy"A has second dimension $j but needs to match first dimension of B, $M"))
end
else
if j != n
throw(DimensionMismatch(lazy"B has second dimension $j but needs to match second dimension of C, $n"))
end
if N != j
throw(DimensionMismatch(lazy"A has second dimension $N but needs to match first dimension of B, $j"))
end
if M != m
throw(DimensionMismatch(lazy"A has first dimension $M but needs to match first dimension of C, $m"))
end
end
chkstride1(A)
chkstride1(B)
Expand Down Expand Up @@ -1639,11 +1656,27 @@ for (mfname, elty) in ((:zhemm_,:ComplexF64),
require_one_based_indexing(A, B, C)
m, n = size(C)
j = checksquare(A)
if j != (side == 'L' ? m : n)
throw(DimensionMismatch(lazy"A has size $(size(A)), C has size ($m,$n)"))
end
if size(B,2) != n
throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)) but needs to match second dimension of C, $n"))
M, N = size(B)
if side == 'L'
if j != m
throw(DimensionMismatch(lazy"A has first dimension $j but needs to match first dimension of C, $m"))
end
if N != n
throw(DimensionMismatch(lazy"B has second dimension $N but needs to match second dimension of C, $n"))
end
if j != M
throw(DimensionMismatch(lazy"A has second dimension $j but needs to match first dimension of B, $M"))
end
else
if j != n
throw(DimensionMismatch(lazy"B has second dimension $j but needs to match second dimension of C, $n"))
end
if N != j
throw(DimensionMismatch(lazy"A has second dimension $N but needs to match first dimension of B, $j"))
end
if M != m
throw(DimensionMismatch(lazy"A has first dimension $M but needs to match first dimension of C, $m"))
end
end
chkstride1(A)
chkstride1(B)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/src/bunchkaufman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ BunchKaufman(A::AbstractMatrix{T}, ipiv::AbstractVector{<:Integer}, uplo::Abstra
BunchKaufman{T,typeof(A),typeof(ipiv)}(A, ipiv, uplo, symmetric, rook, info)
# backwards-compatible constructors (remove with Julia 2.0)
@deprecate(BunchKaufman(LD, ipiv, uplo, symmetric, rook, info) where {T,S},
BunchKaufman{T,S,typeof(ipiv)}(LD, ipiv, uplo, symmetric, rook, info))
BunchKaufman{T,S,typeof(ipiv)}(LD, ipiv, uplo, symmetric, rook, info), false)

# iteration for destructuring into components
Base.iterate(S::BunchKaufman) = (S.D, Val(:UL))
Expand Down
Loading

0 comments on commit 477324a

Please sign in to comment.