GMP C++11 support

Hans Aberg haberg-1 at telia.com
Tue Feb 10 13:22:40 UTC 2015


For GMP C++11 support, there might be the following functions, x = z, q, f:

For use with move constructor/assignment:
  void mpx_move(mpx_t x, mpx_t y);
Move data from y to x, leaving y in a state so that mpx_clear() can be called or assignments be made.

Hash function, for use with hash containers: std::unordered_set, std::unordered_map, etc.
  size_t mpx_hash(mpx_t x);

Both are easy to write, but one has to go below the the GMP API. In addition, mpz_init() allocates a limb, so one would want to have

inline void mpz_move(mpz_t x, mpz_t y) {
  x[0] = y[0];  mpz_null(y);
}

where

inline void mpz_null(mpz_t x) {
  x[0]._mp_alloc = 0;
  x[0]._mp_size = 0;
  x[0]._mp_d = NULL;    // Setting allocation pointer to null probably suffices.
}

But in this variation, one does not know if y is left in a valid GMP state - for that one has to use mpz_init() which will make an allocation that is never used (and immediately destroyed).


For the hash function, one can write:
  size_t mpz_hash(mpz_t x) {
      std::size_t h = 0;
      for (int i = 0; i < abs(x->_mp_size); ++i)
        h ^= std::hash<mp_limb_t>()(x->_mp_d[i]);
      return h;
  }
where std::hash<mp_limb_t>() merely extracts the C++ hash function for the builtin integral type that mp_limb_t represents. 

But then one has to go into the mpz_t type, so if the GMP implementation changes, the hash function must be changed too. GMP having its own hash maps might be more efficient, too.




More information about the gmp-discuss mailing list