"Hoehle, Joerg-Cyril" <Joerg-Cyril.Hoehle@...> writes:
> Hi again,
>
> I sent plenty of comments in the other e-mail, so here's the summary and =
proposed solutions (all untested).
>
> (defun solve (matrice y)
> "R=E9solution MATRICE * x =3D Y par lapack"
> (let ((n (array-dimension matrice 0)))
> (with-foreign-object (mat-alien `(c-array double-float ,(* n n)) matr=
ice)
It does not work, due to rank differences. The conversion works if we
write:
(with-foreign-object (mat-alien `(c-array double-float (,n ,n)) matrice)
Here mat-alien is a 2-dimensional C array, that means a pointer to a
pointer to a double. But 2-D arrays in Fortran are always 1-D behind
the scene. So this won't work either.
> (with-c-var (x-alien `(c-array double-float ,n) y)
> (with-foreign-object (ipiv-alien `(c-array int ,n))
> (let ((info (dgesv
> n
> 1 ; nrhs
> mat-alien
> n ; lda
> ipiv-alien
> (c-var-address x-alien)
> n))) ; ldb
Nice, you do not need to pass the :out argument ! After verification,
yes, it is in the FFI documentation, but I did not believe the FFI was
so smart.
> (if (=3D info 0) x-alien info)))))))
Actually, in most of the Lapack subroutines, an non-null info value is
not an error, and the returned values contain meaningful information
(reduction to triangular form, some eigenvalues computed...).=20
If there is an error, Lapack quits (hence my question about how to
intercept the Fortran STOP statement).
[...]
> One may recognize that this, again, is an instance of passing variable le=
ngth arrays to/from functions. Now that the foreign function constructor is=
easily available in clisp, we can do this:
>
> (defun memofn (n) ; actual memoization not shown
> (parse-c-type
> `(c-function
> (:return-type nil)
> (:arguments (n (c-ptr int))
> (nrhs (c-ptr int))
> ; a is strictly :in-out, but we throw away the result here
> (a (c-ptr (c-array double-float ,n ,n)) :in)
You mean
(a (c-ptr (c-array double-float (,n ,n))) :in)
> (lda (c-ptr int))
> (ipiv (c-ptr (c-array double-float ,n)) :out)
> ; b is strictly :in-out, but we throw away the result here
> (b (c-ptr (c-array double-float ,n)))
> (ldb (c-ptr int))
> (info (c-ptr int) :out))
> (:language :stdc))))
>
> (defun solve (matrice y)
> ;; This code is bad, because the result is dereferenced even in case of
> ;; error. In general, doing so could result in run-time conversion erro=
rs.
> (multiple-value-bind (ipiv info)
> (funcall
> (foreign-function #'dgesv (memofn (length y)))
> n 1 matrice n y n)
> (if (=3D info 0) ipiv)))
So here also ipiv is automatically allocated ?
> In order to not dereference :out variables upon failures, we have to do w=
hat clisp does internally by hand: stack-allocated variables are manipulate=
d explicitly then, with-foreign resurfaces:
>
> (defun memofn (n) ; actual memoization not shown
> (parse-c-type
> `(c-function
> (:return-type nil)
> (:arguments (n (c-ptr int))
> (nrhs (c-ptr int))
> ; a is strictly :in-out, but we throw away the result here
> (a (c-ptr (c-array double-float ,n ,n)) :in)
> (lda (c-ptr int))
> (ipiv c-pointer) ; conceptually :out (c-ptr double-float n)
> ; b is strictly :in-out, but we throw away the result here
> (b (c-ptr (c-array double-float ,n)))
> (ldb (c-ptr int))
> (info (c-ptr int) :out))
> (:language :stdc))))
> ; this differs from the above for ipiv.
>
> (defun solve (matrice y)
> (let ((n (length y)))
> (with-foreign-object (ipiv `(c-array double-float ,n))
> (let ((info (funcall (foreign-function
> #'dgesv (memofn (length y)))
> n 1 matrice n ipiv y n)))
> (if (=3D info 0) (foreign-value ipiv))))))
Nice, but see above my remark about info return values.
I guess you still need a def-call-out definition, as #'dgesv is
not known with the above code alone.
> I expect this memoized function declaration stuff to beat any custom nest=
ing of with-foreign-object any time -- if memoized. Please report.
If n varies from call to call, as is typically the case, it will not
help. I am wondering why in clisp foreign arrays must have fixed
dimensions ?
> One could also memoize the result of foreign-function, but that's less li=
kely to work across saved images.
>
> BTW, UFFI is very far from such conciseness. But then, it's just a matter=
of piling up macros.
>
>
> Remembers me that some month ago, I talked about a macro to provide exact=
ly such variable-length function definition ability, with :guards (for :out=
put checks) and bells and whistles. Any volunteer?
>
> Regards,
> J=F6rg H=F6hle
>
Thank you a lot for your comments, my code has already improved much.
--=20
Bernard Urban
|