aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert2017-03-03 09:17:51 -0800
committerPaul Eggert2017-03-03 09:19:08 -0800
commit74f87fd111904e5156727c72590d6fc4f67e8366 (patch)
treef6802878c5105def6d6889d5b8f71e4fe9285b79 /lib
parentf1fe3fcfc568c1527714ff3a95e678816e2787d4 (diff)
downloademacs-74f87fd111904e5156727c72590d6fc4f67e8366.tar.gz
emacs-74f87fd111904e5156727c72590d6fc4f67e8366.zip
logb now works correctly on large integers
* admin/merge-gnulib (GNULIB_MODULES): Add count-leading-zeros. * etc/NEWS: Document the change. * lib/count-leading-zeros.c, lib/count-leading-zeros.h: * m4/count-leading-zeros.m4: New files, copied from Gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * src/floatfns.c: Include count-leading-zeros.h. (Flogb): Do not convert fixnum to float before taking the log, as the rounding error can cause the answer to be off by 1. * src/lisp.h (EMACS_UINT_WIDTH): New constant. * test/src/floatfns-tests.el (logb-extreme-fixnum): New test.
Diffstat (limited to 'lib')
-rw-r--r--lib/count-leading-zeros.c3
-rw-r--r--lib/count-leading-zeros.h114
-rw-r--r--lib/gnulib.mk10
3 files changed, 126 insertions, 1 deletions
diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c
new file mode 100644
index 00000000000..d0c0704f582
--- /dev/null
+++ b/lib/count-leading-zeros.c
@@ -0,0 +1,3 @@
1#include <config.h>
2#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
3#include "count-leading-zeros.h"
diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
new file mode 100644
index 00000000000..e197137e66e
--- /dev/null
+++ b/lib/count-leading-zeros.h
@@ -0,0 +1,114 @@
1/* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* Written by Eric Blake. */
18
19#ifndef COUNT_LEADING_ZEROS_H
20#define COUNT_LEADING_ZEROS_H 1
21
22#include <limits.h>
23#include <stdlib.h>
24
25#ifndef _GL_INLINE_HEADER_BEGIN
26 #error "Please include config.h first."
27#endif
28_GL_INLINE_HEADER_BEGIN
29#ifndef COUNT_LEADING_ZEROS_INLINE
30# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE
31#endif
32
33/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
34 expand to code that computes the number of leading zeros of the local
35 variable 'x' of type TYPE (an unsigned integer type) and return it
36 from the current function. */
37#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
38# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
39 return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
40#elif _MSC_VER
41# pragma intrinsic _BitScanReverse
42# pragma intrinsic _BitScanReverse64
43# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
44 do \
45 { \
46 unsigned long result; \
47 return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
48 } \
49 while (0)
50#else
51# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
52 do \
53 { \
54 int count; \
55 unsigned int leading_32; \
56 if (! x) \
57 return CHAR_BIT * sizeof x; \
58 for (count = 0; \
59 (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32)) \
60 & 0xffffffffU), \
61 count < CHAR_BIT * sizeof x - 32 && !leading_32); \
62 count += 32) \
63 x = x << 31 << 1; \
64 return count + count_leading_zeros_32 (leading_32); \
65 } \
66 while (0)
67
68/* Compute and return the number of leading zeros in X,
69 where 0 < X < 2**32. */
70COUNT_LEADING_ZEROS_INLINE int
71count_leading_zeros_32 (unsigned int x)
72{
73 /* http://graphics.stanford.edu/~seander/bithacks.html */
74 static const char de_Bruijn_lookup[32] = {
75 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
76 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
77 };
78
79 x |= x >> 1;
80 x |= x >> 2;
81 x |= x >> 4;
82 x |= x >> 8;
83 x |= x >> 16;
84 return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27];
85}
86#endif
87
88/* Compute and return the number of leading zeros in X. */
89COUNT_LEADING_ZEROS_INLINE int
90count_leading_zeros (unsigned int x)
91{
92 COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int);
93}
94
95/* Compute and return the number of leading zeros in X. */
96COUNT_LEADING_ZEROS_INLINE int
97count_leading_zeros_l (unsigned long int x)
98{
99 COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int);
100}
101
102#if HAVE_UNSIGNED_LONG_LONG_INT
103/* Compute and return the number of leading zeros in X. */
104COUNT_LEADING_ZEROS_INLINE int
105count_leading_zeros_ll (unsigned long long int x)
106{
107 COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
108 unsigned long long int);
109}
110#endif
111
112_GL_INLINE_HEADER_END
113
114#endif /* COUNT_LEADING_ZEROS_H */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 4398fe37173..e4aa90ecac9 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings 24# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -151,6 +151,14 @@ EXTRA_DIST += close-stream.h
151 151
152## end gnulib module close-stream 152## end gnulib module close-stream
153 153
154## begin gnulib module count-leading-zeros
155
156libgnu_a_SOURCES += count-leading-zeros.c
157
158EXTRA_DIST += count-leading-zeros.h
159
160## end gnulib module count-leading-zeros
161
154## begin gnulib module count-one-bits 162## begin gnulib module count-one-bits
155 163
156libgnu_a_SOURCES += count-one-bits.c 164libgnu_a_SOURCES += count-one-bits.c