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

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Tue May 11 01:52:03 2004

Hi,

Goffioul Michael wrote:
>> [...] Matlisp does.  However,
>> it does require your Lisp to have a specialized array with
>> double-float elements that are arranged in one contiguous area,
>I don't know(think) that direct memory mapping is possible in CLISP.
>It uses copy to send/retrieve data to/from FFI functions.

The FFI is not the problem if you want to interface to some foreign code. You can always write modules, which, as an other article of mine explained, feature full access to Lisp objects. One could build modules even --without-dynamic-ffi :-)
but few people know about this, or maybe very few people value this possibility.

The problem IMHO is as follows:

Sam Steingold wrote:
>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).

So you cannot have Matlist write the non-existant CLISP FP arrays :-)

The FFI is, by the nature of conversions, a slow interface (it's an interpreter for a foreign-function description language). Some modules
could benefit from direct access to Lisp objects.
So far, few people have come up with time measurements. Modules where it's
known to make a difference are regexp. Modules where it could make a
difference are those where functions are either called very often, or on
large data.
But still, I believe run-time invocations of parse-c-type typically cost
more than the FFI conversion overhead.
Modules where it makes no difference are obviously those where one function
is called for a long computation.

BTW, do you except your function to be called with plenty of different array sizes? Otherwise, typical memoization techniques of the FOREIGN-FUNCTION object could be used: you'd call a memoized specialisation of the foreign function restricted to e.g. exactly (C-ARRAY int 100). That's the fastest you could get with the FFI!

Regards,
	Jörg Höhle.

---

From: Sam Steingold <[email-masked]>
Date: Tue May 11 07:42:01 2004

> * Hoehle, Joerg-Cyril <[email-masked]> [2004-05-11 10:50:03 +0200]:
>
> Goffioul Michael wrote:
> The FFI is not the problem if you want to interface to some foreign
> code. You can always write modules, which, as an other article of mine
> explained, feature full access to Lisp objects. One could build
> modules even --without-dynamic-ffi :-) but few people know about this,
> or maybe very few people value this possibility.

Moreover, many modules bundled with CLISP do not depend on FFI:
regexp, syscalls, pcre, berkeley-db, dirkey, queens, rawsock.

> So you cannot have Matlist write the non-existant CLISP FP arrays :-)

yes you can.  Just allocate (UNSIGNED-BYTE 32) arrays of double size
(for DOUBLE-FLOAT) or required size (for SINGLE-FLOAT) and pass the
data vectors to the FORTRAN functions.

-- 
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>
Daddy, why doesn't this magnet pick up this floppy disk?

---

From: Raymond Toy <[email-masked]>
Date: Tue May 11 08:59:02 2004

>>>>> "Sam" == Sam Steingold <[email-masked]> writes:

    Sam> yes you can.  Just allocate (UNSIGNED-BYTE 32) arrays of double size
    Sam> (for DOUBLE-FLOAT) or required size (for SINGLE-FLOAT) and pass the
    Sam> data vectors to the FORTRAN functions.

That's not really enough.  Matlisp also wants to be able to see those
arrays as Lisp arrays of some sort.

Well, you could have functions that takes such things and converts
them back and forth, but that seems not so nice.

Ray

---

From: Michael Goffioul <[email-masked]>
Date: Wed May 12 07:18:15 2004

Sam Steingold <sds <at> gnu.org> writes: 
 
> > So you cannot have Matlist write the non-existant CLISP FP arrays  
>  
 
I'm a little bit lost among all the answers that requires more and more 
knowledge of CLISP internals (which I don't have). I'll restate the problem as 
simple as possible: 
 
1) there's a foreign function (whether C or FORTRAN) that takes a double array 
as argument AND modifies it: in C it could be "int func(double *a, in len)" 
for example. 
 
2) in LISP, I'd like a kind of wrapper function (whether it's implemented in a 
module, with FFI or plain LISP) that would be called as "(func a)" where a is 
of type (simple-array double-float *). 
 
3) the LISP wrapper should behave as the foreign function, namely it should 
modify its argument (destructive behavior) 
 
4) the wrapper should be *generic*: the input array can have any length, there 
can be more than one input argument that could be modified by the foreign 
function. 
 
Once you've solved this, making MatLisp work with CLISP should be 
straightforward. Thanks anyway for all the answers. 
 
Bye. 
Michael.

---

From: Sam Steingold <[email-masked]>
Date: Wed May 12 07:55:07 2004

> * Michael Goffioul <[email-masked]> [2004-05-12 14:17:43 +0000]:
>
> I'm a little bit lost among all the answers that requires more and
> more knowledge of CLISP internals (which I don't have).

start with little pieces... :-)

> I'll restate the problem as simple as possible:
>  
> 1) there's a foreign function (whether C or FORTRAN) that takes a
> double array as argument AND modifies it: in C it could be "int
> func(double *a, in len)" for example.
>  
> 2) in LISP, I'd like a kind of wrapper function (whether it's
> implemented in a module, with FFI or plain LISP) that would be called
> as "(func a)" where a is of type (simple-array double-float *).
>  
> 3) the LISP wrapper should behave as the foreign function, namely it
> should modify its argument (destructive behavior)
>  
> 4) the wrapper should be *generic*: the input array can have any
> length, there can be more than one input argument that could be
> modified by the foreign function.

completely untested:

DEFUN(fun,arr) {
  uintL pos, index, size = array_total_size(STACK_0 = check_array(STACK_0));
  object data_vector = array_displace_check(STACK_0,size,&index);
  double *c_array = alloca(size*sizeof(double));
  pushSTACK(data_vector);
  for (pos=0; pos<size; pos++)
    c_array[pos] = to_double(TheSvector(STACK_0)->data[pos+index]);
  begin_system_call();
  func(c_array,size);
  end_system_call();
  for (pos=0; pos<size; pos++)
    TheSvector(STACK_0)->data[pos+index] = c_double_to_DF(&c_array[pos]);
  VALUES1(STACK_1); /* return the argument */
  skipSTACK(2);
}

-- 
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>
Please wait, MS Windows are preparing the blue screen of death.