Subject: [clisp-list] FFI with complex numbers?

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Fri May 7 03:41:09 2004

Goffioul Michael wrote:
>Writing conversion routines is a possibility, but I fear that 
>efficiency
>would be low, especially if you want to convert large complex arrays
>(if you need to do it in a loop). Is there a way to make C code access
>LISP variables directly (without copying)?

AFAIK, CLISP doesn't have specialized float arrays anyway (IIRC).
Sam/Bruno, please correct me if my memory is wrong.

You could in theory obtain pointers to Lisp objects. This is really a dangerous thing to do in the presence of a moving GC. While some code may work for you, somebody else using your code but also custom SIGALARM handlers may trigger GC (not that installing a Lisp-level SGIALARM handler is supported anyway, AFAIK). FFI callbacks may also trigger GC.

That's why in the CLISP FFI everything is copyied via the stack to fixed locations (next to the assumption that it's preferrable to let foreign code corrupt the stack than the Lisp heap :).

The best trade-off could be a conversion-routine in C, but I'm not sure it would gain much because I believe CLISP's complex numbers use unboxed representations anyway, since both real and imaginary can be of any real number type, e.g. integer, thus the internal representation is certainly not an array of two doubles. Even the C code would have to be prepared for conversion via COERCE 'double-float.

I'd suggest you go along a simple solution, bear with copying, and investigate whether that really is the performance bottleneck. Gievn the speed of many machines, this "good enough" approach has been working for many people.

(I could tell you how some of the CLISP modules exhibit poor performance, yet nobody ever complained. People are generally happy that it just works.)

Regards,
	Jörg Höhle.

---

From: Sam Steingold <[email-masked]>
Date: Fri May 7 07:09:15 2004

> * Hoehle, Joerg-Cyril <[email-masked]> [2004-05-07 12:38:59 +0200]:
>

You are right, CLISP does not have specialized float arrays.
It would be relatively easy to add them in the NO_TYPECODES model
(mostly used on 32-bit processors).
It would be next to impossible to add them in the TYPECODES model
(mostly used on 64-bit processors) because of limited number of unused
typecodes.

IMO, it does not make much sense from the performance POV to create
specialized arrays for boxed types because there will be boxing on
every access.

If all you are doing with the arrays is passing them between foreign
routines, you might want to view them as an opaque data type.

I am open to corrections...

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Abandon all hope, all ye who press Enter.

---

From: Michael Goffioul <[email-masked]>
Date: Mon May 10 02:17:03 2004

Sam Steingold <sds <at> gnu.org> writes: 
 
>  
> > * Hoehle, Joerg-Cyril <Wbret-Plevy.Ubruyr <at> g-flfgrzf.pbz> [2004-05-07 
> routines, you might want to view them as an opaque data type. 
 
The problem is that arrays are coming from LISP objects and processed 
by underlying FORTRAN code, which usually modifies arrays in-situ. 
Hence it would be more efficient if the FORTRAN/C code could access 
directly LISP memory/data. But I can live with copying... 
 
OTOH, I read with interest a previous post/tutorial in 2003 about 
variable size arrays and how to use them with FFI. It could suit my 
needs, the only problem is that macros like WITH-FOREIGN-OBJECT or 
WITH-C-VAR only accept a single variable (at least that's how I 
understood the doc). Aren't there equivalent for multiple variables? 
 
Up to now, I'm left with code like this: 
 
(use-package "FFI") 
 
(def-call-out c-myfun 
  (:library "libmyfun.so") 
  (:name "myfun5") 
  (:arguments 
    (a c-pointer :in) 
    (la int :in) 
    (b c-pointer :in) 
    (lb int :in)) 
  (:return-type int) 
  (:language :stdc)) 
 
(defun myfun (a b) 
  (let* ((la (length a)) 
         (lb (length b)) 
         (c-a (foreign-allocate (parse-c-type 'int) :count 
la :initial-contents a)) 
         (c-b (foreign-allocate (parse-c-type 'int) :count 
lb :initial-contents b)) 
         (r (c-myfun c-a la c-b lb)) 
         (new-a (foreign-value c-a)) 
         (new-b (foreign-value c-b))) 
    (foreign-free c-a) 
    (foreign-free c-b) 
    (values r new-a new-b))) 
 
Thanks. 
Michael.