|
From: Raymond T. <rt...@us...> - 2012-03-31 02:36:48
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "matlisp".
The branch, matlisp-cffi has been updated
via 21d8ce7bad4335a01727786b8114af348c31d3c9 (commit)
from 45e57ae1f888c8c271a91d42b9231b99bd55691e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 21d8ce7bad4335a01727786b8114af348c31d3c9
Author: Raymond Toy <toy...@gm...>
Date: Fri Mar 30 19:36:29 2012 -0700
Add WITH-FORTRAN-MATRICES to make it a little easier to deal with
Fortran arrays in callback functions.
diff --git a/src/utilities.lisp b/src/utilities.lisp
index 5bf4237..bbd8ad2 100644
--- a/src/utilities.lisp
+++ b/src/utilities.lisp
@@ -225,4 +225,80 @@ else run else-body"
(unless (< -1 n ss)
(error "Index N out of bounds."))
(setf (cffi:mem-aref sap sty n) value)))
+
+
+;;; Rudimentary support for making it a bit easier to deal with Fortran
+;;; arrays in callbacks.
+
+;; If the Array dimensions are (d1, d2, d3, ...)
+;;
+;; Then x(n1, n2, n3, ...) means the index is, essentially,
+;;
+;; n1 + d1*(n2 + d2*(n3 + d3*(n4 + d4*(n5))))
;;
+;; Return an expression that computes the column major index given the
+;; indices (a list) and a list of the bounds on each dimension. Each
+;; bound is a list of the upper and lower bounds for each dimension.
+;; For example, for the Fortran array declared as x(3:10, -4:2), the
+;; bounds would be written as ((3 10) (-4 2)). If the lower bound is
+;; the default of 1, you can omit the lower bound.
+(defun col-major-index (indices dims)
+ ;; Return a form that computes the column major index of a Fortran array.
+ (flet ((get-offset (n bound)
+ (let ((lo (first bound)))
+ (if (and (numberp lo) (zerop lo))
+ n
+ `(the fixnum (- (the fixnum ,n) (the fixnum ,lo))))))
+ (get-size (bound)
+ (destructuring-bind (lo hi)
+ bound
+ (cond ((numberp lo)
+ (cond ((numberp hi)
+ (1+ (- hi lo)))
+ ((= lo 1)
+ hi)
+ (t
+ `(- ,hi ,(- lo 1)))))
+ (t
+ `(the fixnum (- ,hi (the fixnum (- (the fixnum ,lo) 1)))))))))
+ (let* ((rev-idx (reverse indices))
+ (rev-dim (reverse dims))
+ (idx (get-offset (first rev-idx) (first rev-dim))))
+ (do ((d (rest rev-dim) (rest d))
+ (n (rest rev-idx) (rest n)))
+ ((endp d)
+ idx)
+ (setf idx `(the fixnum (+ ,(get-offset (first n) (first d))
+ (the fixnum (* ,(get-size (first d)) ,idx)))))))))
+
+(defmacro with-fortran-matrix ((name fv &rest dims) &body body)
+ (let ((indices (gensym (symbol-name '#:indices-))))
+ `(macrolet ((,name (&rest ,indices)
+ `(fv-ref ,',fv ,(col-major-index ,indices ',dims))))
+ ,@body)))
+
+;; WITH-FORTRAN-MATRICES is a convenience macro for accessing Fortran
+;; arrays that have been passed in as parameters of a callback.
+;;
+;; For example, Fortran callback function that might be
+;;
+;; subroutine sub(z, f)
+;; real z(4), df(2, 4)
+;; df(1,4) = 3*z(2)
+;; end
+;;
+;; This can be written in a Lisp call back as
+;;
+;; (defun fsub (z-arg f-arg)
+;; (with-fortran-matrices ((z z-arg (1 4))
+;; (f f-arg ((1 2) (1 4))))
+;; (setf (f 1 4) (* 3 (z 2)))))
+;;
+
+(defmacro with-fortran-matrices ((&rest array-list) &body body)
+ (if (cdr array-list)
+ `(with-fortran-matrix ,(car array-list)
+ (with-fortran-matrices ,(cdr array-list)
+ ,@body))
+ `(with-fortran-matrix ,(car array-list)
+ ,@body)))
\ No newline at end of file
-----------------------------------------------------------------------
Summary of changes:
src/utilities.lisp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
hooks/post-receive
--
matlisp
|