;;;; integer-specific (quite possibly FIXNUM-specific or
;;;; machine-word-specific) transforms

;;;; This software is part of the SBCL system. See the README file for
;;;; more information.
;;;;
;;;; This software is derived from the CMU CL system, which was
;;;; written at Carnegie Mellon University and released into the
;;;; public domain. The software is in the public domain and is
;;;; provided with absolutely no warranty. See the COPYING and CREDITS
;;;; files for more information.

(in-package "SB!C")

;;;; RANDOM in various integer cases

(deftransform random ((limit &optional state)
                      ((integer 1 #.(ash 1 sb!vm:n-word-bits)) &optional *))
  "transform to a sample no wider than CPU word"
  (let ((type (lvar-type limit)))
    (if (numeric-type-p type)
        (let ((limit-high (numeric-type-high (lvar-type limit))))
          (aver limit-high)
          (if (<= limit-high (1+ most-positive-fixnum))
              '(%inclusive-random-fixnum (1- limit)
                                         (or state *random-state*))
              '(%inclusive-random-integer (1- limit)
                                          (or state *random-state*))))
        (give-up-ir1-transform "too-wide inferred type for LIMIT argument"))))

;;; Boxing the argument to RANDOM (and often the return value as well)
;;; could be quite expensive in speed, while inlining every RANDOM
;;; call could be very expensive in code space, so use policy to
;;; decide.
(deftransform %inclusive-random-integer
    ((inclusive-limit state) (* *) * :policy (> speed space))
  ;; By the way, some natural special cases (notably when the user is
  ;; asking for a full %RANDOM-WORD) could be expanded to much simpler
  ;; code (with no test and loop) if someone finds it important.
  '(let ((n-bits (integer-length inclusive-limit)))
    (%inclusive-random-integer-accept-reject (%random-bits n-bits state)
     inclusive-limit)))
