xref: /freebsd/lib/libc/stdbit/stdc_trailing_zeros.c (revision 6296500a85c8474e3ff3fe2f8e4a9d56dd0acd64)
1*6296500aSRobert Clausecker /*
2*6296500aSRobert Clausecker  * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
3*6296500aSRobert Clausecker  *
4*6296500aSRobert Clausecker  * SPDX-License-Identifier: BSD-2-Clause
5*6296500aSRobert Clausecker  */
6*6296500aSRobert Clausecker 
7*6296500aSRobert Clausecker #include <assert.h>
8*6296500aSRobert Clausecker #include <limits.h>
9*6296500aSRobert Clausecker #include <stdbit.h>
10*6296500aSRobert Clausecker 
11*6296500aSRobert Clausecker /* Ensure we do not shift 1U out of range. */
12*6296500aSRobert Clausecker static_assert(UCHAR_WIDTH < UINT_WIDTH,
13*6296500aSRobert Clausecker     "stdc_trailing_zeros_uc needs UCHAR_WIDTH < UINT_WIDTH");
14*6296500aSRobert Clausecker 
15*6296500aSRobert Clausecker unsigned int
stdc_trailing_zeros_uc(unsigned char x)16*6296500aSRobert Clausecker stdc_trailing_zeros_uc(unsigned char x)
17*6296500aSRobert Clausecker {
18*6296500aSRobert Clausecker 	return (__builtin_ctz(x | 1U << UCHAR_WIDTH));
19*6296500aSRobert Clausecker }
20*6296500aSRobert Clausecker 
21*6296500aSRobert Clausecker /* Ensure we do not shift 1U out of range. */
22*6296500aSRobert Clausecker static_assert(USHRT_WIDTH < UINT_WIDTH,
23*6296500aSRobert Clausecker     "stdc_trailing_zeros_uc needs USHRT_WIDTH < UINT_WIDTH");
24*6296500aSRobert Clausecker 
25*6296500aSRobert Clausecker unsigned int
stdc_trailing_zeros_us(unsigned short x)26*6296500aSRobert Clausecker stdc_trailing_zeros_us(unsigned short x)
27*6296500aSRobert Clausecker {
28*6296500aSRobert Clausecker 	return (__builtin_ctz(x | 1U << USHRT_WIDTH));
29*6296500aSRobert Clausecker }
30*6296500aSRobert Clausecker 
31*6296500aSRobert Clausecker unsigned int
stdc_trailing_zeros_ui(unsigned int x)32*6296500aSRobert Clausecker stdc_trailing_zeros_ui(unsigned int x)
33*6296500aSRobert Clausecker {
34*6296500aSRobert Clausecker 	if (x == 0U)
35*6296500aSRobert Clausecker 		return (UINT_WIDTH);
36*6296500aSRobert Clausecker 
37*6296500aSRobert Clausecker 	return (__builtin_ctz(x));
38*6296500aSRobert Clausecker }
39*6296500aSRobert Clausecker 
40*6296500aSRobert Clausecker unsigned int
stdc_trailing_zeros_ul(unsigned long x)41*6296500aSRobert Clausecker stdc_trailing_zeros_ul(unsigned long x)
42*6296500aSRobert Clausecker {
43*6296500aSRobert Clausecker 	if (x == 0UL)
44*6296500aSRobert Clausecker 		return (ULONG_WIDTH);
45*6296500aSRobert Clausecker 
46*6296500aSRobert Clausecker 	return (__builtin_ctzl(x));
47*6296500aSRobert Clausecker }
48*6296500aSRobert Clausecker 
49*6296500aSRobert Clausecker unsigned int
stdc_trailing_zeros_ull(unsigned long long x)50*6296500aSRobert Clausecker stdc_trailing_zeros_ull(unsigned long long x)
51*6296500aSRobert Clausecker {
52*6296500aSRobert Clausecker 	if (x == 0ULL)
53*6296500aSRobert Clausecker 		return (ULLONG_WIDTH);
54*6296500aSRobert Clausecker 
55*6296500aSRobert Clausecker 	return (__builtin_ctzll(x));
56*6296500aSRobert Clausecker }
57