Skip to content

Commit 5fd95b1

Browse files
oscardssmithnsajko
authored andcommitted
reorganize slightly and add FixedSizeBitArray
1 parent 810c0a0 commit 5fd95b1

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/FixedSizeArrays.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module FixedSizeArrays
22

33
include("FixedSizeArray.jl")
4+
include("FixedSizeBitArray.jl")
45

56
if isdefined(Base, :dataids) && (Base.dataids isa Function)
67
# This is an internal, non-public function which is nevertheless needed to

src/FixedSizeBitArray.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#unlike Base.BitArray, each column gets it's own chunk.
2+
function num_bit_chunks(size::NTuple{N,Int}) where {N}
3+
prod(size[1:end-1]) * ((size[end]+63) >> 6)
4+
end
5+
6+
struct FixedSizeBitArray{N} <: AbstractArray{Bool,N}
7+
chunks::Memory{UInt64}
8+
size::NTuple{N,Int}
9+
10+
function FixedSizeBitArray{N}(::Internal, size::NTuple{N,Int}) where {N}
11+
nc = num_bit_chunks(size)
12+
chunks = Memory{UInt64}(undef, nc)
13+
# we want the last chunks to be zerod and it's easier to just zero all of them
14+
copyto!(chunks UInt64(0))
15+
new{N}(chunks, size)
16+
end
17+
end
18+
19+
const FixedSizeBitVector = FixedSizeBitArray{1}
20+
const FixedSizeBitMatrix = FixedSizeBitArray{2}
21+
22+
23+
function FixedSizeBitArray{N}(::UndefInitializer, size::NTuple{N,Int}) where {N}
24+
checked_dims(size)
25+
FixedSizeBitArray{N}(Internal(), size)
26+
end
27+
function FixedSizeBitArray{N}(::UndefInitializer, size::NTuple{N,Integer}) where {N}
28+
size = map(Int, size)::NTuple{N,Int} # prevent infinite recursion
29+
FixedSizeBitArray{N}(undef, size)
30+
end
31+
function FixedSizeBitArray{N}(::UndefInitializer, size::Vararg{Integer,N}) where {N}
32+
FixedSizeBitArray{N}(undef, size)
33+
end
34+
function FixedSizeBitArray(::UndefInitializer, size::NTuple{N,Integer}) where {N}
35+
FixedSizeBitArray{N}(undef, size)
36+
end
37+
function FixedSizeBitArray(::UndefInitializer, size::Vararg{Integer,N}) where {N}
38+
FixedSizeBitArray{N}(undef, size)
39+
end
40+
41+
Base.IndexStyle(::Type{<:FixedSizeBitArray}) = IndexCartesian()
42+
43+
function get_chunks_id(inds::NTuple{N,Int}) where {N}
44+
prod(inds[1:end-1])+(inds[end] >> 6), inds[end] & 63
45+
end
46+
47+
Base.@propagate_inbounds function Base.getindex(A::FixedSizeBitArray{N}, inds::Vararg{Int, N}) where {N}
48+
@boundscheck checkbounds(A, inds...)
49+
i1, i2 = get_chunks_id(inds)
50+
u = UInt64(1) << i2
51+
@inbounds r = (A.chunks[i1] & u) != 0
52+
return r
53+
54+
end
55+
Base.@propagate_inbounds Base.@assume_effects :noub_if_noinbounds function Base.setindex!(A::FixedSizeBitArray{N}, x, inds::Vararg{Int, N}) where {N}
56+
@boundscheck checkbounds(A, inds...)
57+
i1, i2 = get_chunks_id(inds)
58+
u = UInt64(1) << i2
59+
@inbounds begin
60+
c = A.chunks[i1]
61+
A.chunks[i1] = ifelse(x, c | u, c & ~u)
62+
end
63+
return A
64+
end
65+
66+
Base.size(a::FixedSizeBitArray) = a.size
67+
Base.isassigned(a::FixedSizeBitArray, i::Int) = 1 <= i <= length(a)
68+
function Base.fill!(B::FixedSizeBitArray, x)
69+
y = convert(Bool, x)::Bool
70+
fill!(B.chunks, UInt64(0)-y)
71+
# TODO zero partially filled chunks
72+
return B
73+
end
74+
75+
function (==)(A::FixedSizeBitArray, B::FixedSizeBitArray)
76+
size(A) != size(B) && return false
77+
return A.chunks == B.chunks
78+
end

0 commit comments

Comments
 (0)