--- /dev/null
+#include "Rand.h"
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+using namespace std;
+
+mpz_class Rand::randSize(int sizeBits, bool forceSize)
+{
+ const int nbBitsFirstByte = ((sizeBits - 1) % 8) + 1; // >= 1 and <= 8
+ const int nbBytes = sizeBits / 8 + (nbBitsFirstByte != 8 ? 1 : 0);
+
+ // A fixed rand value used during benchmark tests.
+ // char randBytes[] {(char)0x3d, (char)0x3f, (char)0x74, (char)0xa3, (char)0xcb, (char)0xba, (char)0x2e, (char)0x26, (char)0xf4, (char)0x5a, (char)0x05, (char)0xb0, (char)0x91, (char)0x2d, (char)0x13, (char)0x4c, (char)0x81, (char)0xa4, (char)0x4e, (char)0x8d, (char)0x50, (char)0xc6, (char)0xa5, (char)0x6e, (char)0x69, (char)0x3b, (char)0x1d, (char)0xa1, (char)0x68, (char)0x79, (char)0x87, (char)0xbe, (char)0xbf, (char)0xc0, (char)0x3d, (char)0x06, (char)0x4a, (char)0x74, (char)0xc8, (char)0x36, (char)0xa0, (char)0x92, (char)0x0c, (char)0xb4, (char)0x99, (char)0x6e, (char)0x64, (char)0x27, (char)0x61, (char)0x18, (char)0xe5, (char)0x07, (char)0xf1, (char)0xcb, (char)0x45, (char)0x57, (char)0x84, (char)0xa8, (char)0xbc, (char)0x25, (char)0x00, (char)0x1c, (char)0x7f, (char)0x1c, (char)0xf7, (char)0x40, (char)0xc5, (char)0x09, (char)0x73, (char)0xbf, (char)0xde, (char)0xb2, (char)0x65, (char)0x15, (char)0x64, (char)0xb4, (char)0x94, (char)0x8f, (char)0x1c, (char)0x6b, (char)0x84, (char)0x4b, (char)0x69, (char)0x6f, (char)0xc7, (char)0x71, (char)0x26, (char)0x3c, (char)0x58, (char)0x5f, (char)0x08, (char)0x34, (char)0x29, (char)0x9a, (char)0xfb, (char)0x95, (char)0x9d, (char)0x4f, (char)0x27, (char)0x49, (char)0x94, (char)0xc4, (char)0x26, (char)0x76, (char)0xc1, (char)0x8e, (char)0x30, (char)0x7f, (char)0x93, (char)0x63, (char)0x68, (char)0x3c, (char)0x0b, (char)0x8f, (char)0x5d, (char)0xff, (char)0x09, (char)0x68, (char)0x1b, (char)0x41, (char)0xea, (char)0xfd, (char)0xe1, (char)0xd5, (char)0x77, (char)0x1d, (char)0x3b, (char)0xda, (char)0x6f, (char)0xb8, (char)0xbe, (char)0x86, (char)0x25, (char)0x8a, (char)0xc1, (char)0x2c, (char)0x87, (char)0xd0, (char)0x24, (char)0xe9, (char)0x0d, (char)0xb3, (char)0x23, (char)0xcb, (char)0x40, (char)0xa3, (char)0x40, (char)0xc7, (char)0x2c, (char)0x3e, (char)0x08, (char)0xdf, (char)0xdc, (char)0xaa, (char)0x7a, (char)0x4a, (char)0x02, (char)0x23, (char)0x73, (char)0xb3, (char)0xc9, (char)0xe5, (char)0x2a, (char)0x36, (char)0xf3, (char)0xd1, (char)0x59, (char)0xfd, (char)0x74, (char)0x63, (char)0x46, (char)0x92, (char)0x47, (char)0x48, (char)0xf0, (char)0x05, (char)0x4c, (char)0xf9, (char)0x92, (char)0xe2, (char)0xe8, (char)0x7e, (char)0x52, (char)0x1a, (char)0x84, (char)0x47, (char)0x9a, (char)0xb5, (char)0x25, (char)0xdc, (char)0xb2, (char)0xed, (char)0x02, (char)0x65, (char)0x76, (char)0x3e, (char)0xad, (char)0xc0, (char)0x3c, (char)0xa0, (char)0x30, (char)0x83, (char)0x0c, (char)0xbe, (char)0x09, (char)0x63, (char)0x36, (char)0x3c, (char)0xc4, (char)0x94, (char)0x79, (char)0x74, (char)0x30, (char)0x71, (char)0x1b, (char)0xac, (char)0x0c, (char)0x2f, (char)0xcf, (char)0xf4, (char)0x68, (char)0x26, (char)0xd9, (char)0xb4, (char)0xb5, (char)0x3c, (char)0x07, (char)0x41, (char)0xa4, (char)0xde, (char)0x80, (char)0x00, (char)0x70, (char)0x06, (char)0x8c, (char)0xa7, (char)0x1b, (char)0x81, (char)0xcb, (char)0x6b, (char)0xc7, (char)0x20, (char)0x45, (char)0x0e, (char)0x23, (char)0x19, (char)0xb8, (char)0xa3, (char)0x29, (char)0x29, (char)0xf4, (char)0x99, (char)0xde, (char)0xfb, (char)0xad, (char)0xa5 };
+
+ char randBytes[nbBytes];
+ readRand(randBytes, nbBytes);
+
+ // We discard the n most significant bits where n >= 0 && n <= 7.
+ if (nbBitsFirstByte != 8)
+ randBytes[0] &= 0xFF >> (8 - nbBitsFirstByte);
+
+ // If asked we set the most significant bit to 1.
+ if (forceSize)
+ randBytes[0] |= 0x01 << (nbBitsFirstByte - 1);
+
+ mpz_class n;
+ mpz_import(n.get_mpz_t(), nbBytes, 1, sizeof(char), 1, 0, randBytes); // Big-endian -> most significant byte first.
+ return n;
+}
+
+mpz_class Rand::randLimits(const mpz_class& from, const mpz_class& to)
+{
+ const mpz_class nbValues = to - from + 1;
+ const size_t nbBits = mpz_sizeinbase(mpz_class(nbValues - 1).get_mpz_t(), 2);
+
+ // A 'nbBytes' size random number is generated, if it matches the given limits we return it.
+ for (;;)
+ {
+ mpz_class n = randSize(nbBits, false) + from;
+ if (n >= from && n <= to)
+ return n;
+ }
+}
+
+mpz_class Rand::randPrime(const int size_bits)
+{
+ mpz_class r = randSize(size_bits);
+ mpz_nextprime(r.get_mpz_t(), r.get_mpz_t());
+ return r;
+}
+
+void Rand::readRand(char* to, int size)
+{
+ const string RANDOM_SOURCE("/dev/urandom");
+
+ static fstream ifs(RANDOM_SOURCE, ios_base::in);
+ if (!ifs)
+ {
+ cerr << "Unable to read the random source: " << RANDOM_SOURCE << endl;
+ throw 1;
+ }
+
+ ifs.read(to, size);
+}