@@ -2,7 +2,8 @@ module RecursiveArrayToolsRaggedArrays
22
33import RecursiveArrayTools: RecursiveArrayTools, AbstractRaggedVectorOfArray,
44 AbstractRaggedDiffEqArray, VectorOfArray, DiffEqArray,
5- AbstractVectorOfArray, AbstractDiffEqArray, AllObserved
5+ AbstractVectorOfArray, AbstractDiffEqArray, AllObserved,
6+ recursivefill!, recursivecopy!
67using SymbolicIndexingInterface
78using SymbolicIndexingInterface: ParameterTimeseriesCollection, ParameterIndexingProxy,
89 ScalarSymbolic, ArraySymbolic, NotSymbolic, Timeseries, SymbolCache
@@ -1519,6 +1520,26 @@ end
15191520
15201521Base. map (f, A:: AbstractRaggedVectorOfArray ) = map (f, A. u)
15211522
1523+ # Named functor used by the nested-ragged mapreduce to ensure type-stable dispatch.
1524+ struct _RaggedMapReduce{F, Op}
1525+ f:: F
1526+ op:: Op
1527+ end
1528+ @inline (w:: _RaggedMapReduce )(u) = mapreduce (w. f, w. op, u)
1529+
1530+ # When inner elements are themselves ragged, the view-based approach fails: view uses
1531+ # size(A.u[1]) for every column, causing BoundsErrors when inner shapes differ.
1532+ # We recurse element-by-element instead. Dispatching on the type of A.u (rather than
1533+ # using an if-check at runtime) keeps inference type-stable down to Julia 1.10.
1534+ function Base. mapreduce (
1535+ f, op,
1536+ A:: AbstractRaggedVectorOfArray{T, N, <:AbstractVector{<:AbstractRaggedVectorOfArray}} ;
1537+ kwargs...
1538+ ) where {T, N}
1539+ isempty (kwargs) || return mapreduce (f, op, view (A, ntuple (_ -> :, ndims (A))... ); kwargs... )
1540+ return mapreduce (_RaggedMapReduce (f, op), op, A. u)
1541+ end
1542+
15221543function Base. mapreduce (f, op, A:: AbstractRaggedVectorOfArray ; kwargs... )
15231544 return mapreduce (f, op, view (A, ntuple (_ -> :, ndims (A))... ); kwargs... )
15241545end
@@ -1725,4 +1746,39 @@ end
17251746# Re-export has_discretes and get_discretes for the non-ragged types
17261747has_discretes (:: TT ) where {TT <: AbstractDiffEqArray } = hasfield (TT, :discretes )
17271748
1749+ function recursivecopy! (b:: AbstractRaggedVectorOfArray , a:: AbstractRaggedVectorOfArray )
1750+ @inbounds for i in eachindex (b. u, a. u)
1751+ if ArrayInterface. ismutable (b. u[i]) || b. u[i] isa AbstractRaggedVectorOfArray
1752+ recursivecopy! (b. u[i], a. u[i])
1753+ else
1754+ b. u[i] = copy (a. u[i])
1755+ end
1756+ end
1757+ return b
1758+ end
1759+
1760+ function recursivefill! (
1761+ b:: AbstractRaggedVectorOfArray{T, N} ,
1762+ a:: T2
1763+ ) where {T <: Union{Number, Bool} , T2 <: Union{Number, Bool} , N}
1764+ return fill! (b, a)
1765+ end
1766+
1767+ function recursivefill! (
1768+ b:: AbstractRaggedVectorOfArray{T, N} ,
1769+ a:: T2
1770+ ) where {T <: StaticArraysCore.SArray , T2 <: Union{Number, Bool} , N}
1771+ @inbounds for arr in b. u, i in eachindex (arr)
1772+ arr[i] = map (_ -> a, arr[i])
1773+ end
1774+ return b
1775+ end
1776+
1777+ function recursivefill! (b:: AbstractRaggedVectorOfArray{T, N} , a) where {T <: AbstractArray , N}
1778+ @inbounds for arr in b. u
1779+ recursivefill! (arr, a)
1780+ end
1781+ return b
1782+ end
1783+
17281784end # module RecursiveArrayToolsRaggedArrays
0 commit comments