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