-
Notifications
You must be signed in to change notification settings - Fork 98
/
CompressedArrays.jl
111 lines (94 loc) · 2.74 KB
/
CompressedArrays.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""
struct CompressedArray{T,N,A,P} <: AbstractArray{T,N}
values::A
ptrs::P
end
Type representing an array with a reduced set of values.
The array is represented by a short array of values, namely
the field `values`, and a large array of indices, namely the
field `ptrs`. The `i`-th component of the resulting array is
defined as `values[ptrs[i]]`. The type parameters `A`, and `P`
are restricted to be array types by the inner constructor of this `struct`.
"""
struct CompressedArray{T,N,A,P} <: AbstractArray{T,N}
values::A
ptrs::P
@doc """
CompressedArray(values::AbstractArray,ptrs::AbstractArray)
Creates a `CompressedArray` object by the given arrays of `values` and
`ptrs`.
"""
function CompressedArray(values::AbstractArray,ptrs::AbstractArray)
A = typeof(values)
P = typeof(ptrs)
T = eltype(values)
N = ndims(ptrs)
new{T,N,A,P}(values,ptrs)
end
end
function testitem(a::CompressedArray)
if length(a.ptrs) == 0
testitem(a.values)
else
a.values[first(a.ptrs)]
end
end
size(a::CompressedArray) = size(a.ptrs)
@propagate_inbounds function getindex(a::CompressedArray,i::Integer)
j = a.ptrs[i]
a.values[j]
end
@propagate_inbounds function getindex(a::CompressedArray{T,N},i::Vararg{Integer,N}) where {T,N}
j = a.ptrs[i...]
a.values[j]
end
function IndexStyle(a::Type{CompressedArray{T,N,A,P}}) where {T,N,A,P}
IndexStyle(P)
end
function lazy_map(::typeof(evaluate),::Type{T},g::CompressedArray...) where T
if _have_same_ptrs(g)
_lazy_map_compressed(g...)
else
LazyArray(T,g...)
end
end
function lazy_map(::typeof(evaluate),::Type{T},g::Union{CompressedArray,Fill}...) where T
g_compressed = _find_compressed_ones(g)
if _have_same_ptrs(g_compressed)
g1 = first(g_compressed)
g_all_compressed = map(gi->_compress(gi,g1),g)
_lazy_map_compressed(g_all_compressed...)
else
LazyArray(T,g...)
end
end
function _find_compressed_ones(g)
g_compressed = ( gi for gi in g if isa(gi,CompressedArray) )
g_compressed
end
function _lazy_map_compressed(g::CompressedArray...)
vals = map(evaluate, map(gi->gi.values,g)...)
ptrs = first(g).ptrs
CompressedArray(vals,ptrs)
end
function _have_same_ptrs(g)
g1 = first(g)
all(map( gi -> gi.ptrs === g1.ptrs || gi.ptrs == g1.ptrs, g))
end
function _compress(a::CompressedArray,b::CompressedArray)
@check _have_same_ptrs((a,b))
a
end
function _compress(a::Fill,b::CompressedArray)
vals = fill(a.value,length(b.values))
CompressedArray(vals,b.ptrs)
end
function same_branch(a::CompressedArray,b::CompressedArray)
a.ptrs === b.ptrs && a.values == b.values
end
function Base.unique(a::CompressedArray)
unique(a.values)
end
function Base.view(a::CompressedArray,ids)
CompressedArray(a.values,view(a.ptrs,ids))
end