Skip to content

Commit

Permalink
fix definition of ntuple with a Val argument to not expect inference …
Browse files Browse the repository at this point in the history
…to be non-terminating

this same issue applied to several other similar functions

similarly, need to avoid nesting the use of functional code (like map)
too deeply inside the array code to avoid the appearance of indeterminate recursion in inference
  • Loading branch information
vtjnash committed May 22, 2017
1 parent 8e1deb2 commit 4f1b479
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 205 deletions.
50 changes: 26 additions & 24 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1160,30 +1160,32 @@ cat_similar(A::AbstractArray, T, shape) = similar(A, T, shape)

cat_shape(dims, shape::Tuple) = shape
@inline cat_shape(dims, shape::Tuple, nshape::Tuple, shapes::Tuple...) =
cat_shape(dims, _cshp(dims, (), shape, nshape), shapes...)

_cshp(::Tuple{}, out, ::Tuple{}, ::Tuple{}) = out
_cshp(::Tuple{}, out, ::Tuple{}, nshape) = (out..., nshape...)
_cshp(dims, out, ::Tuple{}, ::Tuple{}) = (out..., map(b -> 1, dims)...)
@inline _cshp(dims, out, shape, ::Tuple{}) =
_cshp(tail(dims), (out..., shape[1] + dims[1]), tail(shape), ())
@inline _cshp(dims, out, ::Tuple{}, nshape) =
_cshp(tail(dims), (out..., nshape[1]), (), tail(nshape))
@inline function _cshp(::Tuple{}, out, shape, ::Tuple{})
_cs(length(out) + 1, false, shape[1], 1)
_cshp((), (out..., 1), tail(shape), ())
end
@inline function _cshp(::Tuple{}, out, shape, nshape)
next = _cs(length(out) + 1, false, shape[1], nshape[1])
_cshp((), (out..., next), tail(shape), tail(nshape))
end
@inline function _cshp(dims, out, shape, nshape)
next = _cs(length(out) + 1, dims[1], shape[1], nshape[1])
_cshp(tail(dims), (out..., next), tail(shape), tail(nshape))
end

_cs(d, concat, a, b) = concat ? (a + b) : (a == b ? a : throw(DimensionMismatch(string(
"mismatch in dimension ", d, " (expected ", a, " got ", b, ")"))))
cat_shape(dims, _cshp(1, dims, shape, nshape), shapes...)

_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)})
@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) =
(nshape[1], _cshp(ndim + 1, tail(dims), (), tail(nshape))...)
@inline function _cshp(ndim::Int, ::Tuple{}, shape, ::Tuple{})
_cs(ndim, shape[1], 1)
(1, _cshp(ndim + 1, (), tail(shape), ())...)
end
@inline function _cshp(ndim::Int, ::Tuple{}, shape, nshape)
next = _cs(ndim, shape[1], nshape[1])
(next, _cshp(ndim + 1, (), tail(shape), tail(nshape))...)
end
@inline function _cshp(ndim::Int, dims, shape, nshape)
a = shape[1]
b = nshape[1]
next = dims[1] ? a + b : _cs(ndim, a, b)
(next, _cshp(ndim + 1, tail(dims), tail(shape), tail(nshape))...)
end

_cs(d, a, b) = (a == b ? a : throw(DimensionMismatch(
"mismatch in dimension $d (expected $a got $b)")))

dims2cat{n}(::Type{Val{n}}) = ntuple(i -> (i == n), Val{n})
dims2cat(dims) = ntuple(i -> (i in dims), maximum(dims))
Expand Down
7 changes: 1 addition & 6 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,7 @@ end
size(a::Array, d) = arraysize(a, d)
size(a::Vector) = (arraysize(a,1),)
size(a::Matrix) = (arraysize(a,1), arraysize(a,2))
size(a::Array) = (@_inline_meta; _size((), a))
_size(out::NTuple{N}, A::Array{_,N}) where {_,N} = out
function _size(out::NTuple{M}, A::Array{_,N}) where _ where M where N
@_inline_meta
_size((out..., size(A,M+1)), A)
end
size(a::Array{<:Any,N}) where {N} = (@_inline_meta; ntuple(M -> size(a, M), Val{N}))

asize_from(a::Array, n) = n > ndims(a) ? () : (arraysize(a,n), asize_from(a, n+1)...)

Expand Down
25 changes: 12 additions & 13 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,22 @@ promote_containertype(::Type{T}, ::Type{T}) where {T} = T
## Calculate the broadcast indices of the arguments, or error if incompatible
# array inputs
broadcast_indices() = ()
broadcast_indices(A) = broadcast_indices(containertype(A), A)
broadcast_indices(::ScalarType, A) = ()
broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),)
broadcast_indices(::Type{Array}, A::Ref) = ()
broadcast_indices(::Type{Array}, A) = indices(A)
@inline broadcast_indices(A, B...) = broadcast_shape((), broadcast_indices(A), map(broadcast_indices, B)...)
broadcast_indices(A) = _broadcast_indices(containertype(A), A)
@inline broadcast_indices(A, B...) = broadcast_shape(broadcast_indices(A), broadcast_indices(B...))
_broadcast_indices(::Type, A) = ()
_broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),)
_broadcast_indices(::Type{Array}, A::Ref) = ()
_broadcast_indices(::Type{Array}, A) = indices(A)

# shape (i.e., tuple-of-indices) inputs
broadcast_shape(shape::Tuple) = shape
@inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs((), shape, shape1), shapes...)
@inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs(shape, shape1), shapes...)
# _bcs consolidates two shapes into a single output shape
_bcs(out, ::Tuple{}, ::Tuple{}) = out
@inline _bcs(out, ::Tuple{}, newshape) = _bcs((out..., newshape[1]), (), tail(newshape))
@inline _bcs(out, shape, ::Tuple{}) = _bcs((out..., shape[1]), tail(shape), ())
@inline function _bcs(out, shape, newshape)
newout = _bcs1(shape[1], newshape[1])
_bcs((out..., newout), tail(shape), tail(newshape))
_bcs(::Tuple{}, ::Tuple{}) = ()
@inline _bcs(::Tuple{}, newshape::Tuple) = (newshape[1], _bcs((), tail(newshape))...)
@inline _bcs(shape::Tuple, ::Tuple{}) = (shape[1], _bcs(tail(shape), ())...)
@inline function _bcs(shape::Tuple, newshape::Tuple)
return (_bcs1(shape[1], newshape[1]), _bcs(tail(shape), tail(newshape))...)
end
# _bcs1 handles the logic for a single dimension
_bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch("arrays could not be broadcast to a common size"))))
Expand Down
7 changes: 4 additions & 3 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ module IteratorsMD
eachindex(::IndexCartesian, A::AbstractArray) = CartesianRange(indices(A))

@inline eachindex(::IndexCartesian, A::AbstractArray, B::AbstractArray...) =
CartesianRange(maxsize((), A, B...))
maxsize(sz) = sz
@inline maxsize(sz, A, B...) = maxsize(maxt(sz, size(A)), B...)
CartesianRange(maxsize(A, B...))
maxsize() = ()
@inline maxsize(A) = size(A)
@inline maxsize(A, B...) = maxt(size(A), maxsize(B...))
@inline maxt(a::Tuple{}, b::Tuple{}) = ()
@inline maxt(a::Tuple{}, b::Tuple) = b
@inline maxt(a::Tuple, b::Tuple{}) = a
Expand Down
Loading

0 comments on commit 4f1b479

Please sign in to comment.