BitPacking

Documentation for BitPacking.

bitwidth interface for narrow types

BitPacking.bitwidthFunction
bitwidth(T)::Int
bitwidth(x)::Int

Return the number of value bits used by T or by the type of x.

The default for bitstypes is 8 * sizeof(T), with Bool specialized to one bit. Packages and users can overload this for narrow primitive types, packed containers, and layout markers such as ZeroPad.

source

Narrow-element arrays

BitPacking.NArrayType
NArray{T,N,S,D} <: StaticArray{S,T,N}
NArray{T,N,S}(values::NTuple)
NVector{T,L}
NMatrix{T,M,N}

Small statically-sized array whose elements are packed into a single storage value.

NArray behaves like a StaticArrays.StaticArray, but stores all lanes in the data field as either an unsigned integer or an NTuple of bytes. The number of bits used for each lane is bitwidth(T), so the total packed width is bitwidth(T) * length(x).

Use NVector{T,L} and NMatrix{T,M,N} for the common one- and two-dimensional forms. Construct from an NTuple of logical values:

julia> v = NVector(true, false, true, false, true, false, true, false)
8-element NVector{Bool, 8, UInt8} with indices SOneTo(8):
 1
 0
 1
 0
 1
 0
 1
 0

julia> reinterpret(UInt8, v)
0x55

Broadcasting treats an NArray as the unpacked static array of its logical values, while reinterpret can be used to access the packed storage.

source
BitPacking.NarrowArrayType
NarrowArray{T}(array::AbstractArray)
NarrowArray{T,N,L}(array::AbstractArray)

Array wrapper whose parent stores packed NArray chunks.

NarrowArray{T} presents an AbstractArray{T} interface while storing groups of logical values in the first dimension as NVector chunks. For an element type T, the default chunk length is pack_count(T) == 8 ÷ gcd(bitwidth(T), 8). Use NarrowArray{T,N,L} or NarrowVector{T,L} to choose a wider chunk length.

The constructor packs an existing logical array:

julia> x = NarrowArray{Bool}([true, false, true, false, true, false, true, false])
8-element NarrowVector{Bool, 8, Vector{NVector{Bool, 8, UInt8}}}:
 1
 0
 1
 0
 1
 0
 1
 0

The input's first dimension must contain whole chunks. For example, NarrowArray{Bool} requires the first dimension to be divisible by 8, and a 4-bit element type requires it to be divisible by 2.

NarrowArray{T}(x) converts values to T before packing when eltype(x) != T. parent(x) exposes the packed chunk array. copy(x) materializes the logical values, while reinterpret(T, x) reinterprets the whole logical bit buffer and rescales the leading dimension by bitwidth. Type broadcasts such as T.(x) convert packed chunks to dense logical T values. Display uses a host-adapted copy so GPU-backed parents do not print through scalar indexing.

source

Narrow tuples

BitPacking.NarrowTupleType
NarrowTuple{Ts,D}
NarrowTuple(xs::Tuple)
NarrowTuple{Ts}(xs...)

A packed, tuple-like value whose fields are stored without Julia field alignment.

Ts is a concrete Tuple layout type. Each non-padding field must be a bitstype with a valid bitwidth. Padding fields such as ZeroPad and OnePad contribute bits to storage and unpack as zero-size marker values like BitPacking.ZeroPad(7).

The storage type D is chosen from the total layout bitwidth. Exact widths of 8, 16, 32, 64, and 128 bits use the matching unsigned integer type. Other widths use NTuple{N,UInt8} with enough bytes to hold the layout.

Fields are packed in declaration order from least-significant bit upward. For byte-tuple storage, byte 1 contains the least-significant byte.

nt = NarrowTuple((0x00, true))

typeof(nt)      # @NarrowTuple{UInt8, Bool}
nt.data         # (0x00, 0x01)
Tuple(nt)       # (0x00, true)
bitwidth(nt)    # 9

Nested NarrowTuples work like any other bitwidth-aware bitstype:

nt = @NarrowTuple(true, @NarrowTuple(0x00, true))
bitwidth(nt)  # 10

Padding fields are visible in the logical tuple representation:

@NarrowTuple{UInt8, BitPacking.ZeroPad{7}, Bool}(0xff, true)
# @NarrowTuple(0xff, BitPacking.ZeroPad(7), true)

See also @NarrowTuple.

source
BitPacking.@NarrowTupleMacro
@NarrowTuple{T1, T2, ...}
@NarrowTuple(x1, x2, ...)
@NarrowTuple((x1, x2, ...))

Convenience syntax for NarrowTuple.

The braced form returns the packed tuple type for a layout:

T = @NarrowTuple{UInt8, Bool}
# @NarrowTuple{UInt8, Bool}

The parenthesized form constructs a value from logical tuple fields:

@NarrowTuple(0x00, true)
# @NarrowTuple(0x00, true)

Padding markers are written in the braced layout form. Constructor arguments may either omit padding values, in which case they are inserted, or include the matching zero-size values explicitly:

T = @NarrowTuple{UInt8, Bool, BitPacking.ZeroPad{7}}
T(0x00, true)
# @NarrowTuple(0x00, true, BitPacking.ZeroPad(7))

T(0x00, true, BitPacking.ZeroPad(7))
# @NarrowTuple(0x00, true, BitPacking.ZeroPad(7))
source
BitPacking.PadType
Pad{N}

Abstract supertype for padding fields in a NarrowTuple.

Padding fields contribute N bits to the packed layout. ZeroPad{N} and OnePad{N} are abstract layout marker families; use ZeroPad(N) and OnePad(N) to construct zero-size values for introspection.

Use ZeroPad or OnePad in layouts.

source
BitPacking.ZeroPadType
ZeroPad{N} <: Pad{N}
ZeroPad(N)

Insert N zero bits into a NarrowTuple layout.

ZeroPad{N} is an abstract layout marker. ZeroPad(N) returns an introspectable zero-size value whose type is a concrete subtype of ZeroPad{N}:

T = @NarrowTuple{UInt8, Bool, BitPacking.ZeroPad{7}}
nt = T(0x00, true)

nt.data    # 0x0100
Tuple(nt)  # (0x00, true, BitPacking.ZeroPad(7))

Raw-storage constructors validate that the corresponding padding bits are zero.

source
BitPacking.OnePadType
OnePad{N} <: Pad{N}
OnePad(N)

Insert N one bits into a NarrowTuple layout.

OnePad{N} is an abstract layout marker. OnePad(N) returns a zero-size value whose type is a concrete subtype of OnePad{N}:

T = @NarrowTuple{UInt8, Bool, BitPacking.OnePad{7}}
nt = T(0x00, true)

nt.data    # 0xff00
Tuple(nt)  # (0x00, true, BitPacking.OnePad(7))

Raw-storage constructors validate that the corresponding padding bits are one.

source