Add graph references
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
igraph library.
|
||||
Copyright (C) 2024-2025 The igraph development team <igraph@igraph.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef IGRAPH_BITSET_H
|
||||
#define IGRAPH_BITSET_H
|
||||
|
||||
#include "igraph_decls.h"
|
||||
#include "igraph_error.h"
|
||||
#include "igraph_vector.h"
|
||||
#include "igraph_types.h"
|
||||
|
||||
/* Required for MSVC intrinsics such as __popcnt and __popcnt64 */
|
||||
#ifdef _MSC_VER
|
||||
#include "intrin.h"
|
||||
#endif
|
||||
|
||||
IGRAPH_BEGIN_C_DECLS
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \section igraph_bitset_accessing_elements Accessing elements
|
||||
*
|
||||
* <para>The simplest way to access an element of a bitset is
|
||||
* to use the \ref IGRAPH_BIT_TEST(), \ref IGRAPH_BIT_SET() and \ref IGRAPH_BIT_CLEAR() macros.
|
||||
* </para>
|
||||
*
|
||||
* <para>There are a few other macros which allow manual manipulation of bitsets.
|
||||
* Those are \ref VECTOR(), \ref IGRAPH_BIT_SLOT(), \ref IGRAPH_BIT_MASK() and
|
||||
* \ref IGRAPH_BIT_NSLOTS().</para>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_MASK
|
||||
* \brief Computes mask used to access a specific bit of an integer.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Used in combination with \ref IGRAPH_BIT_SLOT() to access an element of a bitset.
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_MASK(10) \endverbatim
|
||||
* to obtain an integer where only the 11th least significant bit is set.
|
||||
*
|
||||
* Note that passing negative values here results in undefined behaviour.
|
||||
*
|
||||
* \param b The only bit index that should have its bit set.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_MASK(i) ((igraph_uint_t)(1) << ((i) % IGRAPH_INTEGER_SIZE))
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_SLOT
|
||||
* \brief Computes index used to access a specific slot of a bitset.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Used in combination with \ref IGRAPH_BIT_MASK to access an element of a bitset.
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_SLOT(70) \endverbatim
|
||||
* will return 1 if using 64-bit words or 2 if using 32-bit words.
|
||||
*
|
||||
* \param i The bit index whose slot should be determined.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_SLOT(i) ((i) / IGRAPH_INTEGER_SIZE)
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_SET
|
||||
* \brief Sets a specific bit in a bitset to 1 without altering other bits.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_SET(bitset, 3) \endverbatim
|
||||
* will set the fourth least significant bit in the bitset to 1.
|
||||
*
|
||||
* \param bitset The bitset
|
||||
* \param i The bit index that should have its bit set to 1 after the operation.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_SET(bitset, i) (VECTOR((bitset))[IGRAPH_BIT_SLOT(i)] |= IGRAPH_BIT_MASK(i))
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_CLEAR
|
||||
* \brief Sets a specific bit in a bitset to 0 without altering other bits.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_CLEAR(bitset, 4) \endverbatim
|
||||
* will set the fifth least significant bit in the bitset to 0.
|
||||
*
|
||||
* \param bitset The bitset
|
||||
* \param i The bit index that should have its bit set to 0 after the operation.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_CLEAR(bitset, i) (VECTOR((bitset))[IGRAPH_BIT_SLOT(i)] &= ~IGRAPH_BIT_MASK(i))
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_TEST
|
||||
* \brief Tests whether a bit is set in a bitset.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Returns 0 if the bit at the specified bit index is not set,
|
||||
* otherwise returns a non-zero value.
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_TEST(bitset, 7) \endverbatim
|
||||
* will test the eighth least significant bit in the bitset.
|
||||
*
|
||||
* \param bitset The bitset
|
||||
* \param i The bit index that should have its bit tested.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_TEST(bitset, i) (VECTOR((bitset))[IGRAPH_BIT_SLOT(i)] & IGRAPH_BIT_MASK(i))
|
||||
|
||||
/**
|
||||
* \ingroup bitset
|
||||
* \define IGRAPH_BIT_NSLOTS
|
||||
* \brief Computes the number of slots required to store a specified number of bits.
|
||||
*
|
||||
* \experimental
|
||||
*
|
||||
* Usage:
|
||||
* \verbatim IGRAPH_BIT_NSLOTS(70) \endverbatim
|
||||
* will return 2 if using 64-bit words and 3 if using 32-bit words.
|
||||
* \verbatim IGRAPH_BIT_NSLOTS(128) \endverbatim
|
||||
* will return 2 if using 64-bit words and 4 if using 32-bit words.
|
||||
*
|
||||
* \param nbits The specified number of bits.
|
||||
*
|
||||
* Time complexity: O(1).
|
||||
*/
|
||||
#define IGRAPH_BIT_NSLOTS(nbits) ((nbits + IGRAPH_INTEGER_SIZE - (igraph_int_t)(1)) / IGRAPH_INTEGER_SIZE)
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* GCC and Clang support these six builtins from very early versions. */
|
||||
|
||||
#define IGRAPH_I_POPCOUNT32(x) __builtin_popcount(x)
|
||||
#define IGRAPH_I_POPCOUNT64(x) __builtin_popcountll(x)
|
||||
|
||||
/* The result of the following four builtins is undefined for zero input,
|
||||
* therefore we handle this specially.
|
||||
* See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */
|
||||
#define IGRAPH_I_CTZ32(x) (x ? __builtin_ctz(x) : 32)
|
||||
#define IGRAPH_I_CTZ64(x) (x ? __builtin_ctzll(x) : 64)
|
||||
#define IGRAPH_I_CLZ32(x) (x ? __builtin_clz(x) : 32)
|
||||
#define IGRAPH_I_CLZ64(x) (x ? __builtin_clzll(x) : 64)
|
||||
|
||||
#else
|
||||
/* Non-GNU compilers, i.e. MSVC and others. Attempt to use MSVC intrinsics
|
||||
* when available, otherwise use fallback implementation. */
|
||||
|
||||
#if IGRAPH_INTEGER_SIZE == 32
|
||||
#ifdef HAVE__POPCNT
|
||||
#define IGRAPH_I_POPCOUNT32(x) __popcnt(x)
|
||||
#else
|
||||
igraph_int_t igraph_i_popcnt(igraph_uint_t x);
|
||||
#define IGRAPH_I_POPCOUNT32(x) igraph_i_popcnt(x)
|
||||
#endif
|
||||
#elif IGRAPH_INTEGER_SIZE == 64
|
||||
#ifdef HAVE__POPCNT64
|
||||
#define IGRAPH_I_POPCOUNT64(x) __popcnt64(x)
|
||||
#else
|
||||
igraph_int_t igraph_i_popcnt(igraph_uint_t x);
|
||||
#define IGRAPH_I_POPCOUNT64(x) igraph_i_popcnt(x)
|
||||
#endif
|
||||
#else
|
||||
#error "Unexpected IGRAPH_INTEGER_SIZE value."
|
||||
#endif
|
||||
|
||||
igraph_int_t igraph_i_ctz32(igraph_uint_t x);
|
||||
igraph_int_t igraph_i_ctz64(igraph_uint_t x);
|
||||
igraph_int_t igraph_i_clz32(igraph_uint_t x);
|
||||
igraph_int_t igraph_i_clz64(igraph_uint_t x);
|
||||
#define IGRAPH_I_CTZ32(x) igraph_i_ctz32(x)
|
||||
#define IGRAPH_I_CTZ64(x) igraph_i_ctz64(x)
|
||||
#define IGRAPH_I_CLZ32(x) igraph_i_clz32(x)
|
||||
#define IGRAPH_I_CLZ64(x) igraph_i_clz64(x)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if IGRAPH_INTEGER_SIZE == 32
|
||||
#define IGRAPH_POPCOUNT IGRAPH_I_POPCOUNT32
|
||||
#define IGRAPH_CLZ IGRAPH_I_CLZ32
|
||||
#define IGRAPH_CTZ IGRAPH_I_CTZ32
|
||||
#elif IGRAPH_INTEGER_SIZE == 64
|
||||
#define IGRAPH_POPCOUNT IGRAPH_I_POPCOUNT64
|
||||
#define IGRAPH_CLZ IGRAPH_I_CLZ64
|
||||
#define IGRAPH_CTZ IGRAPH_I_CTZ64
|
||||
#else
|
||||
#error "Unexpected IGRAPH_INTEGER_SIZE value."
|
||||
#endif
|
||||
|
||||
#define IGRAPH_CLO(x) IGRAPH_CLZ(~(x))
|
||||
#define IGRAPH_CTO(x) IGRAPH_CTZ(~(x))
|
||||
|
||||
typedef struct {
|
||||
igraph_int_t size;
|
||||
igraph_uint_t *stor_begin;
|
||||
igraph_uint_t *stor_end;
|
||||
} igraph_bitset_t;
|
||||
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_int_t size);
|
||||
IGRAPH_EXPORT void igraph_bitset_destroy(igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_init_copy(igraph_bitset_t *dest, const igraph_bitset_t *src);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t *src);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_capacity(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_size(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_int_t capacity);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_int_t new_size);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_popcount(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countl_one(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_int_t igraph_bitset_countr_one(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_all_one(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_any_zero(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_bool_t igraph_bitset_is_any_one(const igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT void igraph_bitset_or(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
|
||||
IGRAPH_EXPORT void igraph_bitset_and(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
|
||||
IGRAPH_EXPORT void igraph_bitset_xor(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
|
||||
IGRAPH_EXPORT void igraph_bitset_not(igraph_bitset_t *dest, const igraph_bitset_t *src);
|
||||
IGRAPH_EXPORT void igraph_bitset_fill(igraph_bitset_t *bitset, igraph_bool_t value);
|
||||
IGRAPH_EXPORT void igraph_bitset_null(igraph_bitset_t *bitset);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_fprint(const igraph_bitset_t *bitset, FILE *file);
|
||||
IGRAPH_EXPORT igraph_error_t igraph_bitset_print(const igraph_bitset_t *bitset);
|
||||
|
||||
#define IGRAPH_BITSET_INIT_FINALLY(bitset, size) \
|
||||
do { IGRAPH_CHECK(igraph_bitset_init(bitset, size)); \
|
||||
IGRAPH_FINALLY(igraph_bitset_destroy, bitset); } while (0)
|
||||
|
||||
IGRAPH_END_C_DECLS
|
||||
|
||||
#endif /* IGRAPH_BITSET_H */
|
||||
Reference in New Issue
Block a user