@@ -55,6 +55,11 @@ const PARTIAL_ARRAY_DIM_GROWTH_FACTOR = 4
5555""" A convenience for defining method argument type bounds."""
5656const 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
105110a few scattered values are set, a structure like `SparseArray` may be more appropriate.
106111"""
107112struct 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