<div dir="ltr"><div><div><div><div>matrix-product in blas3.lisp calls the gsl_blas gemm routine. It has optional parameters TransA and TransB to specify whether the matrices A and/or B should be transposed prior to multiplying. These two take values :trans or :notrans.<br>
<br>The bug is twofold. matrix-product calls matrix-product-dimensions (defined in blas2). To do its job properly, matrix-product-dimensions should have TransA and TransB as parameters, and matrix-product should call it with those as arguments.<br>
<br></div>Here is the modified matrix-product-dimensions:<br><br>(defun matrix-product-dimensions (a b &optional (TRANSA :NOTRANS) (TRANSB :NOTRANS))<br> (if (typep b 'grid:matrix)<br> (list (funcall (case transa<br>
(:notrans #'first)<br> (:trans #'second)<br> (t (error "Invalid tranposition keyword, ~a" transa)))<br> (grid:dimensions a))<br> (funcall (case transb<br>
(:notrans #'second)<br> (:trans #'first)<br> (t (error "Invalid tranposition keyword, ~a" transb)))<br> (grid:dimensions b)))<br> (first (funcall (case transa<br>
(:notrans #'first)<br> (:trans #'second)<br> (t (error "Invalid tranposition keyword, ~a" transa)))<br> (grid:dimensions a)))))<br><br></div>This can probably be improved. I applied the same fix to the case when b is not a matrix, since matrix-product in blas2 which works on matrix x vector, also accepts that TransB argument.<br>
<br></div>Finally matrix-product has to be fixed. It is defined in both blas2 (for matrix vector multiplication) and in blas3 (for matrix matrix multiplication). The modifications consist of modifying the call to matrix-product-dimensions to include TransA (and TransB)<br>
<br></div>;; blas2<br><div>(defmfun matrix-product<br> ((A grid:matrix) (x vector)<br> &optional<br> y<br> (alpha 1) (beta 1) (TransA :notrans) TransB<br>
&aux<br> (yarr<br> (grid:ensure-foreign-array<br> y (matrix-product-dimensions A x TransA) element-type 0)))<br> ("gsl_blas_" :type "gemv")<br> ((transa cblas-transpose) (alpha :element-c-type) ((mpointer A) :pointer)<br>
((mpointer x) :pointer) (beta :element-c-type) ((mpointer yarr) :pointer))<br> :definition :generic<br> :element-types #+fsbv :float-complex #-fsbv :float<br> :inputs (A x)<br> :outputs (yarr)<br> :documentation ; FDL<br>
"If the second and third arguments are vectors, compute<br> the matrix-vector product and sum<br> y = alpha op(A) x + beta y, where op(A) = A, A^T, A^H<br> for TransA = :notrans, :trans, :conjtrans.<br> If the second and third arguments are matrices, compute<br>
the matrix-matrix product and sum C = alpha<br> op(A) op(B) + beta C where op(A) = A, A^T, A^H for TransA =<br> :notrans, :trans, :conjtrans and similarly for the<br> parameter TransB.")<br><br></div><div>;; blas3<br>
(defmfun matrix-product<br> ((A grid:matrix) (B grid:matrix)<br> &optional<br> C<br> (alpha 1) (beta 1) (TransA :notrans) (TransB :notrans)<br> &aux<br> (Carr<br> (or C<br> (grid:make-foreign-array element-type :dimensions (matrix-product-dimensions A B TransA TransB)<br>
:initial-element 0))))<br> ("gsl_blas_" :type "gemm")<br> ((TransA cblas-transpose) (TransB cblas-transpose)<br> (alpha :element-c-type) ((mpointer A) :pointer)<br> ((mpointer B) :pointer) (beta :element-c-type) ((mpointer Carr) :pointer))<br>
:definition :methods<br> :element-types #+fsbv :float-complex #-fsbv :float<br> :inputs (A B Carr)<br> :outputs (Carr))<br><br><br></div><div>I did not test this exhaustively, but the modifications did work my a few matrix multiplications that I needed.<br>
<br></div><div>Mirko<br></div></div>