1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-02-11 01:42:17 +02:00

factor: switch to stdc_leading_zeros etc

* bootstrap.conf (gnulib_modules): Add stdc_trailing_zeros.
* cfg.mk (_gl_TS_unmarked_extern_vars): Remove factor_clz_tab,
as it’s no longer present.
* src/factor.c: Include stdbit.h.
(__clz_tab, factor_clz_tab): Remove.
(ASSERT, UHWtype, __GMP_DECLSPEC): Use simpler way to pacify
-Wunused-macros.
(count_leading_zeros, count_trailing_zeros):
Remove.  All uses replaced by stdc_leading_zeros, stdc_trailing_zeros.
(factor_using_division, prime2_p): Add a couple of ‘assume’s
so that GCC knows the stdc_* calls are nonzero and can
optimize accordingly.
This commit is contained in:
Paul Eggert
2024-09-25 16:53:52 -07:00
parent 5867465510
commit e3f3670c7e
3 changed files with 20 additions and 75 deletions

View File

@@ -247,6 +247,7 @@ gnulib_modules="
stat-time stat-time
stdbool stdbool
stdc_leading_zeros stdc_leading_zeros
stdc_trailing_zeros
stdckdint stdckdint
stdlib-safer stdlib-safer
stpcpy stpcpy

6
cfg.mk
View File

