562562function Base.:(:)(start:: Integer , step:: Integer , stop:: RaggedEnd )
563563 return RaggedRange (stop. dim, Int (start), Int (step), stop. offset)
564564end
565+ function Base.:(:)(start:: RaggedEnd , stop:: RaggedEnd )
566+ return RaggedRange (stop. dim, start. offset, 1 , stop. offset)
567+ end
568+ function Base.:(:)(start:: RaggedEnd , step:: Integer , stop:: RaggedEnd )
569+ return RaggedRange (stop. dim, start. offset, Int (step), stop. offset)
570+ end
571+ function Base.:(:)(start:: RaggedEnd , stop:: Integer )
572+ return RaggedRange (start. dim, start. offset, 1 , Int (stop))
573+ end
574+ function Base.:(:)(start:: RaggedEnd , step:: Integer , stop:: Integer )
575+ return RaggedRange (start. dim, start. offset, Int (step), Int (stop))
576+ end
565577Base. broadcastable (x:: RaggedRange ) = Ref (x)
566578
567579@inline function _is_ragged_dim (VA:: AbstractVectorOfArray , d:: Integer )
@@ -579,6 +591,12 @@ Base.@propagate_inbounds function _getindex(
579591 return A. u[I]
580592end
581593
594+ Base. @propagate_inbounds function _getindex (
595+ A:: AbstractDiffEqArray , :: NotSymbolic , :: Colon , I:: Int
596+ )
597+ return A. u[I]
598+ end
599+
582600Base. @propagate_inbounds function _getindex (
583601 A:: AbstractVectorOfArray , :: NotSymbolic ,
584602 I:: Union{Int, AbstractArray{Int}, AbstractArray{Bool}, Colon} ...
@@ -589,6 +607,33 @@ Base.@propagate_inbounds function _getindex(
589607 stack (getindex .(A. u[last (I)], tuple .(Base. front (I))... ))
590608 end
591609end
610+
611+ Base. @propagate_inbounds function _getindex (
612+ A:: AbstractDiffEqArray , :: NotSymbolic ,
613+ I:: Union{Int, AbstractArray{Int}, AbstractArray{Bool}, Colon} ...
614+ )
615+ return if last (I) isa Int
616+ A. u[last (I)][Base. front (I)... ]
617+ else
618+ col_idxs = last (I)
619+ # Only preserve DiffEqArray type if all prefix indices are Colons (selecting whole inner arrays)
620+ if all (idx -> idx isa Colon, Base. front (I))
621+ # For Colon, select all columns
622+ if col_idxs isa Colon
623+ col_idxs = eachindex (A. u)
624+ end
625+ # For DiffEqArray, we need to preserve the time values and type
626+ # Create a vector of sliced arrays instead of stacking into higher-dim array
627+ u_slice = [A. u[col][Base. front (I)... ] for col in col_idxs]
628+ # Return as DiffEqArray with sliced time values
629+ return DiffEqArray (u_slice, A. t[col_idxs], parameter_values (A), symbolic_container (A))
630+ else
631+ # Prefix indices are not all Colons - do the same as VectorOfArray
632+ # (stack the results into a higher-dimensional array)
633+ return stack (getindex .(A. u[col_idxs], tuple .(Base. front (I))... ))
634+ end
635+ end
636+ end
592637Base. @propagate_inbounds function _getindex (
593638 VA:: AbstractVectorOfArray , :: NotSymbolic , ii:: CartesianIndex
594639 )
674719 return idx. dim == 0 ? idx. offset : idx
675720end
676721
722+ @inline function _column_indices (VA:: AbstractVectorOfArray , idx:: RaggedRange )
723+ # RaggedRange with dim=0 means it's a column range with pre-resolved indices
724+ if idx. dim == 0
725+ # Create a range with the offset as the stop value
726+ return Base. range (idx. start; step = idx. step, stop = idx. offset)
727+ else
728+ # dim != 0 means it's an inner-dimension range that needs column expansion
729+ return idx
730+ end
731+ end
732+
677733@inline _resolve_ragged_index (idx, :: AbstractVectorOfArray , :: Any ) = idx
678734@inline function _resolve_ragged_index (idx:: RaggedEnd , VA:: AbstractVectorOfArray , col)
679735 if idx. dim == 0
@@ -757,27 +813,54 @@ end
757813 return (Base. front (args)... , resolved_last)
758814 end
759815 elseif args[end ] isa RaggedRange
760- resolved_last = _resolve_ragged_index (args[end ], A, 1 )
761- if length (args) == 1
762- return (resolved_last,)
816+ # Only pre-resolve if it's an inner-dimension range (dim != 0)
817+ # Column ranges (dim == 0) are handled later by _column_indices
818+ if args[end ]. dim == 0
819+ # Column range - let _column_indices handle it
820+ return args
763821 else
764- return (Base. front (args)... , resolved_last)
822+ resolved_last = _resolve_ragged_index (args[end ], A, 1 )
823+ if length (args) == 1
824+ return (resolved_last,)
825+ else
826+ return (Base. front (args)... , resolved_last)
827+ end
765828 end
766829 end
767830 return args
768831end
769832
833+ # Helper function to preserve DiffEqArray type when slicing
834+ @inline function _preserve_array_type (A:: AbstractVectorOfArray , u_slice, col_idxs)
835+ return VectorOfArray (u_slice)
836+ end
837+
838+ @inline function _preserve_array_type (A:: AbstractDiffEqArray , u_slice, col_idxs)
839+ return DiffEqArray (u_slice, A. t[col_idxs], parameter_values (A), symbolic_container (A))
840+ end
841+
770842@inline function _ragged_getindex (A:: AbstractVectorOfArray , I... )
771843 n = ndims (A)
772844 # Special-case when user provided one fewer index than ndims(A): last index is column selector.
773845 if length (I) == n - 1
774846 raw_cols = last (I)
847+ # Determine if we're doing column selection (preserve type) or inner-dimension selection (don't preserve)
848+ is_column_selection = if raw_cols isa RaggedEnd && raw_cols. dim != 0
849+ false # Inner dimension - don't preserve type
850+ elseif raw_cols isa RaggedRange && raw_cols. dim != 0
851+ true # Inner dimension range converted to column range - DO preserve type
852+ else
853+ true # Column selection (dim == 0 or not ragged)
854+ end
855+
775856 # If the raw selector is a RaggedEnd/RaggedRange referring to inner dims, reinterpret as column selector.
776857 cols = if raw_cols isa RaggedEnd && raw_cols. dim != 0
777858 lastindex (A. u) + raw_cols. offset
778859 elseif raw_cols isa RaggedRange && raw_cols. dim != 0
860+ # Convert inner-dimension range to column range by resolving bounds
861+ start_val = raw_cols. start < 0 ? lastindex (A. u) + raw_cols. start : raw_cols. start
779862 stop_val = lastindex (A. u) + raw_cols. offset
780- Base. range (raw_cols . start ; step = raw_cols. step, stop = stop_val)
863+ Base. range (start_val ; step = raw_cols. step, stop = stop_val)
781864 else
782865 _column_indices (A, raw_cols)
783866 end
@@ -800,37 +883,41 @@ end
800883 end
801884 return A. u[cols][padded... ]
802885 else
803- return VectorOfArray (
804- [
805- begin
806- resolved_prefix = _resolve_ragged_indices (prefix, A, col)
807- inner_nd = ndims (A. u[col])
808- n_missing = inner_nd - length (resolved_prefix)
809- padded = if n_missing > 0
810- if all (idx -> idx === Colon (), resolved_prefix)
811- (
812- resolved_prefix... ,
813- ntuple (_ -> Colon (), n_missing)... ,
814- )
815- else
816- (
817- resolved_prefix... ,
818- (
819- lastindex (
820- A. u[col],
821- length (resolved_prefix) + i
822- ) for i in 1 : n_missing
823- ). .. ,
824- )
825- end
886+ u_slice = [
887+ begin
888+ resolved_prefix = _resolve_ragged_indices (prefix, A, col)
889+ inner_nd = ndims (A. u[col])
890+ n_missing = inner_nd - length (resolved_prefix)
891+ padded = if n_missing > 0
892+ if all (idx -> idx === Colon (), resolved_prefix)
893+ (
894+ resolved_prefix... ,
895+ ntuple (_ -> Colon (), n_missing)... ,
896+ )
826897 else
827- resolved_prefix
828- end
829- A. u[col][padded... ]
898+ (
899+ resolved_prefix... ,
900+ (
901+ lastindex (
902+ A. u[col],
903+ length (resolved_prefix) + i
904+ ) for i in 1 : n_missing
905+ ). .. ,
906+ )
830907 end
831- for col in cols
832- ]
833- )
908+ else
909+ resolved_prefix
910+ end
911+ A. u[col][padded... ]
912+ end
913+ for col in cols
914+ ]
915+ # Only preserve DiffEqArray type if we're selecting actual columns, not inner dimensions
916+ if is_column_selection
917+ return _preserve_array_type (A, u_slice, cols)
918+ else
919+ return VectorOfArray (u_slice)
920+ end
834921 end
835922 end
836923
864951 if col_idxs isa Int
865952 return A. u[col_idxs]
866953 else
867- return VectorOfArray (A . u[col_idxs])
954+ return _preserve_array_type (A, A . u[col_idxs], col_idxs )
868955 end
869956 end
870957 # If col_idxs resolved to a single Int, handle it directly
0 commit comments