return argument;
}
+static Lisp_Object
+ccall2 (Lisp_Object (f) (ptrdiff_t nargs, Lisp_Object *args),
+ Lisp_Object arg1, Lisp_Object arg2)
+{
+ Lisp_Object args[2] = {arg1, arg2};
+ return f (2, args);
+}
+
+static Lisp_Object
+get_random_bignum (Lisp_Object limit)
+{
+ /* This is a naive transcription into bignums of the fixnum algorithm.
+ I'd be quite surprised if that's anywhere near the best algorithm
+ for it. */
+ while (true)
+ {
+ Lisp_Object val = make_fixnum (0);
+ Lisp_Object lim = limit;
+ int bits = 0;
+ int bitsperiteration = FIXNUM_BITS - 1;
+ do
+ {
+ /* Shift by one so it is a valid positive fixnum. */
+ EMACS_INT rand = get_random () >> 1;
+ Lisp_Object lrand = make_fixnum (rand);
+ bits += bitsperiteration;
+ val = ccall2 (Flogior,
+ Fash (val, make_fixnum (bitsperiteration)),
+ lrand);
+ lim = Fash (lim, make_fixnum (- bitsperiteration));
+ }
+ while (!EQ (lim, make_fixnum (0)));
+ /* Return the remainder, except reject the rare case where
+ get_random returns a number so close to INTMASK that the
+ remainder isn't random. */
+ Lisp_Object remainder = Frem (val, limit);
+ if (!NILP (ccall2 (Fleq,
+ ccall2 (Fminus, val, remainder),
+ ccall2 (Fminus,
+ Fash (make_fixnum (1), make_fixnum (bits)),
+ limit))))
+ return remainder;
+ }
+}
+
DEFUN ("random", Frandom, Srandom, 0, 1, 0,
doc: /* Return a pseudo-random integer.
By default, return a fixnum; all fixnums are equally likely.
-With positive fixnum LIMIT, return random integer in interval [0,LIMIT).
+With positive integer LIMIT, return random integer in interval [0,LIMIT).
With argument t, set the random number seed from the system's entropy
pool if available, otherwise from less-random volatile data such as the time.
With a string argument, set the seed based on the string's contents.
init_random ();
else if (STRINGP (limit))
seed_random (SSDATA (limit), SBYTES (limit));
+ if (BIGNUMP (limit))
+ {
+ if (0 > mpz_sgn (*xbignum_val (limit)))
+ xsignal2 (Qwrong_type_argument, Qnatnump, limit);
+ return get_random_bignum (limit);
+ }
val = get_random ();
if (FIXNUMP (limit) && 0 < XFIXNUM (limit))