@@ -7,24 +7,62 @@ extern "C" {
77
88/* This is published for the benefit of "friend" marshal.c only. */
99
10- /* Parameters of the long integer representation.
11- These shouldn't have to be changed as C should guarantee that a short
12- contains at least 16 bits, but it's made changeable anyway.
13- Note: 'digit' should be able to hold 2*MASK+1, and 'twodigits'
14- should be able to hold the intermediate results in 'mul'
15- (at most (BASE-1)*(2*BASE+1) == MASK*(2*MASK+3)).
16- Also, x_sub assumes that 'digit' is an unsigned type, and overflow
17- is handled by taking the result mod 2**N for some N > SHIFT.
18- And, at some places it is assumed that MASK fits in an int, as well.
19- long_pow() requires that SHIFT be divisible by 5. */
10+ /* Parameters of the long integer representation. There are two different
11+ sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit
12+ integer type, and one set for 15-bit digits with each digit stored in an
13+ unsigned short. The value of PYLONG_BITS_IN_DIGIT, defined either at
14+ configure time or in pyport.h, is used to decide which digit size to use.
2015
21- typedef unsigned short digit ;
22- typedef short sdigit ; /* signed variant of digit */
23- #define BASE_TWODIGITS_TYPE long
24- typedef unsigned BASE_TWODIGITS_TYPE twodigits ;
25- typedef BASE_TWODIGITS_TYPE stwodigits ; /* signed variant of twodigits */
16+ Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits'
17+ should be an unsigned integer type able to hold all integers up to
18+ PyLong_BASE*PyLong_BASE-1. x_sub assumes that 'digit' is an unsigned type,
19+ and that overflow is handled by taking the result modulo 2**N for some N >
20+ PyLong_SHIFT. The majority of the code doesn't care about the precise
21+ value of PyLong_SHIFT, but there are some notable exceptions:
22+
23+ - long_pow() requires that PyLong_SHIFT be divisible by 5
24+
25+ - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8
26+
27+ - long_hash() requires that PyLong_SHIFT is *strictly* less than the number
28+ of bits in an unsigned long, as do the PyLong <-> long (or unsigned long)
29+ conversion functions
30+
31+ - the long <-> size_t/Py_ssize_t conversion functions expect that
32+ PyLong_SHIFT is strictly less than the number of bits in a size_t
33+
34+ - the marshal code currently expects that PyLong_SHIFT is a multiple of 15
35+
36+ - NSMALLNEGINTS and NSMALLPOSINTS should be small enough to fit in a single
37+ digit; with the current values this forces PyLong_SHIFT >= 9
2638
39+ The values 15 and 30 should fit all of the above requirements, on any
40+ platform.
41+ */
42+
43+ #if HAVE_STDINT_H
44+ #include <stdint.h>
45+ #endif
46+
47+ #if PYLONG_BITS_IN_DIGIT == 30
48+ #if !(defined HAVE_UINT64_T && defined HAVE_UINT32_T && \
49+ defined HAVE_INT64_T && defined HAVE_INT32_T )
50+ #error "30-bit long digits requested, but the necessary types are not available on this platform"
51+ #endif
52+ typedef PY_UINT32_T digit ;
53+ typedef PY_INT32_T sdigit ; /* signed variant of digit */
54+ typedef PY_UINT64_T twodigits ;
55+ typedef PY_INT64_T stwodigits ; /* signed variant of twodigits */
56+ #define PyLong_SHIFT 30
57+ #elif PYLONG_BITS_IN_DIGIT == 15
58+ typedef unsigned short digit ;
59+ typedef short sdigit ; /* signed variant of digit */
60+ typedef unsigned long twodigits ;
61+ typedef long stwodigits ; /* signed variant of twodigits */
2762#define PyLong_SHIFT 15
63+ #else
64+ #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
65+ #endif
2866#define PyLong_BASE ((digit)1 << PyLong_SHIFT)
2967#define PyLong_MASK ((digit)(PyLong_BASE - 1))
3068
0 commit comments