@@ -112,8 +112,36 @@ size(a::Array{<:Any,N}) where {N} = (@_inline_meta; ntuple(M -> size(a, M), Val(
112
112
113
113
asize_from (a:: Array , n) = n > ndims (a) ? () : (arraysize (a,n), asize_from (a, n+ 1 )... )
114
114
115
+ """
116
+ Base.isbitsunion(::Type{T})
117
+
118
+ Return whether a type is an "is-bits" Union type, meaning each type included in a Union is `isbits`.
119
+ """
120
+ function isbitsunion end
121
+
122
+ function isbitsunion (U:: Union )
123
+ for u in Base. uniontypes (U)
124
+ isbits (u) || return false
125
+ end
126
+ return true
127
+ end
128
+ isbitsunion (T) = false
129
+
130
+ """
131
+ Base.bitsunionsize(U::Union)
132
+
133
+ For a Union of `isbits` types, return the size of the largest type.
134
+ """
135
+ function bitsunionsize (U:: Union )
136
+ sz = 0
137
+ for u in Base. uniontypes (U)
138
+ sz = max (sz, sizeof (u))
139
+ end
140
+ return sz
141
+ end
142
+
115
143
length (a:: Array ) = arraylen (a)
116
- elsize (a:: Array{T} ) where {T} = isbits (T) ? sizeof (T) : sizeof (Ptr)
144
+ elsize (a:: Array{T} ) where {T} = isbits (T) ? sizeof (T) : ( isbitsunion (T) ? bitsunionsize (T) : sizeof (Ptr) )
117
145
sizeof (a:: Array ) = Core. sizeof (a)
118
146
119
147
function isassigned (a:: Array , i:: Int... )
@@ -123,6 +151,19 @@ function isassigned(a::Array, i::Int...)
123
151
ccall (:jl_array_isassigned , Cint, (Any, UInt), a, ii) == 1
124
152
end
125
153
154
+ """
155
+ Base.selectorbytes(A::Array{T, N}) -> Array{UInt8, N}
156
+
157
+ For an Array with `isbits` Union elements, return the "selector bytes" that indicate the index
158
+ of the type for each array element, i.e. the type of `A[1]` is `Base.uniontypes(eltype(A))[Base.selectorbytes(A)[1] + 1]`.
159
+ **NOTE**: The actual array selector bytes are returned, meaning if individual elements are modified, the original array will reflect those changes.
160
+ Setting selector bytes to invalid or out-of-bounds type indexes may corrupt the original array.
161
+ """
162
+ function selectorbytes (a:: Array{T, N} ) where {T, N}
163
+ isbitsunion (T) || return UInt8[]
164
+ return unsafe_wrap (Array{UInt8, N}, convert (Ptr{UInt8}, pointer (a)) + length (a) * elsize (a), size (a))
165
+ end
166
+
126
167
# # copy ##
127
168
128
169
function unsafe_copy! (dest:: Ptr{T} , src:: Ptr{T} , n) where T
@@ -157,7 +198,7 @@ copy!(dest::Array{T}, src::Array{T}) where {T} = copy!(dest, 1, src, 1, length(s
157
198
copy (a:: T ) where {T<: Array } = ccall (:jl_array_copy , Ref{T}, (Any,), a)
158
199
159
200
function reinterpret (:: Type{T} , a:: Array{S,1} ) where T where S
160
- nel = Int (div (length (a)* sizeof (S),sizeof (T)))
201
+ nel = Int (div (length (a) * sizeof (S), sizeof (T)))
161
202
# TODO : maybe check that remainder is zero?
162
203
return reinterpret (T, a, (nel,))
163
204
end
@@ -176,7 +217,7 @@ function reinterpret(::Type{T}, a::Array{S}, dims::NTuple{N,Int}) where T where
176
217
end
177
218
isbits (T) || throwbits (S, T, T)
178
219
isbits (S) || throwbits (S, T, S)
179
- nel = div (length (a)* sizeof (S),sizeof (T))
220
+ nel = div (length (a) * sizeof (S), sizeof (T))
180
221
if prod (dims) != nel
181
222
_throw_dmrsa (dims, nel)
182
223
end
0 commit comments