From: Tamas K Papp <tkpapp@gm...>  20100123 09:13:08

Hi, I need to construct matrices which are "semiconstant": many elements are constant, but a few may be calculated runtime. A further complication is that these matrices need to be columnmajor. I am optimizing for speed (and not too much consing). I thought I would write a macro that constructs a matrix and fills it with elements. Since many elements are zero, I thought I would set that in makearray and not set those elements individually. I am counting on the compiler to fold (coerced) constants, so that I don't have to use decimal dots, making usage convenient. Here is the resulting macro, with an example: (defmacro ccolmajormatrixdouble (&body listofrows) "Construct a matrix of doublefloats from given elements (lists of lists). Elements may be constants or forms, and are coerced to the correct type." (let* ((ncol (length (first listofrows))) (nrow (length listofrows)) (arrayname (gensym "vector"))) `(let ((,arrayname (makearray '(,ncol ,nrow) :elementtype 'doublefloat :initialelement 0d0))) ,@(iter outer (for rowlist :in listofrows) (for row :from 0) (assert (= (length rowlist) ncol) () "Invalid number of elements in row ~A." row) (iter (for element :in rowlist) (for col :from 0) (unless (and (numberp element) (zerop element)) (in outer (collect `(setf (aref ,arrayname ,col ,row) (coerce ,element 'doublefloat))))))) ,arrayname))) (defun makespecialmatrix (a b) "Inane example." (declare (optimize speed) (doublefloat a b)) (ccolmajormatrixdouble (0 0 0 1 (* a b)) (12 a b 0 0) (( a b) 0 0 0 7.8))) where the macro expands to (LET ((#:vector1541 (MAKEARRAY '(5 3) :ELEMENTTYPE 'DOUBLEFLOAT :INITIALELEMENT 0.0d0))) (SETF (AREF #:vector1541 3 0) (COERCE 1 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 4 0) (COERCE (* A B) 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 0 1) (COERCE 12 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 1 1) (COERCE A 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 2 1) (COERCE B 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 0 2) (COERCE ( A B) 'DOUBLEFLOAT)) (SETF (AREF #:vector1541 4 2) (COERCE 7.8 'DOUBLEFLOAT)) #:vector1541) However, the disassembly indicates that this may not be the most "natural" way to do this in SBCL. Is there a better one? Thanks, Tamas 