Thomas Fischbacher <[EMAIL PROTECTED]> writes:

 > You might want to have a look at my with-arith-defs macro. (Just google for 
 > it.)

Looks interesting.  I'll have to take a more careful look.

 > > Added a declaration after the definition of s helps.  The following
 > > doesn't generate any notes:
 > > 
 > >    (defun sumn (n)
 > >      (declare (type (integer 0 10000) n))
 > >      (let ((s 0))
 > >        (declare (type (integer 0 200000000) s))
 > >        (dotimes (i n)
 > >          (incf s i))
 > >        s))
 > 
 > Uh, shouldn't i be declared fixnum as well?

It seems that in cmucl, dotimes includes a declaration for the iteration
variable:

   * (macroexpand-1 '(dotimes (i 100) (incf j i)))

   (DO ((I 0 (1+ I)))
       ((>= I 100) NIL)
     (DECLARE (TYPE (INTEGER 0 100) I))
     (INCF J I))
   T
   * (setq n 1000)
   Warning:  Declaring N special.

   1000
   * (macroexpand-1 '(dotimes (i n) (incf j i)))

   (DO ((I 0 (1+ I))
        (#:G841 N))
       ((>= I #:G841) NIL)
     (DECLARE (TYPE UNSIGNED-BYTE I))
     (INCF J I))
   T

Evidentally, when the number of iterations is a constant X, it
declares it to be of type (integer 0 X), and otherwise declares it to
be of type unsigned-byte.  So I have to leave the decls out.
Otherwise the compiler essentially complains about an incompatible
redefinition.

This actually leads to a problem.  The dotimes macro is essentially
adding an assertion about the iterator that doesn't necessarily hold,
and its existence prevents me from putting in a better declaration.

So, for example, in the bsmc function, when I declare the iterators to
be type (integer 1 1000000), I get compiler warnings that the bindings
aren't of this type.  However, when I don't declare them, I instead
end up with generic comparisons:

   In: DEFUN BSMC
     (DOTIMES (I TRIALS)
       (LET (#)
         (DECLARE #)
         (DOTIMES # #)
         (INCF SUMVAL #)))
   --> DO BLOCK LET TAGBODY UNLESS COND IF NOT IF >= IF 
   ==>
     (< I #:G0)
   Note: Forced to do GENERIC-< (cost 10).
         Unable to do inline fixnum comparison (cost 4) because:
         The first argument is a UNSIGNED-BYTE, not a FIXNUM.

   --> DO BLOCK LET TAGBODY PSETQ LET 1+ 
   ==>
     (+ I 1)
   Note: Forced to do GENERIC-+ (cost 10).
         Unable to do inline fixnum arithmetic (cost 1) because:
         The first argument is a UNSIGNED-BYTE, not a FIXNUM.
         The result is a (INTEGER 1), not a FIXNUM.
         Unable to do inline fixnum arithmetic (cost 2) because:
         The first argument is a UNSIGNED-BYTE, not a FIXNUM.
         The result is a (INTEGER 1), not a FIXNUM.
         etc.

     (CALLPAY (* S0 (EXP #)) K)
   Note: Doing float to pointer coercion (cost 13).
   [Last message occurs 2 times]

How should declarations be handled with dotimes?  Or should I just
redefine it to not include a declaration?  It seems like the
declaration being added isn't optimal.

-- 
Harvey Stein
Bloomberg LP
[EMAIL PROTECTED]


Reply via email to