
Hi there,
we have been bitten by a problem that can be explained as follows: on machines that are not Crays, `mp_size_t' is of type `long int':
#if defined (_CRAY) && ! defined (_CRAYMPP) /* plain `int' is much faster (48 bits) */ #define __GMP_MP_SIZE_T_INT 1 typedef int mp_size_t; typedef int mp_exp_t; #else #define __GMP_MP_SIZE_T_INT 0 typedef long int mp_size_t; typedef long int mp_exp_t; #endif
However, the `_mp_size' field of `_mpz_struct' is of type `int':
typedef struct { int _mp_alloc; /* Number of *limbs* allocated and pointed to by the _mp_d field. */ int _mp_size; /* abs(_mp_size) is the number of limbs the last field points to. If _mp_size is negative this is a negative number. */ mp_limb_t *_mp_d; /* Pointer to the limbs. */ } __mpz_struct; #endif /* __GNU_MP__ */
For some reason (assonance, quite likely), we were assuming that `_mp_size' was of type `mp_size_t' but this wrong assumption fails whenever `int' and `long int' are different types (which happens, e.g., on x86_64-unknown-linux-gnu).
Notice that I am not posting this to gmp-bugs because it is not, I believe, a bug of GMP: we are fiddling with the internal details of GMP and this is something that goes beyond the API. Nonetheless, I wonder why many GMP functions accepts parameters of type `long int' (on non-Crays) when they can never handle anything that does not fit `int'. Is this apparent discrepancy intended? (I know that a size of 2^31-1 fits all present and future purposes, but this does not explain why mp_size_t can go beyond that limit.) All the best,
Roberto

Roberto Bagnara bagnara@cs.unipr.it writes:
Notice that I am not posting this to gmp-bugs because it is not, I believe, a bug of GMP: we are fiddling with the internal details of GMP and this is something that goes beyond the API. Nonetheless, I wonder why many GMP functions accepts parameters of type `long int' (on non-Crays) when they can never handle anything that does not fit `int'.
I'm afraid I don't follow your reasoning here.
(I don't think any mpz/mpq/mpf functions accept mp_size_t arguments. The _ui functions accept an (unsigned) long int but that's 32-bit or 64-bit numerical data, which will at most add 32 or 64 to the _mp_size argument.)
Is this apparent discrepancy intended? (I know that a size of 2^31-1 fits all present and future purposes, but this does not explain why mp_size_t can go beyond that limit.)
Yes, this is intended. It saves a lot of memory for smallish numbers on 64-bit systems, since the mpz_t will use 24 bytes instead of 32 bytes.
We use mp_size_t in the mpn layer to allow larger precisions there, and mp_size_t in scalars elsewhere since 64-bit scalar arithmetic is often somewhat faster on 64-bit machines. (Now there is an exception to this rule in the AMD64 clone Pentiums, where 64-bit arithmetic is often much slower than 32-bit arithmetic.)

Torbjorn Granlund wrote:
Roberto Bagnara bagnara@cs.unipr.it writes:
Notice that I am not posting this to gmp-bugs because it is not, I believe, a bug of GMP: we are fiddling with the internal details of GMP and this is something that goes beyond the API. Nonetheless, I wonder why many GMP functions accepts parameters of type `long int' (on non-Crays) when they can never handle anything that does not fit `int'.
I'm afraid I don't follow your reasoning here.
(I don't think any mpz/mpq/mpf functions accept mp_size_t arguments. The _ui functions accept an (unsigned) long int but that's 32-bit or 64-bit numerical data, which will at most add 32 or 64 to the _mp_size argument.)
Maybe "many" was the wrong word. But there are mpz and mpf functions that accept mp_size_t arguments:
void mpz_array_init (mpz_t integer_array[], size_t array_size, mp_size_t fixed_num_bits) void * _mpz_realloc (mpz_t integer, mp_size_t new_alloc) mp_limb_t mpz_getlimbn (mpz_t op, mp_size_t n) void mpz_random (mpz_t rop, mp_size_t max_size) void mpz_random2 (mpz_t rop, mp_size_t max_size) void mpf_random2 (mpf_t rop, mp_size_t max_size, mp_exp_t exp)
Cheers,
Roberto
participants (2)
-
Roberto Bagnara
-
Torbjorn Granlund