Here's the perfect answer I was looking for. Credits to Miroslav Urbanek from Charles University in Prague.
"Here's the basic idea. I find a function I want to use from
BLAS/LAPACK. In case of matrix multiplication, it's DGEMM. "D" stands
for double float, "GE" stands for general matrices (without a special
shape like symmetric, triangular, etc.), and "MM" stands for matrix
multiplication. The documentation is here:
http://www.netlib.org/lapack/explore-html/d7/d2b/dgemm_8f.html
Then I define an alien routine using SBCL FFI. I pass Lisp array
directly using some special SBCL functions. The Lisp arrays must be
created with an option :element-type 'double-float.
An important point is that SBCL stores array elements in row-major
order, similarly to C. Fortran uses column-major order. This
effectively corresponds to transposed matrices. The order of matrices
and their dimensions must be therefore changed when calling DGEMM from
Lisp."
;; Matrix multiplication in SBCL using BLAS
;; Miroslav Urbanek <[email protected]>
(load-shared-object "libblas.so.3")
(declaim (inline dgemm))
(define-alien-routine ("dgemm_" dgemm) void
(transa c-string)
(transb c-string)
(m int :copy)
(n int :copy)
(k int :copy)
(alpha double :copy)
(a (* double))
(lda int :copy)
(b (* double))
(ldb int :copy)
(beta double :copy)
(c (* double))
(ldc int :copy))
(defun pointer (array)
(sap-alien (sb-sys:vector-sap (array-storage-vector array)) (* double)))
(defun mm (a b)
(unless (= (array-dimension a 1) (array-dimension b 0))
(error "Matrix dimensions do not match."))
(let* ((m (array-dimension a 0))
(n (array-dimension b 1))
(k (array-dimension a 1))
(c (make-array (list m n) :element-type 'double-float)))
(sb-sys:with-pinned-objects (a b c)
(dgemm "n" "n" n m k 1d0 (pointer b) n (pointer a) k 0d0 (pointer c) n))
c))
(defparameter a (make-array '(2 3) :element-type 'double-float :initial-contents '((2d0 1d0 6d0) (7d0 3d0 4d0))))
(defparameter b (make-array '(3 2) :element-type 'double-float :initial-contents '((3d0 1d0) (6d0 5d0) (2d0 3d0))))
(format t "a = ~A~%b = ~A~%" a b)
(defparameter c (mm a b))