Fast IFS using RPN notation
python
c
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

python_rpnexpr.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*
  2. * Copyright (C) 2020,2023 Weber Yann
  3. *
  4. * This file is part of pyrpn.
  5. *
  6. * pyrpn is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * any later version.
  10. *
  11. * pyrpn is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "python_rpnexpr.h"
  20. /**@file python_rpnexpr.c
  21. * @brief Python module & type definition
  22. * @ingroup python_ext
  23. * @ingroup python_pyrpn_RPNExpr
  24. */
  25. /**@brief @ref pymod_pyrpn_RPNExpr methods definition
  26. * @ingroup python_pyrpn_RPNExpr */
  27. static PyMethodDef RPNExpr_methods[] = {
  28. PYRPN_method("random", rpnexpr_random,
  29. METH_CLASS | METH_VARARGS | METH_KEYWORDS,
  30. "cls, args_count, token_count=10",
  31. "Return a new random RPN expression string"),
  32. PYRPN_method("default_mutation_params", rpnexpr_default_mutation_params,
  33. METH_CLASS | METH_FASTCALL,
  34. "cls, /",
  35. "Return the default mutation parameters"),
  36. PYRPN_method("eval", rpnexpr_eval, METH_FASTCALL,
  37. "self, /, *args",
  38. "Evaluate an expression"),
  39. PYRPN_method("mutate", rpnexpr_mutate,
  40. METH_VARARGS | METH_KEYWORDS,
  41. "self, n_mutations=1, params=None",
  42. "Mutate an expression"),
  43. PYRPN_method("reset_stack", rpnexpr_reset_stack,
  44. METH_NOARGS,
  45. "self, /",
  46. "Reset the stack (set all items to 0)"),
  47. PYRPN_method("__getstate__", rpnexpr_getstate,
  48. METH_NOARGS,
  49. "self, /",
  50. "Pickling method (see pickle module).\n"
  51. "Return a bytes representation of the expression state."),
  52. PYRPN_method("__setstate__", rpnexpr_setstate,
  53. METH_O,
  54. "self, state, /",
  55. "Unpickling method (see pickle module)."),
  56. PYRPN_method("__copy__", rpnexpr_copy,
  57. METH_NOARGS,
  58. "self, /",
  59. "Return a new equivalent instance (see copy module)"),
  60. PYRPN_method("uid", rpnexpr_getexprstate,
  61. METH_NOARGS,
  62. "self, /",
  63. "Return a base64 uid for expression"),
  64. {NULL} //Sentinel
  65. };
  66. /**@brief @ref pymod_pyrpn_RPNExpr members definition
  67. * @ingroup python_pyrpn_RPNExpr */
  68. static PyMemberDef RPNExpr_members[] = {
  69. {NULL}
  70. };
  71. /**@brief @ref pymod_pyrpn_RPNExpr methods definition
  72. * @todo Continue sequence implementation with contains, concat, repeat etc.
  73. * @ingroup python_pyrpn_RPNExpr */
  74. static PySequenceMethods RPNExpr_seq_methods = {
  75. .sq_length = rpnexpr_len,
  76. .sq_item = rpnexpr_token_item,
  77. .sq_ass_item = rpnexpr_token_ass_item,
  78. };
  79. PyTypeObject RPNExprType = {
  80. PyVarObject_HEAD_INIT(NULL, 0)
  81. .tp_name = "pyrpn.RPNExpr",
  82. .tp_doc = "RPN expression evaluator\n\
  83. \n\
  84. Instanciation :\n\
  85. RPNExpr(expression:str, args_count:int, stack_size:int=16)",
  86. .tp_basicsize = sizeof(PyRPNExpr_t),
  87. .tp_itemsize = 0,
  88. .tp_del = rpnexpr_del,
  89. .tp_repr = rpnexpr_repr,
  90. .tp_str = rpnexpr_str,
  91. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  92. .tp_richcompare = rpnexpr_richcompare,
  93. .tp_methods = RPNExpr_methods,
  94. .tp_as_sequence = &RPNExpr_seq_methods,
  95. .tp_members = RPNExpr_members,
  96. .tp_init = rpnexpr_init,
  97. .tp_new = rpnexpr_new,
  98. };
  99. PyObject* rpnexpr_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
  100. {
  101. PyObject *ret, *err;
  102. PyRPNExpr_t *expr;
  103. ret = PyType_GenericNew(subtype, args, kwds);
  104. if((err = PyErr_Occurred()))
  105. {
  106. Py_DECREF(err);
  107. return ret;
  108. }
  109. expr = (PyRPNExpr_t*)ret;
  110. expr->rpn = NULL;
  111. expr->args = NULL;
  112. expr->borrowed_expr = 0;
  113. return ret;
  114. }
  115. int rpnexpr_init(PyObject *self, PyObject *args, PyObject *kwds)
  116. {
  117. PyRPNExpr_t *expr_self;
  118. char *names[] = {"expression", "args_count", "stack_size", NULL};
  119. char err_str[256];
  120. const char *expr;
  121. long long int args_count, stack_size;
  122. expr_self = (PyRPNExpr_t*)self;
  123. stack_size = 16;
  124. expr_self->rpn = NULL;
  125. if(!PyArg_ParseTupleAndKeywords(args, kwds, "sL|L:RPNExpr.__init__", names, &expr,
  126. &args_count, &stack_size))
  127. {
  128. return -1;
  129. }
  130. if(args_count < 0 || args_count > 255)
  131. {
  132. snprintf(err_str, 128,
  133. "Argument count should be in [4..255] but %lld given",
  134. args_count);
  135. PyErr_SetString(PyExc_ValueError, err_str);
  136. return -1;
  137. }
  138. if(stack_size < 4 || stack_size > 255)
  139. {
  140. snprintf(err_str, 128,
  141. "Stack size should be in [0..255] but %lld given",
  142. stack_size);
  143. PyErr_SetString(PyExc_ValueError, err_str);
  144. return -1;
  145. }
  146. expr_self->rpn = malloc(sizeof(rpn_expr_t));
  147. if(!expr_self->rpn)
  148. {
  149. snprintf(err_str, 256,
  150. "Expression memory allocation error : %s",
  151. strerror(errno));
  152. }
  153. bzero(expr_self->rpn, sizeof(rpn_expr_t));
  154. if(rpn_expr_init(expr_self->rpn, stack_size, args_count) < 0)
  155. {
  156. snprintf(err_str, 256,
  157. "Expression init error : %s",
  158. expr_self->rpn->err_reason);
  159. PyErr_SetString(PyExc_ValueError, err_str);
  160. return -1;
  161. }
  162. expr_self->args = malloc(sizeof(rpn_value_t) * args_count);
  163. if(!expr_self->args)
  164. {
  165. snprintf(err_str, 256,
  166. "Error allocating arguments memory : %s",
  167. strerror(errno));
  168. return -1;
  169. }
  170. if(rpn_expr_compile(expr_self->rpn, expr))
  171. {
  172. PyErr_SetString(PyExc_ValueError, expr_self->rpn->err_reason);
  173. return -1;
  174. }
  175. return 0;
  176. }
  177. PyObject* rpnexpr_init_borrowing(rpn_expr_t *borrowed)
  178. {
  179. PyObject *args, *ret;
  180. PyRPNExpr_t *instance;
  181. args = Py_BuildValue("sLL", "", borrowed->args_count,
  182. borrowed->stack_sz);
  183. if(!args || PyErr_Occurred())
  184. {
  185. return NULL;
  186. }
  187. ret = PyObject_CallObject((PyObject*)&RPNExprType, args);
  188. if(!ret || PyErr_Occurred())
  189. {
  190. Py_DECREF(args);
  191. return NULL;
  192. }
  193. Py_DECREF(args);
  194. instance = (PyRPNExpr_t*)ret;
  195. rpn_expr_close(instance->rpn);
  196. free(instance->rpn);
  197. instance->borrowed_expr = 1;
  198. instance->rpn = borrowed;
  199. return ret;
  200. }
  201. void rpnexpr_del(PyObject *self)
  202. {
  203. PyRPNExpr_t *expr_self;
  204. expr_self = (PyRPNExpr_t*)self;
  205. if(expr_self->rpn && !expr_self->borrowed_expr)
  206. {
  207. rpn_expr_close(expr_self->rpn);
  208. free(expr_self->rpn);
  209. expr_self->rpn = NULL;
  210. }
  211. if(expr_self->args)
  212. {
  213. free(expr_self->args);
  214. expr_self->args = NULL;
  215. }
  216. }
  217. PyObject* rpnexpr_getexprstate(PyObject *self, PyObject *noargs)
  218. {
  219. /**@todo check if usefull */
  220. PyErr_SetString(PyExc_NotImplementedError, "Not implemented...");
  221. return NULL;
  222. }
  223. PyObject* rpnexpr_getstate(PyObject *self, PyObject *noargs)
  224. {
  225. PyObject *res;
  226. PyRPNExpr_t *expr_self;
  227. size_t total_sz;
  228. char err_str[128];
  229. expr_self = (PyRPNExpr_t*)self;
  230. if(expr_self->rpn->state != RPN_READY)
  231. {
  232. snprintf(err_str, 128,
  233. "RPNExpr.__getstate__() instance in bad state : %s",
  234. expr_self->rpn->state==RPN_ERROR?"error":"init");
  235. PyErr_SetString(PyExc_ValueError, err_str);
  236. return NULL;
  237. }
  238. total_sz = rpn_expr_serialize(expr_self->rpn, NULL, 0);
  239. char serial[total_sz];
  240. rpn_expr_serialize(expr_self->rpn, serial, total_sz);
  241. if(!(res = PyBytes_FromStringAndSize(serial, total_sz)))
  242. {
  243. return NULL;
  244. }
  245. return res;
  246. }
  247. PyObject* rpnexpr_setstate(PyObject *self, PyObject *state_bytes)
  248. {
  249. PyObject *tmp, *tmp2;
  250. PyRPNExpr_t *expr_self;
  251. const char *data;
  252. size_t bsize;
  253. int err;
  254. char err_str[256];
  255. expr_self = (PyRPNExpr_t*)self;
  256. if(!PyBytes_Check(state_bytes)) /* Arg check */
  257. {
  258. tmp2 = NULL;
  259. tmp = PyObject_Type(state_bytes);
  260. if(tmp)
  261. {
  262. tmp2 = PyObject_Str(tmp);
  263. }
  264. if(tmp2)
  265. {
  266. snprintf(err_str, 128,
  267. "RPNExpr.__setstate__() expected a bytes as \
  268. argument but %s found",
  269. PyUnicode_AsUTF8(tmp2));
  270. PyErr_SetString(PyExc_ValueError, err_str);
  271. }
  272. else
  273. {
  274. PyErr_SetString(PyExc_RuntimeError,
  275. "Failing to fetch arguments type will \
  276. generating exception message !");
  277. }
  278. return NULL;
  279. }
  280. if(expr_self->rpn || expr_self->args) /* checking instance state */
  281. {
  282. PyErr_SetString(PyExc_ValueError,
  283. "RPNExpr.__setstate__() instance in bad state : \
  284. should not be initialized");
  285. return NULL;
  286. }
  287. /* Checking data size */
  288. bsize = PyBytes_GET_SIZE(state_bytes);
  289. data = PyBytes_AS_STRING(state_bytes);
  290. if(bsize < sizeof(size_t))
  291. {
  292. PyErr_SetString(PyExc_ValueError, "Invalid argument");
  293. return NULL;
  294. }
  295. //alloc & init
  296. if(!(expr_self->rpn = malloc(sizeof(rpn_expr_t))))
  297. {
  298. err = errno;
  299. snprintf(err_str, 128,
  300. "RPNExpr.__setstate__() failed to allocate memory for \
  301. rpn_expr_t : %s",
  302. strerror(err));
  303. PyErr_SetString(PyExc_MemoryError, err_str);
  304. return NULL;
  305. }
  306. bzero(expr_self->rpn, sizeof(rpn_expr_t));
  307. if(rpn_expr_deserialize(expr_self->rpn, data, bsize) < 0)
  308. {
  309. PyErr_Format(PyExc_ValueError,
  310. "RPNExpr.__setstate__() fails to deserialize (%s)) %s",
  311. strerror(errno), expr_self->rpn->err_reason);
  312. return NULL;
  313. }
  314. if(!(expr_self->args = malloc(sizeof(rpn_value_t)*expr_self->rpn->args_count)))
  315. {
  316. err = errno;
  317. snprintf(err_str, 128,
  318. "RPNExpr.__setstate__() failed to allocate memory for \
  319. args buffer : %s",
  320. strerror(err));
  321. PyErr_SetString(PyExc_MemoryError, err_str);
  322. return NULL;
  323. }
  324. Py_RETURN_NONE;
  325. }
  326. PyObject* rpnexpr_copy(PyObject *self, PyObject *noargs)
  327. {
  328. PyRPNExpr_t *copy;
  329. PyObject *ret, *state, *setret;
  330. ret = PyObject_CallMethod((PyObject*)&RPNExprType, "__new__", "O", &RPNExprType);
  331. copy = (PyRPNExpr_t*)ret;
  332. state = PyObject_CallMethod(self, "__getstate__", NULL);
  333. if(PyErr_Occurred()) {
  334. goto err;
  335. }
  336. setret = PyObject_CallMethod(ret, "__setstate__", "O", state);
  337. if(PyErr_Occurred()) {
  338. Py_DECREF(state);
  339. goto err;
  340. }
  341. Py_DECREF(state);
  342. Py_DECREF(setret);
  343. return ret;
  344. err:
  345. PyObject_Del(copy);
  346. return NULL;
  347. }
  348. Py_ssize_t rpnexpr_len(PyObject *self)
  349. {
  350. PyRPNExpr_t *expr_self = (PyRPNExpr_t*)self;
  351. return (Py_ssize_t)expr_self->rpn->toks.tokens_sz;
  352. }
  353. PyObject* rpnexpr_token_item(PyObject *self, Py_ssize_t idx)
  354. {
  355. PyRPNExpr_t *expr_self = (PyRPNExpr_t*)self;
  356. Py_ssize_t _idx = idx;
  357. if(idx < 0)
  358. {
  359. idx = expr_self->rpn->toks.tokens_sz - 1 + idx;
  360. }
  361. if(idx < 0 || (size_t)idx >= expr_self->rpn->toks.tokens_sz)
  362. {
  363. PyErr_Format(PyExc_IndexError,
  364. "No token %ld in expression of size %ld",
  365. _idx, expr_self->rpn->toks.tokens_sz);
  366. return NULL;
  367. }
  368. return rpntoken_from_token(&expr_self->rpn->toks.tokens[idx]);
  369. }
  370. int rpnexpr_token_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt)
  371. {
  372. PyRPNExpr_t *expr_self = (PyRPNExpr_t*)self;
  373. Py_ssize_t _idx = idx;
  374. if(idx < 0)
  375. {
  376. idx = expr_self->rpn->toks.tokens_sz - 1 + idx;
  377. }
  378. if(idx < 0 || (size_t)idx > expr_self->rpn->toks.tokens_sz)
  379. {
  380. PyErr_Format(PyExc_IndexError,
  381. "Cannot set token %ld in expression of size %ld",
  382. _idx, expr_self->rpn->toks.tokens_sz);
  383. return -1;
  384. }
  385. if(!PyObject_IsInstance(elt, (PyObject*)&RPNTokenType))
  386. {
  387. PyErr_Format(PyExc_TypeError,
  388. "Given element in not RPNToken subtype");
  389. return -1;
  390. }
  391. short new_elt = 0;
  392. if((size_t)idx == expr_self->rpn->toks.tokens_sz)
  393. {
  394. new_elt = 1;
  395. expr_self->rpn->toks.tokens_sz++;
  396. size_t new_sz = expr_self->rpn->toks.tokens_sz*sizeof(rpn_token_t);
  397. rpn_token_t *tmp = realloc(expr_self->rpn->toks.tokens, new_sz);
  398. if(!tmp)
  399. {
  400. PyErr_Format(PyExc_MemoryError,
  401. "Error reallocation tokenized expression : %s",
  402. strerror(errno));
  403. return -1;
  404. }
  405. expr_self->rpn->toks.tokens = tmp;
  406. }
  407. rpn_token_t original = expr_self->rpn->toks.tokens[idx];
  408. RPNToken_t *token = (RPNToken_t*)elt;
  409. expr_self->rpn->toks.tokens[idx] = token->value;
  410. if(rpn_expr_tokens_updated(expr_self->rpn) < 0)
  411. {
  412. PyErr_Format(PyExc_ValueError,
  413. "Unable to update expression : %s",
  414. strerror(errno));
  415. goto rollback;
  416. }
  417. return 0;
  418. rollback:
  419. if(new_elt)
  420. {
  421. expr_self->rpn->toks.tokens_sz--;
  422. }
  423. else
  424. {
  425. expr_self->rpn->toks.tokens[idx] = original;
  426. if(rpn_expr_tokens_updated(expr_self->rpn) < 0)
  427. {
  428. PyErr_Format(PyExc_RuntimeError,
  429. "Unable to rollback expression : %s",
  430. strerror(errno));
  431. goto rollback;
  432. }
  433. }
  434. return -1;
  435. }
  436. PyObject* rpnexpr_eval(PyObject* self, PyObject** argv, Py_ssize_t argc)
  437. {
  438. PyRPNExpr_t *expr_self;
  439. unsigned long res;
  440. char err_str[128];
  441. Py_ssize_t i;
  442. PyObject *cur, *ret;
  443. expr_self = (PyRPNExpr_t*)self;
  444. if((unsigned long)argc != expr_self->rpn->args_count)
  445. {
  446. snprintf(err_str, 128,
  447. "RPNExpr expected %ld arguments but %ld given",
  448. expr_self->rpn->args_count,
  449. argc);
  450. PyErr_SetString(PyExc_ValueError, err_str);
  451. return NULL;
  452. }
  453. for(i=0; i<argc; i++)
  454. {
  455. cur = argv[i];
  456. if(!PyLong_Check(cur))
  457. {
  458. snprintf(err_str, 128,
  459. "RpnExpr.__call__ expect int as arguments but argument %ld is not",
  460. i+1);
  461. PyErr_SetString(PyExc_ValueError, err_str);
  462. return NULL;
  463. }
  464. expr_self->args[i] = PyLong_AsUnsignedLong(argv[i]);
  465. if((ret = PyErr_Occurred()))
  466. {
  467. Py_DECREF(ret);
  468. return NULL;
  469. }
  470. }
  471. res = rpn_expr_eval(expr_self->rpn, expr_self->args);
  472. return PyLong_FromUnsignedLong(res);
  473. }
  474. PyObject* rpnexpr_mutate(PyObject* slf, PyObject *args, PyObject *kwds)
  475. {
  476. PyRPNExpr_t *self = (PyRPNExpr_t*)slf;
  477. char *str_args = "|IO:RPNExpr.mutate";
  478. char *names[] = {"n_mutations", "params", NULL};
  479. PyObject *py_params = NULL;
  480. unsigned int n_mutations = 1;
  481. rpn_mutation_params_t params;
  482. if(!PyArg_ParseTupleAndKeywords(args, kwds, str_args, names,
  483. &n_mutations, &py_params))
  484. {
  485. return NULL;
  486. }
  487. if(!py_params || py_params == Py_None)
  488. {
  489. if(py_params == Py_None) { Py_DECREF(Py_None); }
  490. memcpy(&params, &rpn_mutation_params_default,
  491. sizeof(rpn_mutation_params_t));
  492. }
  493. else
  494. {
  495. if(pyrpn_pyobj_to_mutation_params(py_params, &params) < 0)
  496. {
  497. PyErr_SetString(PyExc_ValueError, "Bad value for params arguments");
  498. return NULL;
  499. }
  500. }
  501. for(size_t i=0; i<n_mutations; i++)
  502. {
  503. if(rpn_mutation(&(self->rpn->toks), &params) < 0)
  504. {
  505. PyErr_Format(PyExc_RuntimeError, "Mutation failed : %s",
  506. strerror(errno));
  507. return NULL;
  508. }
  509. }
  510. rpn_expr_tokens_updated(self->rpn);
  511. Py_RETURN_NONE;
  512. }
  513. PyObject* rpnexpr_reset_stack(PyObject *self, PyObject *noargs)
  514. {
  515. rpn_expr_reset_stack(((PyRPNExpr_t*)self)->rpn);
  516. Py_RETURN_NONE;
  517. }
  518. PyObject* rpnexpr_str(PyObject *self)
  519. {
  520. PyRPNExpr_t *expr_self;
  521. PyObject *res;
  522. expr_self = (PyRPNExpr_t*)self;
  523. res = Py_BuildValue("s", expr_self->rpn->expr);
  524. return res;
  525. }
  526. PyObject* rpnexpr_repr(PyObject *self)
  527. {
  528. PyRPNExpr_t *expr_self;
  529. PyObject *res;
  530. size_t sz;
  531. char *buff, err_str[128];
  532. expr_self = (PyRPNExpr_t*)self;
  533. sz = snprintf(NULL, 0, "<RPNExpr argc:%ld stck_sz:%d '%s'>",
  534. expr_self->rpn->args_count, expr_self->rpn->stack_sz,
  535. expr_self->rpn->expr);
  536. buff = malloc(sizeof(char) * (sz + 1));
  537. if(!buff)
  538. {
  539. snprintf(err_str, 128,
  540. "Error allocating repr : %s",
  541. strerror(errno));
  542. PyErr_SetString(PyExc_RuntimeError, err_str);
  543. return NULL;
  544. }
  545. snprintf(buff, sz+1, "<RPNExpr argc:%ld stck_sz:%d '%s'>",
  546. expr_self->rpn->args_count, expr_self->rpn->stack_sz,
  547. expr_self->rpn->expr);
  548. res = Py_BuildValue("s", buff);
  549. free(buff);
  550. return res;
  551. }
  552. PyObject* rpnexpr_richcompare(PyObject *_self, PyObject *other, int op)
  553. {
  554. PyObject *sta, *stb, *res;
  555. if(!PyObject_IsInstance(other, (PyObject*)&RPNExprType))
  556. {
  557. PyErr_Format(PyExc_TypeError,
  558. "Can only be compared with RPNExpr");
  559. return NULL;
  560. }
  561. sta = rpnexpr_getstate(_self, NULL);
  562. stb = rpnexpr_getstate(other, NULL);
  563. res = PyObject_RichCompare(sta, stb, op);
  564. Py_DECREF(sta);
  565. Py_DECREF(stb);
  566. return res;
  567. }
  568. PyObject* rpnexpr_random(PyObject *cls, PyObject *args, PyObject *kwds)
  569. {
  570. long long int args_count, expr_sz;
  571. char *expr, err_str[128];
  572. PyObject *res;
  573. char *names[] = {"args_count", "token_count", NULL};
  574. expr_sz = 10;
  575. if(!PyArg_ParseTupleAndKeywords(args, kwds, "L|L:pyrpn.random_expr", names,
  576. &args_count, &expr_sz))
  577. {
  578. return NULL;
  579. }
  580. expr = rpn_random(expr_sz, args_count);
  581. if(!expr)
  582. {
  583. snprintf(err_str, 128,
  584. "Error generating random expression : %s",
  585. strerror(errno));
  586. PyErr_SetString(PyExc_RuntimeError, err_str);
  587. return NULL;
  588. }
  589. res = Py_BuildValue("s", expr);
  590. //free(expr);
  591. return res;
  592. }
  593. PyObject* rpnexpr_default_mutation_params(PyObject *cls, PyObject **argv, Py_ssize_t argc)
  594. {
  595. PyObject *res, *wtypes;
  596. if(!(wtypes = PyStructSequence_New(&rpn_token_types_SeqDesc)))
  597. {
  598. return NULL;
  599. }
  600. if(!(res = PyStructSequence_New(&rpn_mutation_params_SeqDesc)))
  601. {
  602. return NULL;
  603. }
  604. // wtypes filled with 1.0
  605. PyObject *one = PyFloat_FromDouble(1.0);
  606. for(size_t i=0; i<3; i++)
  607. {
  608. PyStructSequence_SET_ITEM(wtypes, i, one);
  609. }
  610. // max_len
  611. PyStructSequence_SET_ITEM(res, 0,
  612. PyLong_FromLong(rpn_mutation_params_default.min_len));
  613. // weight_add
  614. PyStructSequence_SET_ITEM(res, 1,
  615. PyFloat_FromDouble(rpn_mutation_params_default.w_add));
  616. // weight_del
  617. PyStructSequence_SET_ITEM(res, 2,
  618. PyFloat_FromDouble(rpn_mutation_params_default.w_del));
  619. // weight_mut
  620. PyStructSequence_SET_ITEM(res, 3,
  621. PyFloat_FromDouble(rpn_mutation_params_default.w_mut));
  622. // weight_mut_soft
  623. PyStructSequence_SET_ITEM(res, 4,
  624. PyFloat_FromDouble(rpn_mutation_params_default.w_mut_soft));
  625. /** TODO use rpn_mutation_params_default instead of wtypes [1,1,1] */
  626. // weight_add_elt
  627. PyStructSequence_SET_ITEM(res, 5, wtypes);
  628. Py_INCREF(wtypes);
  629. // weight_mut_elt
  630. PyStructSequence_SET_ITEM(res, 6, wtypes);
  631. Py_INCREF(wtypes);
  632. return res;
  633. }