Better seed support for (random).
* doc/lispref/numbers.texi (Random Numbers): Document new behavior of the calls (random) and (random STRING). * etc/NEWS: Document new behavior of (random), (random "string"). * lisp/play/5x5.el, lisp/play/animate.el, lisp/play/cookie1.el: * lisp/play/dissociate.el, lisp/play/doctor.el, lisp/play/dunnet.el: * lisp/play/gomoku.el, lisp/play/landmark.el, lisp/play/mpuz.el: * lisp/play/tetris.el, lisp/play/zone.el: * lisp/calc/calc-comb.el (math-init-random-base): * lisp/play/blackbox.el (bb-init-board): * lisp/play/life.el (life): * lisp/server.el (server-use-tcp): * lisp/type-break.el (type-break): Remove unnecessary call to (random t). * lisp/net/sasl.el (sasl-unique-id-function): Change (random t) to (random), now that the latter is more random. * lisp/play/life.el (life-initialized): Remove no-longer-needed var. * lisp/gnus/gnus-sync.el (gnus-sync-lesync-setup): * lisp/gnus/message.el (message-canlock-generate, message-unique-id): Change (random t) to (random), now that the latter is more random. * lisp/org/org-id.el (org-id-uuid): Change (random t) to (random), now that the latter is more random. * src/emacs.c (main): Call init_random. * src/fns.c (Frandom): Set the seed from a string argument, if given. Remove long-obsolete Gentzel cruft. * src/lisp.h, src/sysdep.c (seed_random): Now takes address and size, not long. (init_random): New function.
This commit is contained in:
parent
5bf647499a
commit
0e23ef9dde
33 changed files with 112 additions and 88 deletions
|
@ -1,3 +1,9 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seed support for (random).
|
||||
* numbers.texi (Random Numbers): Document new behavior of
|
||||
the calls (random) and (random STRING).
|
||||
|
||||
2012-08-21 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* windows.texi (Window Point): Document recent changes in
|
||||
|
|
|
@ -1199,30 +1199,32 @@ numbers are not truly random, but they have certain properties that
|
|||
mimic a random series. For example, all possible values occur equally
|
||||
often in a pseudo-random series.
|
||||
|
||||
In Emacs, pseudo-random numbers are generated from a ``seed'' number.
|
||||
In Emacs, pseudo-random numbers are generated from a ``seed''.
|
||||
Starting from any given seed, the @code{random} function always
|
||||
generates the same sequence of numbers. Emacs always starts with the
|
||||
same seed value, so the sequence of values of @code{random} is actually
|
||||
the same in each Emacs run! For example, in one operating system, the
|
||||
first call to @code{(random)} after you start Emacs always returns
|
||||
@minus{}1457731, and the second one always returns @minus{}7692030. This
|
||||
repeatability is helpful for debugging.
|
||||
generates the same sequence of numbers. Emacs typically starts with a
|
||||
different seed each time, so the sequence of values of @code{random}
|
||||
typically differs in each Emacs run.
|
||||
|
||||
If you want random numbers that don't always come out the same, execute
|
||||
@code{(random t)}. This chooses a new seed based on the current time of
|
||||
day and on Emacs's process @acronym{ID} number.
|
||||
Sometimes you want the random number sequence to be repeatable. For
|
||||
example, when debugging a program whose behavior depends on the random
|
||||
number sequence, it is helpful to get the same behavior in each
|
||||
program run. To make the sequence repeat, execute @code{(random "")}.
|
||||
This sets the seed to a constant value for your particular Emacs
|
||||
executable (though it may differ for other Emacs builds). You can use
|
||||
other strings to choose various seed values.
|
||||
|
||||
@defun random &optional limit
|
||||
This function returns a pseudo-random integer. Repeated calls return a
|
||||
series of pseudo-random integers.
|
||||
|
||||
If @var{limit} is a positive integer, the value is chosen to be
|
||||
nonnegative and less than @var{limit}.
|
||||
nonnegative and less than @var{limit}. Otherwise, the value
|
||||
might be any integer representable in Lisp.
|
||||
|
||||
If @var{limit} is @code{t}, it means to choose a new seed based on the
|
||||
current time of day and on Emacs's process @acronym{ID} number.
|
||||
|
||||
On some machines, any integer representable in Lisp may be the result
|
||||
of @code{random}. On other machines, the result can never be larger
|
||||
than a certain maximum or less than a certain (negative) minimum.
|
||||
If @var{limit} is a string, it means to choose a new seed based on the
|
||||
string's contents.
|
||||
|
||||
@end defun
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seeds for (random).
|
||||
* NEWS: Document new behavior of (random), (random "string").
|
||||
|
||||
2012-08-28 Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
* charsets/MULE-ethiopic.map: Fix typo in comment.
|
||||
|
|
5
etc/NEWS
5
etc/NEWS
|
@ -527,6 +527,11 @@ inefficiency, and not namespace-clean.
|
|||
|
||||
* Incompatible Lisp Changes in Emacs 24.3
|
||||
|
||||
** (random) by default now returns a different random sequence in
|
||||
every Emacs run. Use (random S), where S is a string, to set the
|
||||
random seed to a value based on S, in order to get a repeatable
|
||||
sequence in later calls.
|
||||
|
||||
** The function `x-select-font' can return a font spec, instead of a
|
||||
font name as a string. Whether it returns a font spec or a font name
|
||||
depends on the graphical library.
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seed support for (random).
|
||||
* play/5x5.el, play/animate.el, play/cookie1.el, play/dissociate.el:
|
||||
* play/doctor.el, play/dunnet.el, play/gomoku.el, play/landmark.el:
|
||||
* play/mpuz.el, play/tetris.el, play/zone.el:
|
||||
* calc/calc-comb.el (math-init-random-base):
|
||||
* play/blackbox.el (bb-init-board):
|
||||
* play/life.el (life):
|
||||
* server.el (server-use-tcp):
|
||||
* type-break.el (type-break):
|
||||
Remove unnecessary call to (random t).
|
||||
* net/sasl.el (sasl-unique-id-function):
|
||||
Change (random t) to (random), now that the latter is more random.
|
||||
* play/life.el (life-initialized): Remove no-longer-needed var.
|
||||
|
||||
2012-08-31 Alp Aker <alp.tekin.aker@gmail.com>
|
||||
|
||||
* window.el (switch-to-prev-buffer, switch-to-next-buffer):
|
||||
|
|
|
@ -1374,7 +1374,6 @@ FROM and TO must be in increasing order, as must be the pairs in RANGES."
|
|||
;; (time-trial
|
||||
;; '(let ((size 10000)
|
||||
;; doing)
|
||||
;; (random t)
|
||||
;; (dotimes (count size)
|
||||
;; (setq doing (random size))
|
||||
;; (funcall try doing (+ doing (random 5)))
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
4877 4889 4903 4909 4919 4931 4933 4937 4943 4951 4957 4967 4969 4973
|
||||
4987 4993 4999 5003])
|
||||
|
||||
;; The variable math-prime-factors-finished is set by calcFunc-prfac to
|
||||
;; The variable math-prime-factors-finished is set by calcFunc-prfac to
|
||||
;; indicate whether factoring is complete, and used by calcFunc-factors,
|
||||
;; calcFunc-totient and calcFunc-moebius.
|
||||
(defvar math-prime-factors-finished)
|
||||
|
@ -510,8 +510,8 @@
|
|||
(while (<= (length math-stirling-local-cache) n)
|
||||
(let ((i (1- (length math-stirling-local-cache)))
|
||||
row)
|
||||
(setq math-stirling-local-cache
|
||||
(vconcat math-stirling-local-cache
|
||||
(setq math-stirling-local-cache
|
||||
(vconcat math-stirling-local-cache
|
||||
(make-vector (length math-stirling-local-cache) nil)))
|
||||
(aset math-stirling-cache k math-stirling-local-cache)
|
||||
(while (< (setq i (1+ i)) (length math-stirling-local-cache))
|
||||
|
@ -572,7 +572,6 @@
|
|||
(let ((i 200))
|
||||
(while (> (setq i (1- i)) 0)
|
||||
(math-random-base))))
|
||||
(random t)
|
||||
(setq var-RandSeed nil
|
||||
math-random-cache nil
|
||||
math-random-shift -4) ; assume RAND_MAX >= 16383
|
||||
|
@ -629,7 +628,7 @@
|
|||
(i (/ (+ n slop) 3))
|
||||
(rnum 0))
|
||||
(while (> i 0)
|
||||
(setq rnum
|
||||
(setq rnum
|
||||
(math-add
|
||||
(math-random-three-digit-number)
|
||||
(math-mul rnum 1000)))
|
||||
|
@ -823,11 +822,11 @@
|
|||
(setq sum (%
|
||||
(+
|
||||
sum
|
||||
(calcFunc-mod
|
||||
(calcFunc-mod
|
||||
q 1000000))
|
||||
111111))
|
||||
(setq q
|
||||
(math-quotient
|
||||
(setq q
|
||||
(math-quotient
|
||||
q 1000000)))
|
||||
(cond ((= (% sum 3) 0) '(nil 3))
|
||||
((= (% sum 7) 0) '(nil 7))
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seeds for (random).
|
||||
* gnus-sync.el (gnus-sync-lesync-setup):
|
||||
* message.el (message-canlock-generate, message-unique-id):
|
||||
Change (random t) to (random), now that the latter is more random.
|
||||
|
||||
2012-08-31 Dave Abrahams <dave@boostpro.com>
|
||||
|
||||
* auth-source.el (auth-sources): Fix macos keychain access.
|
||||
|
|
|
@ -225,7 +225,7 @@ When SALT is nil, a random one will be generated using `random'."
|
|||
(security-object (concat url "/_security"))
|
||||
(user-record `((names . [,user]) (roles . [])))
|
||||
(couch-user-name (format "org.couchdb.user:%s" user))
|
||||
(salt (or salt (sha1 (format "%s" (random t)))))
|
||||
(salt (or salt (sha1 (format "%s" (random)))))
|
||||
(couch-user-record
|
||||
`((_id . ,couch-user-name)
|
||||
(type . user)
|
||||
|
|
|
@ -4820,9 +4820,7 @@ Do not use this for anything important, it is cryptographically weak."
|
|||
(require 'sha1)
|
||||
(let (sha1-maximum-internal-length)
|
||||
(sha1 (concat (message-unique-id)
|
||||
(format "%x%x%x" (random)
|
||||
(progn (random t) (random))
|
||||
(random))
|
||||
(format "%x%x%x" (random) (random) (random))
|
||||
(prin1-to-string (recent-keys))
|
||||
(prin1-to-string (garbage-collect))))))
|
||||
|
||||
|
@ -5525,7 +5523,6 @@ In posting styles use `(\"Expires\" (make-expires-date 30))'."
|
|||
;; You might for example insert a "." somewhere (not next to another dot
|
||||
;; or string boundary), or modify the "fsf" string.
|
||||
(defun message-unique-id ()
|
||||
(random t)
|
||||
;; Don't use microseconds from (current-time), they may be unsupported.
|
||||
;; Instead we use this randomly inited counter.
|
||||
(setq message-unique-id-char
|
||||
|
|
|
@ -183,7 +183,7 @@ It contain at least 64 bits of entropy."
|
|||
;; Don't use microseconds from (current-time), they may be unsupported.
|
||||
;; Instead we use this randomly inited counter.
|
||||
(setq sasl-unique-id-char
|
||||
(% (1+ (or sasl-unique-id-char (logand (random t) (1- (lsh 1 20)))))
|
||||
(% (1+ (or sasl-unique-id-char (logand (random) (1- (lsh 1 20)))))
|
||||
;; (current-time) returns 16-bit ints,
|
||||
;; and 2^16*25 just fits into 4 digits i base 36.
|
||||
(* 25 25)))
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seed support for (random).
|
||||
* org-id.el (org-id-uuid):
|
||||
Change (random t) to (random), now that the latter is more random.
|
||||
|
||||
2012-07-29 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Don't use the abbreviation "win" to refer to Windows (Bug#10421).
|
||||
|
|
|
@ -318,7 +318,7 @@ So a typical ID could look like \"Org:4nd91V40HI\"."
|
|||
(defun org-id-uuid ()
|
||||
"Return string with random (version 4) UUID."
|
||||
(let ((rnd (md5 (format "%s%s%s%s%s%s%s"
|
||||
(random t)
|
||||
(random)
|
||||
(current-time)
|
||||
(user-uid)
|
||||
(emacs-pid)
|
||||
|
|
|
@ -953,8 +953,6 @@ lest."
|
|||
(y-or-n-p prompt)
|
||||
t))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide '5x5)
|
||||
|
||||
;;; 5x5.el ends here
|
||||
|
|
|
@ -201,8 +201,6 @@ the buffer *Birthday-Present-for-Name*."
|
|||
(animate-string "my sunshine" 18 34)
|
||||
(animate-string "to stay!" 19 34))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'animate)
|
||||
|
||||
;;; animate.el ends here
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
(define-key map (vector 'remap oldfun) newfun))
|
||||
|
||||
|
||||
(defvar blackbox-mode-map
|
||||
(defvar blackbox-mode-map
|
||||
(let ((map (make-keymap)))
|
||||
(suppress-keymap map t)
|
||||
(blackbox-redefine-key map 'backward-char 'bb-left)
|
||||
|
@ -257,7 +257,6 @@ a reflection."
|
|||
(bb-goto (cons bb-x bb-y)))
|
||||
|
||||
(defun bb-init-board (num-balls)
|
||||
(random t)
|
||||
(let (board pos)
|
||||
(while (>= (setq num-balls (1- num-balls)) 0)
|
||||
(while
|
||||
|
|
|
@ -53,9 +53,6 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
; Randomize the seed in the random number generator.
|
||||
(random t)
|
||||
|
||||
(defconst cookie-delimiter "\n%%\n\\|\n%\n\\|\0"
|
||||
"Delimiter used to separate cookie file entries.")
|
||||
|
||||
|
|
|
@ -94,8 +94,6 @@ Default is 2."
|
|||
(funcall search-function overlap opoint t))))))
|
||||
(sit-for 0))))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'dissociate)
|
||||
|
||||
;;; dissociate.el ends here
|
||||
|
|
|
@ -1620,8 +1620,6 @@ Hack on previous word, setting global variable DOCTOR-OWNER to correct result."
|
|||
|
||||
(defun doctor-chat () (doctor-type (doc$ doctor--chatlst)))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'doctor)
|
||||
|
||||
;;; doctor.el ends here
|
||||
|
|
|
@ -3010,7 +3010,6 @@ drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..")
|
|||
(dun-uexit nil)))
|
||||
|
||||
|
||||
(random t)
|
||||
(setq tloc (+ 60 (random 18)))
|
||||
(dun-replace dun-room-objects tloc
|
||||
(append (nth tloc dun-room-objects) (list 18)))
|
||||
|
|
|
@ -1197,8 +1197,6 @@ If the game is finished, this command requests for another game."
|
|||
(move-to-column (+ gomoku-x-offset
|
||||
(* gomoku-square-width (1- gomoku-board-width)))))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'gomoku)
|
||||
|
||||
;;; gomoku.el ends here
|
||||
|
|
|
@ -1683,8 +1683,6 @@ Use \\[describe-mode] for more info."
|
|||
;;;allout-layout: (0 : -1 -1 0)
|
||||
;;;End:
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'landmark)
|
||||
|
||||
;;; landmark.el ends here
|
||||
|
|
|
@ -111,9 +111,6 @@
|
|||
;; Sadly, mode-line-format won't display numbers.
|
||||
(defvar life-generation-string nil)
|
||||
|
||||
(defvar life-initialized nil
|
||||
"Non-nil if `life' has been run at least once.")
|
||||
|
||||
;;;###autoload
|
||||
(defun life (&optional sleeptime)
|
||||
"Run Conway's Life simulation.
|
||||
|
@ -121,9 +118,6 @@ The starting pattern is randomly selected. Prefix arg (optional first
|
|||
arg non-nil from a program) is the number of seconds to sleep between
|
||||
generations (this defaults to 1)."
|
||||
(interactive "p")
|
||||
(or life-initialized
|
||||
(random t))
|
||||
(setq life-initialized t)
|
||||
(or sleeptime (setq sleeptime 1))
|
||||
(life-setup)
|
||||
(catch 'life-exit
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
:prefix "mpuz-"
|
||||
:group 'games)
|
||||
|
||||
(random t) ; randomize
|
||||
|
||||
(defcustom mpuz-silent 'error
|
||||
"Set this to nil if you want dings on inputs.
|
||||
The value t means never ding, and `error' means only ding on wrong input."
|
||||
|
|
|
@ -635,8 +635,6 @@ tetris-mode keybindings:
|
|||
(tetris-mode)
|
||||
(tetris-start-game))
|
||||
|
||||
(random t)
|
||||
|
||||
(provide 'tetris)
|
||||
|
||||
;;; tetris.el ends here
|
||||
|
|
|
@ -675,8 +675,6 @@ If nil, `zone-pgm-random-life' chooses a value from 0-3 (inclusive).")
|
|||
(kill-buffer nil))))
|
||||
|
||||
|
||||
(random t)
|
||||
|
||||
;;;;;;;;;;;;;;;
|
||||
(provide 'zone)
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
(setq val t)
|
||||
(unless load-in-progress
|
||||
(message "Local sockets unsupported, using TCP sockets")))
|
||||
(when val (random t))
|
||||
(set-default sym val))
|
||||
:group 'server
|
||||
:type 'boolean
|
||||
|
|
|
@ -577,7 +577,6 @@ as per the function `type-break-schedule'."
|
|||
(unless type-break-terse-messages
|
||||
(message "Press any key to resume from typing break."))
|
||||
|
||||
(random t)
|
||||
(let* ((len (length type-break-demo-functions))
|
||||
(idx (random len))
|
||||
(fn (nth idx type-break-demo-functions)))
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2012-09-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Better seed support for (random).
|
||||
* emacs.c (main): Call init_random.
|
||||
* fns.c (Frandom): Set the seed from a string argument, if given.
|
||||
Remove long-obsolete Gentzel cruft.
|
||||
* lisp.h, sysdep.c (seed_random): Now takes address and size, not long.
|
||||
(init_random): New function.
|
||||
|
||||
2012-08-31 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
Remove mark_ttys function and fix tty_display_info initialization.
|
||||
|
|
|
@ -1281,6 +1281,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
init_data ();
|
||||
init_atimer ();
|
||||
running_asynch_code = 0;
|
||||
init_random ();
|
||||
|
||||
no_loadup
|
||||
= argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
|
||||
|
|
28
src/fns.c
28
src/fns.c
|
@ -74,32 +74,16 @@ Other values of LIMIT are ignored. */)
|
|||
(Lisp_Object limit)
|
||||
{
|
||||
EMACS_INT val;
|
||||
Lisp_Object lispy_val;
|
||||
|
||||
if (EQ (limit, Qt))
|
||||
{
|
||||
EMACS_TIME t = current_emacs_time ();
|
||||
seed_random (getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t));
|
||||
}
|
||||
init_random ();
|
||||
else if (STRINGP (limit))
|
||||
seed_random (SSDATA (limit), SBYTES (limit));
|
||||
|
||||
val = get_random ();
|
||||
if (NATNUMP (limit) && XFASTINT (limit) != 0)
|
||||
{
|
||||
/* Try to take our random number from the higher bits of VAL,
|
||||
not the lower, since (says Gentzel) the low bits of `random'
|
||||
are less random than the higher ones. We do this by using the
|
||||
quotient rather than the remainder. At the high end of the RNG
|
||||
it's possible to get a quotient larger than n; discarding
|
||||
these values eliminates the bias that would otherwise appear
|
||||
when using a large n. */
|
||||
EMACS_INT denominator = (INTMASK + 1) / XFASTINT (limit);
|
||||
do
|
||||
val = get_random () / denominator;
|
||||
while (val >= XFASTINT (limit));
|
||||
}
|
||||
else
|
||||
val = get_random ();
|
||||
XSETINT (lispy_val, val);
|
||||
return lispy_val;
|
||||
val %= XFASTINT (limit);
|
||||
return make_number (val);
|
||||
}
|
||||
|
||||
/* Heuristic on how many iterations of a tight loop can be safely done
|
||||
|
|
|
@ -3405,7 +3405,8 @@ extern void child_setup_tty (int);
|
|||
extern void setup_pty (int);
|
||||
extern int set_window_size (int, int, int);
|
||||
extern EMACS_INT get_random (void);
|
||||
extern void seed_random (long);
|
||||
extern void seed_random (void *, ptrdiff_t);
|
||||
extern void init_random (void);
|
||||
extern int emacs_open (const char *, int, int);
|
||||
extern int emacs_close (int);
|
||||
extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
|
||||
|
|
24
src/sysdep.c
24
src/sysdep.c
|
@ -1765,19 +1765,37 @@ init_signals (void)
|
|||
#endif /* !RAND_BITS */
|
||||
|
||||
void
|
||||
seed_random (long int arg)
|
||||
seed_random (void *seed, ptrdiff_t seed_size)
|
||||
{
|
||||
#if defined HAVE_RANDOM || ! defined HAV_LRAND48
|
||||
unsigned int arg = 0;
|
||||
#else
|
||||
long int arg = 0;
|
||||
#endif
|
||||
unsigned char *argp = (unsigned char *) &arg;
|
||||
unsigned char *seedp = seed;
|
||||
ptrdiff_t i;
|
||||
for (i = 0; i < seed_size; i++)
|
||||
argp[i % sizeof arg] ^= seedp[i];
|
||||
#ifdef HAVE_RANDOM
|
||||
srandom ((unsigned int)arg);
|
||||
srandom (arg);
|
||||
#else
|
||||
# ifdef HAVE_LRAND48
|
||||
srand48 (arg);
|
||||
# else
|
||||
srand ((unsigned int)arg);
|
||||
srand (arg);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_random (void)
|
||||
{
|
||||
EMACS_TIME t = current_emacs_time ();
|
||||
uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t);
|
||||
seed_random (&v, sizeof v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a nonnegative random integer out of whatever we've got.
|
||||
* It contains enough bits to make a random (signed) Emacs fixnum.
|
||||
|
|
Loading…
Add table
Reference in a new issue