From patchwork Fri Mar 13 17:03:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Sherrill X-Patchwork-Id: 131682 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 4CD4B4B1A357 for ; Fri, 13 Mar 2026 17:04:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4CD4B4B1A357 X-Original-To: newlib@sourceware.org Delivered-To: newlib@sourceware.org Received: from mail-yw1-f176.google.com (mail-yw1-f176.google.com [209.85.128.176]) by sourceware.org (Postfix) with ESMTPS id 31B864B3588E for ; Fri, 13 Mar 2026 17:04:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 31B864B3588E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rtems.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 31B864B3588E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.128.176 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773421461; cv=none; b=KaAijbwHAkOdm+t+59nx9Yu3TUHa5W2gCFdiT3btH9NAktpGYoFDhuoWCNSmbbRrBFQcXhdr/FCc7dB6E8I/pEM5NV3FC5fWxP/o5XJpPDqf4HwMnI2KStcG+9JRhxtUWqDROFlUBRkISV4uWBb5rfQc+r1FCca9Xy9VD0EViYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773421461; c=relaxed/simple; bh=qA1bSjFSyHhGWs8n/C6FT981N5N8t7JPtQiL2NAMlWA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=BRZMKivvoNfZ6Kw3HyYvdShSYUYE0y5304UyxEwFbkpEkZ8emW+jlFonKNG2xxt7liWHWvXGNnL6HKnHNOaaFL3/rli+NOEp7USowurfJm4Pl4WdFC1+/kyw/RUIDQ66BqvjuV5QhZqUo0RQV38x1BLYmY3JKhYG+OzEJScc84o= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 31B864B3588E Received: by mail-yw1-f176.google.com with SMTP id 00721157ae682-7985d11da10so26087777b3.3 for ; Fri, 13 Mar 2026 10:04:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773421460; x=1774026260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ysELile8gRIQamuq+QT+xycgI3eFVY8rI9hhZ+iZynM=; b=fBAQynWyR+8GTSMM0QLey7NTZGNE2MfFsluK9W8hpaFZtqa0xexIwwgRYfnRjhQJqw ztzg2WJ/wXfIo3ct78jzJM+faPh5OAE92CO1wGOtSn/rewebjAraLOPi85BBs8SdvxGJ A4Y7kbbsQVIZjRBFIS6tyQ4gyaHJ2/Eslh6LITmqLtlYG0/FG/21xyltT3sMU9qDV4hx SQyFfSf2QIhyL8igr0eLpEU+3Dk9o5THDWR8zGpe2tJjgWw63mKLUMCqe+VqsLK7MCL3 Yg8twznhU7tZqeyCt5LFFLO48ZdE++s9M597hZWNwt6hNWcdl+Oz2Bskl0/KCkIVQyle vEig== X-Gm-Message-State: AOJu0YzWJmdeKrcWnd7NCTA8ehdjn0LU/z7/T4cmRGEcfqqRxg80gB8k Rvz/APMmNS70U0VjeYJPGBFF05qt3ONc4K0nQXoonV4ciwqplbS7P8ScX9+lCA== X-Gm-Gg: ATEYQzzsjgZtAe/+X6ligxJx9PVETnk5Ntlf4/Qz2myhsQMC/TRJ1J9k6GAsq1wImee H/Dp2jGDWeQRHzW+77OjfX9aRb3ICGX7QUABN3GI5gqEcq71lcNDhgKkVpgyzpPNYd6WmQHn4Gv VgMi/49Y6j3U/q/vmbgfgTCkuAwJuGHHB8C0k6HF8hKzeXEM186V1DdWIGB2P4yuBzDzvciMnbq 8n/KEzWZjeEVcoclvbDr33DhoT2xVVd4wUZfsLYUbO9bpj0pYX/3n8WJM1YZUknr/TTUVaMuWLp am0yQkbBPbVdUo8HP9FPh51S0kI5DBIG/lKroH3YT+qOhjC0Jc6dvY0sQyh4syOVRndQpvi0Z2b 5pCEDpD8cP90DzYVE5vZUD9WcEEw0B3dAv7DT5BLFZg+mJQnecyrlyysV3B5GlZZ2JB/KffgF/J XTBgBRfJ9aCMv9FDe63Cq62MhGdMDjP2BKTqk5plusJd+FnWayGmThU2LKF1iBgg== X-Received: by 2002:a05:690c:6d83:b0:79a:2ea7:36c8 with SMTP id 00721157ae682-79a2ea75000mr575677b3.35.1773421459174; Fri, 13 Mar 2026 10:04:19 -0700 (PDT) Received: from gitlab.oarcorp.com (d27-96-189-151.evv.wideopenwest.com. [96.27.151.189]) by smtp.gmail.com with ESMTPSA id 00721157ae682-79917f3d09fsm48536807b3.50.2026.03.13.10.04.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Mar 2026 10:04:18 -0700 (PDT) From: Joel Sherrill To: newlib@sourceware.org Cc: Joel Sherrill Subject: [PATCH v0 1/2] newlib/libc: Add C23 stdbit.h from FreeBSD Date: Fri, 13 Mar 2026 12:03:34 -0500 Message-ID: <20260313170335.2240233-2-joel@rtems.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260313170335.2240233-1-joel@rtems.org> References: <20260313170335.2240233-1-joel@rtems.org> MIME-Version: 1.0 X-Spam-Status: No, score=-3036.2 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: newlib-bounces~patchwork=sourceware.org@sourceware.org FreeBSD git hash: 80b4129bef8b908eb19fe47853cb6e45e4513d76 --- newlib/libc/include/stdbit.h | 124 ++++++++++++++++++ newlib/libc/stdbit/stdc_bit_ceil.3 | 81 ++++++++++++ newlib/libc/stdbit/stdc_bit_ceil.c | 71 ++++++++++ newlib/libc/stdbit/stdc_bit_floor.3 | 83 ++++++++++++ newlib/libc/stdbit/stdc_bit_floor.c | 53 ++++++++ newlib/libc/stdbit/stdc_bit_width.3 | 104 +++++++++++++++ newlib/libc/stdbit/stdc_bit_width.c | 53 ++++++++ newlib/libc/stdbit/stdc_count_ones.3 | 85 ++++++++++++ newlib/libc/stdbit/stdc_count_ones.c | 38 ++++++ newlib/libc/stdbit/stdc_count_zeros.3 | 84 ++++++++++++ newlib/libc/stdbit/stdc_count_zeros.c | 38 ++++++ newlib/libc/stdbit/stdc_first_leading_one.3 | 93 +++++++++++++ newlib/libc/stdbit/stdc_first_leading_one.c | 57 ++++++++ newlib/libc/stdbit/stdc_first_leading_zero.3 | 92 +++++++++++++ newlib/libc/stdbit/stdc_first_leading_zero.c | 57 ++++++++ newlib/libc/stdbit/stdc_first_trailing_one.3 | 110 ++++++++++++++++ newlib/libc/stdbit/stdc_first_trailing_one.c | 52 ++++++++ newlib/libc/stdbit/stdc_first_trailing_zero.3 | 93 +++++++++++++ newlib/libc/stdbit/stdc_first_trailing_zero.c | 53 ++++++++ newlib/libc/stdbit/stdc_has_single_bit.3 | 98 ++++++++++++++ newlib/libc/stdbit/stdc_has_single_bit.c | 38 ++++++ newlib/libc/stdbit/stdc_leading_ones.3 | 86 ++++++++++++ newlib/libc/stdbit/stdc_leading_ones.c | 60 +++++++++ newlib/libc/stdbit/stdc_leading_zeros.3 | 86 ++++++++++++ newlib/libc/stdbit/stdc_leading_zeros.c | 60 +++++++++ newlib/libc/stdbit/stdc_trailing_ones.3 | 86 ++++++++++++ newlib/libc/stdbit/stdc_trailing_ones.c | 56 ++++++++ newlib/libc/stdbit/stdc_trailing_zeros.3 | 87 ++++++++++++ newlib/libc/stdbit/stdc_trailing_zeros.c | 56 ++++++++ 29 files changed, 2134 insertions(+) create mode 100644 newlib/libc/include/stdbit.h create mode 100644 newlib/libc/stdbit/stdc_bit_ceil.3 create mode 100644 newlib/libc/stdbit/stdc_bit_ceil.c create mode 100644 newlib/libc/stdbit/stdc_bit_floor.3 create mode 100644 newlib/libc/stdbit/stdc_bit_floor.c create mode 100644 newlib/libc/stdbit/stdc_bit_width.3 create mode 100644 newlib/libc/stdbit/stdc_bit_width.c create mode 100644 newlib/libc/stdbit/stdc_count_ones.3 create mode 100644 newlib/libc/stdbit/stdc_count_ones.c create mode 100644 newlib/libc/stdbit/stdc_count_zeros.3 create mode 100644 newlib/libc/stdbit/stdc_count_zeros.c create mode 100644 newlib/libc/stdbit/stdc_first_leading_one.3 create mode 100644 newlib/libc/stdbit/stdc_first_leading_one.c create mode 100644 newlib/libc/stdbit/stdc_first_leading_zero.3 create mode 100644 newlib/libc/stdbit/stdc_first_leading_zero.c create mode 100644 newlib/libc/stdbit/stdc_first_trailing_one.3 create mode 100644 newlib/libc/stdbit/stdc_first_trailing_one.c create mode 100644 newlib/libc/stdbit/stdc_first_trailing_zero.3 create mode 100644 newlib/libc/stdbit/stdc_first_trailing_zero.c create mode 100644 newlib/libc/stdbit/stdc_has_single_bit.3 create mode 100644 newlib/libc/stdbit/stdc_has_single_bit.c create mode 100644 newlib/libc/stdbit/stdc_leading_ones.3 create mode 100644 newlib/libc/stdbit/stdc_leading_ones.c create mode 100644 newlib/libc/stdbit/stdc_leading_zeros.3 create mode 100644 newlib/libc/stdbit/stdc_leading_zeros.c create mode 100644 newlib/libc/stdbit/stdc_trailing_ones.3 create mode 100644 newlib/libc/stdbit/stdc_trailing_ones.c create mode 100644 newlib/libc/stdbit/stdc_trailing_zeros.3 create mode 100644 newlib/libc/stdbit/stdc_trailing_zeros.c diff --git a/newlib/libc/include/stdbit.h b/newlib/libc/include/stdbit.h new file mode 100644 index 000000000..a529676be --- /dev/null +++ b/newlib/libc/include/stdbit.h @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __STDC_VERSION_STDBIT_H__ +#define __STDC_VERSION_STDBIT_H__ 202311L + +#include + +/* byte order */ +#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__ +#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__ + +#define __generic_bitfunc(func, x) (_Generic(x, \ + unsigned char: func ## _uc, \ + unsigned short: func ## _us, \ + unsigned int: func ## _ui, \ + unsigned long: func ## _ul, \ + unsigned long long: func ## _ull)(x)) + +__BEGIN_DECLS +unsigned int stdc_leading_zeros_uc(unsigned char) __pure2; +unsigned int stdc_leading_zeros_us(unsigned short) __pure2; +unsigned int stdc_leading_zeros_ui(unsigned int) __pure2; +unsigned int stdc_leading_zeros_ul(unsigned long) __pure2; +unsigned int stdc_leading_zeros_ull(unsigned long long) __pure2; +#define stdc_leading_zeros(x) __generic_bitfunc(stdc_leading_zeros, x) + +unsigned int stdc_leading_ones_uc(unsigned char) __pure2; +unsigned int stdc_leading_ones_us(unsigned short) __pure2; +unsigned int stdc_leading_ones_ui(unsigned int) __pure2; +unsigned int stdc_leading_ones_ul(unsigned long) __pure2; +unsigned int stdc_leading_ones_ull(unsigned long long) __pure2; +#define stdc_leading_ones(x) __generic_bitfunc(stdc_leading_ones, x) + +unsigned int stdc_trailing_zeros_uc(unsigned char) __pure2; +unsigned int stdc_trailing_zeros_us(unsigned short) __pure2; +unsigned int stdc_trailing_zeros_ui(unsigned int) __pure2; +unsigned int stdc_trailing_zeros_ul(unsigned long) __pure2; +unsigned int stdc_trailing_zeros_ull(unsigned long long) __pure2; +#define stdc_trailing_zeros(x) __generic_bitfunc(stdc_trailing_zeros, x) + +unsigned int stdc_trailing_ones_uc(unsigned char) __pure2; +unsigned int stdc_trailing_ones_us(unsigned short) __pure2; +unsigned int stdc_trailing_ones_ui(unsigned int) __pure2; +unsigned int stdc_trailing_ones_ul(unsigned long) __pure2; +unsigned int stdc_trailing_ones_ull(unsigned long long) __pure2; +#define stdc_trailing_ones(x) __generic_bitfunc(stdc_trailing_ones, x) + +unsigned int stdc_first_leading_zero_uc(unsigned char) __pure2; +unsigned int stdc_first_leading_zero_us(unsigned short) __pure2; +unsigned int stdc_first_leading_zero_ui(unsigned int) __pure2; +unsigned int stdc_first_leading_zero_ul(unsigned long) __pure2; +unsigned int stdc_first_leading_zero_ull(unsigned long long) __pure2; +#define stdc_first_leading_zero(x) __generic_bitfunc(stdc_first_leading_zero, x) + +unsigned int stdc_first_leading_one_uc(unsigned char) __pure2; +unsigned int stdc_first_leading_one_us(unsigned short) __pure2; +unsigned int stdc_first_leading_one_ui(unsigned int) __pure2; +unsigned int stdc_first_leading_one_ul(unsigned long) __pure2; +unsigned int stdc_first_leading_one_ull(unsigned long long) __pure2; +#define stdc_first_leading_one(x) __generic_bitfunc(stdc_first_leading_one, x) + +unsigned int stdc_first_trailing_zero_uc(unsigned char) __pure2; +unsigned int stdc_first_trailing_zero_us(unsigned short) __pure2; +unsigned int stdc_first_trailing_zero_ui(unsigned int) __pure2; +unsigned int stdc_first_trailing_zero_ul(unsigned long) __pure2; +unsigned int stdc_first_trailing_zero_ull(unsigned long long) __pure2; +#define stdc_first_trailing_zero(x) __generic_bitfunc(stdc_first_trailing_zero, x) + +unsigned int stdc_first_trailing_one_uc(unsigned char) __pure2; +unsigned int stdc_first_trailing_one_us(unsigned short) __pure2; +unsigned int stdc_first_trailing_one_ui(unsigned int) __pure2; +unsigned int stdc_first_trailing_one_ul(unsigned long) __pure2; +unsigned int stdc_first_trailing_one_ull(unsigned long long) __pure2; +#define stdc_first_trailing_one(x) __generic_bitfunc(stdc_first_trailing_one, x) + +unsigned int stdc_count_zeros_uc(unsigned char) __pure2; +unsigned int stdc_count_zeros_us(unsigned short) __pure2; +unsigned int stdc_count_zeros_ui(unsigned int) __pure2; +unsigned int stdc_count_zeros_ul(unsigned long) __pure2; +unsigned int stdc_count_zeros_ull(unsigned long long) __pure2; +#define stdc_count_zeros(x) __generic_bitfunc(stdc_count_zeros, x) + +unsigned int stdc_count_ones_uc(unsigned char) __pure2; +unsigned int stdc_count_ones_us(unsigned short) __pure2; +unsigned int stdc_count_ones_ui(unsigned int) __pure2; +unsigned int stdc_count_ones_ul(unsigned long) __pure2; +unsigned int stdc_count_ones_ull(unsigned long long) __pure2; +#define stdc_count_ones(x) __generic_bitfunc(stdc_count_ones, x) + +_Bool stdc_has_single_bit_uc(unsigned char) __pure2; +_Bool stdc_has_single_bit_us(unsigned short) __pure2; +_Bool stdc_has_single_bit_ui(unsigned int) __pure2; +_Bool stdc_has_single_bit_ul(unsigned long) __pure2; +_Bool stdc_has_single_bit_ull(unsigned long long) __pure2; +#define stdc_has_single_bit(x) __generic_bitfunc(stdc_has_single_bit, x) + +unsigned int stdc_bit_width_uc(unsigned char) __pure2; +unsigned int stdc_bit_width_us(unsigned short) __pure2; +unsigned int stdc_bit_width_ui(unsigned int) __pure2; +unsigned int stdc_bit_width_ul(unsigned long) __pure2; +unsigned int stdc_bit_width_ull(unsigned long long) __pure2; +#define stdc_bit_width(x) __generic_bitfunc(stdc_bit_width, x) + +unsigned char stdc_bit_floor_uc(unsigned char) __pure2; +unsigned short stdc_bit_floor_us(unsigned short) __pure2; +unsigned stdc_bit_floor_ui(unsigned int) __pure2; +unsigned long stdc_bit_floor_ul(unsigned long) __pure2; +unsigned long long stdc_bit_floor_ull(unsigned long long) __pure2; +#define stdc_bit_floor(x) __generic_bitfunc(stdc_bit_floor, x) + +unsigned char stdc_bit_ceil_uc(unsigned char) __pure2; +unsigned short stdc_bit_ceil_us(unsigned short) __pure2; +unsigned int stdc_bit_ceil_ui(unsigned int) __pure2; +unsigned long stdc_bit_ceil_ul(unsigned long) __pure2; +unsigned long long stdc_bit_ceil_ull(unsigned long long) __pure2; +#define stdc_bit_ceil(x) __generic_bitfunc(stdc_bit_ceil, x) +__END_DECLS + +#endif /* __STDC_VERSION_STDBIT_H__ */ diff --git a/newlib/libc/stdbit/stdc_bit_ceil.3 b/newlib/libc/stdbit/stdc_bit_ceil.3 new file mode 100644 index 000000000..470b255f4 --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_ceil.3 @@ -0,0 +1,81 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_BIT_CEIL 3 +.Os +.Sh NAME +.Nm stdc_bit_ceil +.Nd round up to the next power of\~2 +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned char +.Fn stdc_bit_ceil_uc "unsigned char value" +.Ft unsigned short +.Fn stdc_bit_ceil_us "unsigned short value" +.Ft unsigned int +.Fn stdc_bit_ceil_ui "unsigned int value" +.Ft unsigned long +.Fn stdc_bit_ceil_ul "unsigned long value" +.Ft unsigned long long +.Fn stdc_bit_ceil_ull "unsigned long long value" +.Ft typeof Ns Pq Em value +.Fn stdc_bit_ceil "value" +.Sh DESCRIPTION +The +.Nm stdc_bit_ceil_ Ns Em type Ns () +family of functions rounds +.Fa value +up to the next power of\~2, where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_bit_ceil "value" +type-generic macro picks the appropriate +.Nm stdc_bit_ceil_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns +.Fa value +round up to the next power of\~2. +If this value is not representable, +0\~is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_bit_floor 3 +.Sh STANDARDS +The +.Nm stdc_bit_ceil_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_ceil +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_bit_ceil_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_ceil +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_bit_ceil.c b/newlib/libc/stdbit/stdc_bit_ceil.c new file mode 100644 index 000000000..2dfd7bbcb --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_ceil.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +/* Ensure we don't shift 1U out of range. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_bit_ceil_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned char +stdc_bit_ceil_uc(unsigned char x) +{ + if (x <= 1) + return (1); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +/* Ensure we don't shift 1U out of range. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_bit_ceil_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned short +stdc_bit_ceil_us(unsigned short x) +{ + if (x <= 1) + return (1); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +unsigned int +stdc_bit_ceil_ui(unsigned int x) +{ + if (x <= 1) + return (1); + + if (x > UINT_MAX/2 + 1) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +unsigned long +stdc_bit_ceil_ul(unsigned long x) +{ + if (x <= 1) + return (1); + + if (x > ULONG_MAX/2 + 1) + return (0); + + return (1UL << (ULONG_WIDTH - __builtin_clzl(x - 1))); +} + +unsigned long long +stdc_bit_ceil_ull(unsigned long long x) +{ + if (x <= 1) + return (1); + + if (x > ULLONG_MAX/2 + 1) + return (0); + + return (1ULL << (ULLONG_WIDTH - __builtin_clzll(x - 1))); +} diff --git a/newlib/libc/stdbit/stdc_bit_floor.3 b/newlib/libc/stdbit/stdc_bit_floor.3 new file mode 100644 index 000000000..3e90c34f0 --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_floor.3 @@ -0,0 +1,83 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_BIT_FLOOR 3 +.Os +.Sh NAME +.Nm stdc_bit_floor +.Nd round down to the previous power of\~2 +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned char +.Fn stdc_bit_floor_uc "unsigned char value" +.Ft unsigned short +.Fn stdc_bit_floor_us "unsigned short value" +.Ft unsigned int +.Fn stdc_bit_floor_ui "unsigned int value" +.Ft unsigned long +.Fn stdc_bit_floor_ul "unsigned long value" +.Ft unsigned long long +.Fn stdc_bit_floor_ull "unsigned long long value" +.Ft typeof Ns Pq Em value +.Fn stdc_bit_floor "value" +.Sh DESCRIPTION +The +.Nm stdc_bit_floor_ Ns Em type Ns () +family of functions rounds +.Fa value +down to the previous power of\~2, where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_bit_floor "value" +type-generic macro picks the appropriate +.Nm stdc_bit_floor_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns +.Fa value +round down to the previous power of\~2. +If +.Fa value +is equal to zero, +zero is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_bit_ceil 3 +.Sh STANDARDS +The +.Nm stdc_bit_floor_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_floor +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_bit_floor_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_floor +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_bit_floor.c b/newlib/libc/stdbit/stdc_bit_floor.c new file mode 100644 index 000000000..0a491d6ec --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_floor.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned char +stdc_bit_floor_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned short +stdc_bit_floor_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned int +stdc_bit_floor_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned long +stdc_bit_floor_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (1UL << (ULONG_WIDTH - __builtin_clzl(x) - 1)); +} + +unsigned long long +stdc_bit_floor_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (1ULL << (ULLONG_WIDTH - __builtin_clzll(x) - 1)); +} diff --git a/newlib/libc/stdbit/stdc_bit_width.3 b/newlib/libc/stdbit/stdc_bit_width.3 new file mode 100644 index 000000000..8d5988681 --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_width.3 @@ -0,0 +1,104 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_BIT_WIDTH 3 +.Os +.Sh NAME +.Nm stdc_bit_width +.Nd find the first trailing one in an intege +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_bit_width_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_bit_width_us "unsigned short value" +.Ft unsigned int +.Fn stdc_bit_width_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_bit_width_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_bit_width_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_bit_width "value" +.Sh DESCRIPTION +The +.Nm stdc_bit_width_ Ns Em type Ns () +family of functions returns the number of bits needed to represent +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_bit_width "value" +type-generic macro picks the appropriate +.Nm stdc_bit_width_ Ns Em type Ns () +function based on the type of +.Fa value . +.Pp +Functions +.Fn stdc_bit_width_ui , +.Fn stdc_bit_width_ul , +and +.Fn stdc_bit_width_ull +are identical to +.Bx 4.3 +functions +.Xr fls 3 , +.Xr flsl 3 , +and +.Xr flsll 3 +respectively, except for operating on unsigned instead of signed values. +.Sh RETURN VALUES +Returns the least number of bits needed to represent +.Fa value . +If +.Fa value +is zero, the return value is zero. +Otherwise it is +.EQ +1 + \(lf log sub 2 italic value \(rf . +.EN +.Sh SEE ALSO +.Xr bit_fls 3 , +.Xr fls 3 , +.Xr flsl 3 , +.Xr flsll 3 , +.Xr stdbit 3 , +.Xr stdc_count_leading_zeros 3 , +.Xr stdc_first_leading_one 3 +.Sh STANDARDS +The +.Nm stdc_bit_width_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_width +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_bit_width_ Ns Em type Ns () +family of functions and the +.Fn stdc_bit_width +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_bit_width.c b/newlib/libc/stdbit/stdc_bit_width.c new file mode 100644 index 000000000..e248fae48 --- /dev/null +++ b/newlib/libc/stdbit/stdc_bit_width.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_bit_width_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (ULONG_WIDTH - __builtin_clzl(x)); +} + +unsigned int +stdc_bit_width_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (ULLONG_WIDTH - __builtin_clzll(x)); +} diff --git a/newlib/libc/stdbit/stdc_count_ones.3 b/newlib/libc/stdbit/stdc_count_ones.3 new file mode 100644 index 000000000..6de92216c --- /dev/null +++ b/newlib/libc/stdbit/stdc_count_ones.3 @@ -0,0 +1,85 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_COUNT_ONES 3 +.Os +.Sh NAME +.Nm stdc_count_ones +.Nd count the ones in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_count_ones_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_count_ones_us "unsigned short value" +.Ft unsigned int +.Fn stdc_count_ones_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_count_ones_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_count_ones_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_count_ones "value" +.Sh DESCRIPTION +The +.Nm stdc_count_ones_ Ns Em type Ns () +family of functions returns the number of bits set to\~1 in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +This is also known as the +.Dq population count +(popcount) or +.Dq Hamming weight +operation. +The +.Fn stdc_count_ones "value" +type-generic macro picks the appropriate +.Nm stdc_count_ones_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of bits set to\~1 in +.Fa value . +.Sh SEE ALSO +.Xr bit_count 3 , +.Xr stdbit 3 , +.Xr stdc_count_zeros 3 , +.Xr stdc_has_single_bit 3 +.Sh STANDARDS +The +.Nm stdc_count_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_count_ones +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_count_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_count_ones +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_count_ones.c b/newlib/libc/stdbit/stdc_count_ones.c new file mode 100644 index 000000000..c5198dca8 --- /dev/null +++ b/newlib/libc/stdbit/stdc_count_ones.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_count_ones_uc(unsigned char x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_us(unsigned short x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_ui(unsigned int x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_ul(unsigned long x) +{ + return (__builtin_popcountl(x)); +} + +unsigned int +stdc_count_ones_ull(unsigned long long x) +{ + return (__builtin_popcountll(x)); +} diff --git a/newlib/libc/stdbit/stdc_count_zeros.3 b/newlib/libc/stdbit/stdc_count_zeros.3 new file mode 100644 index 000000000..762ba62d3 --- /dev/null +++ b/newlib/libc/stdbit/stdc_count_zeros.3 @@ -0,0 +1,84 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_COUNT_ZEROS 3 +.Os +.Sh NAME +.Nm stdc_count_zeros +.Nd count the zeros in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_count_zeros_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_count_zeros_us "unsigned short value" +.Ft unsigned int +.Fn stdc_count_zeros_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_count_zeros_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_count_zeros_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_count_zeros "value" +.Sh DESCRIPTION +The +.Nm stdc_count_zeros_ Ns Em type Ns () +family of functions returns the number of bits set to\~0 in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +This is also known as the +.Dq population count +(popcount) or +.Dq Hamming weight +of the complement of +.Fa value . +The +.Fn stdc_count_zeros "value" +type-generic macro picks the appropriate +.Nm stdc_count_zeros_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of bits set to\~0 in +.Fa value . +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_count_ones 3 +.Sh STANDARDS +The +.Nm stdc_count_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_count_zeros +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_count_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_count_zeros +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_count_zeros.c b/newlib/libc/stdbit/stdc_count_zeros.c new file mode 100644 index 000000000..35db965af --- /dev/null +++ b/newlib/libc/stdbit/stdc_count_zeros.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_count_zeros_uc(unsigned char x) +{ + return (__builtin_popcount(x ^ UCHAR_MAX)); +} + +unsigned int +stdc_count_zeros_us(unsigned short x) +{ + return (__builtin_popcount(x ^ USHRT_MAX)); +} + +unsigned int +stdc_count_zeros_ui(unsigned int x) +{ + return (__builtin_popcount(~x)); +} + +unsigned int +stdc_count_zeros_ul(unsigned long x) +{ + return (__builtin_popcountl(~x)); +} + +unsigned int +stdc_count_zeros_ull(unsigned long long x) +{ + return (__builtin_popcountll(~x)); +} diff --git a/newlib/libc/stdbit/stdc_first_leading_one.3 b/newlib/libc/stdbit/stdc_first_leading_one.3 new file mode 100644 index 000000000..48f62d997 --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_leading_one.3 @@ -0,0 +1,93 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_FIRST_LEADING_ONE 3 +.Os +.Sh NAME +.Nm stdc_first_leading_one +.Nd find the first leading one in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_first_leading_one_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_first_leading_one_us "unsigned short value" +.Ft unsigned int +.Fn stdc_first_leading_one_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_first_leading_one_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_first_leading_one_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_first_leading_one "value" +.Sh DESCRIPTION +The +.Nm stdc_first_leading_one_ Ns Em type Ns () +family of functions returns the index of the most significant set bit in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_first_leading_one "value" +type-generic macro picks the appropriate +.Nm stdc_first_leading_one_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the index of the most significant set bit in +.Fa value . +The bits are numbered such that the most significant bit has number\~1, +and the least significant bit has number +.Ms w +where +.Ms w +is the number of bits in the type of +.Fa value . +If no bits are set in +.Fa value +(i.\^e.\& +.Fa value +is zero), zero is returned. +.Sh SEE ALSO +.Xr fls 3 , +.Xr stdbit 3 , +.Xr stdc_leading_zeros 3 , +.Xr stdc_first_leading_zero 3 , +.Xr stdc_first_trailing_one 3 +.Sh STANDARDS +The +.Nm stdc_first_leading_one_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_leading_one +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_first_leading_one_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_leading_one +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_first_leading_one.c b/newlib/libc/stdbit/stdc_first_leading_one.c new file mode 100644 index 000000000..de4368565 --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_leading_one.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_first_leading_one_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + if (x == 0) + return (0); + + return (__builtin_clz(x << offset) + 1); +} + +unsigned int +stdc_first_leading_one_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + if (x == 0) + return (0); + + return (__builtin_clz(x << offset) + 1); +} + +unsigned int +stdc_first_leading_one_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (__builtin_clz(x) + 1); +} + +unsigned int +stdc_first_leading_one_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (__builtin_clzl(x) + 1); +} + +unsigned int +stdc_first_leading_one_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (__builtin_clzll(x) + 1); +} diff --git a/newlib/libc/stdbit/stdc_first_leading_zero.3 b/newlib/libc/stdbit/stdc_first_leading_zero.3 new file mode 100644 index 000000000..317b6263a --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_leading_zero.3 @@ -0,0 +1,92 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_FIRST_LEADING_ZERO 3 +.Os +.Sh NAME +.Nm stdc_first_leading_zero +.Nd find the first leading zero in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_first_leading_zero_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_first_leading_zero_us "unsigned short value" +.Ft unsigned int +.Fn stdc_first_leading_zero_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_first_leading_zero_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_first_leading_zero_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_first_leading_zero "value" +.Sh DESCRIPTION +The +.Nm stdc_first_leading_zero_ Ns Em type Ns () +family of functions returns the index of the most significant clear bit in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_first_leading_zero "value" +type-generic macro picks the appropriate +.Nm stdc_first_leading_zero_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the index of the most significant clear bit in +.Fa value . +The bits are numbered such that the most significant bit has number\~1, +and the least significant bit has number +.Ms w +where +.Ms w +is the number of bits in the type of +.Fa value . +If no bits are clear in +.Fa value +(i.\^e.\& +.Fa value +is the bitwise complement of zero), zero is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_leading_ones 3 , +.Xr stdc_first_leading_ones 3 , +.Xr stdc_first_trailing_zero 3 +.Sh STANDARDS +The +.Nm stdc_first_leading_zero_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_leading_zero +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_first_leading_zero_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_leading_zero +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_first_leading_zero.c b/newlib/libc/stdbit/stdc_first_leading_zero.c new file mode 100644 index 000000000..e6609b51b --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_leading_zero.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_first_leading_zero_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + if (x == UCHAR_MAX) + return (0); + + return (__builtin_clz(~(unsigned int)x << offset) + 1); +} + +unsigned int +stdc_first_leading_zero_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + if (x == USHRT_MAX) + return (0); + + return (__builtin_clz(~(unsigned int)x << offset) + 1); +} + +unsigned int +stdc_first_leading_zero_ui(unsigned int x) +{ + if (x == ~0U) + return (0); + + return (__builtin_clz(~x) + 1); +} + +unsigned int +stdc_first_leading_zero_ul(unsigned long x) +{ + if (x == ~0UL) + return (0); + + return (__builtin_clzl(~x) + 1); +} + +unsigned int +stdc_first_leading_zero_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (0); + + return (__builtin_clzll(~x) + 1); +} diff --git a/newlib/libc/stdbit/stdc_first_trailing_one.3 b/newlib/libc/stdbit/stdc_first_trailing_one.3 new file mode 100644 index 000000000..0b590ac39 --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_trailing_one.3 @@ -0,0 +1,110 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_FIRST_TRAILING_ONE 3 +.Os +.Sh NAME +.Nm stdc_first_trailing_one +.Nd find the first trailing one in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_first_trailing_one_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_first_trailing_one_us "unsigned short value" +.Ft unsigned int +.Fn stdc_first_trailing_one_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_first_trailing_one_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_first_trailing_one_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_first_trailing_one "value" +.Sh DESCRIPTION +The +.Nm stdc_first_trailing_one_ Ns Em type Ns () +family of functions returns the index of the least significant set bit in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_first_trailing_one "value" +type-generic macro picks the appropriate +.Nm stdc_first_trailing_one_ Ns Em type Ns () +function based on the type of +.Fa value . +.Pp +Functions +.Fn stdc_first_trailing_one_ui , +.Fn stdc_first_trailing_one_ul , +and +.Fn stdc_first_trailing_one_ull +are identical to +.Bx 4.3 +functions +.Xr ffs 3 , +.Xr ffsl 3 , +and +.Xr ffsll 3 +respectively, except for operating on unsigned instead of signed values. +.Sh RETURN VALUES +Returns the index of the least significant set bit in +.Fa value . +The bits are numbered such that the least significant bit has number\~1, +and the most significant bit has number +.Ms w +where +.Ms w +is the number of bits in the type of +.Fa value . +If no bits are set in +.Fa value +(i.\^e.\& +.Fa value +is zero), one is returned. +.Sh SEE ALSO +.Xr bit_ffs 3 , +.Xr ffs 3 , +.Xr ffsl 3 , +.Xr ffsll 3 , +.Xr stdbit 3 , +.Xr stdc_trailing_zeros 3 , +.Xr stdc_first_trailing_zero 3 , +.Xr stdc_first_leading_one 3 +.Sh STANDARDS +The +.Nm stdc_first_trailing_one_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_trailing_one +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_first_trailing_one_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_trailing_one +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_first_trailing_one.c b/newlib/libc/stdbit/stdc_first_trailing_one.c new file mode 100644 index 000000000..22972758d --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_trailing_one.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +unsigned int +stdc_first_trailing_one_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (__builtin_ctzl(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (__builtin_ctzll(x) + 1); +} diff --git a/newlib/libc/stdbit/stdc_first_trailing_zero.3 b/newlib/libc/stdbit/stdc_first_trailing_zero.3 new file mode 100644 index 000000000..bc4f7982d --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_trailing_zero.3 @@ -0,0 +1,93 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_FIRST_TRAILING_ZERO 3 +.Os +.Sh NAME +.Nm stdc_first_trailing_zero +.Nd find the first trailing zero in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_first_trailing_zero_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_first_trailing_zero_us "unsigned short value" +.Ft unsigned int +.Fn stdc_first_trailing_zero_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_first_trailing_zero_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_first_trailing_zero_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_first_trailing_zero "value" +.Sh DESCRIPTION +The +.Nm stdc_first_trailing_zero_ Ns Em type Ns () +family of functions returns the index of the least significant clear bit in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_first_trailing_zero "value" +type-generic macro picks the appropriate +.Nm stdc_first_trailing_zero_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the index of the least significant clear bit in +.Fa value . +The bits are numbered such that the least significant bit has number\~1, +and the most significant bit has number +.Ms w +where +.Ms w +is the number of bits in the type of +.Fa value . +If no bits are clear in +.Fa value +(i.\^e.\& +.Fa value +is the bitwise complement of zero), zero is returned. +.Sh SEE ALSO +.Xr bit_ffc 3 , +.Xr stdbit 3 , +.Xr stdc_trailing_ones 3 , +.Xr stdc_first_trailing_ones 3 , +.Xr stdc_first_leading_zero 3 +.Sh STANDARDS +The +.Nm stdc_first_trailing_zero_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_trailing_zero +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_first_trailing_zero_ Ns Em type Ns () +family of functions and the +.Fn stdc_first_trailing_zero +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_first_trailing_zero.c b/newlib/libc/stdbit/stdc_first_trailing_zero.c new file mode 100644 index 000000000..27395c697 --- /dev/null +++ b/newlib/libc/stdbit/stdc_first_trailing_zero.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +unsigned int +stdc_first_trailing_zero_uc(unsigned char x) +{ + if (x == UCHAR_MAX) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_us(unsigned short x) +{ + if (x == USHRT_MAX) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ui(unsigned int x) +{ + if (x == ~0U) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ul(unsigned long x) +{ + if (x == ~0UL) + return (0); + + return (__builtin_ctzl(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (0); + + return (__builtin_ctzll(~x) + 1); +} diff --git a/newlib/libc/stdbit/stdc_has_single_bit.3 b/newlib/libc/stdbit/stdc_has_single_bit.3 new file mode 100644 index 000000000..8f82c5522 --- /dev/null +++ b/newlib/libc/stdbit/stdc_has_single_bit.3 @@ -0,0 +1,98 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_HAS_SINGLE_BIT 3 +.Os +.Sh NAME +.Nm stdc_has_single_bit +.Nd check for single bit set +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft bool +.Fn stdc_has_single_bit_uc "unsigned char value" +.Ft bool +.Fn stdc_has_single_bit_us "unsigned short value" +.Ft bool +.Fn stdc_has_single_bit_ui "unsigned int value" +.Ft bool +.Fn stdc_has_single_bit_ul "unsigned long value" +.Ft bool +.Fn stdc_has_single_bit_ull "unsigned long long value" +.Ft bool +.Fn stdc_has_single_bit "value" +.Sh DESCRIPTION +The +.Nm stdc_has_single_bit_ Ns Em type Ns () +family of functions checks if there is exactly one bit +set in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_has_single_bit "value" +type-generic macro picks the appropriate +.Nm stdc_has_single_bit_ Ns Em type Ns () +function based on the type of +.Fa value . +.Pp +The functions in this family behave similarly to the +.Fn powerof2 "value" +macro of +.In sys/param.h , +but differ when +.Fa value +is zero: while +.Fn powerof2 +considers zero to be a power of two, +.Fn stdc_has_single_bit +does not. +.Sh RETURN VALUES +Returns +.Sy true +if exactly one bit is set in +.Fa value , +otherwise returns +.Sy false . +I.\^e. the function determines if +.Fa value +is a power of two. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_count_ones 3 +.Sh STANDARDS +The +.Nm stdc_has_single_bit_ Ns Em type Ns () +family of functions and the +.Fn stdc_has_single_bit +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_has_single_bit_ Ns Em type Ns () +family of functions and the +.Fn stdc_has_single_bit +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_has_single_bit.c b/newlib/libc/stdbit/stdc_has_single_bit.c new file mode 100644 index 000000000..a448464b0 --- /dev/null +++ b/newlib/libc/stdbit/stdc_has_single_bit.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +bool +stdc_has_single_bit_uc(unsigned char x) +{ + return (x != 0 && (x & (x - 1)) == 0); +} + +bool +stdc_has_single_bit_us(unsigned short x) +{ + return (x != 0 && (x & (x - 1)) == 0); +} + +bool +stdc_has_single_bit_ui(unsigned int x) +{ + return (x != 0 && (x & (x - 1)) == 0); +} + +bool +stdc_has_single_bit_ul(unsigned long x) +{ + return (x != 0 && (x & (x - 1)) == 0); +} + +bool +stdc_has_single_bit_ull(unsigned long long x) +{ + return (x != 0 && (x & (x - 1)) == 0); +} diff --git a/newlib/libc/stdbit/stdc_leading_ones.3 b/newlib/libc/stdbit/stdc_leading_ones.3 new file mode 100644 index 000000000..6cf7989b7 --- /dev/null +++ b/newlib/libc/stdbit/stdc_leading_ones.3 @@ -0,0 +1,86 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_LEADING_ONES 3 +.Os +.Sh NAME +.Nm stdc_leading_ones +.Nd find the number of leading ones in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_leading_ones_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_leading_ones_us "unsigned short value" +.Ft unsigned int +.Fn stdc_leading_ones_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_leading_ones_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_leading_ones_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_leading_ones "value" +.Sh DESCRIPTION +The +.Nm stdc_leading_ones_ Ns Em type Ns () +family of functions returns the number of leading ones in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_leading_ones "value" +type-generic macro picks the appropriate +.Nm stdc_leading_ones_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of leading ones in +.Fa value . +If +.Fa value +is all ones, +the total number of bits in the type of +.Fa value +is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_leading_zeros 3 , +.Xr stdc_trailing_ones 3 , +.Xr stdc_first_leading_zero 3 +.Sh STANDARDS +The +.Nm stdc_leading_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_leading_ones +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_leading_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_leading_ones +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_leading_ones.c b/newlib/libc/stdbit/stdc_leading_ones.c new file mode 100644 index 000000000..79d3ec7f2 --- /dev/null +++ b/newlib/libc/stdbit/stdc_leading_ones.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +/* Avoid triggering undefined behavior if x == 0. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_leading_ones_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_ones_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + return (__builtin_clz(~(x << offset))); +} + +/* Avoid triggering undefined behavior if x == 0. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_leading_ones_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_ones_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + return (__builtin_clz(~(x << offset))); +} + +unsigned int +stdc_leading_ones_ui(unsigned int x) +{ + if (x == ~0U) + return (UINT_WIDTH); + + return (__builtin_clz(~x)); +} + +unsigned int +stdc_leading_ones_ul(unsigned long x) +{ + if (x == ~0UL) + return (ULONG_WIDTH); + + return (__builtin_clzl(~x)); +} + +unsigned int +stdc_leading_ones_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (ULLONG_WIDTH); + + return (__builtin_clzll(~x)); +} diff --git a/newlib/libc/stdbit/stdc_leading_zeros.3 b/newlib/libc/stdbit/stdc_leading_zeros.3 new file mode 100644 index 000000000..7a7a203ac --- /dev/null +++ b/newlib/libc/stdbit/stdc_leading_zeros.3 @@ -0,0 +1,86 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_LEADING_ZEROS 3 +.Os +.Sh NAME +.Nm stdc_leading_zeros +.Nd find the number of leading zeros in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_leading_zeros_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_leading_zeros_us "unsigned short value" +.Ft unsigned int +.Fn stdc_leading_zeros_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_leading_zeros_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_leading_zeros_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_leading_zeros "value" +.Sh DESCRIPTION +The +.Nm stdc_leading_zeros_ Ns Em type Ns () +family of functions returns the number of leading zeros in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_leading_zeros "value" +type-generic macro picks the appropriate +.Nm stdc_leading_zeros_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of leading zeros in +.Fa value . +If +.Fa value +is all zeros, +the total number of bits in the type of +.Fa value +is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_leading_ones 3 , +.Xr stdc_trailing_zeros 3 , +.Xr stdc_first_leading_one 3 +.Sh STANDARDS +The +.Nm stdc_leading_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_leading_zeros +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_leading_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_leading_zeros +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_leading_zeros.c b/newlib/libc/stdbit/stdc_leading_zeros.c new file mode 100644 index 000000000..2fdf64ec9 --- /dev/null +++ b/newlib/libc/stdbit/stdc_leading_zeros.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +/* Offset must be greater than zero. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_leading_zeros_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_zeros_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + return (__builtin_clz((x << offset) + (1U << (offset - 1)))); +} + +/* Offset must be greater than zero. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_leading_zeros_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_zeros_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + return (__builtin_clz((x << offset) + (1U << (offset - 1)))); +} + +unsigned int +stdc_leading_zeros_ui(unsigned int x) +{ + if (x == 0) + return (UINT_WIDTH); + + return (__builtin_clz(x)); +} + +unsigned int +stdc_leading_zeros_ul(unsigned long x) +{ + if (x == 0) + return (ULONG_WIDTH); + + return (__builtin_clzl(x)); +} + +unsigned int +stdc_leading_zeros_ull(unsigned long long x) +{ + if (x == 0) + return (ULLONG_WIDTH); + + return (__builtin_clzll(x)); +} diff --git a/newlib/libc/stdbit/stdc_trailing_ones.3 b/newlib/libc/stdbit/stdc_trailing_ones.3 new file mode 100644 index 000000000..96277506f --- /dev/null +++ b/newlib/libc/stdbit/stdc_trailing_ones.3 @@ -0,0 +1,86 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_TRAILING_ONES 3 +.Os +.Sh NAME +.Nm stdc_trailing_ones +.Nd find the number of trailing ones in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_trailing_ones_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_trailing_ones_us "unsigned short value" +.Ft unsigned int +.Fn stdc_trailing_ones_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_trailing_ones_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_trailing_ones_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_trailing_ones "value" +.Sh DESCRIPTION +The +.Nm stdc_trailing_ones_ Ns Em type Ns () +family of functions returns the number of trailing ones in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_trailing_ones "value" +type-generic macro picks the appropriate +.Nm stdc_trailing_ones_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of trailing ones in +.Fa value . +If +.Fa value +is all ones, +the total number of bits in the type of +.Fa value +is returned. +.Sh SEE ALSO +.Xr stdbit 3 , +.Xr stdc_leading_ones 3 , +.Xr stdc_trailing_zeros 3 , +.Xr stdc_first_trailing_zero 3 +.Sh STANDARDS +The +.Nm stdc_trailing_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_trailing_ones +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_trailing_ones_ Ns Em type Ns () +family of functions and the +.Fn stdc_trailing_ones +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_trailing_ones.c b/newlib/libc/stdbit/stdc_trailing_ones.c new file mode 100644 index 000000000..c1a0e6b99 --- /dev/null +++ b/newlib/libc/stdbit/stdc_trailing_ones.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +/* Avoid triggering undefined behavior if x == ~0. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_trailing_ones_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_trailing_ones_uc(unsigned char x) +{ + return (__builtin_ctz(~x)); +} + +/* Avoid triggering undefined behavior if x == ~0. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_trailing_ones_uc needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_trailing_ones_us(unsigned short x) +{ + return (__builtin_ctz(~x)); +} + +unsigned int +stdc_trailing_ones_ui(unsigned int x) +{ + if (x == ~0U) + return (UINT_WIDTH); + + return (__builtin_ctz(~x)); +} + +unsigned int +stdc_trailing_ones_ul(unsigned long x) +{ + if (x == ~0UL) + return (ULONG_WIDTH); + + return (__builtin_ctzl(~x)); +} + +unsigned int +stdc_trailing_ones_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (ULLONG_WIDTH); + + return (__builtin_ctzll(~x)); +} diff --git a/newlib/libc/stdbit/stdc_trailing_zeros.3 b/newlib/libc/stdbit/stdc_trailing_zeros.3 new file mode 100644 index 000000000..4bc675590 --- /dev/null +++ b/newlib/libc/stdbit/stdc_trailing_zeros.3 @@ -0,0 +1,87 @@ +.\" +.\" Copyright (c) 2025 Robert Clausecker +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd November 9, 2025 +.Dt STDC_TRAILING_ZEROS 3 +.Os +.Sh NAME +.Nm stdc_trailing_zeros +.Nd find the number of trailing zeros in an integer +.Sh SYNOPSIS +.Lb libc +.In stdbit.h +.Ft unsigned int +.Fn stdc_trailing_zeros_uc "unsigned char value" +.Ft unsigned int +.Fn stdc_trailing_zeros_us "unsigned short value" +.Ft unsigned int +.Fn stdc_trailing_zeros_ui "unsigned int value" +.Ft unsigned int +.Fn stdc_trailing_zeros_ul "unsigned long value" +.Ft unsigned int +.Fn stdc_trailing_zeros_ull "unsigned long long value" +.Ft unsigned int +.Fn stdc_trailing_zeros "value" +.Sh DESCRIPTION +The +.Nm stdc_trailing_zeros_ Ns Em type Ns () +family of functions returns the number of trailing zeros in +.Fa value , +where +.Fa value +is of type +.Va unsigned char , +.Va unsigned short , +.Va unsigned int , +.Va unsigned long , +or +.Va unsigned long long +for +.Em type +being +.Sy uc , +.Sy us , +.Sy ui , +.Sy ul , +or +.Sy ull +respectively. +The +.Fn stdc_trailing_zeros "value" +type-generic macro picks the appropriate +.Nm stdc_trailing_zeros_ Ns Em type Ns () +function based on the type of +.Fa value . +.Sh RETURN VALUES +Returns the number of trailing zeros in +.Fa value . +If +.Fa value +is all zeros, +the total number of bits in the type of +.Fa value +is returned. +.Sh SEE ALSO +.Xr ffs 3 , +.Xr stdbit 3 , +.Xr stdc_leading_zeros 3 , +.Xr stdc_trailing_ones 3 , +.Xr stdc_first_trailing_one 3 +.Sh STANDARDS +The +.Nm stdc_trailing_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_trailing_zeros +type-generic macro conform to +.St -isoC-2023 . +.Sh HISTORY +The +.Nm stdc_trailing_zeros_ Ns Em type Ns () +family of functions and the +.Fn stdc_trailing_zeros +type-generic macro were added in +.Fx 15.1. +.Sh AUTHOR +.An Robert Clausecker Aq Mt fuz@FreeBSD.org diff --git a/newlib/libc/stdbit/stdc_trailing_zeros.c b/newlib/libc/stdbit/stdc_trailing_zeros.c new file mode 100644 index 000000000..6213f62cf --- /dev/null +++ b/newlib/libc/stdbit/stdc_trailing_zeros.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Robert Clausecker + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +/* Ensure we do not shift 1U out of range. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_trailing_zeros_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_trailing_zeros_uc(unsigned char x) +{ + return (__builtin_ctz(x | 1U << UCHAR_WIDTH)); +} + +/* Ensure we do not shift 1U out of range. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_trailing_zeros_uc needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_trailing_zeros_us(unsigned short x) +{ + return (__builtin_ctz(x | 1U << USHRT_WIDTH)); +} + +unsigned int +stdc_trailing_zeros_ui(unsigned int x) +{ + if (x == 0U) + return (UINT_WIDTH); + + return (__builtin_ctz(x)); +} + +unsigned int +stdc_trailing_zeros_ul(unsigned long x) +{ + if (x == 0UL) + return (ULONG_WIDTH); + + return (__builtin_ctzl(x)); +} + +unsigned int +stdc_trailing_zeros_ull(unsigned long long x) +{ + if (x == 0ULL) + return (ULLONG_WIDTH); + + return (__builtin_ctzll(x)); +}