interpreter_support.cc
Go to the documentation of this file.
1 #include <kernel/mod2.h>
2 #ifdef HAVE_PYTHON_MOD
3 #include <sstream>
4 #include <boost/python.hpp>
5 #include <boost/python/numpy.hpp>
6 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
7 #include "Singular/subexpr.h"
8 #include "Poly.h"
9 #include "Ideal.h"
10 #include "kernel/structs.h"
11 #include "Singular/lists.h"
12 #include "Singular/ipid.h"
13 #include "Singular/ipshell.h"
14 #include "coeffs/numbers.h"
15 
16 #include "Singular/ipid.h"
17 #include "Singular/ipshell.h"
18 #include "polys/matpol.h"
19 #include "ring_wrap.h"
20 #include "intvec_wrap.h"
21 #include "poly_wrap.h"
22 extern int inerror;
23 using namespace boost::python;
24 using boost::python::numpy::ndarray;
25 using boost::python::extract;
26 static void free_leftv(leftv args)
27 {
28  args->CleanUp();
29  omFreeBin(args, sleftv_bin);
30 }
31 
32 matrix matrixFromArray(const boost::python::numpy::ndarray& f)
33 {
34  object o=f.attr("shape");
35  object o1=o[0];
36  object o2=o[1];
37  int l1=extract<int>(o1);
38  int l2=extract<int>(o2);
39  matrix m=mpNew(l1,l2);
40  for(int i=0;i<l1;i++)
41  {
42  for(int j=0;j<l2;j++)
43  {
44  Poly& x = boost::python::extract<Poly&>(f[boost::python::make_tuple(i,j)]);
45  poly p=x.as_poly();
46  MATELEM(m,i+1,j+1)=p;
47  }
48  }
49  return m;
50 }
51 bool is_builtin(const char* name)
52 {
53  int cmd_n=-1;
54  IsCmd(name,cmd_n);
55  return (cmd_n!=-1);
56 }
57 class arg_list
58 {
59  public:
60  leftv args;
61  arg_list()
62  {
63  args=(leftv) NULL;
64  }
65  ~arg_list()
66  {
67  if (args!=NULL)
68  {
69  args->CleanUp();
70  omFreeBin(args, sleftv_bin);
71  }
72  }
73  leftv pop_front()
74  {
75  assume(args!=NULL);
76  leftv res=args;
77  args=args->next;
78  res->next=NULL;
79  return res;
80  }
81  int length()
82  {
83  leftv v=args;
84  int l=0;
85  while(v!=NULL)
86  {
87  l++;
88  v=v->next;
89  }
90  return l;
91  }
92  void appendPoly(const Poly& p)
93  {
94  leftv v=initArg();
95  v->data=p.as_poly();
96  v->rtyp=POLY_CMD;
97  internal_append(v);
98  }
99  void appendIdeal(const Ideal& p)
100  {
101  leftv v=initArg();
102  v->data=p.as_ideal();
103  v->rtyp=IDEAL_CMD;
104  internal_append(v);
105  }
106  void appendModule(const Module& p)
107  {
108  leftv v=initArg();
109  v->data=p.as_module();
110  v->rtyp=MODUL_CMD;
111  internal_append(v);
112  }
113  void appendint(int p)
114  {
115  leftv v=initArg();
116  v->data=(void*)((long)p);
117  v->rtyp=INT_CMD;
118  internal_append(v);
119  }
120  void appendNumber(const Number& p)
121  {
122  leftv v=initArg();
123  v->data=(void*) p.as_number();
124  v->rtyp=NUMBER_CMD;
125  internal_append(v);
126  }
127  void appendVector(const Vector& p)
128  {
129  leftv v=initArg();
130  v->data=p.as_poly();
131  v->rtyp=VECTOR_CMD;
132  internal_append(v);
133  }
134  void appendArray(const boost::python::numpy::ndarray& f)
135  {
136  leftv v=initArg();
137  matrix m=matrixFromArray(f);
138  v->data=m;
139  v->rtyp=MATRIX_CMD;
140  internal_append(v);
141  }
142  void appendString(const char* s)
143  {
144  leftv v=initArg();
145  v->data=omStrDup(s);
146  v->rtyp=STRING_CMD;
147  internal_append(v);
148  }
149  void appendRing(const Ring& r)
150  {
151  leftv v=initArg();
152  v->data=r.pimpl.get();
153  r.pimpl->ref++;
154  v->rtyp=RING_CMD;
155  internal_append(v);
156  }
157  lists dumpToLists()
158  {
159  int n=length();
161  res->Init(n);
162  for(int i=0;i<n;i++)
163  {
164  leftv iv=pop_front();
165  //swap the content
166  memcpy(&res->m[i],iv,sizeof(sleftv));
167  //iv->Init();
168  omFreeBin(iv, sleftv_bin);
169  }
170  return res;
171  }
172  void appendPrelist(arg_list& l)
173  {
174  leftv v=initArg();
175  v->data=l.dumpToLists();
176  v->rtyp=LIST_CMD;
177  internal_append(v);
178  }
179  void appendIntvec(Intvec& iv)
180  {
181  leftv v=initArg();
182  v->data=iv.allocate_legacy_intvec_copy();
183  v->rtyp=INTVEC_CMD;
184  internal_append(v);
185  }
186 protected:
187  leftv initArg()
188  {
190  res->Init();
191  return res;
192  }
193  void internal_append(leftv v)
194  {
195  if (args!=NULL)
196  {
197  leftv last=args;
198  while(last->next!=NULL)
199  {
200  last=last->next;
201  }
202  last->next=v;
203  }
204  else
205  args=v;
206  }
207 };
208 
209 class idhdl_wrap
210 {
211  public:
212  idhdl id;
213  idhdl_wrap(idhdl id)
214  {
215  this->id=id;
216  }
217  idhdl_wrap()
218  {
219  id=(idhdl) NULL;
220  }
221  bool is_zero()
222  {
223  return id==NULL;
224  }
225  bool id_is_proc()
226  {
227  return (id->typ==PROC_CMD);
228  }
229  bool print_type()
230  {
231  Print("type:%d\n",id->typ);
232  }
233  void writePoly(const Poly& p)
234  {
235  if (id->typ==POLY_CMD)
236  {
237  p_Delete(&id->data.p, currRing);
238  id->data.p=p.as_poly();
239  }
240  }
241  void writeIdeal(const Ideal& p)
242  {
243  if (id->typ==IDEAL_CMD)
244  {
245  id_Delete(&id->data.uideal, currRing);
246  id->data.uideal=p.as_ideal();
247  }
248  }
249  void writeModule(const Module& p)
250  {
251  if (id->typ==MODUL_CMD)
252  {
253  id_Delete(&id->data.uideal, currRing);
254  id->data.uideal=p.as_module();
255  }
256  }
257  void writeint(int p)
258  {
259  if (id->typ==INT_CMD)
260  {
261  id->data.i=p;
262  }
263  }
264  void writeNumber(const Number& p)
265  {
266  if (id->typ==NUMBER_CMD)
267  {
268  n_Delete(&id->data.n, currRing);
269  id->data.n=p.as_number();
270  }
271  }
272  void writeVector(const Vector& p)
273  {
274  if (id->typ==VECTOR_CMD)
275  {
276  p_Delete(&id->data.p, currRing);
277  id->data.p=p.as_poly();
278  }
279  }
280  void writeArray(const boost::python::numpy::ndarray& f)
281  {
282  if(id->typ=MATRIX_CMD)
283  {
284  matrix m=matrixFromArray(f);
285  id_Delete((ideal*) &id->data.umatrix,currRing);
286  id->data.umatrix=m;
287  }
288  }
289  void writeRing(const Ring& r)
290  {
291  if(id->typ=RING_CMD)
292  {
293  r.pimpl->ref++;
294  ((ring) id->data.uring)->ref--;//FIXME: destruct it
295  ring r2=r.pimpl.get();
296  id->data.uring=r2;
297  }
298  }
299  void writeString(const char* s)
300  {
301  if(id->typ=STRING_CMD)
302  {
303  omFree((ADDRESS) id->data.ustring);
304  id->data.ustring=omStrDup(s);
305  }
306  }
307  void writeIntvec(const Intvec& iv)
308  {
309  if(id->typ=INTVEC_CMD)
310  {
311  delete id->data.iv;
312  id->data.iv=iv.allocate_legacy_intvec_copy();;
313  }
314  }
315  void writeList(arg_list& f)
316  {
317  //warning f gets empty
318  if(id->typ=LIST_CMD)
319  {
320  id->data.l->Clean(currRing);
321  id->data.l=f.dumpToLists();
322  }
323  }
324 };
325 
326 
327 static boost::python::numpy::ndarray buildPythonMatrix(matrix m, ring r)
328 {
329  using boost::python::numpy::ndarray;
330  using boost::python::self;
331  using boost::python::make_tuple;
332  using boost::python::tuple;
333  using boost::python::object;
334  using boost::python::list;
335 
336  list l;
337  for(int i=1;i<=MATROWS(m);i++)
338  {
339  list row;
340  for(int j=1;j<=MATCOLS(m);j++)
341  {
342  Poly ip(MATELEM(m,i,j),r);//copy it
343  row.append(ip);
344  //a[boost::python::make_tuple(i%2,i%5)]=ip;
345  //a[boost::python::make_tuple(i%2,i%5)]=ip;
346  }
347  l.append(row);
348  }
349  return boost::python::numpy::array(l);
350 }
351 boost::python::object buildPyObjectFromLeftv(leftv v);
352 boost::python::list buildPythonList(lists l, ring r)
353 {
354  using boost::python::list;
355  list res;
356 
357  for(int i=0;i<=l->nr;i++)
358  {
359  leftv lv=&l->m[i];
360  object o=buildPyObjectFromLeftv(lv);
361  res.append(o);
362  }
363  return res;
364 }
365 
366 boost::python::object buildPyObjectFromLeftv(leftv v)
367 {
368  using boost::python::object;
369  switch (v->rtyp)
370  {
371  case INT_CMD:
372  return object((int)((long)v->data));
373  case POLY_CMD:
374  return object(Poly((poly) v->data, currRing));
375  case STRING_CMD:
376  return str((const char*) v->data);
377  case VECTOR_CMD:
378  return object( Vector((poly) v->data, currRing));
379  case IDEAL_CMD:
380  return object(Ideal((ideal) v->data, currRing));
381  case MODUL_CMD:
382  return object(Module((ideal) v->data, currRing));
383  case NUMBER_CMD:
384  return object(Number((number) v->data, currRing));
385  case MATRIX_CMD:
386  return buildPythonMatrix((matrix) v->data,currRing);
387  case LIST_CMD:
388  return buildPythonList((lists) v->data, currRing);
389  case RING_CMD:
390  return object(Ring((ring) v->data));
391  case INTVEC_CMD:
392  return object(Intvec(*(intvec*) v->data));
393 
394  default:
395  return object();
396  }
397 }
398 boost::python::object buildPyObjectFromIdhdl(const idhdl_wrap& id)
399 {
400  using boost::python::object;
401 
402  switch (id.id->typ)
403  {
404  case STRING_CMD:
405  return str((const char*) id.id->data.ustring);
406 
407  case INT_CMD:
408  return object((int)id.id->data.i);
409  case POLY_CMD:
410 
411  return object(Poly((poly) id.id->data.p, currRing));
412  case VECTOR_CMD:
413 
414  return object( Vector((poly) id.id->data.p, currRing));
415  case IDEAL_CMD:
416  //object res;
417 
418  return object(Ideal((ideal) id.id->data.uideal, currRing));
419  case MODUL_CMD:
420  //object res;
421 
422  return object(Module((ideal) id.id->data.uideal, currRing));
423  case NUMBER_CMD:
424 
425  return object(Number((number) id.id->data.n, currRing));
426  case MATRIX_CMD:
427  {
428  return buildPythonMatrix((matrix) id.id->data.umatrix,currRing);
429  }
430  case LIST_CMD:
431  return buildPythonList((lists) id.id->data.l, currRing);
432  case RING_CMD:
433  return object(Ring((ring) id.id->data.uring));
434  case INTVEC_CMD:
435  return object(Intvec(*(intvec*) id.id->data.iv));
436  default:
437  return object();
438  //Py_INCREF(Py_None);
439  //return Py_None;
440  }
441 }
442 
443 boost::python::object call_interpreter_method(const idhdl_wrap& proc, const arg_list& args)
444 {
445  int err=iiMake_proc(proc.id, NULL, args.args);
447 
448  return buildPyObjectFromLeftv(&iiRETURNEXPR);
449 }
450 boost::python::object call_builtin_method_general(const char* name, arg_list& l)
451 {
452  int cmd_n=-1;
453  IsCmd(name,cmd_n);
454 // Py_INCREF(Py_None);
455 
456 // return Py_None;
457  if (cmd_n<0)
458  {
459  return object();
460  }
461  else
462  {
464  res->Init();
465  switch(l.length())
466  {
467  case 1:
468  iiExprArith1(res,l.args,cmd_n);
469  break;
470  case 2:
471  {
472  leftv arg1=l.pop_front();
473  leftv arg2=l.pop_front();
474  iiExprArith2(res,arg1,cmd_n,arg2,TRUE);
475  free_leftv(arg1);
476  free_leftv(arg2);
477  break;
478  }
479  case 3:
480  {
481  leftv arg1=l.pop_front();
482  leftv arg2=l.pop_front();
483  leftv arg3=l.pop_front();
484  iiExprArith3(res,cmd_n,arg1,arg2,arg3);
485  free_leftv(arg1);
486  free_leftv(arg2);
487  free_leftv(arg3);
488  break;
489  }
490  default:
491  iiExprArithM(res, l.args, cmd_n);
492  }
493  boost::python::object real_res=buildPyObjectFromLeftv(res);
494  res->CleanUp();
497  return real_res;
498  //cleanup not to forget
499  }
500 }
501 static boost::python::str idhdl_as_str(idhdl_wrap iw)
502 {
503  idhdl i=iw.id;
504  using boost::python::str;
505  //ring r=p.getRing();
506 
507  std::basic_stringstream<char> s;
508  s<<i;
509  return boost::python::str(s.str());
510 }
511 static idhdl_wrap get_idhdl(const char *n)
512 {
513  //idhdl ggetid(const char *n);
514  return idhdl_wrap(ggetid(n));
515 }
516 void export_interpreter()
517 {
518  def("get_idhdl", get_idhdl);
519  boost::python::class_<arg_list>("i_arg_list")
520  .def("append", &arg_list::appendPoly)
521  .def("append", &arg_list::appendArray)
522  .def("append", &arg_list::appendNumber)
523  .def("append", &arg_list::appendint)
524  .def("append", &arg_list::appendIdeal)
525  .def("append", &arg_list::appendModule)
526  .def("append", &arg_list::appendPrelist)
527  .def("append", &arg_list::appendVector)
528  .def("append", &arg_list::appendRing)
529  .def("append", &arg_list::appendIntvec)
530  .def("append", &arg_list::appendString);
531  boost::python::class_<idhdl_wrap>("interpreter_id")
532  .def("is_zero", &idhdl_wrap::is_zero)
533  .def("is_proc", &idhdl_wrap::id_is_proc)
534  .def("print_type", &idhdl_wrap::print_type)
535  .def("write", &idhdl_wrap::writePoly)
536  .def("write", &idhdl_wrap::writeArray)
537  .def("write", &idhdl_wrap::writeNumber)
538  .def("write", &idhdl_wrap::writeint)
539  .def("write", &idhdl_wrap::writeIdeal)
540  .def("write", &idhdl_wrap::writeModule)
541  .def("write", &idhdl_wrap::writeVector)
542  .def("write", &idhdl_wrap::writeList)
543  .def("write", &idhdl_wrap::writeString)
544  .def("write", &idhdl_wrap::writeIntvec)
545  .def("write", &idhdl_wrap::writeRing)
546  .def("__str__", idhdl_as_str);
547  def("call_interpreter_method",call_interpreter_method);
548  def("cbm",call_builtin_method_general);
549  def("transfer_to_python",buildPyObjectFromIdhdl);
550  def("is_builtin", is_builtin);
551 }
552 #endif
#define omAllocBin(bin)
Definition: omAllocDecl.h:205
const CanonicalForm int s
Definition: facAbsFact.cc:55
idhdl ggetid(const char *n)
Definition: ipid.cc:510
unsigned char * proc[NUM_PROC]
Definition: checklibs.c:16
Definition: janet.h:14
Class used for (list of) interpreter objects.
Definition: subexpr.h:82
#define Print
Definition: emacs.cc:83
Definition: tok.h:95
Definition: lists.h:22
BOOLEAN iiExprArith1(leftv res, leftv a, int op)
Definition: iparith.cc:8319
return P p
Definition: myNF.cc:203
BOOLEAN iiExprArith3(leftv res, int op, leftv a, leftv b, leftv c)
Definition: iparith.cc:8531
Definition: Poly.h:509
static poly last
Definition: hdegree.cc:1077
sleftv iiRETURNEXPR
Definition: iplib.cc:473
void id_Delete(ideal *h, ring r)
deletes an ideal/module/matrix
#define TRUE
Definition: auxiliary.h:98
Definition: Ideal.h:86
void * ADDRESS
Definition: auxiliary.h:115
sleftv * leftv
Definition: structs.h:60
BOOLEAN iiExprArithM(leftv res, leftv a, int op)
Definition: iparith.cc:8621
int inerror
Definition: grammar.cc:175
Definition: idrec.h:34
poly res
Definition: myNF.cc:322
ring currRing
Widely used global variable which specifies the current polynomial ring for Singular interpreter and ...
Definition: polys.cc:10
const ring r
Definition: syzextra.cc:208
Definition: IIntvec.h:5
Definition: ring_wrap.h:20
Definition: intvec.h:14
int j
Definition: myNF.cc:70
#define omFree(addr)
Definition: omAllocDecl.h:261
#define assume(x)
Definition: mod2.h:394
Definition: Ideal.h:119
void export_interpreter()
int m
Definition: cfEzgcd.cc:119
idrec * idhdl
Definition: ring.h:18
FILE * f
Definition: checklibs.c:9
omBin sleftv_bin
Definition: subexpr.cc:50
int i
Definition: cfEzgcd.cc:123
char name(const Variable &v)
Definition: factory.h:178
Variable next() const
Definition: factory.h:135
intvec * allocate_legacy_intvec_copy() const
Definition: IIntvec.h:21
short errorreported
Definition: feFopen.cc:23
leftv next
Definition: subexpr.h:86
matrix mpNew(int r, int c)
create a r x c zero-matrix
Definition: matpol.cc:44
static void p_Delete(poly *p, const ring r)
Definition: p_polys.h:843
#define omAlloc0Bin(bin)
Definition: omAllocDecl.h:206
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:37
BOOLEAN iiMake_proc(idhdl pn, package pack, leftv sl)
Definition: iplib.cc:503
#define MATCOLS(i)
Definition: matpol.h:28
#define NULL
Definition: omList.c:10
slists * lists
Definition: mpr_numeric.h:146
Definition: Number.h:34
Variable x
Definition: cfModGcd.cc:4023
void CleanUp(ring r=currRing)
Definition: subexpr.cc:332
int typ
Definition: idrec.h:43
Definition: tok.h:117
omBin slists_bin
Definition: lists.cc:23
static FORCE_INLINE void n_Delete(number *p, const coeffs r)
delete &#39;p&#39;
Definition: coeffs.h:459
#define MATROWS(i)
Definition: matpol.h:27
polyrec * poly
Definition: hilb.h:10
#define omFreeBin(addr, bin)
Definition: omAllocDecl.h:259
BOOLEAN iiExprArith2(leftv res, leftv a, int op, leftv b, BOOLEAN proccall)
Definition: iparith.cc:8130
int l
Definition: cfEzgcd.cc:94
#define MATELEM(mat, i, j)
Definition: matpol.h:29
utypes data
Definition: idrec.h:40
int IsCmd(const char *n, int &tok)
Definition: iparith.cc:8729
#define omStrDup(s)
Definition: omAllocDecl.h:263