On Sun, Apr 3, 2011 at 10:10 AM, Christophe Rhodes <csr21@cantab.net> wrote:
Elliott Slaughter <elliottslaughter@gmail.com> writes:

> I'm wondering why in the following code SBCL complains about being unable to
> optimize the arithmetic despite my type declarations? I am on 1.0.46 on Mac
> OS X (64-bit, threaded).
>
> The code:
>
> (declaim (optimize (speed 3) (safety 0)))
>
> (defun dot-sa (a b)
>   (declare (type (simple-array fixnum (4)) a b))
>   (+ (* (aref a 0) (aref b 0))
>      (* (aref a 1) (aref b 1))
>      (* (aref a 2) (aref b 2))
>      (* (aref a 3) (aref b 3))))

The compiler note that you gave, about generic-* rather than inline
fixnum arithmetic, is emitted because in doing an efficient
multiplication not only must the arguments in (* x y) be fixnums, so
also must the result -- and there's no way the compiler can guarantee
that from your type declaration.  (It could if either the arguments were
known to be smaller than the square root of MOST-POSITIVE-FIXNUM, or if
you make the promise that it will using (THE FIXNUM (* X Y)))

That makes sense. (It also makes the code uglier, but I suppose that is to be expected.)

> (defun test-dot-sa ()
>   (let ((a (vector 1 2 3 4))
>         (b (vector 4 3 2 1)))
>     (time (loop for i from 1 to 100000000 do (dot-sa a b)))))

Note that (vector 1 2 3 4) does not return an object of type
(simple-array fixnum (4)) -- just because all the elements are a vector
are of type fixnum at a given time does not make the vector specialized
only to hold fixnums.

Doh! That should have been (make-array '(4) :element-type 'fixnum :initial-contents '(1 2 3 4)) .

Cheers,

Christophe



--
Elliott Slaughter

"Don't worry about what anybody else is going to do. The best way to predict the future is to invent it." - Alan Kay