Skip to content

Commit 1978380

Browse files
committed
Add content to readme and add tests for examples
1 parent c9257a5 commit 1978380

File tree

4 files changed

+215
-2
lines changed

4 files changed

+215
-2
lines changed

README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,147 @@
33
[![Build Status](https://travis-ci.com/oschulz/ArraysOfArrays.jl.svg?branch=master)](https://travis-ci.com/oschulz/ArraysOfArrays.jl)
44
[![Build Status](https://ci.appveyor.com/api/projects/status/github/oschulz/ArraysOfArrays.jl?branch=master&svg=true)](https://ci.appveyor.com/project/oschulz/ArraysOfArrays-jl)
55
[![Codecov](https://codecov.io/gh/oschulz/ArraysOfArrays.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/oschulz/ArraysOfArrays.jl)
6+
7+
8+
A Julia package for efficient storage of nested arrays.
9+
10+
ArraysOfArrays provides two different types of nested arrays: `ArrayOfSimilarArrays` and `VectorOfArrays`.
11+
12+
13+
## ArrayOfSimilarArrays
14+
15+
An `ArrayOfSimilarArrays` offers duality of viewing the same data as both a flat multi-dimensional array and as an array of equally-sized arrays.
16+
17+
```julia
18+
A_flat = rand(2,3,4,5,6)
19+
A_nested = nestedview(A_flat, 2)
20+
```
21+
22+
creates a view of `A_flat` as an array of arrays:
23+
24+
```julia
25+
A_nested isa AbstractArray{<:AbstractArray{T,2},3} where T
26+
```
27+
28+
`A_flat` is always available via `flatview`. `A_flat` and `A_nested` are backed by the same data, no data is copied:
29+
30+
```julia
31+
flatview(A_nested) === A_flat
32+
```
33+
34+
Calling `getindex` on `A_nested` returns a view into `A_flat`:
35+
36+
```julia
37+
fill!(A_nested[2, 4, 3], 4.2)
38+
all(x -> x == 4.2, A_flat[:, :, 2, 4, 3])
39+
```
40+
41+
### Type aliases
42+
43+
The following type aliases are defined:
44+
45+
* `VectorOfSimilarArrays{T,M} = AbstractArrayOfSimilarArrays{T,M,1}`
46+
* `ArrayOfSimilarVectors{T,N} = AbstractArrayOfSimilarArrays{T,1,N}`
47+
* `VectorOfSimilarVectors{T} = AbstractArrayOfSimilarArrays{T,1,1}`
48+
49+
For each of the types there is also an abstract type (`AbstractArrayOfSimilarArrays`, etc.).
50+
51+
If a `VectorOfSimilarArrays` is backed by an `ElasticArrays.ElasticArray`, additional element arrays can be pushed into it and `resize!` is available too:
52+
53+
### Appending data and resizing
54+
55+
```julia
56+
using ElasticArrays
57+
58+
A_nested = nestedview(ElasticArray{Float64}(undef, 2, 3, 0), 2)
59+
60+
for i in 1:4
61+
push!(A_nested, rand(2, 3))
62+
end
63+
size(flatview(A_nested)) == (2, 3, 4)
64+
65+
resize!(A_nested, 6)
66+
size(flatview(A_nested)) == (2, 3, 6)
67+
```
68+
69+
There is a full duality between the nested and the flat view of the data. `A_flat` may be resized freely without breaking the inner consistency of `A_nested`: Changes in the shape of one will result in changes in the shape of the other.
70+
71+
72+
## VectorOfArrays
73+
74+
A `VectorOfArrays` represents a vector of arrays of equal dimensionality but different size. It is a nested interpretation of the concept of a "ragged array".
75+
76+
```julia
77+
VA = VectorOfArrays{Float64, 2}()
78+
79+
push!(VA, rand(2, 3))
80+
push!(VA, rand(4, 2))
81+
82+
size(VA[1]) == (2,3)
83+
size(VA[2]) == (4,2)
84+
```
85+
86+
Internally, all data is stored efficiently in a single, flat and memory-contiguous vector, accessible via `flatview`:
87+
88+
```julia
89+
VA_flat = flatview(VA)
90+
VA_flat isa Vector{Float64}
91+
```
92+
93+
Calling `getindex` on `A_nested` returns a view into `A_flat`:
94+
95+
```julia
96+
VA_flat = flatview(VA)
97+
view(VA_flat, 7:14) == vec(VA[2])
98+
99+
fill!(view(VA_flat, 7:14), 2.4)
100+
all(x -> x == 2.4, VA[2])
101+
102+
fill!(view(VA_flat, 7:14), 4.2)
103+
all(x -> x == 4.2, VA[2])
104+
```
105+
106+
### Type aliases
107+
The following type aliases are defined:
108+
109+
* `VectorOfVectors{T,VT,VI,VD} = VectorOfArrays{T,1,VT,VI,VD}`
110+
111+
### Appending data and resizing
112+
113+
A `VectorOfArrays` is grown by appending data to it. `resize!` can be used to shrink it, but not to grow it (the size of the additional element arrays would be unknown):
114+
115+
```
116+
length(resize!(VA, 1)) == 1
117+
```
118+
119+
but
120+
121+
```
122+
resize!(VA, 4)
123+
```
124+
125+
will fail.
126+
127+
Note: The vector returned by `flatview(VA)` *must not* be resized directly, doing so would break the internal consistency of `VA`.
128+
129+
130+
## Allocation free element access
131+
132+
Element access via `getindex` returns (possibly reshaped) instances of `SubArray` for both `ArrayOfSimilarArrays` and `VectorOfArrays`. Usually this is not a problem, but frequent allocation of a large number of views can become a limiting factor in multi-threaded applications.
133+
134+
Both types support `UnsafeArrays.@uviews` for allocation-free getindex:
135+
136+
```julia
137+
using UnsafeArrays
138+
139+
A = nestedview(rand(2,3,4,5), 2)
140+
141+
isbits(A[2,2]) == false
142+
143+
@uviews A begin
144+
isbits(A[2,2]) == true
145+
end
146+
```
147+
148+
As always, `UnsafeArray`s should be used with great care: The pointer-based bitstype
149+
views *must not* be allowed to escape the `@uviews` scope, and internal data of `A` *must not* be reallocated (e.g. due to a `push!` or `append!` on `A`) while the `@uviews` scope is active.

test/array_of_similar_arrays.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,20 @@ using UnsafeArrays
113113
@testset "examples" begin
114114
A_flat = rand(2,3,4,5,6)
115115
A_nested = nestedview(A_flat, 2)
116-
A_nested isa AbstractArray{<:AbstractArray{T,2},3} where T
117-
flatview(A_nested) === A_flat
116+
@test A_nested isa AbstractArray{<:AbstractArray{T,2},3} where T
117+
@test flatview(A_nested) === A_flat
118+
119+
# -------------------------------------------------------------------
120+
121+
A_nested = nestedview(ElasticArray{Float64}(undef, 2, 3, 0), 2)
122+
123+
for i in 1:4
124+
push!(A_nested, rand(2, 3))
125+
end
126+
@test size(flatview(A_nested)) == (2, 3, 4)
127+
128+
resize!(A_nested, 6)
129+
@test size(flatview(A_nested)) == (2, 3, 6)
130+
118131
end
119132
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ using Test
44

55
Test.@testset "Package ArraysOfArrays" begin
66
include("array_of_similar_arrays.jl")
7+
include("vector_of_arrays.jl")
78
end

test/vector_of_arrays.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# This file is a part of ArraysOfArrays.jl, licensed under the MIT License (MIT).
2+
3+
using ArraysOfArrays
4+
using Test
5+
6+
using UnsafeArrays
7+
8+
9+
@testset "vector_of_arrays" begin
10+
@testset "examples" begin
11+
VA = VectorOfArrays{Float64, 2}()
12+
13+
push!(VA, rand(2, 3))
14+
push!(VA, rand(4, 2))
15+
16+
@test size(VA[1]) == (2,3)
17+
@test size(VA[2]) == (4,2)
18+
19+
# -------------------------------------------------------------------
20+
21+
22+
VA_flat = flatview(VA)
23+
@test VA_flat isa Vector{Float64}
24+
25+
# -------------------------------------------------------------------
26+
27+
28+
VA_flat = flatview(VA)
29+
@test view(VA_flat, 7:14) == vec(VA[2])
30+
31+
fill!(view(VA_flat, 7:14), 2.4)
32+
@test all(x -> x == 2.4, VA[2])
33+
34+
fill!(view(VA_flat, 7:14), 4.2)
35+
@test all(x -> x == 4.2, VA[2])
36+
37+
# -------------------------------------------------------------------
38+
39+
40+
@test length(@inferred resize!(VA, 1)) == 1
41+
@test_throws ArgumentError resize!(VA, 4)
42+
43+
# -------------------------------------------------------------------
44+
45+
using UnsafeArrays
46+
47+
A = nestedview(rand(2,3,4,5), 2)
48+
49+
@test isbits(A[2,2]) == false
50+
51+
@test @uviews A begin
52+
isbits(A[2,2]) == true
53+
end
54+
end
55+
end

0 commit comments

Comments
 (0)