3

I would like to generate a random integer z of n bytes such that

2^(n-1) <= z <= 2^n - 1

Whenever I run the following code gmp spits out the same exact integer, what am I doing wrong?

// Random int of n bits.
const auto n_bits = 1024;
mpz_t mpz_int;
gmp_randstate_t state;
mpz_init(mpz_int);
gmp_randinit_default(state);
mpz_rrandomb(mpz_int, state, n_bits);

std::cout<<"Random int generated:"<<std::endl;
std::cout<<mpz_get_str(nullptr, 10, mpz_int)<<std::endl;

The output of mpz_rrandomb changes only when I change the n_bits parameter. I tried this on Ubuntu and MacOS.. I also tried mpz_urandomb -- same problem. I assume I am missing some initializations, I've been going over gmp documentation for hours and I can't find a reason why the above wouldn't work.

To reproduce, stuff the above code into the main function, compile with flags:

g++ main.cpp -O2 -Wall -std=c++14 -lstdc++ -lgmp -lgmpxx

Thank You.

lead-free
  • 128
  • 2
  • 11
  • I don't know how to use GMP but it seems you initiallize the random state with the default-initialized struct. I would naively assume that this default value is always the same. Perhaps there is a function to get "real" randomness from the system for that state? – Adomas Baliuka Mar 26 '21 at 13:09
  • Are you doing this in a loop? Once only, in the `main` function? And when and where do you [set the *seed*](https://gmplib.org/manual/Random-State-Seeding)? Please try to create a [mcve] to show us. – Some programmer dude Mar 26 '21 at 13:09

1 Answers1

2

gmp_randinit_default apparently sets the seed to some fixed value. You are supposed to call gmp_randseed or gmp_randseed_ui afterwards to set the seed to your own value which will not be the same on every run.

For an initial test, you could try gmp_randseed_ui(state, getpid()). On Linux you can get a much more random seed by calling getrandom() or reading /dev/urandom. Not sure which of these are provided on MacOS.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Silly goose, `gmp_randseed_ui` was missing indeed. I read an `unsigned long int` from `/dev/urandom `, then pass it to `gmp_randseed_ui` and everything works like a charm. I wonder how much is enough to read from `/dev/urandom` to reliably generate utterly long (say 8192 bits) integers, but I guess it is a whole different question.. – lead-free Mar 27 '21 at 01:59
  • 1
    @lead-free: The default PRNG is Mersenne Twister, so I'd start by looking at [How to properly seed a mersenne twister RNG?](https://stackoverflow.com/q/8395037/364696) – ShadowRanger Mar 27 '21 at 02:08