Skip to content

Commit 35c3e20

Browse files
committed
ArrayLikeBlock WIP
1 parent 3c02da4 commit 35c3e20

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

src/varnamedtuple.jl

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ const PARTIAL_ARRAY_DIM_GROWTH_FACTOR = 4
5555
"""A convenience for defining method argument type bounds."""
5656
const INDEX_TYPES = Union{Integer,UnitRange,Colon}
5757

58+
struct ArrayLikeBlock{T,I}
59+
block::T
60+
inds::I
61+
end
62+
5863
"""
5964
PartialArray{ElType,numdims}
6065
@@ -105,6 +110,9 @@ means that the largest index set so far determines the memory usage of the `Part
105110
a few scattered values are set, a structure like `SparseArray` may be more appropriate.
106111
"""
107112
struct PartialArray{ElType,num_dims}
113+
# TODO(mhauru) Consider trying FixedSizeArrays instead, see how it would change
114+
# performance. We reallocate new Arrays every time when resizing anyway, except for
115+
# Vectors, which can be extended in place.
108116
data::Array{ElType,num_dims}
109117
mask::Array{Bool,num_dims}
110118

@@ -395,7 +403,34 @@ function _setindex!!(pa::PartialArray, value, inds::Vararg{INDEX_TYPES})
395403
else
396404
_resize_partialarray!!(pa, inds)
397405
end
398-
new_data = setindex!!(pa.data, value, inds...)
406+
407+
new_data = pa.data
408+
if _is_multiindex(inds) && !(isa(value, AbstractArray))
409+
if !hasmethod(size, value)
410+
throw(ArgumentError("Cannot assign a scalar value to a range."))
411+
end
412+
if size(value) != map(x -> _length_needed(x), inds)
413+
throw(
414+
DimensionMismatch(
415+
"Assigned value has size $(size(value)), which does not match the size " *
416+
"implied by the indices $(map(x -> _length_needed(x), inds)).",
417+
),
418+
)
419+
end
420+
# At this point we know we have a value that is not an AbstractArray, but it has
421+
# some notion of size, and that size matches the indices that are being set. In this
422+
# case we wrap the value in a ArrayLikeBlock, and set all the individual indices
423+
# point to that, with the right subindices.
424+
first_index = first.(inds)
425+
# Iterate over all the subindices of inds.
426+
for ind in CartesianIndices(map(x -> _length_needed(x), inds))
427+
subinds = ntuple(i -> first_index[i] + ind[i] - 1, length(inds))
428+
new_data = _setindex!!(new_data, ArrayLikeBlock(value, Tuple(ind)), subinds...)
429+
end
430+
else
431+
new_data = setindex!!(new_data, value, inds...)
432+
end
433+
399434
if _is_multiindex(inds)
400435
pa.mask[inds...] .= true
401436
else

0 commit comments

Comments
 (0)