Bill Allombert on Mon, 22 Apr 2019 14:19:12 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Creating inline closures


On Mon, Apr 22, 2019 at 04:07:07AM -0700, Ilya Zakharevich wrote:
> On Sat, Dec 08, 2018 at 02:15:17PM +0100, Bill Allombert wrote:
> > >       Suppose I have a C function
> > >         GEN mysummand(GEN I, void *mydata);
> > >       It is completely unclear how can I make out of it something to
> > >       pass to (e.g.) somme() to make an analogue of
> > >         sum(I=1,3,mysummand(I))
> > 
> > Hello Ilya,
> > 
> > To help you to upgrade, I join a program that should do what you want.
> > 
> > 1) use pari_add_module to add your functions to GP.
> >   pari_add_module(functions_ilya);
> 
> ???  Why would I want to expose my function to the interpreter, if it
>      is not usable standalone?

GP name starting with "_" cannot be called from GP, so it does not
interfer with the GP language.

> > 2) use strtoclosure to create the partial function as t_CLOSURE object
> >   fun = strtoclosure("_ilya_mysummand",1,stoi((long)&mydata));
> > This returns a t_CLOSURE x -> mysummand(x, &mydata)
> 
> It looks like a very strong overkill.  As far as I can see, (1)+(2)
> can be replaced by a call to snm_closure().

This is needed when using the MPI parallel engine (--mt=mpi) because
MPI does not allow to pass function pointers between nodes.
In any case you still need an entree *.

> > At this point you can use the t_CLOSURE directly in functions like
> > apply that need a true closure (code "G" or "J")
> 
> I do not care about these anyway…

I think you should care about G and apply(), select() etc.

> > 3) for functions like sum that need a inline closure (code "E" or "I"),
> > you need to create a gadget that will inline your closure inside the
> > sum. The simplest is to use the GP compiler:
> >   sum_gadget = gp_read_str("(a,b,C)->sum(i=a,b,C(i))")
> > and then use closure_callgenall to evaluate it with C set to your
> > closure.
> >   s = closure_callgenall(sum_gadget, 3, stoi(1), stoi(3), fun);
> 
> Using a compiler is exactly what I want to avoid.

You only need to run the compiler once (as gp_read_str here) to create
sum_gadget at start up.

Cheers,
Bill.