Skip to content

Commit

Permalink
feat: many methods for PrimitiveArray and ListOffsetArray (#2)
Browse files Browse the repository at this point in the history
* Implemented a type and overrode a Base function for it.

* Implemented most methods for PrimitiveArray and ListOffsetArray.

* ListOffsetArray's is_valid.

* Some tweaks.

* More robust is_valid(::ListOffsetArray).

* Concrete types no longer contain abstract-typed fields.

* Rename x/y -> layout.

* Empty constructors and appending methods.

* Done for now.
  • Loading branch information
jpivarski authored Aug 9, 2023
1 parent 8a3651a commit 1903e04
Show file tree
Hide file tree
Showing 2 changed files with 245 additions and 2 deletions.
144 changes: 143 additions & 1 deletion src/AwkwardArray.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,147 @@
module AwkwardArray

# Write your package code here.
### Index ################################################################

Index8 = AbstractArray{Int8,1}
IndexU8 = AbstractArray{UInt8,1}
Index32 = AbstractArray{Int32,1}
IndexU32 = AbstractArray{UInt32,1}
Index64 = AbstractArray{Int64,1}
IndexBig = Union{Index32,IndexU32,Index64}

### Content ##############################################################

abstract type Content <: AbstractArray{T where T,1} end

function Base.iterate(layout::Content)
start = firstindex(layout)
stop = lastindex(layout)
if stop >= start
layout[start], start + 1
else
nothing
end
end

function Base.iterate(layout::Content, state)
stop = lastindex(layout)
if stop >= state
layout[state], state + 1
else
nothing
end
end

function Base.size(layout::Content)
(length(layout),)
end

### PrimitiveArray #######################################################

struct PrimitiveArray{T,ARRAY<:AbstractArray{T,1}} <: Content
data::ARRAY
end

function PrimitiveArray{T}() where {T}
PrimitiveArray(Vector{T}([]))
end

function is_valid(layout::PrimitiveArray)
true
end

function Base.length(layout::PrimitiveArray)
length(layout.data)
end

function Base.firstindex(layout::PrimitiveArray)
firstindex(layout.data)
end

function Base.lastindex(layout::PrimitiveArray)
lastindex(layout.data)
end

function Base.getindex(layout::PrimitiveArray, i::Int)
layout.data[i]
end

function Base.getindex(layout::PrimitiveArray, r::UnitRange{Int})
PrimitiveArray(layout.data[r])
end

function Base.:(==)(layout1::PrimitiveArray, layout2::PrimitiveArray)
layout1.data == layout2.data
end

function push!(layout::PrimitiveArray{T}, x::T) where {T}
Base.push!(layout.data, x)
end

### ListOffsetArray ######################################################

struct ListOffsetArray{INDEX<:IndexBig,CONTENT<:Content} <: Content
offsets::INDEX
content::CONTENT
end

function ListOffsetArray{INDEX,CONTENT}() where {INDEX<:IndexBig} where {CONTENT<:Content}
AwkwardArray.ListOffsetArray(INDEX([0]), CONTENT())
end

function is_valid(layout::ListOffsetArray)
if length(layout.offsets) < 1
return false
end
if layout.offsets[end] + firstindex(layout.content) - 1 > lastindex(layout.content)
return false
end
for i in eachindex(layout)
if layout.offsets[i] < 0 || layout.offsets[i+1] < layout.offsets[i]
return false
end
end
return true
end

function Base.length(layout::ListOffsetArray)
length(layout.offsets) - 1
end

function Base.firstindex(layout::ListOffsetArray)
firstindex(layout.offsets)
end

function Base.lastindex(layout::ListOffsetArray)
lastindex(layout.offsets) - 1
end

function Base.getindex(layout::ListOffsetArray, i::Int)
start = layout.offsets[i] + firstindex(layout.content)
stop = layout.offsets[i+1] + firstindex(layout.content) - 1
layout.content[start:stop]
end

function Base.getindex(layout::ListOffsetArray, r::UnitRange{Int})
ListOffsetArray(layout.offsets[(r.start):(r.stop+1)], layout.content)
end

function Base.:(==)(layout1::ListOffsetArray, layout2::ListOffsetArray)
if length(layout1) != length(layout2)
return false
else
for (x, y) in zip(layout1, layout2)
if x != y
return false
end
end
return true
end
end

function end_list!(layout::ListOffsetArray)
Base.push!(layout.offsets, length(layout.content))
layout.content
end

end
103 changes: 102 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,106 @@ using AwkwardArray
using Test

@testset "AwkwardArray.jl" begin
# Write your tests here.
begin
layout = AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5])
@test AwkwardArray.is_valid(layout)
@test length(layout) == 5
@test layout[2] == 2.2
@test layout[end] == 5.5
@test layout[end-1] == 4.4
@test layout[2:4] == AwkwardArray.PrimitiveArray([2.2, 3.3, 4.4])
tmp = 0.0
for x in layout
@test x < 6
tmp += x
end
@test tmp == 16.5
end

begin
layout = AwkwardArray.PrimitiveArray{Float64}()
@test length(layout) == 0
AwkwardArray.push!(layout, 1.1)
@test length(layout) == 1
AwkwardArray.push!(layout, 2.2)
@test length(layout) == 2
AwkwardArray.push!(layout, 3.3)
@test length(layout) == 3
AwkwardArray.push!(layout, 4.4)
@test length(layout) == 4
AwkwardArray.push!(layout, 5.5)
@test length(layout) == 5
@test layout == AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5])
end

begin
layout = AwkwardArray.ListOffsetArray(
[0, 3, 3, 5],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5]),
)
@test AwkwardArray.is_valid(layout)
@test length(layout) == 3
@test layout[1] == AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3])
@test layout[end-1] == AwkwardArray.PrimitiveArray([])
@test layout[end] == AwkwardArray.PrimitiveArray([4.4, 5.5])
@test layout[1:2] == AwkwardArray.ListOffsetArray(
[0, 3, 3],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3]),
)
tmp = 0
for x in layout
@test length(x) <= 3
tmp += length(x)
end
@test tmp == 5
end

begin
layout = AwkwardArray.ListOffsetArray(
[0, 3, 2, 5],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5]),
)
@test !AwkwardArray.is_valid(layout)
end

begin
layout = AwkwardArray.ListOffsetArray(
[0, 3, 3, 6],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5]),
)
@test !AwkwardArray.is_valid(layout)
end

begin
layout = AwkwardArray.ListOffsetArray(
[-1, 3, 3, 5],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5]),
)
@test !AwkwardArray.is_valid(layout)
end

begin
layout = AwkwardArray.ListOffsetArray{
AwkwardArray.Index64,
AwkwardArray.PrimitiveArray{Float64},
}()
sublayout = layout.content
@test length(layout) == 0
AwkwardArray.push!(sublayout, 1.1)
AwkwardArray.push!(sublayout, 2.2)
AwkwardArray.push!(sublayout, 3.3)
AwkwardArray.end_list!(layout)
@test length(layout) == 1
AwkwardArray.end_list!(layout)
@test length(layout) == 2
AwkwardArray.push!(sublayout, 4.4)
AwkwardArray.push!(sublayout, 5.5)
AwkwardArray.end_list!(layout)
@test length(layout) == 3
@test layout == AwkwardArray.ListOffsetArray(
[0, 3, 3, 5],
AwkwardArray.PrimitiveArray([1.1, 2.2, 3.3, 4.4, 5.5]),
)
end

end

0 comments on commit 1903e04

Please sign in to comment.