Fast IFS using RPN notation
python
c
x86-64
nasm
Ви не можете вибрати більше 25 тем Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853
  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_if.h"
  20. /**@file python_if.c
  21. * @brief Python RPNIterExpr type definition
  22. * @ingroup python_ext
  23. * @ingroup pymod_pyrpn_RPNExprIter
  24. */
  25. /**@brief @ref pymod_pyrpn_RPNExprIter methods definition
  26. * @ingroup pymod_pyrpn_RPNExprIter */
  27. static PyMethodDef RPNIterExpr_methods[] = {
  28. PYRPN_method("params", rpnif_params,
  29. METH_VARARGS | METH_KEYWORDS | METH_CLASS,
  30. /**@todo add default values */
  31. "cls, pos_flag, res_flag, size_lim, const_values, stack_size",
  32. "Get a name tuple with parameters given a position \
  33. flag, a result flag and size limits"),
  34. PYRPN_method("get_params", rpnif_get_params,
  35. METH_NOARGS,
  36. "self, /",
  37. "Get a name tuple with parameters"),
  38. PYRPN_method("set_mmap", rpnif_set_mmap,
  39. METH_O,
  40. "self, mmap, /",
  41. "Set the mmap that stores data"),
  42. PYRPN_method("shape", rpnif_shape,
  43. METH_NOARGS,
  44. "self, /",
  45. "Get the shape of the data buffer"),
  46. PYRPN_method("keys", rpnif_keys,
  47. METH_NOARGS,
  48. "self, /",
  49. "Return items keys (see dict.keys)"),
  50. PYRPN_method("values", rpnif_values,
  51. METH_NOARGS,
  52. "self, /",
  53. "Return items values (see dict.values)"),
  54. PYRPN_method("items", rpnif_items,
  55. METH_NOARGS,
  56. "self, /",
  57. "Return items (key, value) list (see dict.items)"),
  58. PYRPN_method("step", rpnif_step,
  59. METH_O,
  60. "self, position, /",
  61. "Run an IF given a position and return a new position"),
  62. PYRPN_method("mutate", rpnif_mutate,
  63. METH_VARARGS | METH_KEYWORDS,
  64. "self, n_mutations=1, params=None",
  65. "Mutate the expressions in the IF"),
  66. PYRPN_method("to_pos", rpnif_to_pos,
  67. METH_FASTCALL,
  68. "self, *args, /",
  69. "Return a position (int) from a coordinates given as"
  70. "argument."),
  71. PYRPN_method("from_pos", rpnif_from_pos,
  72. METH_O,
  73. "self, position, /",
  74. "Return a coordinates tuple from given position."),
  75. PYRPN_method("__getstate__", rpnif_getstate,
  76. METH_NOARGS,
  77. "self, /",
  78. "Pickling method (see pickle module).\n"
  79. "Return a bytes representation of the expression state."),
  80. PYRPN_method("__setstate__", rpnif_setstate,
  81. METH_O,
  82. "self, state, /",
  83. "Unpickling method (see pickle module)."),
  84. {NULL} //Sentinel
  85. };
  86. /**@brief @ref pymod_pyrpn_RPNExprIter members definition
  87. * @ingroup pymod_pyrpn_RPNExprIter */
  88. static PyMemberDef RPNIterExpr_members[] = {
  89. {"expressions", T_OBJECT, offsetof(PyRPNIterExpr_t, expr), READONLY,
  90. "The tuple of expressions"},
  91. {"mmap", T_OBJECT, offsetof(PyRPNIterExpr_t, mmap), READONLY,
  92. "The mmap storing data"},
  93. {NULL}
  94. };
  95. /**@brief @ref pymod_pyrpn_RPNExprIter sequence methods definition
  96. * @ingroup pymod_pyrpn_RPNExprIter */
  97. static PySequenceMethods RPNIterExpr_seq_methods = {
  98. .sq_length = rpnif_len,
  99. .sq_item = rpnif_expr_item,
  100. .sq_ass_item = rpnif_expr_ass_item,
  101. };
  102. /**@brief @ref pymod_pyrpn_RPNExprIter mapping methods definition
  103. * @ingroup pymod_pyrpn_RPNExprIter */
  104. static PyMappingMethods RPNIterExpr_mapping_methods = {
  105. .mp_length = rpnif_len,
  106. .mp_subscript = rpnif_subscript,
  107. .mp_ass_subscript = rpnif_ass_subscript,
  108. };
  109. /**@brief @ref pymod_pyrpn_RPNExprIter attributes definition
  110. * @ingroup pymod_pyrpn_RPNExprIter */
  111. static PyGetSetDef RPNIterExpr_getset[] = {
  112. {NULL}
  113. };
  114. /**@brief @ref pymod_pyrpn_RPNExprIter buffer methods definition
  115. * @ingroup pymod_pyrpn_RPNExprIter */
  116. static PyBufferProcs RPNIterExpr_as_buffer = {
  117. (getbufferproc)rpnif_getbuffer,
  118. (releasebufferproc)rpnif_releasebuffer,
  119. };
  120. PyTypeObject RPNIterExprType = {
  121. PyVarObject_HEAD_INIT(NULL, 0)
  122. .tp_name = "pyrpn.RPNIterExpr",
  123. .tp_basicsize = sizeof(PyRPNIterExpr_t),
  124. .tp_itemsize = 0,
  125. .tp_del = rpnif_del,
  126. .tp_repr = rpnif_repr,
  127. .tp_as_sequence = &RPNIterExpr_seq_methods,
  128. .tp_as_mapping = &RPNIterExpr_mapping_methods,
  129. .tp_str = rpnif_str,
  130. .tp_as_buffer = &RPNIterExpr_as_buffer,
  131. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  132. .tp_doc = "RPN expression evaluator",
  133. .tp_methods = RPNIterExpr_methods,
  134. .tp_members = RPNIterExpr_members,
  135. .tp_getset = RPNIterExpr_getset,
  136. .tp_init = rpnif_init,
  137. .tp_new = rpnif_new,
  138. };
  139. PyObject* rpnif_params(PyObject *cls, PyObject *args, PyObject *kwds)
  140. {
  141. char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", NULL};
  142. unsigned short pos_flag, res_flag, stack_size;
  143. PyObject *lim_obj, *const_values_obj;
  144. stack_size = 16;
  145. const_values_obj = lim_obj = NULL;
  146. if(!PyArg_ParseTupleAndKeywords(args, kwds,
  147. "HHO|OH:RPNIterExppr.get_params", names,
  148. &pos_flag, &res_flag, &lim_obj, &const_values_obj,
  149. &stack_size))
  150. {
  151. return NULL;
  152. }
  153. rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
  154. lim_obj, const_values_obj, stack_size);
  155. if(!rif_params)
  156. {
  157. return NULL;
  158. }
  159. PyObject *res = _rpnif_params_to_tuple(rif_params);
  160. if(!res)
  161. {
  162. goto err;
  163. }
  164. free(rif_params);
  165. return res;
  166. err:
  167. free(rif_params);
  168. return NULL;
  169. }
  170. PyObject* rpnif_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
  171. {
  172. PyObject *ret, *err;
  173. PyRPNIterExpr_t *expr;
  174. ret = PyType_GenericNew(subtype, args, kwds);
  175. if((err = PyErr_Occurred()))
  176. {
  177. Py_DECREF(err);
  178. return ret;
  179. }
  180. expr = (PyRPNIterExpr_t*)ret;
  181. expr->rif = NULL;
  182. expr->rif_params = NULL;
  183. expr->borrowed_if = 0;
  184. return ret;
  185. }
  186. int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds)
  187. {
  188. PyRPNIterExpr_t *expr_self;
  189. char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", "mmap", NULL};
  190. unsigned short pos_flag, res_flag, stack_size;
  191. PyObject *lim_obj, *const_values_obj, *mmap_obj;
  192. expr_self = (PyRPNIterExpr_t*)self;
  193. stack_size = 16;
  194. const_values_obj = lim_obj = mmap_obj = NULL;
  195. expr_self->rif = NULL;
  196. expr_self->mmap = NULL;
  197. if(!PyArg_ParseTupleAndKeywords(args, kwds, "HHO|OHO:RPNIterExpr.__init__", names,
  198. &pos_flag, &res_flag, &lim_obj, &const_values_obj, &stack_size,
  199. &mmap_obj))
  200. {
  201. return -1;
  202. }
  203. rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
  204. lim_obj, const_values_obj, stack_size);
  205. expr_self->rif_params = rif_params;
  206. if(!rif_params)
  207. {
  208. return -1;
  209. }
  210. expr_self->ndim = ((rpn_if_default_data_t*)(rif_params->data))->ndim;
  211. const Py_ssize_t expt_sz = rif_params->mem_sz * rif_params->value_sz;
  212. if(mmap_obj == Py_None)
  213. {
  214. Py_DECREF(mmap_obj);
  215. mmap_obj = NULL;
  216. }
  217. if(!mmap_obj)
  218. {
  219. PyObject *fileno = PyLong_FromLong(-1);
  220. PyObject *length = PyLong_FromSize_t(expt_sz);
  221. mmap_obj = PyObject_CallFunctionObjArgs(mmap_cls, fileno, length, NULL);
  222. Py_DECREF(fileno);
  223. Py_DECREF(length);
  224. if(PyErr_Occurred())
  225. {
  226. return -1;
  227. }
  228. }
  229. else
  230. {
  231. if(!PyObject_TypeCheck(mmap_obj, (PyTypeObject*)mmap_cls))
  232. {
  233. PyErr_SetString(PyExc_TypeError,
  234. "The mmap argument MUST be an instance \
  235. of mmap.mmap");
  236. return -1;
  237. }
  238. /**@todo check if mmap is shared & writable ? */
  239. if(PyObject_Length(mmap_obj) != (Py_ssize_t) expt_sz)
  240. {
  241. PyErr_Format(PyExc_ValueError,
  242. "Expected mmap length is %ld but mmap with length %ld provided",
  243. rif_params->mem_sz, PyObject_Length(mmap_obj));
  244. return -1;
  245. }
  246. }
  247. if(PyObject_GetBuffer(mmap_obj, &expr_self->mm_buff,
  248. PyBUF_CONTIG) == -1)
  249. {
  250. return -1;
  251. }
  252. expr_self->mmap = mmap_obj;
  253. expr_self->_mmap = expr_self->mm_buff.buf;
  254. // Creating rif with a new memory map
  255. expr_self->rif = rpn_if_new(rif_params, expr_self->mm_buff.buf, NULL);
  256. if(!expr_self->rif)
  257. {
  258. PyErr_Format(PyExc_RuntimeError,
  259. "Error initalizing if : %s", strerror(errno));
  260. return -1;
  261. }
  262. // Creating the tuple holding RPNExpr instances of expressions
  263. return _rpnif_init_expr_tuple(expr_self);
  264. }
  265. PyObject* rpnif_init_borrowed(rpn_if_t *borrowed_if, PyObject *mmap_obj)
  266. {
  267. PyObject *sz_lim, *const_val;
  268. PyObject *args, *ret;
  269. rpn_if_default_data_t *params;
  270. params = (rpn_if_default_data_t*)(borrowed_if->params->data);
  271. const size_t nsz = params->ndim + (params->pos_flag == RPN_IF_POSITION_XDIM?1:0);
  272. sz_lim = PyTuple_New(nsz);
  273. for(size_t i=0; i<nsz; i++)
  274. {
  275. PyObject *v = PyLong_FromLong(params->size_lim[i]);
  276. PyTuple_SET_ITEM(sz_lim, i, v);
  277. }
  278. const size_t const_val_sz = params->res_flag == RPN_IF_RES_CONST ? 1 : \
  279. (params->res_flag == RPN_IF_RES_CONST_RGBA ? 4 : 0);
  280. if(const_val_sz)
  281. {
  282. const_val = PyTuple_New(const_val_sz);
  283. for(size_t i=0; i<const_val_sz; i++)
  284. {
  285. PyObject *v = PyLong_FromLong(params->const_val[i]);
  286. PyTuple_SET_ITEM(const_val, i, v);
  287. }
  288. }
  289. else
  290. {
  291. const_val = Py_None;
  292. Py_INCREF(const_val);
  293. }
  294. // no mmap :/
  295. // It seems there is no elegant solutions for the moment
  296. // if we give None a new mmap is created
  297. // if we give a dummy mmap it has to have the expected size...
  298. // using None for the moment...
  299. /**@todo find a solution */
  300. PyObject *mmap_arg = Py_None;
  301. if(mmap_obj)
  302. {
  303. mmap_arg = mmap_obj;
  304. }
  305. args = Py_BuildValue("hhOOBO", params->pos_flag, params->res_flag,
  306. sz_lim, const_val,
  307. borrowed_if->params->rpn_stack_sz,
  308. mmap_arg);
  309. Py_DECREF(sz_lim);
  310. Py_DECREF(const_val);
  311. if(!args || PyErr_Occurred())
  312. {
  313. return NULL;
  314. }
  315. ret = PyObject_CallObject((PyObject*)&RPNIterExprType, args);
  316. Py_DECREF(args);
  317. if(!ret || PyErr_Occurred())
  318. {
  319. return NULL;
  320. }
  321. PyRPNIterExpr_t* instance = (PyRPNIterExpr_t*)ret;
  322. // changing if instance
  323. rpn_if_free(instance->rif);
  324. instance->rif = borrowed_if;
  325. // reseting expr tuple
  326. Py_DECREF(instance->expr);
  327. instance->expr = NULL;
  328. // mmap update
  329. PyBuffer_Release(&instance->mm_buff);
  330. if(!mmap_obj)
  331. {
  332. Py_DECREF(instance->mmap);
  333. instance->mmap = NULL;
  334. instance->mm_buff.buf = NULL;
  335. instance->_mmap = borrowed_if->mem;
  336. }
  337. instance->borrowed_if = 1;
  338. // someone else will take care to free the rif params
  339. if(instance->rif_params) { free(instance->rif_params); }
  340. instance->rif_params = NULL;
  341. if(_rpnif_init_expr_tuple(instance) < 0)
  342. {
  343. return NULL;
  344. }
  345. return ret;
  346. }
  347. /**@brief Returns the parameters in a named tuple */
  348. PyObject *rpnif_get_params(PyObject *self)
  349. {
  350. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  351. return _rpnif_params_to_tuple(expr_self->rif->params);
  352. }
  353. PyObject *rpnif_set_mmap(PyObject *self, PyObject *mm_obj)
  354. {
  355. if(!PyObject_TypeCheck(mm_obj, (PyTypeObject*)mmap_cls))
  356. {
  357. PyErr_Format(PyExc_TypeError,
  358. "Excpected instance of mmap.mmap");
  359. return NULL;
  360. }
  361. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  362. Py_buffer buff;
  363. /**@todo check mm size &writable ? */
  364. if(PyObject_GetBuffer(mm_obj, &buff, PyBUF_CONTIG) == -1)
  365. {
  366. return NULL;
  367. }
  368. // Release old mmap
  369. if(expr_self->mmap)
  370. {
  371. PyBuffer_Release(&expr_self->mm_buff);
  372. Py_DECREF(expr_self->mmap);
  373. }
  374. if(expr_self->rif->self_mem) // should never be true ?
  375. {
  376. const size_t mm_sz = expr_self->rif->params->mem_sz *\
  377. expr_self->rif->params->value_sz;
  378. munmap(expr_self->rif->mem, mm_sz);
  379. }
  380. // Set new mmap in python struct & rif struct
  381. expr_self->mm_buff = buff;
  382. expr_self->mmap = mm_obj;
  383. expr_self->_mmap = buff.buf;
  384. expr_self->rif->mem = buff.buf;
  385. expr_self->rif->self_mem = 0;
  386. Py_RETURN_NONE;
  387. }
  388. PyObject *rpnif_shape(PyObject *self)
  389. {
  390. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  391. rpn_if_default_data_t *params;
  392. params = (rpn_if_default_data_t*)(expr_self->rif->params->data);
  393. size_t res_sz;
  394. switch(params->res_flag)
  395. {
  396. case RPN_IF_RES_RGB:
  397. res_sz = 3;
  398. break;
  399. case RPN_IF_RES_RGBA:
  400. res_sz = 4;
  401. break;
  402. default:
  403. res_sz = 1;
  404. break;
  405. }
  406. const size_t shape_sz = params->ndim + (res_sz > 1 ?1:0);
  407. PyObject *ret = PyTuple_New(shape_sz);
  408. if(!ret)
  409. {
  410. return NULL;
  411. }
  412. size_t i;
  413. for(i = 0; i < params->ndim; i++)
  414. {
  415. size_t idx = params->pos_flag == RPN_IF_POSITION_XDIM ? i+1:i;
  416. PyObject *d = PyLong_FromLong(params->size_lim[idx]);
  417. if(!d)
  418. {
  419. goto item_err;
  420. }
  421. PyTuple_SET_ITEM(ret, i, d);
  422. }
  423. if(res_sz > 1)
  424. {
  425. PyObject *d = PyLong_FromLong(res_sz);
  426. if(!d)
  427. {
  428. goto item_err;
  429. }
  430. PyTuple_SET_ITEM(ret, i, d);
  431. }
  432. return ret;
  433. item_err:
  434. Py_DECREF(ret);
  435. return NULL;
  436. }
  437. PyObject *rpnif_step(PyObject *self, PyObject* opos)
  438. {
  439. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  440. /** @todo allow tuple as argument !!!!! */
  441. if(!PyLong_Check(opos))
  442. {
  443. PyErr_SetString(PyExc_TypeError, "Expected position to be an int");
  444. return NULL;
  445. }
  446. size_t pos = PyLong_AsSize_t(opos);
  447. if(PyErr_Occurred())
  448. {
  449. return NULL;
  450. }
  451. pos = rpn_if_step(expr_self->rif, pos);
  452. return PyLong_FromSize_t(pos);
  453. }
  454. PyObject* rpnif_mutate(PyObject *self, PyObject *args, PyObject *kwargs)
  455. {
  456. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  457. size_t rpn_sz = expr_self->rif->params->rpn_sz;
  458. char *str_args = "|IOO:RPNExpr.mutate";
  459. char *names[] = {"n_mutations", "params", "weights", NULL};
  460. PyObject *py_params = NULL, *py_weights = NULL;
  461. unsigned int n_mutations = 1;
  462. rpn_mutation_params_t params;
  463. rnd_t *weights;
  464. if(!if_mutation_alloc_weights(expr_self->rif, &weights))
  465. {
  466. PyErr_Format(PyExc_MemoryError,
  467. "Unable to allocate weights : %s\n",
  468. strerror(errno));
  469. return NULL;
  470. }
  471. if(!PyArg_ParseTupleAndKeywords(args, kwargs, str_args, names,
  472. &n_mutations, &py_params, &py_weights))
  473. {
  474. goto err;
  475. }
  476. if(!py_weights || py_weights == Py_None)
  477. {
  478. for(size_t i=0; i<rpn_sz; i++)
  479. {
  480. weights[i] = (rnd_t)((rnd_t_max / rpn_sz)*(i+1));
  481. }
  482. }
  483. else
  484. {
  485. // Parsing weights sequence into a weights array suitable
  486. // for rpn_mutate utility function
  487. PyObject *seq = PySequence_Fast(py_weights,
  488. "weights argument must be a sequence");
  489. if(!seq)
  490. {
  491. goto err;
  492. }
  493. if((size_t)PySequence_Fast_GET_SIZE(seq) != rpn_sz)
  494. {
  495. Py_DECREF(seq);
  496. char err[] = "expected weights to be a sequence of \
  497. %ld elements, but got %ld elements";
  498. PyErr_Format(PyExc_TypeError, err,
  499. rpn_sz,
  500. PySequence_Fast_GET_SIZE(seq));
  501. goto err;
  502. }
  503. float *fweights;
  504. if(!if_mutation_alloc_weights(expr_self->rif, &fweights))
  505. {
  506. PyErr_Format(PyExc_MemoryError,
  507. "Unable to allocate memory : %s",
  508. strerror(errno));
  509. goto err;
  510. }
  511. for(size_t i=0; i<rpn_sz; i++)
  512. {
  513. PyObject *elt = PySequence_Fast_GET_ITEM(seq, i);
  514. if(!PyNumber_Check(elt))
  515. {
  516. Py_DECREF(seq);
  517. free(fweights);
  518. PyErr_SetString(PyExc_TypeError,
  519. "weights must contains float values");
  520. goto err;
  521. }
  522. fweights[i] = (float)PyFloat_AsDouble(elt);
  523. if(PyErr_Occurred())
  524. {
  525. Py_DECREF(seq);
  526. free(fweights);
  527. goto err;
  528. }
  529. }
  530. rpnifs_fast_rnd_weights(rpn_sz, fweights, weights);
  531. free(fweights);
  532. Py_DECREF(seq);
  533. }
  534. if(!py_params || py_params == Py_None)
  535. {
  536. if(py_params == Py_None) { Py_DECREF(Py_None); }
  537. memcpy(&params, &rpn_mutation_params_default,
  538. sizeof(rpn_mutation_params_t));
  539. }
  540. else
  541. {
  542. if(pyrpn_pyobj_to_mutation_params(py_params, &params) < 0)
  543. {
  544. if(!PyErr_Occurred())
  545. {
  546. PyErr_Format(PyExc_ValueError,
  547. "Bad value for params arguments : %s",
  548. strerror(errno));
  549. }
  550. goto err;
  551. }
  552. }
  553. if(if_mutation(expr_self->rif, weights, n_mutations, &params) < 0)
  554. {
  555. free(weights);
  556. PyErr_Format(PyExc_RuntimeError,
  557. "Error during mutations : %s",
  558. strerror(errno));
  559. goto err;
  560. }
  561. free(weights);
  562. Py_RETURN_NONE;
  563. err:
  564. free(weights);
  565. return NULL;
  566. }
  567. PyObject *rpnif_to_pos(PyObject *self, PyObject** argv, Py_ssize_t argc)
  568. {
  569. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  570. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  571. return _rpnif_to_pos(rif_data, argv, argc);
  572. }
  573. PyObject *rpnif_from_pos(PyObject *self, PyObject* _pos)
  574. {
  575. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  576. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  577. return _rpnif_from_pos(rif_data, _pos);
  578. }
  579. PyObject *rpnif_keys(PyObject *self)
  580. {
  581. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  582. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  583. Py_ssize_t ret_idx = 0;
  584. char xdim_key[64];
  585. PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
  586. if(PyErr_Occurred())
  587. {
  588. return NULL;
  589. }
  590. #define _ret_append(key) PyTuple_SET_ITEM(ret, ret_idx++, \
  591. PyUnicode_FromString(key))
  592. switch(rif_data->pos_flag)
  593. {
  594. case RPN_IF_POSITION_XY:
  595. _ret_append("X");
  596. _ret_append("Y");
  597. break;
  598. case RPN_IF_POSITION_LINEAR:
  599. _ret_append("X");
  600. break;
  601. case RPN_IF_POSITION_XDIM:
  602. for(size_t i=0; i<rif_data->size_lim[0];i++)
  603. {
  604. snprintf(xdim_key, 64, "D%ld", i);
  605. _ret_append(xdim_key);
  606. }
  607. break;
  608. default:
  609. PyErr_SetString(PyExc_RuntimeError,
  610. "UNKOWN POS_FLAG3");
  611. return NULL;
  612. }
  613. switch(rif_data->res_flag)
  614. {
  615. case RPN_IF_RES_BOOL:
  616. case RPN_IF_RES_XFUN:
  617. _ret_append("R");
  618. break;
  619. case RPN_IF_RES_RGB:
  620. _ret_append("R");
  621. _ret_append("G");
  622. _ret_append("B");
  623. break;
  624. case RPN_IF_RES_RGBA:
  625. _ret_append("R");
  626. _ret_append("G");
  627. _ret_append("B");
  628. _ret_append("A");
  629. break;
  630. default:
  631. break;
  632. }
  633. if(PyErr_Occurred())
  634. {
  635. return NULL;
  636. }
  637. return ret;
  638. #undef _ret_append
  639. }
  640. PyObject *rpnif_values(PyObject *self)
  641. {
  642. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  643. Py_INCREF(expr_self->expr);
  644. return expr_self->expr;
  645. }
  646. PyObject *rpnif_items(PyObject *self)
  647. {
  648. size_t i;
  649. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  650. PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
  651. if(PyErr_Occurred())
  652. {
  653. return NULL;
  654. }
  655. PyObject *keys = rpnif_keys(self);
  656. for(i=0; i<expr_self->rif->params->rpn_sz; i++)
  657. {
  658. PyObject *tmp = PyTuple_New(2);
  659. if(PyErr_Occurred())
  660. {
  661. goto err_loop_newtuple;
  662. }
  663. PyObject *key = PyTuple_GET_ITEM(keys, i);
  664. PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
  665. Py_INCREF(key);
  666. Py_INCREF(value);
  667. PyTuple_SET_ITEM(tmp, 0, key);
  668. PyTuple_SET_ITEM(tmp, 1, value);
  669. PyTuple_SET_ITEM(ret, i, tmp);
  670. if(PyErr_Occurred())
  671. {
  672. goto err_loop_setitem;
  673. }
  674. }
  675. return ret;
  676. /** @todo cleanup seems wrong... */
  677. for(i=i; i>=0; i--)
  678. {
  679. err_loop_setitem:
  680. PyObject *key = PyTuple_GET_ITEM(keys, i);
  681. PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
  682. Py_DECREF(key);
  683. Py_DECREF(value);
  684. err_loop_newtuple:
  685. }
  686. Py_DECREF(ret);
  687. return NULL;
  688. }
  689. void rpnif_del(PyObject *self)
  690. {
  691. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  692. if((!expr_self->borrowed_if) && expr_self->rif)
  693. {
  694. rpn_if_free(expr_self->rif);
  695. expr_self->rif = NULL;
  696. }
  697. if(expr_self->mmap)
  698. {
  699. if(expr_self->mm_buff.buf)
  700. {
  701. PyBuffer_Release(&expr_self->mm_buff);
  702. expr_self->mm_buff.buf = NULL;
  703. }
  704. Py_DECREF(expr_self->mmap);
  705. expr_self->mmap = NULL;
  706. }
  707. if(expr_self->expr)
  708. {
  709. Py_DECREF(expr_self->expr);
  710. expr_self->expr = NULL;
  711. }
  712. if(expr_self->rif_params) { free(expr_self->rif_params); }
  713. }
  714. Py_ssize_t rpnif_len(PyObject *self)
  715. {
  716. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  717. return expr_self->rif->params->rpn_sz;
  718. }
  719. PyObject* rpnif_expr_item(PyObject *self, Py_ssize_t idx)
  720. {
  721. Py_ssize_t _idx = idx;
  722. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  723. if(idx < 0)
  724. {
  725. idx = expr_self->rif->params->rpn_sz - 1 + idx;
  726. }
  727. if(idx < 0 || (size_t) idx >= expr_self->rif->params->rpn_sz)
  728. {
  729. PyErr_Format(PyExc_IndexError,
  730. "No expression %ld with given options",
  731. _idx);
  732. return NULL;
  733. }
  734. PyObject *ret = PyTuple_GET_ITEM(expr_self->expr, idx);
  735. Py_INCREF(ret);
  736. return ret;
  737. }
  738. int rpnif_expr_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt)
  739. {
  740. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  741. if(!PyUnicode_Check(elt))
  742. {
  743. PyErr_SetString(PyExc_TypeError, "RPNExpr expected");
  744. return -1;
  745. }
  746. PyObject *bytes_str = PyUnicode_AsASCIIString(elt);
  747. if(PyErr_Occurred())
  748. {
  749. return -1;
  750. }
  751. const char *code = PyBytes_AS_STRING(bytes_str);
  752. rpn_expr_t *expr = &(expr_self->rif->rpn[idx]);
  753. if(rpn_expr_recompile(expr, code) < 0)
  754. {
  755. PyErr_Format(PyExc_ValueError,
  756. "Error during expression '%s' compilation : %s",
  757. code, expr->err_reason);
  758. return -1;
  759. }
  760. return 0;
  761. }
  762. /** Convert key to integer index
  763. * @param self @ref PyRPNIterExpr_t instance
  764. * @param _key An expression name (str)
  765. * @return The expression index or -1 on error (raise python exception)
  766. */
  767. static Py_ssize_t _rpnif_subscript_idx(PyObject *self, PyObject *_key)
  768. {
  769. if(!PyUnicode_Check(_key))
  770. {
  771. PyErr_SetString(PyExc_TypeError, "Key should be a str");
  772. return -1;
  773. }
  774. PyObject *bytes_str = PyUnicode_AsASCIIString(_key);
  775. if(PyErr_Occurred())
  776. {
  777. return -1;
  778. }
  779. const char *key = PyBytes_AS_STRING(bytes_str);
  780. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  781. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  782. Py_ssize_t idx = -1;
  783. Py_ssize_t res_idx = -1;
  784. switch(rif_data->pos_flag)
  785. {
  786. case RPN_IF_POSITION_XY:
  787. res_idx = 2;
  788. if(key[1] != '\0') { break; }
  789. switch(key[0])
  790. {
  791. case 'X':
  792. idx=0;
  793. break;
  794. case 'Y':
  795. idx=1;
  796. break;
  797. }
  798. break;
  799. case RPN_IF_POSITION_LINEAR:
  800. res_idx = 1;
  801. if(!strcmp("X", key))
  802. {
  803. idx = 0;
  804. }
  805. break;
  806. case RPN_IF_POSITION_XDIM:
  807. size_t ndim = rif_data->size_lim[0];
  808. res_idx = ndim;
  809. char possible_key[64];
  810. for(size_t i=0; i<ndim; i++)
  811. {
  812. snprintf(possible_key, 64, "D%ld", i);
  813. if(!strcmp(possible_key, key))
  814. {
  815. idx = i;
  816. break;
  817. }
  818. }
  819. break;
  820. default:
  821. PyErr_SetString(PyExc_RuntimeError,
  822. "UNKOWN POS_FLAG");
  823. return -1;
  824. }
  825. if(idx < 0)
  826. {
  827. // not found yet, looking for result key
  828. switch(rif_data->res_flag)
  829. {
  830. case RPN_IF_RES_BOOL:
  831. case RPN_IF_RES_XFUN:
  832. if(!strcmp("R", key))
  833. {
  834. idx = res_idx;
  835. }
  836. break;
  837. case RPN_IF_RES_RGBA:
  838. if(!strcmp("A", key))
  839. {
  840. idx = res_idx + 3;
  841. }
  842. case RPN_IF_RES_RGB:
  843. if(key[1] != '\0')
  844. {
  845. break;
  846. }
  847. switch(key[0])
  848. {
  849. case 'R':
  850. idx=res_idx;
  851. break;
  852. case 'G':
  853. idx=res_idx+1;
  854. break;
  855. case 'B':
  856. idx=res_idx+2;
  857. break;
  858. }
  859. break;
  860. default:
  861. // not implemented, not unknown....
  862. PyErr_SetString(PyExc_RuntimeError,
  863. "UNKOWN RES_FLAG");
  864. return -1;
  865. }
  866. }
  867. return idx;
  868. }
  869. PyObject* rpnif_subscript(PyObject *self, PyObject *key)
  870. {
  871. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  872. Py_ssize_t idx = _rpnif_subscript_idx(self, key);
  873. if(idx < 0)
  874. {
  875. PyErr_Format(PyExc_IndexError,
  876. "No expression '%R' with given parameters",
  877. key);
  878. return NULL;
  879. }
  880. PyObject *expr = PyTuple_GET_ITEM(expr_self->expr, idx);
  881. Py_INCREF(expr);
  882. return expr;
  883. }
  884. int rpnif_ass_subscript(PyObject *self, PyObject *key, PyObject *elt)
  885. {
  886. Py_ssize_t idx = _rpnif_subscript_idx(self, key);
  887. if(idx < 0)
  888. {
  889. PyErr_Format(PyExc_IndexError,
  890. "Cannot set expression '%R' that do not exists with this parameters",
  891. key);
  892. return -1;
  893. }
  894. return rpnif_expr_ass_item(self, idx, elt);
  895. }
  896. int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags)
  897. {
  898. PyRPNIterExpr_t *expr_self;
  899. expr_self = (PyRPNIterExpr_t*)self;
  900. if(expr_self->mmap)
  901. {
  902. return PyObject_GetBuffer(expr_self->mmap, view, flags);
  903. }
  904. return _rpnif_getbuffer_nopymap(self, expr_self->rif->params,
  905. expr_self->_mmap, view, flags);
  906. }
  907. void rpnif_releasebuffer(PyObject *self, Py_buffer *view)
  908. {
  909. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  910. if(expr_self->mmap)
  911. {
  912. return PyBuffer_Release(view);
  913. }
  914. return _rpnif_releasebuffer_nopymap(self, view);
  915. }
  916. PyObject* rpnif_str(PyObject *self)
  917. {
  918. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  919. rpn_if_default_data_t *rif_data = \
  920. (rpn_if_default_data_t*)expr_self->rif->params->data;
  921. const size_t rpn_sz = expr_self->rif->params->rpn_sz;
  922. const char pyfmt[] = "%VA%ld=%U=\"%S\";";
  923. size_t i;
  924. PyObject *buf, *tmp, *items;
  925. buf = NULL;
  926. items = rpnif_items(self);
  927. if(PyErr_Occurred()) { return NULL; }
  928. for(i=0; i<rpn_sz; i++)
  929. {
  930. PyObject *key, *value, *elt;
  931. elt = PyTuple_GET_ITEM(items, i);
  932. key = PyTuple_GET_ITEM(elt, 0);
  933. value = PyTuple_GET_ITEM(elt, 1);
  934. tmp = PyUnicode_FromFormat(pyfmt,
  935. buf, "",
  936. i, key, value);
  937. if(buf) { Py_DECREF(buf); }
  938. if(PyErr_Occurred()) { return NULL; }
  939. buf = tmp;
  940. }
  941. switch(rif_data->res_flag)
  942. {
  943. case RPN_IF_RES_CONST:
  944. tmp = PyUnicode_FromFormat("%U A%ld=C(*)=%lld",
  945. buf, i+1, rif_data->const_val[0]);
  946. Py_DECREF(buf);
  947. buf=tmp;
  948. break;
  949. case RPN_IF_RES_CONST_RGBA:
  950. tmp = PyUnicode_FromFormat("%U A%ld=R(*)=%lld A%ld=G(*)=%lld A%ld=B(*)=%lld A%ld=A(*)=%lld",
  951. buf,
  952. i+1, rif_data->const_val[0],
  953. i+2, rif_data->const_val[1],
  954. i+3, rif_data->const_val[2],
  955. i+4, rif_data->const_val[3]);
  956. Py_DECREF(buf);
  957. buf=tmp;
  958. break;
  959. }
  960. Py_INCREF(buf);
  961. return buf;
  962. }
  963. /** Return a string representation of expressions dict
  964. * @param self @ref PyRPNIterExpr_t instance
  965. * @return a str instance */
  966. static PyObject* _rpnif_expr_repr(PyObject *self)
  967. {
  968. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  969. rpn_if_default_data_t *rif_data = \
  970. (rpn_if_default_data_t*)expr_self->rif->params->data;
  971. PyObject *buf, *tmp, *items, *const_res;
  972. const char pyfmt[] = "%V\"%U\":\"%S\"%V";
  973. buf = const_res = NULL;
  974. items = rpnif_items(self);
  975. if(PyErr_Occurred()) { return NULL; }
  976. #define _const_res_key ",\"const_res\":"
  977. switch(rif_data->res_flag)
  978. {
  979. case RPN_IF_RES_CONST:
  980. const_res = PyUnicode_FromFormat(
  981. _const_res_key "{\"r\":%llu}}",
  982. rif_data->const_val[0]);
  983. break;
  984. /*
  985. case RPN_IF_RES_CONST_RGB:
  986. const_res = PyUnicode_FromFormat(
  987. "\"const_res\": {\"r\":%llu, \"g\":%llu, \"b\":%llu}}",
  988. rif_data->const_val[0],
  989. rif_data->const_val[1],
  990. rif_data->const_val[2])
  991. break;
  992. */
  993. case RPN_IF_RES_CONST_RGBA:
  994. const_res = PyUnicode_FromFormat(
  995. _const_res_key \
  996. "{\"r\":%llu,\"g\":%llu,\"b\":%llu,\"a\":%llu}}",
  997. rif_data->const_val[0],
  998. rif_data->const_val[1],
  999. rif_data->const_val[2],
  1000. rif_data->const_val[3]);
  1001. break;
  1002. default:
  1003. const_res = PyUnicode_FromFormat("}");
  1004. break;
  1005. }
  1006. #undef _const_res_key
  1007. const size_t rpn_sz = expr_self->rif->params->rpn_sz;
  1008. for(size_t i=0; i<rpn_sz; i++)
  1009. {
  1010. PyObject *key, *value, *elt;
  1011. elt = PyTuple_GET_ITEM(items, i);
  1012. key = PyTuple_GET_ITEM(elt, 0);
  1013. value = PyTuple_GET_ITEM(elt, 1);
  1014. tmp = PyUnicode_FromFormat(pyfmt,
  1015. buf, "{", key, value,
  1016. i==rpn_sz-1?const_res:NULL, ",");
  1017. if(buf)
  1018. {
  1019. Py_DECREF(buf);
  1020. }
  1021. if(PyErr_Occurred())
  1022. {
  1023. return NULL;
  1024. }
  1025. buf = tmp;
  1026. }
  1027. return buf;
  1028. }
  1029. PyObject* rpnif_repr(PyObject *self)
  1030. {
  1031. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  1032. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  1033. char *str_pos, *str_res;
  1034. char tmp[64];
  1035. PyObject *expr_repr = _rpnif_expr_repr(self);
  1036. if(PyErr_Occurred()) { return NULL; }
  1037. switch(rif_data->pos_flag)
  1038. {
  1039. case RPN_IF_POSITION_XY:
  1040. str_pos = "XY";
  1041. break;
  1042. case RPN_IF_POSITION_LINEAR:
  1043. str_pos = "LINEAR";
  1044. break;
  1045. case RPN_IF_POSITION_XDIM:
  1046. snprintf(tmp, 64, "XDIM%ld", rif_data->size_lim[0]);
  1047. str_pos = tmp;
  1048. break;
  1049. default:
  1050. PyErr_SetString(PyExc_RuntimeError,
  1051. "UNKOWN POS_FLAG2");
  1052. return NULL;
  1053. }
  1054. PyObject *const_res = NULL;
  1055. switch(rif_data->res_flag)
  1056. {
  1057. case RPN_IF_RES_BOOL:
  1058. str_res = "BOOL";
  1059. break;
  1060. case RPN_IF_RES_CONST:
  1061. str_res = "CONST";
  1062. const_res = PyTuple_New(1);
  1063. break;
  1064. case RPN_IF_RES_CONST_RGBA:
  1065. str_res = "CONST_RGBA";
  1066. break;
  1067. case RPN_IF_RES_COUNT:
  1068. str_res = "COUNT";
  1069. break;
  1070. case RPN_IF_RES_XFUN:
  1071. str_res = "XFUN";
  1072. break;
  1073. case RPN_IF_RES_RGB:
  1074. str_res = "RGB";
  1075. break;
  1076. case RPN_IF_RES_RGBA:
  1077. str_res = "RGBA";
  1078. break;
  1079. default:
  1080. PyErr_SetString(PyExc_RuntimeError,
  1081. "UNKOWN RES_FLAG2");
  1082. return NULL;
  1083. }
  1084. PyObject *res;
  1085. const_res = const_res?const_res:Py_None;
  1086. res = PyUnicode_FromFormat(
  1087. "<RPNIterExpr pos_flag:%s res_flag:%s expr:'%U' const_res:%S>",
  1088. str_pos, str_res, expr_repr, const_res);
  1089. if(PyErr_Occurred()) { return NULL; }
  1090. return res;
  1091. }
  1092. PyObject* rpnif_getstate(PyObject *self, PyObject *noargs)
  1093. {
  1094. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  1095. const rpn_if_param_t *params = expr_self->rif->params;
  1096. rpn_if_default_data_t *data = (rpn_if_default_data_t*)(params->data);
  1097. const size_t const_val_sz = data->res_flag == RPN_IF_RES_CONST ? 1 : \
  1098. (data->res_flag == RPN_IF_RES_CONST_RGBA ? 4 : 0);
  1099. const size_t nszlim = data->ndim +
  1100. (data->pos_flag == RPN_IF_POSITION_XDIM ?1:0);
  1101. size_t buf_sz = sizeof(void*) + \
  1102. sizeof(rpn_if_param_t) + \
  1103. sizeof(rpn_if_default_data_t) + \
  1104. sizeof(rpn_value_t) * ( \
  1105. params->rpn_sz + params->rpn_argc) + \
  1106. sizeof(size_t) * nszlim + \
  1107. sizeof(rpn_value_t) * const_val_sz;
  1108. // all stack allocation grouped here
  1109. void *new_rpn[params->rpn_sz];
  1110. size_t rpn_sz[params->rpn_sz];
  1111. size_t sz_max = 0;
  1112. for(size_t i=0; i<params->rpn_sz; i++)
  1113. {
  1114. rpn_sz[i] = rpn_expr_serialize(&expr_self->rif->rpn[i],
  1115. NULL, 0);
  1116. // each expression stores a size and a picled repr
  1117. buf_sz += rpn_sz[i] + sizeof(size_t);
  1118. if(rpn_sz[i] > sz_max) { sz_max = rpn_sz[i]; }
  1119. }
  1120. void *buf = malloc(buf_sz);
  1121. if(!buf)
  1122. {
  1123. PyErr_Format(PyExc_MemoryError,
  1124. "Unable to allocate pickled representation : ",
  1125. strerror(errno));
  1126. return NULL;
  1127. }
  1128. bzero(buf, buf_sz);
  1129. bzero(new_rpn, sizeof(*new_rpn));
  1130. void **ptr = buf; // mmap ptr
  1131. rpn_if_param_t *new_params = (void*)(ptr+1);
  1132. rpn_if_default_data_t *new_data = (void*)(new_params + 1);
  1133. size_t *new_size_lim = (void*)(new_data+1);
  1134. rpn_value_t *new_const_val = (void*)(new_size_lim + nszlim);
  1135. size_t *new_rpn_sz = (void*)(new_const_val + const_val_sz);
  1136. size_t cur_offset = sizeof(size_t)*params->rpn_sz;
  1137. *ptr = expr_self->_mmap;
  1138. new_params->mem_sz = params->mem_sz;
  1139. new_params->value_sz = params->value_sz;
  1140. new_params->rpn_sz = params->rpn_sz;
  1141. new_params->rpn_argc = params->rpn_argc;
  1142. new_params->rpn_stack_sz = params->rpn_stack_sz;
  1143. // The following should be more efficient, but result
  1144. // in some badly initialized bytes in new_params struct
  1145. // padding...
  1146. //*new_params = *params;
  1147. new_params->getarg_f = NULL;
  1148. new_params->setres_f = NULL;
  1149. new_params->data = NULL;
  1150. new_data->pos_flag = data->pos_flag;
  1151. new_data->res_flag = data->res_flag;
  1152. new_data->ndim = data->ndim;
  1153. // Same as above
  1154. //*new_data = *data;
  1155. new_data->size_lim = NULL;
  1156. new_data->const_val = NULL;
  1157. memcpy(new_size_lim, data->size_lim, sizeof(size_t)*nszlim);
  1158. if(const_val_sz)
  1159. {
  1160. memcpy(new_const_val, data->const_val, sizeof(rpn_value_t)*const_val_sz);
  1161. }
  1162. // set sizes & rpn expressions
  1163. for(size_t i=0; i<params->rpn_sz; i++)
  1164. {
  1165. new_rpn[i] = ((void*)new_rpn_sz)+cur_offset;
  1166. new_rpn_sz[i] = rpn_sz[i];
  1167. bzero(new_rpn[i], rpn_sz[i]);
  1168. cur_offset += rpn_sz[i];
  1169. if(!rpn_expr_serialize(&expr_self->rif->rpn[i],
  1170. new_rpn[i], rpn_sz[i]))
  1171. {
  1172. goto err_rpn;
  1173. }
  1174. }
  1175. PyObject *res = PyBytes_FromStringAndSize(buf, buf_sz);
  1176. return res;
  1177. err_rpn:
  1178. /**@todo handle error */
  1179. free(buf);
  1180. return NULL;
  1181. }
  1182. PyObject* rpnif_setstate(PyObject *self, PyObject *state_bytes)
  1183. {
  1184. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  1185. if(!PyBytes_Check(state_bytes)) /* Arg check */
  1186. {
  1187. PyErr_SetString(PyExc_TypeError, "Expected bytes");
  1188. return NULL;
  1189. }
  1190. size_t bsize = PyBytes_GET_SIZE(state_bytes);
  1191. const void *data = (void*)PyBytes_AS_STRING(state_bytes);
  1192. if(bsize < sizeof(void*))
  1193. {
  1194. PyErr_SetString(PyExc_ValueError, "Smaller than expected given");
  1195. return NULL;
  1196. }
  1197. rpn_if_param_t *params, *ser_params;
  1198. rpn_if_default_data_t *ser_data;
  1199. size_t *ser_size_lim;
  1200. rpn_value_t *ser_const_val;
  1201. expr_self->mmap = NULL;
  1202. expr_self->_mmap = *(void**)data;
  1203. ser_params = (void*)((void**)data+1);
  1204. ser_data = (void*)(ser_params+1);
  1205. ser_size_lim = (void*)(ser_data+1);
  1206. const size_t nszlim = ser_data->ndim + \
  1207. (ser_data->pos_flag == RPN_IF_POSITION_XDIM ?1:0);
  1208. ser_const_val = (void*)(ser_size_lim + nszlim);
  1209. params = rpn_if_default_params(ser_data->pos_flag, ser_data->res_flag,
  1210. ser_size_lim, ser_const_val,
  1211. ser_params->rpn_stack_sz);
  1212. const size_t const_val_sz = ser_data->res_flag == RPN_IF_RES_CONST?1:\
  1213. (ser_data->res_flag == RPN_IF_RES_CONST_RGBA?4:0);
  1214. rpn_expr_t *ser_rpn = malloc(sizeof(*ser_rpn) * ser_params->rpn_sz);
  1215. if(!ser_rpn)
  1216. {
  1217. PyErr_Format(PyExc_MemoryError,
  1218. "Unable to alloc rpn expressions : %s",
  1219. strerror(errno));
  1220. return NULL;
  1221. }
  1222. size_t *ser_rpn_sz = (void*)(ser_const_val + const_val_sz);
  1223. void *ser_rpn_buf = (void*)(ser_rpn_sz + ser_params->rpn_sz);
  1224. for(size_t i=0; i<ser_params->rpn_sz; i++)
  1225. {
  1226. if(rpn_expr_deserialize(&ser_rpn[i], ser_rpn_buf, ser_rpn_sz[i]) < 0)
  1227. {
  1228. PyErr_Format(PyExc_ValueError,
  1229. "Unable to deserialize expr#%ld : %s",
  1230. i, ser_rpn[i].err_reason);
  1231. return NULL;
  1232. }
  1233. ser_rpn_buf = (void*)ser_rpn_buf + ser_rpn_sz[i];
  1234. }
  1235. expr_self->rif = rpn_if_new(params, expr_self->_mmap, ser_rpn);
  1236. if(!expr_self->rif)
  1237. {
  1238. PyErr_SetString(PyExc_ValueError,
  1239. "Unable to initialize rif expression");
  1240. return NULL;
  1241. }
  1242. expr_self->rif_params = params;
  1243. expr_self->ndim = ser_data->ndim;
  1244. if(_rpnif_init_expr_tuple(expr_self) < 0)
  1245. {
  1246. return NULL;
  1247. }
  1248. expr_self->borrowed_if = 0; // explicitly not borrowed
  1249. Py_RETURN_NONE;
  1250. }
  1251. rpn_if_param_t *_rpnif_get_params(unsigned short pos_flag, unsigned short res_flag,
  1252. PyObject *lim_obj, PyObject *const_values_obj,
  1253. unsigned short stack_size)
  1254. {
  1255. char err_str[256];
  1256. int ndim;
  1257. // Args checking
  1258. if(stack_size < 4 || stack_size > 255)
  1259. {
  1260. snprintf(err_str, 128,
  1261. "Stack size should be in [0..255] but %u given",
  1262. stack_size);
  1263. PyErr_SetString(PyExc_ValueError, err_str);
  1264. return NULL;
  1265. }
  1266. // Checks flags & fetch expected sizes for size_lim & const_values
  1267. short expt_sizes[2];
  1268. if(rpn_if_sizes_from_flag(pos_flag, res_flag, expt_sizes) < 0)
  1269. {
  1270. if(expt_sizes[0] < 0)
  1271. {
  1272. PyErr_SetString(PyExc_ValueError,
  1273. "Invalid position flag given");
  1274. }
  1275. else
  1276. {
  1277. PyErr_SetString(PyExc_ValueError,
  1278. "Invalid result flag given");
  1279. }
  1280. return NULL;
  1281. }
  1282. //Check & convert lim
  1283. PyObject *tmp;
  1284. tmp = PySequence_Fast(lim_obj, "Sequence expected for size_lim argument");
  1285. if(PyErr_Occurred())
  1286. {
  1287. return NULL;
  1288. }
  1289. Py_ssize_t lim_obj_sz = PySequence_Fast_GET_SIZE(tmp);
  1290. ndim = lim_obj_sz;
  1291. if(PyErr_Occurred())
  1292. {
  1293. Py_DECREF(tmp);
  1294. return NULL;
  1295. }
  1296. if(lim_obj_sz < 1)
  1297. {
  1298. Py_DECREF(tmp);
  1299. PyErr_SetString(PyExc_ValueError,
  1300. "Size limits cannot be empty");
  1301. return NULL;
  1302. }
  1303. if(pos_flag == RPN_IF_POSITION_XDIM)
  1304. {
  1305. PyObject *item = PySequence_Fast_GET_ITEM(tmp, 0);
  1306. Py_ssize_t tmp = PyLong_AsSsize_t(item);
  1307. if(PyErr_Occurred())
  1308. {
  1309. PyErr_SetString(PyExc_ValueError,
  1310. "Unable to convert size_lim[0] to int");
  1311. Py_DECREF(tmp);
  1312. return NULL;
  1313. }
  1314. if(lim_obj_sz != tmp + 1)
  1315. {
  1316. PyErr_Format(PyExc_ValueError,
  1317. "Xdim indicate %d size_lim but len(size_lim)=%d",
  1318. tmp+1, lim_obj_sz);
  1319. Py_DECREF(tmp);
  1320. return NULL;
  1321. }
  1322. expt_sizes[0] = ndim = tmp;
  1323. }
  1324. else
  1325. {
  1326. if(lim_obj_sz != expt_sizes[0])
  1327. {
  1328. PyErr_Format(PyExc_ValueError,
  1329. "Expected %d size_lim but len(size_lim)=%d",
  1330. expt_sizes[0], lim_obj_sz);
  1331. Py_DECREF(tmp);
  1332. return NULL;
  1333. }
  1334. }
  1335. size_t sz_limits[lim_obj_sz];
  1336. for(Py_ssize_t i = 0; i<lim_obj_sz; i++)
  1337. {
  1338. PyObject *item = PySequence_Fast_GET_ITEM(tmp, i);
  1339. sz_limits[i] = PyLong_AsSize_t(item);
  1340. if(PyErr_Occurred())
  1341. {
  1342. PyErr_Format(PyExc_ValueError,
  1343. "Unable to convert size_lim[%d] to unsigned int",
  1344. i);
  1345. Py_DECREF(tmp);
  1346. return NULL;
  1347. }
  1348. }
  1349. Py_DECREF(tmp);
  1350. tmp = NULL;
  1351. //Check & convert const values
  1352. Py_ssize_t values_obj_sz = 0;
  1353. if(expt_sizes[1] > 0)
  1354. {
  1355. tmp = const_values_obj;
  1356. if(!PyTuple_Check(tmp))
  1357. {
  1358. PyErr_SetString(PyExc_ValueError,
  1359. "Invalid type for const_values argument");
  1360. return NULL;
  1361. }
  1362. values_obj_sz = PyTuple_Size(tmp);
  1363. if(values_obj_sz != expt_sizes[1])
  1364. {
  1365. PyErr_Format(PyExc_ValueError,
  1366. "Expected %d const_values but len(const_values)=%d",
  1367. expt_sizes[1], values_obj_sz);
  1368. return NULL;
  1369. }
  1370. }
  1371. rpn_value_t const_values[values_obj_sz];
  1372. for(Py_ssize_t i = 0; i<values_obj_sz; i++)
  1373. {
  1374. PyObject *item = PyTuple_GET_ITEM(tmp, i);
  1375. const_values[i] = PyLong_AsRpnValue_t(item);
  1376. if(PyErr_Occurred())
  1377. {
  1378. PyErr_Format(PyExc_ValueError,
  1379. "Unable to convert size_lim[%d] to unsigned int",
  1380. i);
  1381. return NULL;
  1382. }
  1383. }
  1384. // Creating rif params
  1385. rpn_if_param_t *rif_params;
  1386. if(!(rif_params = rpn_if_default_params(pos_flag, res_flag,
  1387. sz_limits, const_values, stack_size)))
  1388. {
  1389. PyErr_SetString(PyExc_ValueError, "Unable to create parameters \
  1390. with given arguments");
  1391. return NULL;
  1392. }
  1393. return rif_params;
  1394. }
  1395. PyObject *_rpnif_params_to_tuple(const rpn_if_param_t *_params)
  1396. {
  1397. PyObject *res, *val;
  1398. short expt_sizes[2];
  1399. rpn_if_default_data_t *params;
  1400. params = (rpn_if_default_data_t*)(_params->data);
  1401. if(rpn_if_sizes_from_flag(params->pos_flag, params->res_flag, expt_sizes) < 0)
  1402. {
  1403. PyErr_SetString(PyExc_RuntimeError, "Invalid internal state");
  1404. return NULL;
  1405. }
  1406. res = PyStructSequence_New(&rpnif_params_SeqDesc);
  1407. if(!res)
  1408. {
  1409. return NULL;
  1410. }
  1411. val = PyLong_FromLong(_params->rpn_argc);
  1412. PyStructSequence_SET_ITEM(res, 0, val);
  1413. val = PyLong_FromLong(params->pos_flag);
  1414. PyStructSequence_SET_ITEM(res, 1, val);
  1415. val = PyLong_FromLong(params->res_flag);
  1416. PyStructSequence_SET_ITEM(res, 2, val);
  1417. if(params->pos_flag == RPN_IF_POSITION_XDIM)
  1418. {
  1419. expt_sizes[0] = params->size_lim[0] + 1;
  1420. }
  1421. PyObject *lim = PyTuple_New(expt_sizes[0]);
  1422. if(!lim)
  1423. {
  1424. Py_DECREF(res);
  1425. return NULL;
  1426. }
  1427. PyStructSequence_SET_ITEM(res, 3, lim);
  1428. for(Py_ssize_t i=0; i<expt_sizes[0]; i++)
  1429. {
  1430. val = PyLong_FromSize_t(params->size_lim[i]);
  1431. PyTuple_SET_ITEM(lim, i, val);
  1432. }
  1433. if(!params->const_val)
  1434. {
  1435. Py_INCREF(Py_None);
  1436. PyTuple_SET_ITEM(res, 4, Py_None);
  1437. }
  1438. else
  1439. {
  1440. PyObject *values = PyTuple_New(expt_sizes[1]);
  1441. if(!values)
  1442. {
  1443. Py_DECREF(res);
  1444. return NULL;
  1445. }
  1446. PyStructSequence_SET_ITEM(res, 4, values);
  1447. for(Py_ssize_t i=0; i<expt_sizes[1]; i++)
  1448. {
  1449. val = PyLong_FromRpnValue_t(params->const_val[i]);
  1450. PyTuple_SET_ITEM(values, i, val);
  1451. }
  1452. }
  1453. val = PyLong_FromUnsignedLong(_params->mem_sz * _params->value_sz);
  1454. PyStructSequence_SET_ITEM(res, 5, val);
  1455. return res;
  1456. }
  1457. PyObject *_rpnif_to_pos(rpn_if_default_data_t *rif_data, PyObject** argv, Py_ssize_t argc)
  1458. {
  1459. const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
  1460. long long value;
  1461. if((size_t)argc != rif_data->ndim)
  1462. {
  1463. PyErr_Format(PyExc_IndexError,
  1464. "Expression expect %lu dimentions coordinates,"
  1465. " but %ld arguments given.",
  1466. rif_data->ndim, argc);
  1467. return NULL;
  1468. }
  1469. rpn_value_t result=0;
  1470. size_t cur_dim_sz = 1;
  1471. for(size_t i=0; i<rif_data->ndim; i++)
  1472. {
  1473. if(!PyLong_Check(argv[i]))
  1474. {
  1475. PyErr_SetString(PyExc_TypeError,
  1476. "coordinates must be integers");
  1477. return NULL;
  1478. }
  1479. value = PyLong_AsLongLong(argv[i]);
  1480. if(value < 0)
  1481. {
  1482. value = (-(rpn_value_t)-value)%rif_data->size_lim[i+idx_off];
  1483. }
  1484. if((size_t)value >= rif_data->size_lim[i+idx_off])
  1485. {
  1486. PyErr_Format(PyExc_IndexError,
  1487. "Coordinate %ld overflows : %R/%lu",
  1488. i, argv[i],
  1489. rif_data->size_lim[i+idx_off]);
  1490. return NULL;
  1491. }
  1492. result += value * cur_dim_sz;
  1493. cur_dim_sz *= rif_data->size_lim[i+idx_off];
  1494. }
  1495. return PyLong_FromUnsignedLongLong(result);
  1496. }
  1497. PyObject *_rpnif_from_pos(rpn_if_default_data_t *rif_data, PyObject* _pos)
  1498. {
  1499. const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
  1500. if(!PyLong_Check(_pos))
  1501. {
  1502. PyErr_SetString(PyExc_TypeError,
  1503. "Expected position to be an integer");
  1504. return NULL;
  1505. }
  1506. size_t pos = PyLong_AsUnsignedLong(_pos);
  1507. if(PyErr_Occurred())
  1508. {
  1509. return NULL;
  1510. }
  1511. PyObject *res = PyTuple_New(rif_data->ndim);
  1512. if(PyErr_Occurred())
  1513. {
  1514. return NULL;
  1515. }
  1516. for(size_t i=0; i<rif_data->ndim; i++)
  1517. {
  1518. size_t val;
  1519. size_t lim = rif_data->size_lim[i+idx_off];
  1520. val = pos % lim;
  1521. pos /= lim;
  1522. PyObject *elt = PyLong_FromUnsignedLong(val);
  1523. if(PyErr_Occurred())
  1524. {
  1525. goto err;
  1526. }
  1527. PyTuple_SET_ITEM(res, i, elt);
  1528. }
  1529. return res;
  1530. err:
  1531. Py_DECREF(res);
  1532. return NULL;
  1533. }
  1534. int _rpnif_getbuffer_nopymap(PyObject *self, const rpn_if_param_t *params,
  1535. void *buf, Py_buffer *view, int flags)
  1536. {
  1537. rpn_if_default_data_t *data = (rpn_if_default_data_t*)params->data;
  1538. view->buf = buf;
  1539. view->obj = self;
  1540. view->len = params->mem_sz * params->value_sz;
  1541. view->readonly = 0;
  1542. view->itemsize = sizeof(rpn_value_t);
  1543. view->format = (flags & PyBUF_FORMAT)?"L":NULL;
  1544. view->ndim = 1;
  1545. view->shape = NULL;
  1546. if(flags & PyBUF_ND)
  1547. {
  1548. short nval;
  1549. switch(data->res_flag)
  1550. {
  1551. case RPN_IF_RES_BOOL:
  1552. case RPN_IF_RES_CONST:
  1553. case RPN_IF_RES_COUNT:
  1554. nval = 1;
  1555. break;
  1556. case RPN_IF_RES_RGBA:
  1557. case RPN_IF_RES_CONST_RGBA:
  1558. nval = 4;
  1559. break;
  1560. case RPN_IF_RES_RGB:
  1561. nval = 3;
  1562. break;
  1563. default:
  1564. PyErr_SetString(PyExc_BufferError,
  1565. "Unsupported result flag");
  1566. return -1;
  1567. }
  1568. view->ndim += (nval>1)?1:0;
  1569. if(!(view->shape = malloc(sizeof(Py_ssize_t) * view->ndim)))
  1570. {
  1571. PyErr_Format(PyExc_BufferError,
  1572. "Buffer's shape allocation error : %s",
  1573. strerror(errno));
  1574. return -1;
  1575. }
  1576. for(size_t i=0; i<data->ndim; i++)
  1577. {
  1578. const int idx = i + \
  1579. (data->pos_flag == RPN_IF_POSITION_XDIM)?1:0;
  1580. view->shape[i] = data->size_lim[idx];
  1581. }
  1582. if(nval>1)
  1583. {
  1584. view->shape[data->ndim] = nval;
  1585. }
  1586. }
  1587. view->strides = NULL;
  1588. view->suboffsets = NULL;
  1589. Py_INCREF(self);
  1590. return 0;
  1591. }
  1592. void _rpnif_releasebuffer_nopymap(PyObject *self, Py_buffer *view)
  1593. {
  1594. if(view->shape) { free(view->shape); }
  1595. view->buf = NULL;
  1596. Py_DECREF(self);
  1597. }
  1598. int _rpnif_init_expr_tuple(PyRPNIterExpr_t *expr_self)
  1599. {
  1600. expr_self->expr = PyTuple_New(expr_self->rif->params->rpn_sz);
  1601. for(size_t i=0; i<expr_self->rif->params->rpn_sz;i++)
  1602. {
  1603. rpn_expr_t *expr = &expr_self->rif->rpn[i];
  1604. PyObject *instance = rpnexpr_init_borrowing(expr);
  1605. if(!instance)
  1606. {
  1607. //! @todo set exception
  1608. return -1;
  1609. }
  1610. PyTuple_SET_ITEM(expr_self->expr, i, instance);
  1611. }
  1612. return 0;
  1613. }
  1614. /**@def _ret_append(key)
  1615. * @hiderefs
  1616. * local macro */
  1617. /**@def _const_res_key()
  1618. * @hiderefs
  1619. * local macro*/