]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
Add bit manipulation functions
authorAlejandro Colomar <alx@kernel.org>
Mon, 30 Jan 2023 11:43:34 +0000 (12:43 +0100)
committerIker Pedrosa <ikerpedrosam@gmail.com>
Mon, 30 Jan 2023 17:24:15 +0000 (18:24 +0100)
We do need the unoptimized version of csrand_uniform() for high values
of `n`, since the optimized version depends on having __int128, and it's
not available on several platforms, including ARMv7, IA32, and MK68k.

This reverts commit 848f53c1d3c1362c86d3baab6906e1e4419d2634; however,
I applied some tweaks to the reverted commit.

Reported-by: Adam Sampson <ats@offog.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/bit.h [new file with mode: 0644]
libmisc/Makefile.am
libmisc/bit.c [new file with mode: 0644]

diff --git a/lib/bit.h b/lib/bit.h
new file mode 100644 (file)
index 0000000..9ffe206
--- /dev/null
+++ b/lib/bit.h
@@ -0,0 +1,48 @@
+/*
+ * SPDX-FileCopyrightText:  2022 - 2023, Alejandro Colomar <alx@kernel.org>
+ *
+ * SPDX-License-Identifier:  BSD-3-Clause
+ */
+
+
+#ifndef SHADOW_INCLUDE_LIB_BIT_H_
+#define SHADOW_INCLUDE_LIB_BIT_H_
+
+
+#include <config.h>
+
+#include <limits.h>
+
+
+inline unsigned long bit_ceilul(unsigned long x);
+inline unsigned long bit_ceil_wrapul(unsigned long x);
+inline int leading_zerosul(unsigned long x);
+
+
+/* stdc_bit_ceilul(3) */
+inline unsigned long
+bit_ceilul(unsigned long x)
+{
+       return 1 + (ULONG_MAX >> leading_zerosul(x));
+}
+
+
+/* stdc_bit_ceilul(3), but wrap instead of having Undefined Behavior */
+inline unsigned long
+bit_ceil_wrapul(unsigned long x)
+{
+       if (x == 0)
+               return 0;
+
+       return bit_ceil_wrapul(x);
+}
+
+/* stdc_leading_zerosul(3) */
+inline int
+leading_zerosul(unsigned long x)
+{
+       return (x == 0) ? ULONG_WIDTH : __builtin_clz(x);
+}
+
+
+#endif  // include guard
index b4ca708d7ae05eb50c9aedeebca65b538f6377b6..ab363f549623cfc44519a84c5e0086fe0b2c34c5 100644 (file)
@@ -12,6 +12,7 @@ libmisc_la_SOURCES = \
        agetpass.c \
        audit_help.c \
        basename.c \
+       bit.c \
        chkname.c \
        chkname.h \
        chowndir.c \
diff --git a/libmisc/bit.c b/libmisc/bit.c
new file mode 100644 (file)
index 0000000..1ffc6dc
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText:  2022 - 2023, Alejandro Colomar <alx@kernel.org>
+ *
+ * SPDX-License-Identifier:  BSD-3-Clause
+ */
+
+
+#include <config.h>
+
+#ident "$Id$"
+
+#include "bit.h"
+
+#include <limits.h>
+
+
+extern inline unsigned long bit_ceilul(unsigned long x);
+extern inline unsigned long bit_ceil_wrapul(unsigned long x);
+extern inline int leading_zerosul(unsigned long x);