forked from JuliaIO/DiskArrays.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreshape.jl
More file actions
104 lines (91 loc) · 3.2 KB
/
reshape.jl
File metadata and controls
104 lines (91 loc) · 3.2 KB
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
import Base: _throw_dmrs
"""
AbstractReshapedDiskArray <: AbstractDiskArray
Abstract supertype for a replacements of `Base.ReshapedArray` for `AbstractDiskArray`s`
"""
abstract type AbstractReshapedDiskArray{T,N,P,M} <: AbstractDiskArray{T,N} end
"""
ReshapedDiskArray <: AbstractReshapedDiskArray
A replacement for `Base.ReshapedArray` for disk arrays,
returned by `reshape`.
Reshaping is really not trivial, because the access pattern would
completely change for reshaped arrays, rectangles would not remain
rectangles in the parent array.
However, we can support the case where only singleton dimensions are added,
later we could allow more special cases like joining two dimensions to one
"""
struct ReshapedDiskArray{T,N,P<:AbstractArray{T},M} <: AbstractReshapedDiskArray{T,N,P,M}
parent::P
keepdim::NTuple{M,Int}
newsize::NTuple{N,Int}
end
# Base methods
Base.size(r::AbstractReshapedDiskArray) = r.newsize
Base.parent(r::AbstractReshapedDiskArray) = r.parent
keepdim(r::AbstractReshapedDiskArray) = r.keepdim
# DiskArrays interface
haschunks(a::AbstractReshapedDiskArray) = haschunks(parent(a))
function eachchunk(a::AbstractReshapedDiskArray{<:Any,N}) where {N}
pchunks = eachchunk(parent(a))
inow::Int = 0
outchunks = ntuple(N) do idim
if in(idim, keepdim(a))
inow += 1
pchunks.chunks[inow]
else
RegularChunks(1, 0, size(a, idim))
end
end
return GridChunks(outchunks...)
end
function DiskArrays.readblock!(a::AbstractReshapedDiskArray, aout, i::OrdinalRange...)
inew = tuple_tuple_getindex(i, keepdim(a))
DiskArrays.readblock!(parent(a), reshape(aout, map(length, inew)), inew...)
return nothing
end
function DiskArrays.writeblock!(a::AbstractReshapedDiskArray, v, i::OrdinalRange...)
inew = tuple_tuple_getindex(i, keepdim(a))
DiskArrays.writeblock!(parent(a), reshape(v, map(length, inew)), inew...)
return nothing
end
function reshape_disk(parent, dims)
n = length(parent)
ndims(parent) > length(dims) &&
error("For DiskArrays, reshape is restricted to adding singleton dimensions")
prod(dims) == n || _throw_dmrs(n, "size", dims)
ipassed::Int = 0
keepdim = map(size(parent)) do s
while true
ipassed += 1
d = dims[ipassed]
if d > 1
d != s && error(
"For DiskArrays, reshape is restricted to adding singleton dimensions",
)
return ipassed
else
# For existing trailing 1s
d == s == 1 && return ipassed
end
end
end
return ReshapedDiskArray{eltype(parent),length(dims),typeof(parent),ndims(parent)}(
parent, keepdim, dims
)
end
tuple_tuple_getindex(t, i) = _ttgi((), t, i...)
_ttgi(o, t, i1, irest...) = _ttgi((o..., t[i1]), t, irest...)
_ttgi(o, t, i1) = (o..., t[i1])
# Implementaion macro
macro implement_reshape(t)
t = esc(t)
quote
function Base._reshape(A::$t, dims::NTuple{N,Int}) where {N}
return reshape_disk(A, dims)
end
end
end
# For ambiguity
function Base._reshape(A::AbstractDiskArray{<:Any,1}, dims::Tuple{Int64})
return reshape_disk(A, dims)
end