Making the following changes reduced the run time from 13.5 seconds to
about 3 seconds.  I'm running under FreeBSD with a 1.1 Ghz Athlon.

(I also rearranged the code a little for test purposes and to avoid
magic-numbers scattered around the code but that shouldn't present any
problems....)

----------------------------------------

(declaim (optimize (speed 3) (safety 1) (space 0)))

(declaim (fixnum *sides* *num*))
(defconstant *sides* 10)
(defconstant *num* 6)

(declaim (type (simple-array (unsigned-byte 32) (#.*sides*)) r))
(defvar r (make-array *sides* :element-type '(unsigned-byte 32))) 

(defun check (dice num succ fail botch)
  (declare (type (simple-array (unsigned-byte 32) (#.*num*)) dice)
           (type (simple-array (unsigned-byte 32) (#.*sides*)) succ fail botch))
  ;; reset counters
  (dotimes (i *sides*)
    (setf (aref r i) 0))
  ;; scan dices
  (let ((ones 0))
    (dotimes (i num)
      (if (= (aref dice i) 0)
        (incf ones)
        (progn
          (loop for j from (aref dice i) downto 1
                do (incf (aref r j))))))
    ;; record results
    (dotimes (i *sides*)
      (cond
        ((> (aref r i) ones) (incf (aref succ i)))
        ((and (> ones 0) (= (aref r i) 0)) (incf (aref botch i)))
        (t (incf (aref fail i)))))))

(defun increment (dice num)
  (declare (type (simple-array (unsigned-byte 32) (#.*num*)) dice))
  (loop for i from 0 below num
        do (incf (aref dice i))
        when (>= (aref dice i) *sides*) do (setf (aref dice i) 0)
        else do (return-from increment nil)
        finally (return-from increment t)))


(defun test-it ()
  (let* ((num *num*)
         (dice  (make-array num :initial-element 0 :element-type '(unsigned-byte 32)))
         (succ  (make-array *sides* :initial-element 0 :element-type '(unsigned-byte 
32)))
         (fail  (make-array *sides* :initial-element 0 :element-type '(unsigned-byte 
32)))
         (botch (make-array *sides* :initial-element 0 :element-type '(unsigned-byte 
32))))
    (declare (fixnum num))
    (declare (type (simple-array (unsigned-byte 32) (#.*num*)) dice)
             (type (simple-array (unsigned-byte 32) (#.*sides*)) succ fail botch))
    (format t "Start...~%")
    (loop
     do (check dice num succ fail botch)
     until (increment dice num))
    (print succ)
    (print fail)
    (print botch)
    ))

----------------------------------------


I also noticed that using (unsigned-byte 16) instead of
(unsigned-byte 32) reduces the run time still further, to a bit more
than 2 seconds.

The main point is that CMUCL only optimizes specialized arrays of the
following types:

     bit
     (unsigned-byte 2)
     (unsigned-byte 4)
     (unsigned-byte 8)
     (unsigned-byte 16)
     (unsigned-byte 32)
     base-character
     single-float
     double-float


(at least according to the version of the user manual I have).  FIXNUM
is not one of these types --- I suppose that's because it's not a
native-hardware word size.

-- 
Fred Gilham                     [EMAIL PROTECTED]
We have yet to find the Galileo who will question
our me-centred universe. --- Christina Odone

Reply via email to