@@ -928,13 +928,9 @@ _gl_TS_unmarked_extern_functions = main usage
_gl_TS_unmarked_extern_functions += single_binary_main_.* _usage_.* _gl_TS_unmarked_extern_functions += single_binary_main_.* _usage_.*
# Headers to search for single line extern _data_ declarations. # Headers to search for single line extern _data_ declarations.
_gl_TS_other_headers = $(srcdir)/src/*.h src/*.h _gl_TS_other_headers = $(srcdir)/src/*.h src/*.h
# Tell the tight_scope rule about an exceptional "extern" variable.
# Normally, the rule would detect its declaration, but that uses a
# different name, __clz_tab.
_gl_TS_unmarked_extern_vars = factor_clz_tab
# Avoid tight_scope rule stating these should be static # Avoid tight_scope rule stating these should be static
# as there is no way to achieve that with the way these are defined. # as there is no way to achieve that with the way these are defined.
_gl_TS_unmarked_extern_vars += ptr_MD5_.* _gl_TS_unmarked_extern_vars = ptr_MD5_.*
# Other tight_scope settings # Other tight_scope settings
_gl_TS_dir = . _gl_TS_dir = .
_gl_TS_obj_files = src/*.$(OBJEXT) _gl_TS_obj_files = src/*.$(OBJEXT)

View File

@@ -103,6 +103,7 @@
#include <config.h> #include <config.h>
#include <getopt.h> #include <getopt.h>
#include <stdbit.h>
#include <stdio.h> #include <stdio.h>
#include <gmp.h> #include <gmp.h>
@@ -172,32 +173,19 @@ typedef unsigned long int UDItype;
# define LONGLONG_STANDALONE /* Don't require GMP's longlong.h mdep files */ # define LONGLONG_STANDALONE /* Don't require GMP's longlong.h mdep files */
# define ASSERT(x) /* FIXME make longlong.h really standalone */ # define ASSERT(x) /* FIXME make longlong.h really standalone */
# define __GMP_DECLSPEC /* FIXME make longlong.h really standalone */ # define __GMP_DECLSPEC /* FIXME make longlong.h really standalone */
# define __clz_tab factor_clz_tab /* Rename to avoid glibc collision */
# ifndef __GMP_GNUC_PREREQ # ifndef __GMP_GNUC_PREREQ
# define __GMP_GNUC_PREREQ(a,b) 1 # define __GMP_GNUC_PREREQ(a,b) 1
# endif # endif
/* These stub macros are only used in longlong.h in certain system compiler /* longlong.h uses these macros only in certain system compiler combinations.
combinations, so ensure usage to avoid -Wunused-macros warnings. */ Ensure usage to pacify -Wunused-macros. */
# if __GMP_GNUC_PREREQ (1,1) && defined __clz_tab #if defined ASSERT || defined UHWtype || defined __GMP_DECLSPEC
ASSERT (1) #endif
__GMP_DECLSPEC
# endif
# if _ARCH_PPC # if _ARCH_PPC
# define HAVE_HOST_CPU_FAMILY_powerpc 1 # define HAVE_HOST_CPU_FAMILY_powerpc 1
# endif # endif
# include "longlong.h" # include "longlong.h"
# ifdef COUNT_LEADING_ZEROS_NEED_CLZ_TAB
const unsigned char factor_clz_tab[129] =
{
1,2,3,3,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
9
};
# endif
#else /* not USE_LONGLONG_H */ #else /* not USE_LONGLONG_H */
@@ -208,12 +196,6 @@ const unsigned char factor_clz_tab[129] =
#endif #endif
#if !defined __clz_tab && !defined UHWtype
/* Without this seemingly useless conditional, gcc -Wunused-macros
warns that each of the two tested macros is unused on Fedora 18.
FIXME: this is just an ugly band-aid. Fix it properly. */
#endif
/* 2*3*5*7*11...*101 is 128 bits, and has 26 prime factors */ /* 2*3*5*7*11...*101 is 128 bits, and has 26 prime factors */
#define MAX_NFACTS 26 #define MAX_NFACTS 26
@@ -347,33 +329,6 @@ static void factor (uintmax_t, uintmax_t, struct factors *);
} while (0) } while (0)
#endif #endif
#ifndef count_leading_zeros
# define count_leading_zeros(count, x) do { \
uintmax_t __clz_x = (x); \
int __clz_c; \
for (__clz_c = 0; \
(__clz_x & ((uintmax_t) 0xff << (W_TYPE_SIZE - 8))) == 0; \
__clz_c += 8) \
__clz_x <<= 8; \
for (; (intmax_t)__clz_x >= 0; __clz_c++) \
__clz_x <<= 1; \
(count) = __clz_c; \
} while (0)
#endif
#ifndef count_trailing_zeros
# define count_trailing_zeros(count, x) do { \
uintmax_t __ctz_x = (x); \
int __ctz_c = 0; \
while ((__ctz_x & 1) == 0) \
{ \
__ctz_x >>= 1; \
__ctz_c++; \
} \
(count) = __ctz_c; \
} while (0)
#endif
/* Requires that a < n and b <= n */ /* Requires that a < n and b <= n */
#define submod(r,a,b,n) \ #define submod(r,a,b,n) \
do { \ do { \
@@ -411,8 +366,6 @@ static void factor (uintmax_t, uintmax_t, struct factors *);
static uintmax_t static uintmax_t
mod2 (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t d1, uintmax_t d0) mod2 (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t d1, uintmax_t d0)
{ {
int cntd, cnta;
affirm (d1 != 0); affirm (d1 != 0);
if (a1 == 0) if (a1 == 0)
@@ -421,8 +374,8 @@ mod2 (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t d1, uintmax_t d0)
return a0; return a0;
} }
count_leading_zeros (cntd, d1); int cntd = stdc_leading_zeros (d1);
count_leading_zeros (cnta, a1); int cnta = stdc_leading_zeros (a1);
int cnt = cntd - cnta; int cnt = cntd - cnta;
if (0 < cnt) if (0 < cnt)
{ {
@@ -767,14 +720,15 @@ factor_using_division (uintmax_t *t1p, uintmax_t t1, uintmax_t t0,
if (t0 == 0) if (t0 == 0)
{ {
count_trailing_zeros (cnt, t1); assume (t1);
cnt = stdc_trailing_zeros (t1);
t0 = t1 >> cnt; t0 = t1 >> cnt;
t1 = 0; t1 = 0;
cnt += W_TYPE_SIZE; cnt += W_TYPE_SIZE;
} }
else else
{ {
count_trailing_zeros (cnt, t0); cnt = stdc_trailing_zeros (t0);
rsh2 (t1, t0, t1, t0, cnt); rsh2 (t1, t0, t1, t0, cnt);
} }
@@ -1299,7 +1253,8 @@ prime2_p (uintmax_t n1, uintmax_t n0)
nm1[0] = n0 - 1; nm1[0] = n0 - 1;
if (nm1[0] == 0) if (nm1[0] == 0)
{ {
count_trailing_zeros (k, nm1[1]); assume (nm1[1]);
k = stdc_trailing_zeros (nm1[1]);
q[0] = nm1[1] >> k; q[0] = nm1[1] >> k;
q[1] = 0; q[1] = 0;
@@ -1307,7 +1262,7 @@ prime2_p (uintmax_t n1, uintmax_t n0)
} }
else else
{ {
count_trailing_zeros (k, nm1[0]); k = stdc_trailing_zeros (nm1[0]);
rsh2 (q[1], q[0], nm1[1], nm1[0], k); rsh2 (q[1], q[0], nm1[1], nm1[0], k);
} }
@@ -1771,15 +1726,13 @@ ATTRIBUTE_CONST
static uintmax_t static uintmax_t
isqrt (uintmax_t n) isqrt (uintmax_t n)
{ {
uintmax_t x;
int c;
if (n == 0) if (n == 0)
return 0; return 0;
count_leading_zeros (c, n); int c = stdc_leading_zeros (n);
/* Make x > sqrt(n). This will be invariant through the loop. */ /* Make x > sqrt(n). This will be invariant through the loop. */
x = (uintmax_t) 1 << ((W_TYPE_SIZE + 1 - c) >> 1); uintmax_t x = (uintmax_t) 1 << ((W_TYPE_SIZE + 1 - c) >> 1);
for (;;) for (;;)
{ {
@@ -1795,20 +1748,16 @@ ATTRIBUTE_CONST
static uintmax_t static uintmax_t
isqrt2 (uintmax_t nh, uintmax_t nl) isqrt2 (uintmax_t nh, uintmax_t nl)
{ {
int shift;
uintmax_t x;
/* Ensures the remainder fits in an uintmax_t. */ /* Ensures the remainder fits in an uintmax_t. */
affirm (nh < ((uintmax_t) 1 << (W_TYPE_SIZE - 2))); affirm (nh < ((uintmax_t) 1 << (W_TYPE_SIZE - 2)));
if (nh == 0) if (nh == 0)
return isqrt (nl); return isqrt (nl);
count_leading_zeros (shift, nh); int shift = stdc_leading_zeros (nh) & ~1;
shift &= ~1;
/* Make x > sqrt (n). */ /* Make x > sqrt (n). */
x = isqrt ((nh << shift) + (nl >> (W_TYPE_SIZE - shift))) + 1; uintmax_t x = isqrt ((nh << shift) + (nl >> (W_TYPE_SIZE - shift))) + 1;
x <<= (W_TYPE_SIZE - shift) >> 1; x <<= (W_TYPE_SIZE - shift) >> 1;
/* Do we need more than one iteration? */ /* Do we need more than one iteration? */
@@ -1891,9 +1840,8 @@ static short const invtab[0x81] =
do { \ do { \
if ((u) / 0x40 < (d)) \ if ((u) / 0x40 < (d)) \
{ \ { \
int _cnt; \
uintmax_t _dinv, _mask, _q, _r; \ uintmax_t _dinv, _mask, _q, _r; \
count_leading_zeros (_cnt, (d)); \ int _cnt = stdc_leading_zeros (d); \
_r = (u); \ _r = (u); \
if (UNLIKELY (_cnt > (W_TYPE_SIZE - 8))) \ if (UNLIKELY (_cnt > (W_TYPE_SIZE - 8))) \
{ \ { \