diff --git a/kos/.clang-format b/kos/.clang-format index 0bafc111cc..b0d07b3c80 100644 --- a/kos/.clang-format +++ b/kos/.clang-format @@ -193,6 +193,10 @@ ForEachMacros: - BSEARCH_RANGE - BSEARCH_RANGE_EX - BSEARCH_EX + - bitset_foreach + - bitset_nforeach + - __hybrid_bitset_foreach + - __hybrid_bitset_nforeach - PCI_FOREACH_DEVICE - PCI_FOREACH_DEVICE_CLASS - __STATIC_IF diff --git a/kos/cpp.hint b/kos/cpp.hint index b0074466df..3eeff44cf8 100644 --- a/kos/cpp.hint +++ b/kos/cpp.hint @@ -641,8 +641,10 @@ // #define __hybrid_bitset_decl(x,n) x[n] #define __hybrid_bitset_foreach(x,y,z) for(;;) +#define __hybrid_bitset_nforeach(x,y,z,a) for(;;) #define bitset_decl(x,n) x[n] #define bitset_foreach(x,y,z) for(;;) +#define bitset_nforeach(x,y,z,a) for(;;) diff --git a/kos/include/compiler/msvc.h b/kos/include/compiler/msvc.h index 8bd9f24c0e..67c988c912 100644 --- a/kos/include/compiler/msvc.h +++ b/kos/include/compiler/msvc.h @@ -605,7 +605,9 @@ void __builtin_va_end(__builtin_va_list &__ap); #define __GCC_HAS_WARNING_Wunreachable_code _xS(4702) #define __GCC_HAS_WARNING_Wmaybe_uninitialized _xS(4701 4703) #define __GCC_HAS_WARNING_Wcast_function_type _xS(4054 4152) +#if _MSC_VER >= 1500 #define __GCC_HAS_WARNING_MSconditional_expression_is_constant _xS(4127) +#endif /* _MSC_VER >= 1500 */ #define __GCC_HAS_WARNING_Wdiv_by_zero _xS(4723 4724) #define __GCC_HAS_WARNING_Winvalid_offsetof _xS(4597 4749 4842) #define __GCC_HAS_WARNING_Woverflow _xS(4056 4178 4340 4427 4756 4757) diff --git a/kos/include/hybrid/__atomic.h b/kos/include/hybrid/__atomic.h index d429514ad2..c6baf3cc52 100644 --- a/kos/include/hybrid/__atomic.h +++ b/kos/include/hybrid/__atomic.h @@ -1155,4 +1155,22 @@ template typename ::__intern::____INTELLISENSE_enableif< ::__intern::__ #define __GCC_ATOMIC_POINTER_LOCK_FREE __HYBRID_ATOMIC_LOCKFREE(__SIZEOF_POINTER__) #endif /* !__GCC_ATOMIC_POINTER_LOCK_FREE */ +/* Atomic bitset operations. */ +#ifdef __GUARD_HYBRID___BITSET_H +#define __hybrid_bitset_atomic_set(self, bitno) __hybrid_atomic_or(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_clear(self, bitno) __hybrid_atomic_and(&(self)[__HYBRID_BITSET_WORD(bitno)], ~__HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_flip(self, bitno) __hybrid_atomic_xor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_fetchset(self, bitno) (__hybrid_atomic_fetchor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#define __hybrid_bitset_atomic_fetchclear(self, bitno) (__hybrid_atomic_fetchand(&(self)[__HYBRID_BITSET_WORD(bitno)], ~__HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#define __hybrid_bitset_atomic_fetchflip(self, bitno) (__hybrid_atomic_fetchxor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#ifdef __GUARD_HYBRID_BITSET_H +#define bitset_atomic_set(self, bitno) __hybrid_bitset_atomic_set(self, bitno) +#define bitset_atomic_clear(self, bitno) __hybrid_bitset_atomic_clear(self, bitno) +#define bitset_atomic_flip(self, bitno) __hybrid_bitset_atomic_flip(self, bitno) +#define bitset_atomic_fetchset(self, bitno) __hybrid_bitset_atomic_fetchset(self, bitno) +#define bitset_atomic_fetchclear(self, bitno) __hybrid_bitset_atomic_fetchclear(self, bitno) +#define bitset_atomic_fetchflip(self, bitno) __hybrid_bitset_atomic_fetchflip(self, bitno) +#endif /* __GUARD_HYBRID_BITSET_H */ +#endif /* __GUARD_HYBRID___BITSET_H */ + #endif /* !__GUARD_HYBRID___ATOMIC_H */ diff --git a/kos/include/hybrid/__bitset.h b/kos/include/hybrid/__bitset.h index 79d067124d..ad761d140d 100644 --- a/kos/include/hybrid/__bitset.h +++ b/kos/include/hybrid/__bitset.h @@ -33,52 +33,64 @@ #if __HYBRID_BITSET_WORD_BITS == 8 #define __hybrid_bitset_t __UINT8_TYPE__ -#define __HYBRID_BITSET_WORD_SIGN __UINT8_C(0x80) #define __HYBRID_BITSET_WORD_BMAX __UINT8_C(0xff) #define __HYBRID_BITSET_WORD_BMSK 7 #define __HYBRID_BITSET_WORD_SHFT 3 #define __HYBRID_BITSET_WORD_POPCOUNT __hybrid_popcount8 -#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz8 #define __HYBRID_BITSET_WORD_CLZ __hybrid_clz8 +#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz8 #elif __HYBRID_BITSET_WORD_BITS == 16 #define __hybrid_bitset_t __UINT16_TYPE__ -#define __HYBRID_BITSET_WORD_SIGN __UINT16_C(0x8000) #define __HYBRID_BITSET_WORD_BMAX __UINT16_C(0xffff) #define __HYBRID_BITSET_WORD_BMSK 15 #define __HYBRID_BITSET_WORD_SHFT 4 #define __HYBRID_BITSET_WORD_POPCOUNT __hybrid_popcount16 -#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz16 #define __HYBRID_BITSET_WORD_CLZ __hybrid_clz16 +#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz16 #elif __HYBRID_BITSET_WORD_BITS == 32 #define __hybrid_bitset_t __UINT32_TYPE__ -#define __HYBRID_BITSET_WORD_SIGN __UINT32_C(0x80000000) #define __HYBRID_BITSET_WORD_BMAX __UINT32_C(0xffffffff) #define __HYBRID_BITSET_WORD_BMSK 31 #define __HYBRID_BITSET_WORD_SHFT 5 #define __HYBRID_BITSET_WORD_POPCOUNT __hybrid_popcount32 -#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz32 #define __HYBRID_BITSET_WORD_CLZ __hybrid_clz32 +#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz32 #elif __HYBRID_BITSET_WORD_BITS == 64 #define __hybrid_bitset_t __UINT64_TYPE__ -#define __HYBRID_BITSET_WORD_SIGN __UINT64_C(0x8000000000000000) #define __HYBRID_BITSET_WORD_BMAX __UINT64_C(0xffffffffffffffff) #define __HYBRID_BITSET_WORD_BMSK 63 #define __HYBRID_BITSET_WORD_SHFT 6 #define __HYBRID_BITSET_WORD_POPCOUNT __hybrid_popcount64 -#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz64 #define __HYBRID_BITSET_WORD_CLZ __hybrid_clz64 +#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz64 #else /* __HYBRID_BITSET_WORD_BITS == ... */ #define __hybrid_bitset_t __TYPEFOR_UINTIB() -#define __HYBRID_BITSET_WORD_SIGN (__CCAST(__hybrid_bitset_t)1 << (__HYBRID_BITSET_WORD_BITS - 1)) #define __HYBRID_BITSET_WORD_BMAX ((__CCAST(__hybrid_bitset_t)1 << __HYBRID_BITSET_WORD_BITS) - 1) #define __HYBRID_BITSET_WORD_BMSK (__HYBRID_BITSET_WORD_BITS - 1) #define __HYBRID_BITSET_WORD_SHFT log2(__HYBRID_BITSET_WORD_BITS) #define __HYBRID_BITSET_WORD_POPCOUNT __hybrid_popcount -#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz #define __HYBRID_BITSET_WORD_CLZ __hybrid_clz +#define __HYBRID_BITSET_WORD_CTZ __hybrid_ctz #endif /* __HYBRID_BITSET_WORD_BITS != ... */ -#define __HYBRID_BITSET_BYTE(bitno) ((bitno) >> __HYBRID_BITSET_WORD_SHFT) +/* UNDEFINED WHEN `x == 0xff' + * >> result = 0; + * >> while (x & 0x80) { + * >> ++result; + * >> x <<= 1; + * >> } */ +#define __HYBRID_BITSET_WORD_CLO(x) __HYBRID_BITSET_WORD_CLZ(~(x)) + +/* UNDEFINED WHEN `x == 0x00' + * >> result = 0; + * >> while (x & 1) { + * >> ++result; + * >> x >>= 1; + * >> } */ +#define __HYBRID_BITSET_WORD_CTO(x) __HYBRID_BITSET_WORD_CTZ(~(x)) + + +#define __HYBRID_BITSET_WORD(bitno) ((bitno) >> __HYBRID_BITSET_WORD_SHFT) #define __HYBRID_BITSET_MASK(bitno) (__CCAST(__hybrid_bitset_t) 1 << ((bitno) & __HYBRID_BITSET_WORD_BMSK)) #define __HYBRID_BITSET_LENGTHOF(n_bits) (((n_bits) + __HYBRID_BITSET_WORD_BMSK) >> __HYBRID_BITSET_WORD_SHFT) @@ -103,19 +115,19 @@ __DECL_BEGIN /* >> bool __hybrid_bitset_test(__hybrid_bitset_t const *self, size_t bitno); */ #define __hybrid_bitset_test(self, bitno) \ - ((self)[__HYBRID_BITSET_BYTE(bitno)] & __HYBRID_BITSET_MASK(bitno)) + ((self)[__HYBRID_BITSET_WORD(bitno)] & __HYBRID_BITSET_MASK(bitno)) /* >> void __hybrid_bitset_set(__hybrid_bitset_t *self, size_t bitno); */ #define __hybrid_bitset_set(self, bitno) \ - (void)((self)[__HYBRID_BITSET_BYTE(bitno)] |= __HYBRID_BITSET_MASK(bitno)) + (void)((self)[__HYBRID_BITSET_WORD(bitno)] |= __HYBRID_BITSET_MASK(bitno)) /* >> void __hybrid_bitset_clear(__hybrid_bitset_t *self, size_t bitno); */ #define __hybrid_bitset_clear(self, bitno) \ - (void)((self)[__HYBRID_BITSET_BYTE(bitno)] &= ~__HYBRID_BITSET_MASK(bitno)) + (void)((self)[__HYBRID_BITSET_WORD(bitno)] &= ~__HYBRID_BITSET_MASK(bitno)) /* >> void __hybrid_bitset_flip(__hybrid_bitset_t *self, size_t bitno); */ #define __hybrid_bitset_flip(self, bitno) \ - (void)((self)[__HYBRID_BITSET_BYTE(bitno)] ^= __HYBRID_BITSET_MASK(bitno)) + (void)((self)[__HYBRID_BITSET_WORD(bitno)] ^= __HYBRID_BITSET_MASK(bitno)) /* >> void __hybrid_bitset_setall(__hybrid_bitset_t *self, size_t n_bits); */ @@ -134,6 +146,16 @@ __DECL_BEGIN (self)[__bfa_i] ^= __HYBRID_BITSET_WORD_BMAX; \ } __WHILE0 +/* Atomic bitset operations. */ +#ifdef __GUARD_HYBRID___ATOMIC_H +#define __hybrid_bitset_atomic_set(self, bitno) __hybrid_atomic_or(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_clear(self, bitno) __hybrid_atomic_and(&(self)[__HYBRID_BITSET_WORD(bitno)], ~__HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_flip(self, bitno) __hybrid_atomic_xor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) +#define __hybrid_bitset_atomic_fetchset(self, bitno) (__hybrid_atomic_fetchor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#define __hybrid_bitset_atomic_fetchclear(self, bitno) (__hybrid_atomic_fetchand(&(self)[__HYBRID_BITSET_WORD(bitno)], ~__HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#define __hybrid_bitset_atomic_fetchflip(self, bitno) (__hybrid_atomic_fetchxor(&(self)[__HYBRID_BITSET_WORD(bitno)], __HYBRID_BITSET_MASK(bitno), __ATOMIC_SEQ_CST) & __HYBRID_BITSET_MASK(bitno)) +#endif /* __GUARD_HYBRID___ATOMIC_H */ + /* >> size_t bitno; * >> __hybrid_bitset_t bitset[__HYBRID_BITSET_LENGTHOF(42)]; * >> ... @@ -145,6 +167,11 @@ __DECL_BEGIN if (!__hybrid_bitset_test(self, bitno)) \ ; \ else +#define __hybrid_bitset_nforeach(bitno, self, minbitno, maxbitno) \ + for ((bitno) = (minbitno); (bitno) <= (maxbitno); ++(bitno)) \ + if (!__hybrid_bitset_test(self, bitno)) \ + ; \ + else @@ -167,12 +194,12 @@ __DECL_BEGIN self[maxbyte] |= __HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BMSK - maxbyte_bitno); \ } #define __HYBRID_PRIVATE_BITSET_NCLEAR(self, minbitno, maxbitno) \ - __register __SIZE_TYPE__ __hbs_minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(minbitno); \ - __register __SIZE_TYPE__ __hbs_maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(maxbitno); \ + __register __SIZE_TYPE__ __hbs_minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(minbitno); \ + __register __SIZE_TYPE__ __hbs_maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(maxbitno); \ __HYBRID_PRIVATE_BITSET_NCLEAR_IMPL(self, __hbs_minbyte, __hbs_maxbyte, (minbitno & __HYBRID_BITSET_WORD_BMSK), (maxbitno & __HYBRID_BITSET_WORD_BMSK)) #define __HYBRID_PRIVATE_BITSET_NSET(self, minbitno, maxbitno) \ - __register __SIZE_TYPE__ __hbs_minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(minbitno); \ - __register __SIZE_TYPE__ __hbs_maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(maxbitno); \ + __register __SIZE_TYPE__ __hbs_minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(minbitno); \ + __register __SIZE_TYPE__ __hbs_maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(maxbitno); \ __HYBRID_PRIVATE_BITSET_NSET_IMPL(self, __hbs_minbyte, __hbs_maxbyte, (minbitno & __HYBRID_BITSET_WORD_BMSK), (maxbitno & __HYBRID_BITSET_WORD_BMSK)) /* >> void __hybrid_bitset_nclear(__hybrid_bitset_t *self, size_t minbitno, size_t maxbitno); @@ -221,61 +248,33 @@ __LOCAL __ATTR_NONNULL((1)) void #define __HYBRID_PRIVATE_BITSET_FFC_I_IMPL(self, n_bits, result) \ - __register __SIZE_TYPE__ __bffc_bindex, __bffc_maxbyte; \ - __bffc_maxbyte = __HYBRID_BITSET_BYTE(n_bits - 1); \ + __register __SSIZE_TYPE__ __bffc_bindex, __bffc_maxword; \ + __bffc_maxword = __HYBRID_BITSET_WORD(n_bits - 1); \ result = -1; \ - for (__bffc_bindex = 0; __bffc_bindex <= __bffc_maxbyte; ++__bffc_bindex) { \ + for (__bffc_bindex = 0; __bffc_bindex <= __bffc_maxword; ++__bffc_bindex) { \ __hybrid_bitset_t __word = self[__bffc_bindex]; \ if (__word == __HYBRID_BITSET_WORD_BMAX) \ continue; \ result = __bffc_bindex << __HYBRID_BITSET_WORD_SHFT; \ - while (__word & 1) { \ - ++result; \ - __word >>= 1; \ - } \ + result += __HYBRID_BITSET_WORD_CTO(__word); \ if __unlikely(result >= nbits) \ result = -1; \ break; \ } -#define __HYBRID_PRIVATE_BITSET_FFS_I_IMPL(self, n_bits, result) \ - __register __SIZE_TYPE__ __bffs_bindex, __bffs_maxbyte; \ - __bffs_maxbyte = __HYBRID_BITSET_BYTE(n_bits - 1); \ - result = -1; \ - for (__bffs_bindex = 0; __bffs_bindex <= __bffs_maxbyte; ++__bffs_bindex) { \ - __hybrid_bitset_t __word = self[__bffs_bindex]; \ - if (__word == 0) \ - continue; \ - result = (__bffs_bindex << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTZ(__word); \ - if __unlikely(result >= nbits) \ - result = -1; \ - break; \ - } -#define __HYBRID_PRIVATE_BITSET_FFC_IMPL(self, n_bits, result) \ - __register __SIZE_TYPE__ __bffc_bindex, __bffc_maxbyte; \ - __bffc_maxbyte = __HYBRID_BITSET_BYTE(n_bits - 1); \ - result = (n_bits); \ - for (__bffc_bindex = 0; __bffc_bindex <= __bffc_maxbyte; ++__bffc_bindex) { \ - __hybrid_bitset_t __word = self[__bffc_bindex]; \ - if (__word == __HYBRID_BITSET_WORD_BMAX) \ +#define __HYBRID_PRIVATE_BITSET_FFS_I_IMPL(self, n_bits, result) \ + __register __SSIZE_TYPE__ __bffs_bindex, __bffs_maxbyte; \ + __bffs_maxbyte = __HYBRID_BITSET_WORD(n_bits - 1); \ + result = -1; \ + for (__bffs_bindex = 0; __bffs_bindex <= __bffs_maxbyte; ++__bffs_bindex) { \ + __hybrid_bitset_t __word = self[__bffs_bindex]; \ + if (__word == 0) \ continue; \ - result = __bffc_bindex << __HYBRID_BITSET_WORD_SHFT; \ - while (__word & 1) { \ - ++result; \ - __word >>= 1; \ - } \ + result = (__bffs_bindex << __HYBRID_BITSET_WORD_SHFT); \ + result += __HYBRID_BITSET_WORD_CTZ(__word); \ + if __unlikely(result >= nbits) \ + result = -1; \ break; \ } -#define __HYBRID_PRIVATE_BITSET_FFS_IMPL(self, n_bits, result) \ - __register __SIZE_TYPE__ __bffs_bindex, __bffs_maxbyte; \ - __bffs_maxbyte = __HYBRID_BITSET_BYTE(n_bits - 1); \ - result = (n_bits); \ - for (__bffs_bindex = 0; __bffs_bindex <= __bffs_maxbyte; ++__bffs_bindex) { \ - __hybrid_bitset_t __word = self[__bffs_bindex]; \ - if (__word == 0) \ - continue; \ - result = (__bffs_bindex << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTZ(__word); \ - break; \ - } /* >> void __hybrid_bitset_ffc_i(__hybrid_bitset_t const *self, size_t n_bits, ssize_t *p_value); @@ -308,7 +307,17 @@ __LOCAL __ATTR_NONNULL((1)) void __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ __NOTHROW_NCX(__hybrid_bitset_ffc)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { __register __SIZE_TYPE__ __result; - __HYBRID_PRIVATE_BITSET_FFC_IMPL(__self, __n_bits, __result); + __register __SSIZE_TYPE__ __bffc_bindex, __bffc_maxword; + __bffc_maxword = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); + __result = __n_bits; + for (__bffc_bindex = 0; __bffc_bindex <= __bffc_maxword; ++__bffc_bindex) { + __hybrid_bitset_t __word = __self[__bffc_bindex]; + if (__word == __HYBRID_BITSET_WORD_BMAX) + continue; + __result = __bffc_bindex << __HYBRID_BITSET_WORD_SHFT; + __result += __HYBRID_BITSET_WORD_CTO(__word); + break; + } return __result; } @@ -317,10 +326,236 @@ __NOTHROW_NCX(__hybrid_bitset_ffc)(__hybrid_bitset_t const *__restrict __self, _ __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ __NOTHROW_NCX(__hybrid_bitset_ffs)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { __register __SIZE_TYPE__ __result; - __HYBRID_PRIVATE_BITSET_FFS_IMPL(__self, __n_bits, __result); + __register __SSIZE_TYPE__ __bffs_bindex, __bffs_maxbyte; + __bffs_maxbyte = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); + __result = __n_bits; + for (__bffs_bindex = 0; __bffs_bindex <= __bffs_maxbyte; ++__bffs_bindex) { + __hybrid_bitset_t __word = __self[(__SIZE_TYPE__)__bffs_bindex]; + if (__word == 0) + continue; + __result = ((__SIZE_TYPE__)__bffs_bindex << __HYBRID_BITSET_WORD_SHFT); + __result += __HYBRID_BITSET_WORD_CTZ(__word); + break; + } return __result; } +/* Find the last bitno within [0, n_bits) that is off and return + * its index. If no such bit exists, return some value `>= n_bits'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_flc)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { + __register __SIZE_TYPE__ __result; + __register __SSIZE_TYPE__ __bffc_maxword; + __bffc_maxword = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); + if (__n_bits & __HYBRID_BITSET_WORD_BMSK) { + __hybrid_bitset_t __word = __self[__bffc_maxword]; + __word |= ~(((__hybrid_bitset_t)1 << (__n_bits & __HYBRID_BITSET_WORD_BMSK)) - 1); + if (__word != __HYBRID_BITSET_WORD_BMAX) { + __result = (__SIZE_TYPE__)__bffc_maxword << __HYBRID_BITSET_WORD_SHFT; + __result += (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLO(__word)); + return __result; + } + --__bffc_maxword; + } + __result = __n_bits; + while (__bffc_maxword >= 0) { + __hybrid_bitset_t __word = __self[(__SIZE_TYPE__)__bffc_maxword]; + if (__word == __HYBRID_BITSET_WORD_BMAX) { + --__bffc_maxword; + continue; + } + __result = (__SIZE_TYPE__)__bffc_maxword << __HYBRID_BITSET_WORD_SHFT; + __result += (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLO(__word)); + break; + } + return __result; +} + +/* Find the last bitno within [0, n_bits) that is on and return + * its index. If no such bit exists, return some value `>= n_bits'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_fls)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { + __register __SIZE_TYPE__ __result; + __register __SSIZE_TYPE__ __bffc_maxword; + __bffc_maxword = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); + if (__n_bits & __HYBRID_BITSET_WORD_BMSK) { + __hybrid_bitset_t __word = __self[__bffc_maxword]; + __word &= ((__hybrid_bitset_t)1 << (__n_bits & __HYBRID_BITSET_WORD_BMSK)) - 1; + if (__word != 0) { + __result = (__SIZE_TYPE__)__bffc_maxword << __HYBRID_BITSET_WORD_SHFT; + __result += (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLZ(__word)); + return __result; + } + --__bffc_maxword; + } + __result = __n_bits; + while (__bffc_maxword >= 0) { + __hybrid_bitset_t __word = __self[(__SIZE_TYPE__)__bffc_maxword]; + if (__word == 0) { + --__bffc_maxword; + continue; + } + __result = (__SIZE_TYPE__)__bffc_maxword << __HYBRID_BITSET_WORD_SHFT; + __result += (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLZ(__word)); + break; + } + return __result; +} + +/* Find the first bitno within [minbitno,maxbitno] that is on and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_nffs)(__hybrid_bitset_t const *__restrict __self, + __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + __register __hybrid_bitset_t __word; + __word = __self[__maxword] & ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | + (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + if (__word != 0) { + __word >>= __minbitno & __HYBRID_BITSET_WORD_BMSK; + return __minbitno + __HYBRID_BITSET_WORD_CTZ(__word); + } + } else { + __register __SIZE_TYPE__ __i; + __register __hybrid_bitset_t __word; + __word = __self[__minword] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))); + if (__word != 0) { + __word >>= __minbitno & __HYBRID_BITSET_WORD_BMSK; + return __minbitno + __HYBRID_BITSET_WORD_CTZ(__word); + } + for (__i = __minword + 1; __i < __maxword; ++__i) { + __word = __self[__i]; + if (__word != 0) + return (__minword << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTZ(__word); + } + __word = __self[__maxword] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)); + if (__word != 0) + return (__maxword << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTZ(__word); + } + return __maxbitno + 1; +} + +/* Find the first bitno within [minbitno,maxbitno] that is off and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_nffc)(__hybrid_bitset_t const *__restrict __self, + __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + __register __hybrid_bitset_t __word; + __register __hybrid_bitset_t __mask; + __mask = ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | + (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + __word = __self[__maxword] & __mask; + if (__word != __mask) { + __word >>= __minbitno & __HYBRID_BITSET_WORD_BMSK; + return __minbitno + __HYBRID_BITSET_WORD_CTO(__word); + } + } else { + __register __SIZE_TYPE__ __i; + __register __hybrid_bitset_t __word; + __register __hybrid_bitset_t __mask; + __mask = ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))); + __word = __self[__minword] & __mask; + if (__word != __mask) { + __word >>= __minbitno & __HYBRID_BITSET_WORD_BMSK; + return __minbitno + __HYBRID_BITSET_WORD_CTO(__word); + } + for (__i = __minword + 1; __i < __maxword; ++__i) { + __word = __self[__i]; + if (__word != __HYBRID_BITSET_WORD_BMAX) + return (__minword << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTO(__word); + } + __mask = ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)); + __word = __self[__maxword] & __mask; + if (__word != __mask) + return (__maxword << __HYBRID_BITSET_WORD_SHFT) + __HYBRID_BITSET_WORD_CTO(__word); + } + return __maxbitno + 1; +} + +/* Find the last bitno within [minbitno,maxbitno] that is on and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_nfls)(__hybrid_bitset_t const *__restrict __self, + __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + __register __hybrid_bitset_t __word; + __word = __self[__maxword] & ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | + (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + if (__word != 0) { + __word <<= __HYBRID_BITSET_WORD_BMSK - (__maxbitno & __HYBRID_BITSET_WORD_BMSK); + return __maxbitno - __HYBRID_BITSET_WORD_CLZ(__word); + } + } else { + __register __SIZE_TYPE__ __i; + __register __hybrid_bitset_t __word; + __word = __self[__maxword] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)); + if (__word != 0) { + __word <<= __HYBRID_BITSET_WORD_BMSK - (__maxbitno & __HYBRID_BITSET_WORD_BMSK); + return __maxbitno - __HYBRID_BITSET_WORD_CLZ(__word); + } + for (__i = __maxword - 1; __i > __minword; --__i) { + __word = __self[__i]; + if (__word != 0) { + return (__minword << __HYBRID_BITSET_WORD_SHFT) + + (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLZ(__word)); + } + } + __word = __self[__minword] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))); + if (__word != 0) + return __minbitno + (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLZ(__word)); + } + return __maxbitno + 1; +} + +/* Find the last bitno within [minbitno,maxbitno] that is off and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_nflc)(__hybrid_bitset_t const *__restrict __self, + __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + __register __hybrid_bitset_t __word; + __register __hybrid_bitset_t __mask; + __mask = ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | + (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + __word = __self[__maxword] & __mask; + if (__word != __mask) { + __word <<= __HYBRID_BITSET_WORD_BMSK - (__maxbitno & __HYBRID_BITSET_WORD_BMSK); + return __maxbitno - __HYBRID_BITSET_WORD_CLO(__word); + } + } else { + __register __SIZE_TYPE__ __i; + __register __hybrid_bitset_t __mask; + __register __hybrid_bitset_t __word; + __mask = ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)); + __word = __self[__maxword] & __mask; + if (__word != __mask) { + __word <<= __HYBRID_BITSET_WORD_BMSK - (__maxbitno & __HYBRID_BITSET_WORD_BMSK); + return __maxbitno - __HYBRID_BITSET_WORD_CLO(__word); + } + for (__i = __maxword - 1; __i > __minword; --__i) { + __word = __self[__i]; + if (__word != __HYBRID_BITSET_WORD_BMAX) { + return (__minword << __HYBRID_BITSET_WORD_SHFT) + + (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLO(__word)); + } + } + __mask = ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))); + __word = __self[__minword] & __mask; + if (__word != __mask) + return __minbitno + (__HYBRID_BITSET_WORD_BMSK - __HYBRID_BITSET_WORD_CLO(__word)); + } + return __maxbitno + 1; +} + /* Check if the bitset contains any 1-elements */ __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __BOOL @@ -359,21 +594,21 @@ __NOTHROW_NCX(__hybrid_bitset_allset)(__hybrid_bitset_t const *__restrict __self __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __BOOL __NOTHROW_NCX(__hybrid_bitset_nanyset)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { - __register __SIZE_TYPE__ __minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__minbitno); - __register __SIZE_TYPE__ __maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__maxbitno); - if (__minbyte >= __maxbyte) { - if (__self[__maxbyte] & ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + if (__self[__maxword] & ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)))) return 1; } else { __register __SIZE_TYPE__ __i; - if (__self[__minbyte] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK)))) + if (__self[__minword] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK)))) return 1; - for (__i = __minbyte + 1; __i < __maxbyte; ++__i) { + for (__i = __minword + 1; __i < __maxword; ++__i) { if (__self[__i] != 0) return 1; } - if (__self[__maxbyte] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))) + if (__self[__maxword] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))) return 1; } return 0; @@ -383,25 +618,25 @@ __NOTHROW_NCX(__hybrid_bitset_nanyset)(__hybrid_bitset_t const *__restrict __sel __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __BOOL __NOTHROW_NCX(__hybrid_bitset_nallset)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { - __register __SIZE_TYPE__ __minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__minbitno); - __register __SIZE_TYPE__ __maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__maxbitno); - if (__minbyte >= __maxbyte) { + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { __hybrid_bitset_t __mask = ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); - if ((__self[__maxbyte] & __mask) != __mask) + if ((__self[__maxword] & __mask) != __mask) return 0; } else { __register __SIZE_TYPE__ __i; __hybrid_bitset_t __mask; __mask = ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))); - if ((__self[__minbyte] & __mask) != __mask) + if ((__self[__minword] & __mask) != __mask) return 0; - for (__i = __minbyte + 1; __i < __maxbyte; ++__i) { + for (__i = __minword + 1; __i < __maxword; ++__i) { if (__self[__i] != __HYBRID_BITSET_WORD_BMAX) return 0; } __mask = ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)); - if ((__self[__maxbyte] & __mask) != __mask) + if ((__self[__maxword] & __mask) != __mask) return 0; } return 1; @@ -426,62 +661,106 @@ __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ __NOTHROW_NCX(__hybrid_bitset_npopcount)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __minbitno, __SIZE_TYPE__ __maxbitno) { __SIZE_TYPE__ __result; - __register __SIZE_TYPE__ __minbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__minbitno); - __register __SIZE_TYPE__ __maxbyte = (__SIZE_TYPE__)__HYBRID_BITSET_BYTE(__maxbitno); - if (__minbyte >= __maxbyte) { - __result = __HYBRID_BITSET_WORD_POPCOUNT(__self[__maxbyte] & + __register __SIZE_TYPE__ __minword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__minbitno); + __register __SIZE_TYPE__ __maxword = (__SIZE_TYPE__)__HYBRID_BITSET_WORD(__maxbitno); + if (__minword >= __maxword) { + __result = __HYBRID_BITSET_WORD_POPCOUNT(__self[__maxword] & ~((__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK))) | (__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1)))); } else { __register __SIZE_TYPE__ __i; - __result = __HYBRID_BITSET_WORD_POPCOUNT(__self[__minbyte] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK)))); - for (__i = __minbyte + 1; __i < __maxbyte; ++__i) + __result = __HYBRID_BITSET_WORD_POPCOUNT(__self[__minword] & ~(__HYBRID_BITSET_WORD_BMAX >> (__HYBRID_BITSET_WORD_BITS - (__minbitno & __HYBRID_BITSET_WORD_BMSK)))); + for (__i = __minword + 1; __i < __maxword; ++__i) __result += __HYBRID_BITSET_WORD_POPCOUNT(__self[__i]); - __result += __HYBRID_BITSET_WORD_POPCOUNT(__self[__maxbyte] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + __result += __HYBRID_BITSET_WORD_POPCOUNT(__self[__maxword] & ~(__HYBRID_BITSET_WORD_BMAX << ((__maxbitno & __HYBRID_BITSET_WORD_BMSK) + 1))); + } + return __result; +} + +/* Count-leading-zeroes (returns ">= n_bits" when `self' doesn't contain any set bits) */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_clz)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { + __SIZE_TYPE__ __result = 0; + __SSIZE_TYPE__ __maxword = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); + if (__n_bits & __HYBRID_BITSET_WORD_BMSK) { + __hybrid_bitset_t __word = __self[__maxword]; + __word <<= __HYBRID_BITSET_WORD_BITS - (__n_bits & __HYBRID_BITSET_WORD_BMSK); + if (__word != 0) + return __HYBRID_BITSET_WORD_CLZ(__word); + __result = __n_bits & __HYBRID_BITSET_WORD_BMSK; + --__maxword; + } + if (__maxword >= 0) { + __hybrid_bitset_t __word; + for (;;) { + if (__maxword < 0) + return __n_bits; + __word = __self[__maxword]; + if (__word != 0) + break; + __result += __HYBRID_BITSET_WORD_BITS; + --__maxword; + } + __result += __HYBRID_BITSET_WORD_CLZ(__word); } return __result; } -/* Count-leading-zeroes (undefined when `self' doesn't contain any set bits) */ +/* Count-trailing-zeroes (returns ">= n_bits" when `self' doesn't contain any set bits) */ __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ -__NOTHROW_NCX(__hybrid_bitset_clz)(__hybrid_bitset_t const *__restrict __self) { +__NOTHROW_NCX(__hybrid_bitset_ctz)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { + __hybrid_bitset_t __word; __SIZE_TYPE__ __result = 0; - for (; *__self == 0; ++__self) + for (;;) { + if (__n_bits < __HYBRID_BITSET_WORD_BITS) + break; + __word = *__self; + if (__word != 0) + return __result + __HYBRID_BITSET_WORD_CTZ(__word); __result += __HYBRID_BITSET_WORD_BITS; - return __result + __HYBRID_BITSET_WORD_CLZ(*__self); + ++__self; + } + if (__n_bits) { + __word = *__self & (((__hybrid_bitset_t)1 << (__n_bits /*& __HYBRID_BITSET_WORD_BMSK*/)) - 1); + __result += __HYBRID_BITSET_WORD_CTZ(__word); + } + return __result; } -/* Count-trailing-zeroes (undefined when `self' doesn't contain any set bits) */ +/* Count-leading-zeroes (hard undefined behavior when `self' doesn't contain any set bits) */ __LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ -__NOTHROW_NCX(__hybrid_bitset_ctz)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { +__NOTHROW_NCX(__hybrid_bitset_rawclz)(__hybrid_bitset_t const *__restrict __self, __SIZE_TYPE__ __n_bits) { + __hybrid_bitset_t __word; __SIZE_TYPE__ __result = 0; - __SIZE_TYPE__ __byteoff = __n_bits >> __HYBRID_BITSET_WORD_SHFT; + __SSIZE_TYPE__ __maxword = __HYBRID_BITSET_WORD((__SSIZE_TYPE__)__n_bits - 1); if (__n_bits & __HYBRID_BITSET_WORD_BMSK) { - __hybrid_bitset_t __word = __self[__byteoff]; + __word = __self[__maxword]; __word <<= __HYBRID_BITSET_WORD_BITS - (__n_bits & __HYBRID_BITSET_WORD_BMSK); - if (__word) { - while (!(__word & __HYBRID_BITSET_WORD_SIGN)) { - __word <<= 1; - ++__result; - } - return __result; - } + if (__word != 0) + return __HYBRID_BITSET_WORD_CLZ(__word); __result = __n_bits & __HYBRID_BITSET_WORD_BMSK; + --__maxword; } - if (__byteoff) { - __hybrid_bitset_t __word; - --__byteoff; - for (; __self[__byteoff] == 0; --__byteoff) - __result += __HYBRID_BITSET_WORD_BITS; - __word = __self[__byteoff]; - while (!(__word & __HYBRID_BITSET_WORD_SIGN)) { - ++__result; - __word <<= 1; - } + for (;;) { + __word = __self[__maxword]; + if (__word != 0) + break; + __result += __HYBRID_BITSET_WORD_BITS; + --__maxword; } + __result += __HYBRID_BITSET_WORD_CLZ(__word); return __result; } +/* Count-trailing-zeroes (hard undefined behavior when `self' doesn't contain any set bits) */ +__LOCAL __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ +__NOTHROW_NCX(__hybrid_bitset_rawctz)(__hybrid_bitset_t const *__restrict __self) { + __SIZE_TYPE__ __result = 0; + for (; *__self == 0; ++__self) + __result += __HYBRID_BITSET_WORD_BITS; + return __result + __HYBRID_BITSET_WORD_CTZ(*__self); +} + __DECL_END #endif /* __CC__ */ diff --git a/kos/include/hybrid/bitset.h b/kos/include/hybrid/bitset.h index f3e26d2acf..712a3c6190 100644 --- a/kos/include/hybrid/bitset.h +++ b/kos/include/hybrid/bitset.h @@ -29,7 +29,7 @@ __DECL_BEGIN #define _BITSET_WORD_BITS __HYBRID_BITSET_WORD_BITS /* 8: # of bits in a bitset_t-word */ #define _BITSET_WORD_BMSK __HYBRID_BITSET_WORD_BMSK /* 7: # of bits in a bitset_t-word minus 1 */ #define _BITSET_WORD_SHFT __HYBRID_BITSET_WORD_SHFT /* 3: log2(_BITSET_BITS) */ -#define _BITSET_BYTE(bitno) __HYBRID_BITSET_BYTE(bitno) /* Index of `bitno' in `bitset_t[]' */ +#define _BITSET_WORD(bitno) __HYBRID_BITSET_WORD(bitno) /* Index of `bitno' in `bitset_t[]' */ #define _BITSET_MASK(bitno) __HYBRID_BITSET_MASK(bitno) /* Mask for `bitno' in `bitset_t[]' */ #define BITSET_LENGTHOF(n_bits) __HYBRID_BITSET_LENGTHOF(n_bits) /* Length of `bitset_t[]' for `n_bits' bits */ #define BITSET_SIZEOF(n_bits) __HYBRID_BITSET_SIZEOF(n_bits) /* Size (in bytes) of `bitset_t[]' for `n_bits' bits */ @@ -85,6 +85,30 @@ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_ffc(bitset_t * its index. If no such bit exists, return some value `>= n_bits'. */ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_ffs(bitset_t const *self, __SIZE_TYPE__ n_bits); +/* Find the last bitno within [0, n_bits) that is off and return + * its index. If no such bit exists, return some value `>= n_bits'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_flc(bitset_t const *self, __SIZE_TYPE__ n_bits); + +/* Find the last bitno within [0, n_bits) that is on and return + * its index. If no such bit exists, return some value `>= n_bits'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_fls(bitset_t const *self, __SIZE_TYPE__ n_bits); + +/* Find the first bitno within [minbitno,maxbitno] that is on and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_nffs(bitset_t const *self, __SIZE_TYPE__ minbitno, __SIZE_TYPE__ maxbitno); + +/* Find the first bitno within [minbitno,maxbitno] that is off and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_nffc(bitset_t const *self, __SIZE_TYPE__ minbitno, __SIZE_TYPE__ maxbitno); + +/* Find the last bitno within [minbitno,maxbitno] that is on and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_nfls(bitset_t const *self, __SIZE_TYPE__ minbitno, __SIZE_TYPE__ maxbitno); + +/* Find the last bitno within [minbitno,maxbitno] that is off and return + * its index. If no such bit exists, return some value `> maxbitno'. */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_nflc(bitset_t const *self, __SIZE_TYPE__ minbitno, __SIZE_TYPE__ maxbitno); + /* Check if the bitset contains any 1-elements */ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __BOOL bitset_anyset(bitset_t const *self, __SIZE_TYPE__ n_bits); @@ -103,11 +127,17 @@ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_popcount(bit /* Returns the # of 1-bits within the given range */ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_npopcount(bitset_t const *self, __SIZE_TYPE__ minbitno, __SIZE_TYPE__ maxbitno); -/* Count-leading-zeroes (undefined when `self' doesn't contain any set bits) */ -__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_clz(bitset_t const *__restrict self); +/* Count-leading-zeroes (returns ">= n_bits" when `self' doesn't contain any set bits) */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_clz(bitset_t const *__restrict self, __SIZE_TYPE__ n_bits); -/* Count-trailing-zeroes (undefined when `self' doesn't contain any set bits) */ +/* Count-trailing-zeroes (returns ">= n_bits" when `self' doesn't contain any set bits) */ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_ctz(bitset_t const *__restrict self, __SIZE_TYPE__ n_bits); + +/* Count-leading-zeroes (hard undefined behavior when `self' doesn't contain any set bits) */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_rawclz(bitset_t const *__restrict self, __SIZE_TYPE__ n_bits); + +/* Count-trailing-zeroes (hard undefined behavior when `self' doesn't contain any set bits) */ +__ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_rawctz(bitset_t const *__restrict self); #else /* __INTELLISENSE__ */ #define bitset_t __hybrid_bitset_t #define bitset_test(self, bitno) __hybrid_bitset_test(self, bitno) @@ -123,14 +153,22 @@ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_ctz(bitset_t #define bitset_ffs_i(self, n_bits, p_value) __hybrid_bitset_ffs_i(self, n_bits, p_value) #define bitset_ffc(self, n_bits) __hybrid_bitset_ffc(self, n_bits) #define bitset_ffs(self, n_bits) __hybrid_bitset_ffs(self, n_bits) +#define bitset_flc(self, n_bits) __hybrid_bitset_flc(self, n_bits) +#define bitset_fls(self, n_bits) __hybrid_bitset_fls(self, n_bits) +#define bitset_nffc(self, minbitno, maxbitno) __hybrid_bitset_nffc(self, minbitno, maxbitno) +#define bitset_nffs(self, minbitno, maxbitno) __hybrid_bitset_nffs(self, minbitno, maxbitno) +#define bitset_nflc(self, minbitno, maxbitno) __hybrid_bitset_nflc(self, minbitno, maxbitno) +#define bitset_nfls(self, minbitno, maxbitno) __hybrid_bitset_nfls(self, minbitno, maxbitno) #define bitset_anyset(self, n_bits) __hybrid_bitset_anyset(self, n_bits) #define bitset_allset(self, n_bits) __hybrid_bitset_allset(self, n_bits) #define bitset_nanyset(self, minbitno, maxbitno) __hybrid_bitset_nanyset(self, minbitno, maxbitno) #define bitset_nallset(self, minbitno, maxbitno) __hybrid_bitset_nallset(self, minbitno, maxbitno) #define bitset_popcount(self, n_bits) __hybrid_bitset_popcount(self, n_bits) #define bitset_npopcount(self, minbitno, maxbitno) __hybrid_bitset_npopcount(self, minbitno, maxbitno) -#define bitset_clz(self) __hybrid_bitset_clz(self) +#define bitset_clz(self, n_bits) __hybrid_bitset_clz(self, n_bits) #define bitset_ctz(self, n_bits) __hybrid_bitset_ctz(self, n_bits) +#define bitset_rawclz(self, n_bits) __hybrid_bitset_rawclz(self, n_bits) +#define bitset_rawctz(self) __hybrid_bitset_rawctz(self) #endif /* !__INTELLISENSE__ */ /* >> size_t bitno; @@ -141,6 +179,18 @@ __ATTR_PURE __ATTR_WUNUSED __ATTR_NONNULL((1)) __SIZE_TYPE__ bitset_ctz(bitset_t * >> } */ #define bitset_foreach(bitno, self, n_bits) \ __hybrid_bitset_foreach(bitno, self, n_bits) +#define bitset_nforeach(bitno, self, minbitno, maxbitno) \ + __hybrid_bitset_nforeach(bitno, self, minbitno, maxbitno) + +/* Atomic bitset operations. */ +#ifdef __GUARD_HYBRID___ATOMIC_H +#define bitset_atomic_set(self, bitno) __hybrid_bitset_atomic_set(self, bitno) +#define bitset_atomic_clear(self, bitno) __hybrid_bitset_atomic_clear(self, bitno) +#define bitset_atomic_flip(self, bitno) __hybrid_bitset_atomic_flip(self, bitno) +#define bitset_atomic_fetchset(self, bitno) __hybrid_bitset_atomic_fetchset(self, bitno) +#define bitset_atomic_fetchclear(self, bitno) __hybrid_bitset_atomic_fetchclear(self, bitno) +#define bitset_atomic_fetchflip(self, bitno) __hybrid_bitset_atomic_fetchflip(self, bitno) +#endif /* __GUARD_HYBRID___ATOMIC_H */ __DECL_END #endif /* __CC__ */ diff --git a/kos/include/sys/bitstring.h b/kos/include/sys/bitstring.h index 9cbd80ba9e..9e749c5c04 100644 --- a/kos/include/sys/bitstring.h +++ b/kos/include/sys/bitstring.h @@ -146,10 +146,10 @@ __NOTHROW_NCX(__PRIVATE_bit_ffs)(bitstr_t const *__restrict __self, __SIZE_TYPE_ #define bit_popcount(self, nbits) __hybrid_bitset_popcount(self, nbits) /* Count-leading-zeroes (undefined when `self' doesn't contain any set bits) */ -#define bit_clz(self) (unsigned int)__hybrid_bitset_clz(self) +#define bit_clz(self, nbits) (unsigned int)__hybrid_bitset_rawclz(self, nbits) /* Count-trailing-zeroes (undefined when `self' doesn't contain any set bits) */ -#define bit_ctz(self, nbits) (unsigned int)__hybrid_bitset_ctz(self, nbits) +#define bit_ctz(self) (unsigned int)__hybrid_bitset_rawctz(self) #endif /* __USE_KOS */ __DECL_END diff --git a/kos/src/_verify/include-everything.h b/kos/src/_verify/include-everything.h index 529122cbc6..d760d3970c 100644 --- a/kos/src/_verify/include-everything.h +++ b/kos/src/_verify/include-everything.h @@ -694,12 +694,14 @@ incdir(""); #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -708,6 +710,7 @@ incdir(""); #include #include #include +#include #include #include #include @@ -767,6 +770,8 @@ incdir(""); #include #include #include +#include +#include #include #include #include diff --git a/kos/src/libregex b/kos/src/libregex index 48178c22ab..32878c623e 160000 --- a/kos/src/libregex +++ b/kos/src/libregex @@ -1 +1 @@ -Subproject commit 48178c22abb2df0066496d3cbd9eb2f7af97f57b +Subproject commit 32878c623e08c48803b8a57974d6ca28ed74a6f0