Projects/1BIT/summer-semester/IJC-1/bitset.h
2026-04-14 19:28:46 +02:00

106 lines
4.9 KiB
C

// bitset.h
// Řešení IJC-DU1, příklad a), 22.3.2024
// Autor: Roman Nečas, FIT
// Přeloženo: gcc 13.2.1
#ifndef BITSET_H
#define BITSET_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include "error.h"
#include <stdbool.h>
#define WORD_BITS (sizeof(unsigned long) * CHAR_BIT) // Number of bits in an unsigned long
#define WORD_BYTES sizeof(unsigned long) // Number of bytes in an unsigned long
#define HEADER_WORD 1 // First element is reserved for size
/* Index type for the bit set. */
typedef unsigned long bitset_index_t;
/* Bit set type (for passing as a parameter by reference). */
typedef unsigned long *bitset_t;
/* MACROS that are used always */
/* defines and initializes the variable name */
#define bitset_create(name, size) \
static_assert(size > 0 && size < ULONG_MAX, "ERROR: bitset_create: Invalid array size."); \
bitset_index_t name[(size)/WORD_BITS + HEADER_WORD + (((size) % WORD_BITS) ? 1 : 0)] = {size}
#define bitset_alloc(name, size) \
static_assert(size > 0 && size < ULONG_MAX, "ERROR: bitset_create: Invalid array size."); \
bitset_t name = calloc((size)/WORD_BITS + HEADER_WORD + (((size) % WORD_BITS) ? 1 : 0), sizeof(bitset_index_t)); \
if (name == NULL) error_exit("bitset_alloc: Memory allocation error"); \
name[0] = size
/* Frees the memory of a dynamically allocated array. */
#define bitset_free(name) free(name)
#ifdef USE_INLINE
/* INLINE FUNCTIONS */
/* Returns the declared size of the array stored at index 0 */
inline bitset_index_t bitset_size(bitset_t name)
{
return name[0];
}
/* Sets all bits in the array to 0 (false) or 1 (true) */
inline void bitset_fill(bitset_t name, bool bool_expr)
{
unsigned long i;
for (i = HEADER_WORD; i < ((bitset_size(name) / WORD_BITS) + HEADER_WORD + (((bitset_size(name)) % WORD_BITS) ? 1 : 0)); i++)
{
name[i] = (bool_expr) ? ~0UL : 0UL;
}
}
/* Sets the specified bit in the array to the value given by the expression */
inline void bitset_setbit(bitset_t name, bitset_index_t index, bool bool_expr)
{
if (index >= bitset_size(name))
error_exit("bitset_setbit: Index %lu out of range 0..%lu", (unsigned long)index, (unsigned long)bitset_size(name));
name[(index/WORD_BITS) + HEADER_WORD] = (bool_expr) ? (name[(index/WORD_BITS) + HEADER_WORD] | (1UL << (index & (WORD_BITS - 1))))
: (name[(index/WORD_BITS) + HEADER_WORD] & ~(1UL << (index & (WORD_BITS - 1))));
}
/* Gets the value of the specified bit, returns 0 or 1 */
inline char bitset_getbit(bitset_t name, bitset_index_t index)
{
if (index >= bitset_size(name))
error_exit("bitset_getbit: Index %lu out of range 0..%lu", (unsigned long)index, (unsigned long)bitset_size(name));
return name[(index/WORD_BITS + HEADER_WORD)] >> (index & (WORD_BITS - 1)) & 1UL;
}
#else
/* MACROS */
/* Sets all bits in the array to 0 (false) or 1 (true) */
#define bitset_fill(name, bool_expr) do \
{ \
unsigned long i; \
for (i = HEADER_WORD; i < ((bitset_size(name) / WORD_BITS) + HEADER_WORD + (((bitset_size(name)) % WORD_BITS) ? 1 : 0)); i++) \
{ \
name[i] = (bool_expr) ? ~0UL : 0UL; \
} \
} while (0)
/* Sets the specified bit in the array to the value given by the expression */
#define bitset_setbit(name, index, bool_expr) do \
{ \
if ((index) >= bitset_size(name)) error_exit("bitset_setbit: Index %lu out of range 0..%lu", \
(unsigned long)index, (unsigned long)bitset_size(name)); \
name[((index)/WORD_BITS) + HEADER_WORD] = (bool_expr) ? (name[((index)/WORD_BITS) + HEADER_WORD] | (1UL << ((index) & (WORD_BITS - 1)))) \
: (name[((index)/WORD_BITS) + HEADER_WORD] & ~(1UL << ((index) & (WORD_BITS - 1)))); \
} while (0)
/* Gets the value of the specified bit, returns 0 or 1 */
#define bitset_getbit(name, index) \
(((index) >= bitset_size(name)) ? (error_exit("bitset_getbit: Index %lu out of range 0..%lu", (unsigned long)index, (unsigned long)bitset_size(name)), 0) \
: ((name[((index)/WORD_BITS + HEADER_WORD)] >> ((index) & (WORD_BITS - 1))) & 1UL))
/* Returns the declared size of the array stored at index 0 */
#define bitset_size(name) name[0]
#endif
#endif