utils/naf.c: Non-adjacent form calculator, from math/mpreduce.c.
[u/mdw/catacomb] / m4 / mdw-uint-bits.m4
1 dnl -*-autoconf-*-
2
3 ### SYNOPSIS
4 ###
5 ### dnl mdw_UINT_BITS(TYPE, ABBREV)
6 ###
7 ### DESCRIPTION
8 ###
9 ### Defines ABBREV_BITS to be the number of bits representable by the
10 ### unsigned type named TYPE. This works even if the compiler in question
11 ### is a cross-compiler, and correctly handles systems without 8-bit bytes,
12 ### or which have hidden bits in their integer representations.
13 ###
14 ### LICENSE
15 ###
16 ### Copyright (c) 2013 Mark Wooding <mdw@distorted.org.uk>
17 ###
18 ### This program is free software: you can redistribute it and/or modify it
19 ### under the terms of the GNU General Public License as published by the
20 ### Free Software Foundation, either version 2 of the License, or (at your
21 ### option) any later version.
22 ###
23 ### This program is distributed in the hope that it will be useful, but
24 ### WITHOUT ANY WARRANTY; without even the implied warranty of
25 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 ### General Public License for more details.
27 ###
28 ### You should have received a copy of the GNU General Public License along
29 ### with this program. If not, see <http://www.gnu.org/licenses/>.
30 ###
31 ### In particular, no exception to the GPL is granted regarding generated
32 ### `configure' scripts which are the output of Autoconf.
33
34 dnl Algorithm:
35 dnl
36 dnl We first find an upper bound on the number of bits in the type as
37 dnl sizeof(TYPE) * CHAR_BIT. This is usually a good guess at the actual
38 dnl value, since most modern systems don't have hidden bits, so we test to
39 dnl see if it's correct. If not, we start a binary search to find the true
40 dnl value.
41 dnl
42 dnl To test a guess n, we form X = (TYPE)~(TYPE)0, which is the largest value
43 dnl representable as a TYPE, and attempt to shift it right by n places. This
44 dnl is a little subtle, since shifting by more than the word length is
45 dnl undefined behaviour. The implementation isn't completely perfect. It
46 dnl assumes that a shift of 15 bits must be allowed (which is reasonable,
47 dnl since an int must be at least 16 bits, and the standard integer
48 dnl promotions will map shorter integer types to an int). If n > 15, we
49 dnl shift down in two stages, once by dividing by 2^15 = 32768, and once by
50 dnl shifting by n - 15; otherwise we just shift. (This strange chicanery is
51 dnl to deal with Microsoft compilers which incorrectly `optimize' adjacent
52 dnl correct shifts into a single invalid one.) If X >> n is nonzero then n
53 dnl is too small; if X >> (n - 1) is zero then n is too large; if neither
54 dnl condition holds then n is correct.
55 dnl
56 dnl This is, unfortunately, logarithmic if the initial guess is wrong, but
57 dnl that will happen rarely on interesting platforms. Sites wanting to speed
58 dnl up the configuration process can pre-seed the configuration cache. If
59 dnl anyone really cares, we can detect a native compiler (as opposed to a
60 dnl cross-compiler) and do the binary-search in C.
61
62 # Serial 1
63 AC_DEFUN([mdw_UINT_BITS],
64 [AC_CACHE_CHECK([size of type `$1' in bits], [mdw_cv_$2_bits],
65 [mdw_PROBE_CONSTANT([guess], [sizeof($1) * CHAR_BIT], [
66 #include <limits.h>
67 #ifdef HAVE_STDINT_H
68 # include <stdint.h>
69 #endif])
70 down=0
71 while :; do
72 mdw_PROBE_CONSTANT([answer],
73 [low($guess) ? -1 : low($guess - 1) ? 0 : +1], [
74 #ifdef HAVE_STDINT_H
75 # include <stdint.h>
76 #endif
77 #define srs(x, n) ((n) <= 15 ? (x) >> (n) : ((x)/32768) >> ((n) - 15))
78 #define max (($1)~($1)0 | 0u)
79 #define low(b) (srs(max, b) != 0)
80 ])
81 case "$answer" in
82 0) break;;
83 1) up=$guess;;
84 -1) down=$guess;;
85 esac
86 guess=$(expr \( $up + $down \) / 2)
87 done
88 mdw_cv_$2_bits=$guess])
89 AS_TR_SH($2_bits)=$mdw_cv_$2_bits
90 AC_DEFINE_UNQUOTED(AS_TR_CPP([$2_BITS]), [$mdw_cv_$2_bits],
91 [number of bits in an object of type `$1'])])