Overhaul `math' representation machinery.
[u/mdw/catacomb] / m4 / mdw-uint-bits.m4
CommitLineData
1c3d4cf5
MW
1dnl -*-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
34dnl Algorithm:
35dnl
36dnl We first find an upper bound on the number of bits in the type as
37dnl sizeof(TYPE) * CHAR_BIT. This is usually a good guess at the actual
38dnl value, since most modern systems don't have hidden bits, so we test to
39dnl see if it's correct. If not, we start a binary search to find the true
40dnl value.
41dnl
42dnl To test a guess n, we form X = (TYPE)~(TYPE)0, which is the largest value
43dnl representable as a TYPE, and attempt to shift it right by n places. This
44dnl is a little subtle, since shifting by more than the word length is
45dnl undefined behaviour. The implementation isn't completely perfect. It
46dnl assumes that a shift of 15 bits must be allowed (which is reasonable,
47dnl since an int must be at least 16 bits, and the standard integer
48dnl promotions will map shorter integer types to an int). If n > 15, we
49dnl shift down in two stages, once by dividing by 2^15 = 32768, and once by
50dnl shifting by n - 15; otherwise we just shift. (This strange chicanery is
51dnl to deal with Microsoft compilers which incorrectly `optimize' adjacent
52dnl correct shifts into a single invalid one.) If X >> n is nonzero then n
53dnl is too small; if X >> (n - 1) is zero then n is too large; if neither
54dnl condition holds then n is correct.
55dnl
56dnl This is, unfortunately, logarithmic if the initial guess is wrong, but
57dnl that will happen rarely on interesting platforms. Sites wanting to speed
58dnl up the configuration process can pre-seed the configuration cache. If
59dnl anyone really cares, we can detect a native compiler (as opposed to a
60dnl cross-compiler) and do the binary-search in C.
61
62# Serial 1
63AC_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'])])