From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_LOW,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 10125 invoked from network); 31 May 2023 14:49:09 -0000 Received: from second.openwall.net (193.110.157.125) by inbox.vuxu.org with ESMTPUTF8; 31 May 2023 14:49:09 -0000 Received: (qmail 28245 invoked by uid 550); 31 May 2023 14:48:51 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 27995 invoked from network); 31 May 2023 14:48:50 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=inria.fr; s=dc; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=b0l2S0joiAN8wQVbwyAlZvYXbpXaxvjY3Aal+FrnL9U=; b=dMzeGPemHX5Ivh5bLFrwKlCov9TRn6f/6Zp/b85YYogCcXlglGsWT2DU aFOoWltvnUwr/gs3FD+Ywnuparh0JAaMn6g1uQ8+gAoyPTZ2veXRzgl6Z 3boRHOyc23Ft8cazGE8Oy+vh/frvYLd+Rv0K0AZPlkWEa3GBkNnS0iUYM 8=; Authentication-Results: mail3-relais-sop.national.inria.fr; dkim=none (message not signed) header.i=none; spf=SoftFail smtp.mailfrom=Jens.Gustedt@inria.fr; dmarc=fail (p=none dis=none) d=inria.fr X-IronPort-AV: E=Sophos;i="6.00,207,1681164000"; d="scan'208";a="57467757" From: Jens Gustedt To: musl@lists.openwall.com Date: Wed, 31 May 2023 16:48:34 +0200 Message-Id: <6cf62f9e770900a2225fff53056a63bf8927cd23.1685538619.git.Jens.Gustedt@inria.fr> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [musl] [C23 stdbit.h 2/2] C23: add the bit and byte utilities Warning: this is not yet ready for inclusion, because the C23 may still change last minute. For the moment these interfaces have too much redundancy. This is probably the feature that has the most impact in terms of numbers: a new header with a whole bunch of function interfaces. The implementation is based on the internal bit operations that we already had, plus a new implementation of a popcount feature. This is probably suboptimal in some cases, but compiler implementors could easily have builtins for these, now they are standardized. Since these interfaces are new and in a separate header with a proper prefix, we do not protect them with a feature macro and also we do not make the symbols weak. We also synthesize versions for these functions for 128 bit types if the platform has them. To claim full support for these types it is necessary to provide them through the type-generic interfaces. Since when compiling musl we may not assume that the compiler knows about 128 bit types, the implementation has two levels. The bottom level are internal functions that receive the high and low word as separate parameters. Around these functions are synthesized static inline wrappers for __int128 and _BitInt(128), if these types are available. These wrappers always stay on the application side and are never part of the musl library object itself. --- include/stdbit.h | 442 ++++++++++++++++++++++++++++++++++++++++++++ src/stdbit/stdbit.c | 231 +++++++++++++++++++++++ 2 files changed, 673 insertions(+) create mode 100644 include/stdbit.h create mode 100644 src/stdbit/stdbit.c diff --git a/include/stdbit.h b/include/stdbit.h new file mode 100644 index 00000000..cf6d196a --- /dev/null +++ b/include/stdbit.h @@ -0,0 +1,442 @@ +#ifndef __STDC_VERSION_STDBIT_H__ +#define __STDC_VERSION_STDBIT_H__ 202311L + +#include +#include + +#ifndef __STDC_ENDIAN_BIG__ +#define __STDC_ENDIAN_BIG__ __BIG_ENDIAN +#endif +#ifndef __STDC_ENDIAN_LITTLE__ +#define __STDC_ENDIAN_LITTLE__ __LITTLE_ENDIAN +#endif +#ifndef __STDC_ENDIAN_NATIVE__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER +#endif + +unsigned int stdc_count_ones_uc(unsigned char) __unsequenced; +unsigned int stdc_count_ones_us(unsigned short) __unsequenced; +unsigned int stdc_count_ones_ui(unsigned int) __unsequenced; +unsigned int stdc_count_ones_ul(unsigned long) __unsequenced; +unsigned int stdc_count_ones_ull(unsigned long long) __unsequenced; + +unsigned int stdc_count_zeros_uc(unsigned char) __unsequenced; +unsigned int stdc_count_zeros_us(unsigned short) __unsequenced; +unsigned int stdc_count_zeros_ui(unsigned int) __unsequenced; +unsigned int stdc_count_zeros_ul(unsigned long) __unsequenced; +unsigned int stdc_count_zeros_ull(unsigned long long) __unsequenced; + +unsigned int stdc_leading_zeros_uc(unsigned char) __unsequenced; +unsigned int stdc_leading_zeros_us(unsigned short) __unsequenced; +unsigned int stdc_leading_zeros_ui(unsigned int) __unsequenced; +unsigned int stdc_leading_zeros_ul(unsigned long) __unsequenced; +unsigned int stdc_leading_zeros_ull(unsigned long long) __unsequenced; + +unsigned int stdc_leading_ones_uc(unsigned char) __unsequenced; +unsigned int stdc_leading_ones_us(unsigned short) __unsequenced; +unsigned int stdc_leading_ones_ui(unsigned int) __unsequenced; +unsigned int stdc_leading_ones_ul(unsigned long) __unsequenced; +unsigned int stdc_leading_ones_ull(unsigned long long) __unsequenced; + +unsigned int stdc_trailing_zeros_uc(unsigned char) __unsequenced; +unsigned int stdc_trailing_zeros_us(unsigned short) __unsequenced; +unsigned int stdc_trailing_zeros_ui(unsigned int) __unsequenced; +unsigned int stdc_trailing_zeros_ul(unsigned long) __unsequenced; +unsigned int stdc_trailing_zeros_ull(unsigned long long) __unsequenced; + +unsigned int stdc_trailing_ones_uc(unsigned char) __unsequenced; +unsigned int stdc_trailing_ones_us(unsigned short) __unsequenced; +unsigned int stdc_trailing_ones_ui(unsigned int) __unsequenced; +unsigned int stdc_trailing_ones_ul(unsigned long) __unsequenced; +unsigned int stdc_trailing_ones_ull(unsigned long long) __unsequenced; + +unsigned int stdc_first_leading_zero_uc(unsigned char) __unsequenced; +unsigned int stdc_first_leading_zero_us(unsigned short) __unsequenced; +unsigned int stdc_first_leading_zero_ui(unsigned int) __unsequenced; +unsigned int stdc_first_leading_zero_ul(unsigned long) __unsequenced; +unsigned int stdc_first_leading_zero_ull(unsigned long long) __unsequenced; + +unsigned int stdc_first_leading_one_uc(unsigned char) __unsequenced; +unsigned int stdc_first_leading_one_us(unsigned short) __unsequenced; +unsigned int stdc_first_leading_one_ui(unsigned int) __unsequenced; +unsigned int stdc_first_leading_one_ul(unsigned long) __unsequenced; +unsigned int stdc_first_leading_one_ull(unsigned long long) __unsequenced; + +unsigned int stdc_first_trailing_one_uc(unsigned char) __unsequenced; +unsigned int stdc_first_trailing_one_us(unsigned short) __unsequenced; +unsigned int stdc_first_trailing_one_ui(unsigned int) __unsequenced; +unsigned int stdc_first_trailing_one_ul(unsigned long) __unsequenced; +unsigned int stdc_first_trailing_one_ull(unsigned long long) __unsequenced; + +unsigned int stdc_first_trailing_zero_uc(unsigned char) __unsequenced; +unsigned int stdc_first_trailing_zero_us(unsigned short) __unsequenced; +unsigned int stdc_first_trailing_zero_ui(unsigned int) __unsequenced; +unsigned int stdc_first_trailing_zero_ul(unsigned long) __unsequenced; +unsigned int stdc_first_trailing_zero_ull(unsigned long long) __unsequenced; + +_Bool stdc_has_single_bit_uc(unsigned char) __unsequenced; +_Bool stdc_has_single_bit_us(unsigned short) __unsequenced; +_Bool stdc_has_single_bit_ui(unsigned int) __unsequenced; +_Bool stdc_has_single_bit_ul(unsigned long) __unsequenced; +_Bool stdc_has_single_bit_ull(unsigned long long) __unsequenced; + +unsigned int stdc_bit_width_uc(unsigned char) __unsequenced; +unsigned int stdc_bit_width_us(unsigned short) __unsequenced; +unsigned int stdc_bit_width_ui(unsigned int) __unsequenced; +unsigned int stdc_bit_width_ul(unsigned long) __unsequenced; +unsigned int stdc_bit_width_ull(unsigned long long) __unsequenced; + +unsigned char stdc_bit_floor_uc(unsigned char) __unsequenced; +unsigned short stdc_bit_floor_us(unsigned short) __unsequenced; +unsigned int stdc_bit_floor_ui(unsigned int) __unsequenced; +unsigned long stdc_bit_floor_ul(unsigned long) __unsequenced; +unsigned long long stdc_bit_floor_ull(unsigned long long) __unsequenced; + +unsigned char stdc_bit_ceil_uc(unsigned char) __unsequenced; +unsigned short stdc_bit_ceil_us(unsigned short) __unsequenced; +unsigned int stdc_bit_ceil_ui(unsigned int) __unsequenced; +unsigned long stdc_bit_ceil_ul(unsigned long) __unsequenced; +unsigned long long stdc_bit_ceil_ull(unsigned long long) __unsequenced; + +unsigned int __leading_zeros_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __leading_ones_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __trailing_zeros_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __trailing_ones_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __first_leading_zero_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __first_leading_one_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __first_trailing_zero_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __first_trailing_one_u128(unsigned long long, unsigned long long) __unsequenced; +unsigned int __count_zeros_u128(unsigned long long, unsigned long long) __unsequenced; +int __count_ones_u128(unsigned long long, unsigned long long) __unsequenced; +_Bool __has_single_bit_u128(unsigned long long, unsigned long long) __unsequenced; +void __bit_floor_u128(unsigned long long[2]); +void __bit_ceil_u128(unsigned long long[2]); + + +#if __SIZEOF_INT128__ + +static __inline +unsigned int __stdc_leading_zeros_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_leading_ones_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_trailing_zeros_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_trailing_ones_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_first_leading_zero_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_first_leading_one_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_first_trailing_zero_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_first_trailing_one_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned int __stdc_count_zeros_u128(unsigned __int128) __unsequenced; + +static __inline +int __stdc_count_ones_u128(unsigned __int128) __unsequenced; + +static __inline +_Bool __stdc_has_single_bit_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned __int128 __stdc_bit_floor_u128(unsigned __int128) __unsequenced; + +static __inline +unsigned __int128 __stdc_bit_ceil_u128(unsigned __int128) __unsequenced; + + +static __inline +unsigned int __stdc_leading_zeros_u128(unsigned __int128 __val) +{ + return __leading_zeros_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_leading_ones_u128(unsigned __int128 __val) +{ + return __leading_ones_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_trailing_zeros_u128(unsigned __int128 __val) +{ + return __trailing_zeros_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_trailing_ones_u128(unsigned __int128 __val) +{ + return __trailing_ones_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_leading_zero_u128(unsigned __int128 __val) +{ + return __first_leading_zero_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_leading_one_u128(unsigned __int128 __val) +{ + return __first_leading_one_u128(__val, __val>>64); +} + +#define __stdc_bit_width_u128 __stdc_first_leading_one_u128 + +static __inline +unsigned int __stdc_first_trailing_zero_u128(unsigned __int128 __val) +{ + return __first_trailing_zero_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_trailing_one_u128(unsigned __int128 __val) +{ + return __first_trailing_one_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_count_zeros_u128(unsigned __int128 __val) +{ + return __count_zeros_u128(__val, __val>>64); +} + +static __inline +int __stdc_count_ones_u128(unsigned __int128 __val) +{ + return __count_ones_u128(__val, __val>>64); +} + +static __inline +_Bool __stdc_has_single_bit_u128(unsigned __int128 __val) +{ + return __has_single_bit_u128(__val, __val>>64); +} + +static __inline +unsigned __int128 __stdc_bit_floor_u128(unsigned __int128 __val) +{ + unsigned long long __ar[2] = { __val, __val>>64, }; + __bit_floor_u128(__ar); + return (((unsigned __int128)__ar[1])<<64) | __ar[0]; +} + +static __inline +unsigned __int128 __stdc_bit_ceil_u128(unsigned __int128 __val) +{ + unsigned long long __ar[2] = { __val, __val>>64, }; + __bit_ceil_u128(__ar); + return (((unsigned __int128)__ar[1])<<64) | __ar[0]; +} + +#endif + +#if __has_bitint128 + +static __inline +unsigned int __stdc_leading_zeros_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_leading_ones_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_trailing_zeros_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_trailing_ones_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_first_leading_zero_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_first_leading_one_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_first_trailing_zero_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_first_trailing_one_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned int __stdc_count_zeros_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +int __stdc_count_ones_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +_Bool __stdc_has_single_bit_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned _BitInt(128) __stdc_bit_floor_b128(unsigned _BitInt(128)) __unsequenced; + +static __inline +unsigned _BitInt(128) __stdc_bit_ceil_b128(unsigned _BitInt(128)) __unsequenced; + + +static __inline +unsigned int __stdc_leading_zeros_b128(unsigned _BitInt(128) __val) +{ + return __leading_zeros_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_leading_ones_b128(unsigned _BitInt(128) __val) +{ + return __leading_ones_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_trailing_zeros_b128(unsigned _BitInt(128) __val) +{ + return __trailing_zeros_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_trailing_ones_b128(unsigned _BitInt(128) __val) +{ + return __trailing_ones_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_leading_zero_b128(unsigned _BitInt(128) __val) +{ + return __first_leading_zero_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_leading_one_b128(unsigned _BitInt(128) __val) +{ + return __first_leading_one_u128(__val, __val>>64); +} + +#define __stdc_bit_width_b128 __stdc_first_leading_one_b128 + +static __inline +unsigned int __stdc_first_trailing_zero_b128(unsigned _BitInt(128) __val) +{ + return __first_trailing_zero_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_first_trailing_one_b128(unsigned _BitInt(128) __val) +{ + return __first_trailing_one_u128(__val, __val>>64); +} + +static __inline +unsigned int __stdc_count_zeros_b128(unsigned _BitInt(128) __val) +{ + return __count_zeros_u128(__val, __val>>64); +} + +static __inline +int __stdc_count_ones_b128(unsigned _BitInt(128) __val) +{ + return __count_ones_u128(__val, __val>>64); +} + +static __inline +_Bool __stdc_has_single_bit_b128(unsigned _BitInt(128) __val) +{ + return __has_single_bit_u128(__val, __val>>64); +} + +static __inline +unsigned _BitInt(128) __stdc_bit_floor_b128(unsigned _BitInt(128) __val) +{ + unsigned long long __ar[2] = { __val, __val>>64, }; + __bit_floor_u128(__ar); + return (((unsigned _BitInt(128))__ar[1])<<64) | __ar[0]; +} + +static __inline +unsigned _BitInt(128) __stdc_bit_ceil_b128(unsigned _BitInt(128) __val) +{ + unsigned long long __ar[2] = { __val, __val>>64, }; + __bit_ceil_u128(__ar); + return (((unsigned _BitInt(128))__ar[1])<<64) | __ar[0]; +} + +#endif + +/* Start the definition of the type-generic interfaces. We have to + include 128 bit types and _BitInt types if they exist. */ +#if __STDC_VERSION__ >= 201112L + +#if __SIZEOF_INT128__ +#if __has_bitint128 +#define __U128_SELECTION(F) \ + unsigned __int128: __stdc_ ## F ## _u128, \ + unsigned _BitInt(128): __stdc_ ## F ## _b128 \ + , /* don't remove comma */ +#else +#define __U128_SELECTION(F) \ + unsigned __int128: __stdc_ ## F ## _u128 \ + , /* don't remove comma */ +#endif +#else +#if __has_bitint128 +#define __U128_SELECTION(F) \ + unsigned _BitInt(128): __stdc_ ## F ## _b128 \ + , /* don't remove comma */ +#else +#define __U128_SELECTION(F) +#endif +#endif + +#if __BITINT_MAXWIDTH__ +#define __BITINT_SELECTION(F) \ + unsigned _BitInt(8): stdc_ ## F ## _uc, \ + unsigned _BitInt(16): stdc_ ## F ## _us, \ + unsigned _BitInt(32): stdc_ ## F ## _ui, \ + unsigned _BitInt(64): stdc_ ## F ## _ull \ + , /* don't remove comma */ +#else +#define __BITINT_SELECTION(F) +#endif + +/* The following macros are intended that they may receive multiple + macro arguments, but which should expand into a single C expression + after preprocessing. */ + +#define __stdc_bit_generic(F, ...) \ + _Generic(__VA_ARGS__, \ + __BITINT_SELECTION(F) \ + __U128_SELECTION(F) \ + unsigned char: stdc_ ## F ## _uc, \ + unsigned short: stdc_ ## F ## _us, \ + unsigned int: stdc_ ## F ## _ui, \ + unsigned long: stdc_ ## F ## _ul, \ + unsigned long long: stdc_ ## F ## _ull \ + )(__VA_ARGS__) + +#define stdc_leading_zeros(...) __stdc_bit_generic(leading_zeros, __VA_ARGS__) +#define stdc_leading_ones(...) __stdc_bit_generic(leading_ones, __VA_ARGS__) +#define stdc_trailing_zeros(...) __stdc_bit_generic(trailing_zeros, __VA_ARGS__) +#define stdc_trailing_ones(...) __stdc_bit_generic(trailing_ones, __VA_ARGS__) + +#define stdc_first_leading_zero(...) __stdc_bit_generic(first_leading_zero, __VA_ARGS__) +#define stdc_first_leading_one(...) __stdc_bit_generic(first_leading_one, __VA_ARGS__) +#define stdc_first_trailing_zero(...) __stdc_bit_generic(first_trailing_zero, __VA_ARGS__) +#define stdc_first_trailing_one(...) __stdc_bit_generic(first_trailing_one, __VA_ARGS__) + +#define stdc_count_zeros(...) __stdc_bit_generic(count_zeros, __VA_ARGS__) +#define stdc_count_ones(...) __stdc_bit_generic(count_ones, __VA_ARGS__) + +#define stdc_has_single_bit(...) __stdc_bit_generic(has_single_bit, __VA_ARGS__) +#define stdc_bit_width(...) __stdc_bit_generic(bit_width, __VA_ARGS__) +#define stdc_bit_floor(...) __stdc_bit_generic(bit_floor, __VA_ARGS__) +#define stdc_bit_ceil(...) __stdc_bit_generic(bit_ceil, __VA_ARGS__) + +#endif +#endif diff --git a/src/stdbit/stdbit.c b/src/stdbit/stdbit.c new file mode 100644 index 00000000..b42514dd --- /dev/null +++ b/src/stdbit/stdbit.c @@ -0,0 +1,231 @@ +#include +#include +#include "atomic.h" + +#define a_clz a_clz_32 +#define a_ctz a_ctz_32 +#if ULONG_WIDTH == 32 +#define a_clz_l a_clz_32 +#define a_popcount_l a_popcount_32 +#else +#define a_clz_l a_clz_64 +#define a_popcount_l a_popcount_64 +#endif +#define a_clz_ll a_clz_64 +#define a_ctz_ll a_ctz_64 + +unsigned int stdc_count_ones_uc(unsigned char __val) { return a_popcount_8(__val); } +unsigned int stdc_count_ones_us(unsigned short __val) { return a_popcount_16(__val); } +unsigned int stdc_count_ones_ui(unsigned int __val) { return a_popcount_32(__val); } +unsigned int stdc_count_ones_ul(unsigned long __val) { return a_popcount_l(__val); } +unsigned int stdc_count_ones_ull(unsigned long long __val) { return a_popcount_64(__val); } + +unsigned int stdc_count_zeros_uc(unsigned char __val) { return stdc_count_ones_uc(~__val); } +unsigned int stdc_count_zeros_us(unsigned short __val) { return stdc_count_ones_us(~__val); } +unsigned int stdc_count_zeros_ui(unsigned int __val) { return stdc_count_ones_ui(~__val); } +unsigned int stdc_count_zeros_ul(unsigned long __val) { return stdc_count_ones_ul(~__val); } +unsigned int stdc_count_zeros_ull(unsigned long long __val) { return stdc_count_ones_ull(~__val); } + +unsigned int stdc_leading_zeros_uc(unsigned char __val) +{ + return __val + ? (a_clz(__val) - (UINT_WIDTH-UCHAR_WIDTH)) + : UCHAR_WIDTH; +} + +unsigned int stdc_leading_zeros_us(unsigned short __val) +{ + return __val + ? (a_clz(__val) - (UINT_WIDTH-USHRT_WIDTH)) + : USHRT_WIDTH; +} + +unsigned int stdc_leading_zeros_ui(unsigned int __val) { return __val ? a_clz(__val) : UINT_WIDTH; } +unsigned int stdc_leading_zeros_ul(unsigned long __val) { return __val ? a_clz_l(__val) : ULONG_WIDTH; } +unsigned int stdc_leading_zeros_ull(unsigned long long __val) { return __val ? a_clz_ll(__val) : ULLONG_WIDTH; } + +unsigned int stdc_leading_ones_uc(unsigned char __val) { return stdc_leading_zeros_uc(~__val); } +unsigned int stdc_leading_ones_us(unsigned short __val) { return stdc_leading_zeros_us(~__val); } +unsigned int stdc_leading_ones_ui(unsigned int __val) { return stdc_leading_zeros_ui(~__val); } +unsigned int stdc_leading_ones_ul(unsigned long __val) { return stdc_leading_zeros_ul(~__val); } +unsigned int stdc_leading_ones_ull(unsigned long long __val) { return stdc_leading_zeros_ull(~__val); } + +unsigned int stdc_trailing_zeros_uc(unsigned char __val) { return __val ? a_ctz(__val) : UCHAR_WIDTH; } +unsigned int stdc_trailing_zeros_us(unsigned short __val) { return __val ? a_ctz(__val) : USHRT_WIDTH; } +unsigned int stdc_trailing_zeros_ui(unsigned int __val) { return __val ? a_ctz(__val) : UINT_WIDTH; } +unsigned int stdc_trailing_zeros_ul(unsigned long __val) { return __val ? a_ctz_l(__val) : ULONG_WIDTH; } +unsigned int stdc_trailing_zeros_ull(unsigned long long __val) { return __val ? a_ctz_ll(__val) : ULLONG_WIDTH; } + +unsigned int stdc_trailing_ones_uc(unsigned char __val) { return stdc_trailing_zeros_uc(~__val); } +unsigned int stdc_trailing_ones_us(unsigned short __val) { return stdc_trailing_zeros_us(~__val); } +unsigned int stdc_trailing_ones_ui(unsigned int __val) { return stdc_trailing_zeros_ui(~__val); } +unsigned int stdc_trailing_ones_ul(unsigned long __val) { return stdc_trailing_zeros_ul(~__val); } +unsigned int stdc_trailing_ones_ull(unsigned long long __val) { return stdc_trailing_zeros_ull(~__val); } + +unsigned int stdc_first_leading_zero_uc(unsigned char __val) { return (UCHAR_WIDTH-stdc_leading_ones_uc(__val)); } +unsigned int stdc_first_leading_zero_us(unsigned short __val) { return (USHRT_WIDTH-stdc_leading_ones_us(__val)); } +unsigned int stdc_first_leading_zero_ui(unsigned int __val) { return (UINT_WIDTH-stdc_leading_ones_ui(__val)); } +unsigned int stdc_first_leading_zero_ul(unsigned long __val) { return (ULONG_WIDTH-stdc_leading_ones_ul(__val)); } +unsigned int stdc_first_leading_zero_ull(unsigned long long __val) { return (ULLONG_WIDTH-stdc_leading_ones_ull(__val)); } + +unsigned int stdc_first_leading_one_uc(unsigned char __val) { return (UCHAR_WIDTH-stdc_leading_zeros_uc(__val)); } +unsigned int stdc_first_leading_one_us(unsigned short __val) { return (USHRT_WIDTH-stdc_leading_zeros_us(__val)); } +unsigned int stdc_first_leading_one_ui(unsigned int __val) { return (UINT_WIDTH-stdc_leading_zeros_ui(__val)); } +unsigned int stdc_first_leading_one_ul(unsigned long __val) { return (ULONG_WIDTH-stdc_leading_zeros_ul(__val)); } +unsigned int stdc_first_leading_one_ull(unsigned long long __val) { return (ULLONG_WIDTH-stdc_leading_zeros_ull(__val)); } + +unsigned int stdc_first_trailing_one_uc(unsigned char __val) { return __val ? a_ctz(__val) : 0; } +unsigned int stdc_first_trailing_one_us(unsigned short __val) { return __val ? a_ctz(__val) : 0; } +unsigned int stdc_first_trailing_one_ui(unsigned int __val) { return __val ? a_ctz(__val) : 0; } +unsigned int stdc_first_trailing_one_ul(unsigned long __val) { return __val ? a_ctz_l(__val) : 0; } +unsigned int stdc_first_trailing_one_ull(unsigned long long __val) { return __val ? a_ctz_ll(__val) : 0; } + + +unsigned int stdc_first_trailing_zero_uc(unsigned char __val) { return stdc_first_trailing_one_uc(~__val); } +unsigned int stdc_first_trailing_zero_us(unsigned short __val) { return stdc_first_trailing_one_us(~__val); } +unsigned int stdc_first_trailing_zero_ui(unsigned int __val) { return stdc_first_trailing_one_ui(~__val); } +unsigned int stdc_first_trailing_zero_ul(unsigned long __val) { return stdc_first_trailing_one_ul(~__val); } +unsigned int stdc_first_trailing_zero_ull(unsigned long long __val) { return stdc_first_trailing_one_ull(~__val); } + +_Bool stdc_has_single_bit_uc(unsigned char __s) { return __s ? !(__s & (__s - 1)) : 0; } +_Bool stdc_has_single_bit_us(unsigned short __s) { return __s ? !(__s & (__s - 1)) : 0; } +_Bool stdc_has_single_bit_ui(unsigned int __s) { return __s ? !(__s & (__s - 1)) : 0; } +_Bool stdc_has_single_bit_ul(unsigned long __s) { return __s ? !(__s & (__s - 1)) : 0; } +_Bool stdc_has_single_bit_ull(unsigned long long __s) { return __s ? !(__s & (__s - 1)) : 0; } + +unsigned int stdc_bit_width_uc(unsigned char __val) { return stdc_first_leading_one_uc(__val); } +unsigned int stdc_bit_width_us(unsigned short __val) { return stdc_first_leading_one_us(__val); } +unsigned int stdc_bit_width_ui(unsigned int __val) { return stdc_first_leading_one_ui(__val); } +unsigned int stdc_bit_width_ul(unsigned long __val) { return stdc_first_leading_one_ul(__val); } +unsigned int stdc_bit_width_ull(unsigned long long __val) { return stdc_first_leading_one_ull(__val); } + +unsigned char stdc_bit_floor_uc(unsigned char __val) { return __val ? 1U<<(stdc_first_leading_one_uc(__val)-1) : 0U; } +unsigned short stdc_bit_floor_us(unsigned short __val) { return __val ? 1U<<(stdc_first_leading_one_us(__val)-1) : 0U; } +unsigned int stdc_bit_floor_ui(unsigned int __val) { return __val ? 1U<<(stdc_first_leading_one_ui(__val)-1) : 0U; } +unsigned long stdc_bit_floor_ul(unsigned long __val) { return __val ? 1UL<<(stdc_first_leading_one_ul(__val)-1) : 0UL; } +unsigned long long stdc_bit_floor_ull(unsigned long long __val) { return __val ? 1ULL<<(stdc_first_leading_one_ull(__val)-1) : 0ULL; } + +unsigned char stdc_bit_ceil_uc(unsigned char __val) +{ + return (__val & ((__val - 1)&UCHAR_MAX)) + ? 1U< ULONG_MAX/2 ? 0UL : 1UL< ULLONG_MAX/2 ? 0ULL : 1ULL< (1ULL << 63)) __lohi[1] = 1ULL; + __lohi[0] = stdc_bit_ceil_ull(__lohi[0]); + } +} -- 2.34.1