Skip to content

BitVecData

Description

Pointer to the raw byte-packed storage backing the bitvector. The caller MUST NOT free this pointer or write past BitVecByteSize(bv) bytes. Useful for serialising the underlying bits or for hand-rolled bit-level routines outside the standard BitVecGet/Set/Flip access pattern. Returns NULL when the bitvector has never been allocated into.

Usage example (Cross-references)

Usage examples (Cross-references)
        // highest set bit inside the top non-zero limb. int_load_le8 masks the top
        // limb to `len`, so stale bits above the length never leak in.
        const u8 *d   = BitVecData(INT_BITS(value));
        u64       off = ((len - 1u) / 64u) * 8u;
        u64       bits      = IntBitLength(value);
        u64       bytes     = bits == 0 ? 0 : CEIL_DIV(bits, 8u);
        const u8 *magnitude = (const u8 *)BitVecData(INT_BITS(value));
        for (u64 i = 0; i < bytes; i++) {
            hash ^= (u64)magnitude[i];
        }
    
        const u8 *ad  = BitVecData(INT_BITS(a));
        const u8 *bd  = BitVecData(INT_BITS(b));
        u64       n   = (a_bits + 7u) / 8u;
    
        const u8 *ad  = BitVecData(INT_BITS(a));
        const u8 *bd  = BitVecData(INT_BITS(b));
        u64       n   = (a_bits + 7u) / 8u;
        u64       off = ((n - 1u) / 8u) * 8u;
        // Funnel shift over 64-bit limbs, high to low so each source limb is read
        // before it is overwritten: out[k] = src[k-ls] << bs | src[k-ls-1] >> (64-bs).
        u8 *d          = BitVecData(INT_BITS(value));
        u64 limb_shift = positions / 64u;
        u64 bit_shift  = positions % 64u;
        // Funnel shift over 64-bit limbs, low to high: out[k] = src[k+ls] >> bs |
        // src[k+ls+1] << (64-bs). Written limbs are below the limbs still being read.
        u8 *d          = BitVecData(INT_BITS(value));
        u64 limb_shift = positions / 64u;
        u64 bit_shift  = positions % 64u;
        // 64 bits per step with the hardware carry chain instead of bit-by-bit. A
        // left-to-right limb ripple keeps it safe when result aliases a or b.
        u8       *rd    = BitVecData(INT_BITS(result));
        const u8 *ad    = BitVecData(INT_BITS(a));
        const u8 *bd    = BitVecData(INT_BITS(b));
        // left-to-right limb ripple keeps it safe when result aliases a or b.
        u8       *rd    = BitVecData(INT_BITS(result));
        const u8 *ad    = BitVecData(INT_BITS(a));
        const u8 *bd    = BitVecData(INT_BITS(b));
        u64       n     = (max_bits + 1u + 7u) / 8u;
        u8       *rd    = BitVecData(INT_BITS(result));
        const u8 *ad    = BitVecData(INT_BITS(a));
        const u8 *bd    = BitVecData(INT_BITS(b));
        u64       n     = (max_bits + 1u + 7u) / 8u;
        u64       carry = 0;
        }
    
        u8       *rd     = BitVecData(INT_BITS(result));
        const u8 *ad     = BitVecData(INT_BITS(a));
        const u8 *bd     = BitVecData(INT_BITS(b));
    
        u8       *rd     = BitVecData(INT_BITS(result));
        const u8 *ad     = BitVecData(INT_BITS(a));
        const u8 *bd     = BitVecData(INT_BITS(b));
        u64       n      = (a_bits + 7u) / 8u;
        u8       *rd     = BitVecData(INT_BITS(result));
        const u8 *ad     = BitVecData(INT_BITS(a));
        const u8 *bd     = BitVecData(INT_BITS(b));
        u64       n      = (a_bits + 7u) / 8u;
        u64       borrow = 0;
            }
    
            u8       *rd  = BitVecData(INT_BITS(result));
            const u8 *ad  = BitVecData(INT_BITS(a));
            const u8 *bd  = BitVecData(INT_BITS(b));
    
            u8       *rd  = BitVecData(INT_BITS(result));
            const u8 *ad  = BitVecData(INT_BITS(a));
            const u8 *bd  = BitVecData(INT_BITS(b));
            u64       n_r = r_words * 8u;
            u8       *rd  = BitVecData(INT_BITS(result));
            const u8 *ad  = BitVecData(INT_BITS(a));
            const u8 *bd  = BitVecData(INT_BITS(b));
            u64       n_r = r_words * 8u;
    
            {
                u8       *qd     = BitVecData(INT_BITS(quotient));
                u8       *rd     = BitVecData(INT_BITS(remainder));
                const u8 *dd     = BitVecData(INT_BITS(dividend));
            {
                u8       *qd     = BitVecData(INT_BITS(quotient));
                u8       *rd     = BitVecData(INT_BITS(remainder));
                const u8 *dd     = BitVecData(INT_BITS(dividend));
                const u8 *vd     = BitVecData(INT_BITS(divisor));
                u8       *qd     = BitVecData(INT_BITS(quotient));
                u8       *rd     = BitVecData(INT_BITS(remainder));
                const u8 *dd     = BitVecData(INT_BITS(dividend));
                const u8 *vd     = BitVecData(INT_BITS(divisor));
                u64       rbytes = r_words * 8u;
                u8       *rd     = BitVecData(INT_BITS(remainder));
                const u8 *dd     = BitVecData(INT_BITS(dividend));
                const u8 *vd     = BitVecData(INT_BITS(divisor));
                u64       rbytes = r_words * 8u;
                u64       rbits  = r_words * 64u;
    
        bool result = (BitVecCapacity(&bv) == 64);
        result      = result && (BitVecData(&bv) != NULL);
        result      = result && (BitVecLen(&bv) == 0);
        bool result = (BitVecLen(&bv) == 0);
        result      = result && (BitVecCapacity(&bv) == 0);
        result      = result && (BitVecData(&bv) == NULL);
        result      = result && (BitVecByteSize(&bv) == 0);
    
        // Check that data was allocated
        bool result = (BitVecLen(&bv) == 3) && (BitVecData(&bv) != NULL);
    
        // Deinitialize
        result = result && (BitVecLen(&bv) == 0);
        result = result && (BitVecCapacity(&bv) == 0);
        result = result && (BitVecData(&bv) == NULL);
        result = result && (BitVecByteSize(&bv) == 0);
        bool result = (BitVecCapacity(&bv) >= 50);
        result      = result && (BitVecLen(&bv) == 0);     // Length should still be 0
        result      = result && (BitVecData(&bv) != NULL); // Memory should be allocated
    
        // Add some bits to make sure the reserved space works
    
        // Check initial state
        bool result            = (BitVecLen(&bv) == 4) && (BitVecData(&bv) != NULL);
        u64  original_capacity = BitVecCapacity(&bv);
        result = result && (BitVecLen(&bv) == 0);
        result = result && (BitVecCapacity(&bv) == original_capacity);
        result = result && (BitVecData(&bv) != NULL); // Memory should still be allocated
    
        // Test that we can still add data after clearing
    
        bool result = (BitVecLen(&bv1) == 0) && (BitVecLen(&bv2) == 0) && (BitVecLen(&bv3) == 0);
        result      = result && (BitVecData(&bv1) == NULL) && (BitVecData(&bv2) == NULL) && (BitVecData(&bv3) == NULL);
    
        // Clean up all
        // Test reserving 0 (should be safe no-op)
        BitVecReserve(&bv, 0);
        result = result && (BitVecCapacity(&bv) == 0) && (BitVecData(&bv) == NULL);
    
        // Test reserving 1 bit (minimum meaningful size)
        // Test reserving 1 bit (minimum meaningful size)
        BitVecReserve(&bv, 1);
        result = result && (BitVecCapacity(&bv) >= 1) && (BitVecData(&bv) != NULL);
    
        // Test very large but reasonable reservation
        // Check initial state
        bool result =
            (BitVecLen(&bitvec) == 0 && BitVecCapacity(&bitvec) == 0 && BitVecData(&bitvec) == NULL &&
             BitVecByteSize(&bitvec) == 0);
Last updated on