12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853 |
- /*
- * Copyright (C) 2020,2023 Weber Yann
- *
- * This file is part of pyrpn.
- *
- * pyrpn is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * pyrpn is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "python_if.h"
- /**@file python_if.c
- * @brief Python RPNIterExpr type definition
- * @ingroup python_ext
- * @ingroup pymod_pyrpn_RPNExprIter
- */
-
- /**@brief @ref pymod_pyrpn_RPNExprIter methods definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PyMethodDef RPNIterExpr_methods[] = {
- PYRPN_method("params", rpnif_params,
- METH_VARARGS | METH_KEYWORDS | METH_CLASS,
- /**@todo add default values */
- "cls, pos_flag, res_flag, size_lim, const_values, stack_size",
- "Get a name tuple with parameters given a position \
- flag, a result flag and size limits"),
- PYRPN_method("get_params", rpnif_get_params,
- METH_NOARGS,
- "self, /",
- "Get a name tuple with parameters"),
- PYRPN_method("set_mmap", rpnif_set_mmap,
- METH_O,
- "self, mmap, /",
- "Set the mmap that stores data"),
- PYRPN_method("shape", rpnif_shape,
- METH_NOARGS,
- "self, /",
- "Get the shape of the data buffer"),
- PYRPN_method("keys", rpnif_keys,
- METH_NOARGS,
- "self, /",
- "Return items keys (see dict.keys)"),
- PYRPN_method("values", rpnif_values,
- METH_NOARGS,
- "self, /",
- "Return items values (see dict.values)"),
- PYRPN_method("items", rpnif_items,
- METH_NOARGS,
- "self, /",
- "Return items (key, value) list (see dict.items)"),
- PYRPN_method("step", rpnif_step,
- METH_O,
- "self, position, /",
- "Run an IF given a position and return a new position"),
- PYRPN_method("mutate", rpnif_mutate,
- METH_VARARGS | METH_KEYWORDS,
- "self, n_mutations=1, params=None",
- "Mutate the expressions in the IF"),
- PYRPN_method("to_pos", rpnif_to_pos,
- METH_FASTCALL,
- "self, *args, /",
- "Return a position (int) from a coordinates given as"
- "argument."),
- PYRPN_method("from_pos", rpnif_from_pos,
- METH_O,
- "self, position, /",
- "Return a coordinates tuple from given position."),
- PYRPN_method("__getstate__", rpnif_getstate,
- METH_NOARGS,
- "self, /",
- "Pickling method (see pickle module).\n"
- "Return a bytes representation of the expression state."),
- PYRPN_method("__setstate__", rpnif_setstate,
- METH_O,
- "self, state, /",
- "Unpickling method (see pickle module)."),
- {NULL} //Sentinel
- };
-
- /**@brief @ref pymod_pyrpn_RPNExprIter members definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PyMemberDef RPNIterExpr_members[] = {
- {"expressions", T_OBJECT, offsetof(PyRPNIterExpr_t, expr), READONLY,
- "The tuple of expressions"},
- {"mmap", T_OBJECT, offsetof(PyRPNIterExpr_t, mmap), READONLY,
- "The mmap storing data"},
- {NULL}
- };
-
- /**@brief @ref pymod_pyrpn_RPNExprIter sequence methods definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PySequenceMethods RPNIterExpr_seq_methods = {
- .sq_length = rpnif_len,
- .sq_item = rpnif_expr_item,
- .sq_ass_item = rpnif_expr_ass_item,
- };
-
- /**@brief @ref pymod_pyrpn_RPNExprIter mapping methods definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PyMappingMethods RPNIterExpr_mapping_methods = {
- .mp_length = rpnif_len,
- .mp_subscript = rpnif_subscript,
- .mp_ass_subscript = rpnif_ass_subscript,
- };
-
- /**@brief @ref pymod_pyrpn_RPNExprIter attributes definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PyGetSetDef RPNIterExpr_getset[] = {
- {NULL}
- };
-
- /**@brief @ref pymod_pyrpn_RPNExprIter buffer methods definition
- * @ingroup pymod_pyrpn_RPNExprIter */
- static PyBufferProcs RPNIterExpr_as_buffer = {
- (getbufferproc)rpnif_getbuffer,
- (releasebufferproc)rpnif_releasebuffer,
- };
-
- PyTypeObject RPNIterExprType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pyrpn.RPNIterExpr",
- .tp_basicsize = sizeof(PyRPNIterExpr_t),
- .tp_itemsize = 0,
- .tp_del = rpnif_del,
- .tp_repr = rpnif_repr,
- .tp_as_sequence = &RPNIterExpr_seq_methods,
- .tp_as_mapping = &RPNIterExpr_mapping_methods,
- .tp_str = rpnif_str,
- .tp_as_buffer = &RPNIterExpr_as_buffer,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "RPN expression evaluator",
- .tp_methods = RPNIterExpr_methods,
- .tp_members = RPNIterExpr_members,
- .tp_getset = RPNIterExpr_getset,
- .tp_init = rpnif_init,
- .tp_new = rpnif_new,
- };
-
- PyObject* rpnif_params(PyObject *cls, PyObject *args, PyObject *kwds)
- {
- char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", NULL};
-
- unsigned short pos_flag, res_flag, stack_size;
- PyObject *lim_obj, *const_values_obj;
-
- stack_size = 16;
- const_values_obj = lim_obj = NULL;
-
- if(!PyArg_ParseTupleAndKeywords(args, kwds,
- "HHO|OH:RPNIterExppr.get_params", names,
- &pos_flag, &res_flag, &lim_obj, &const_values_obj,
- &stack_size))
- {
- return NULL;
- }
-
- rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
- lim_obj, const_values_obj, stack_size);
- if(!rif_params)
- {
- return NULL;
- }
-
- PyObject *res = _rpnif_params_to_tuple(rif_params);
- if(!res)
- {
- goto err;
- }
- free(rif_params);
- return res;
-
- err:
- free(rif_params);
- return NULL;
- }
-
- PyObject* rpnif_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
- {
- PyObject *ret, *err;
- PyRPNIterExpr_t *expr;
- ret = PyType_GenericNew(subtype, args, kwds);
- if((err = PyErr_Occurred()))
- {
- Py_DECREF(err);
- return ret;
- }
- expr = (PyRPNIterExpr_t*)ret;
- expr->rif = NULL;
- expr->rif_params = NULL;
- expr->borrowed_if = 0;
-
- return ret;
- }
-
-
- int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds)
- {
- PyRPNIterExpr_t *expr_self;
- char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", "mmap", NULL};
- unsigned short pos_flag, res_flag, stack_size;
- PyObject *lim_obj, *const_values_obj, *mmap_obj;
-
-
- expr_self = (PyRPNIterExpr_t*)self;
-
- stack_size = 16;
- const_values_obj = lim_obj = mmap_obj = NULL;
- expr_self->rif = NULL;
- expr_self->mmap = NULL;
-
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "HHO|OHO:RPNIterExpr.__init__", names,
- &pos_flag, &res_flag, &lim_obj, &const_values_obj, &stack_size,
- &mmap_obj))
- {
- return -1;
- }
-
- rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
- lim_obj, const_values_obj, stack_size);
- expr_self->rif_params = rif_params;
-
- if(!rif_params)
- {
- return -1;
- }
-
- expr_self->ndim = ((rpn_if_default_data_t*)(rif_params->data))->ndim;
-
- const Py_ssize_t expt_sz = rif_params->mem_sz * rif_params->value_sz;
- if(mmap_obj == Py_None)
- {
- Py_DECREF(mmap_obj);
- mmap_obj = NULL;
- }
- if(!mmap_obj)
- {
- PyObject *fileno = PyLong_FromLong(-1);
- PyObject *length = PyLong_FromSize_t(expt_sz);
- mmap_obj = PyObject_CallFunctionObjArgs(mmap_cls, fileno, length, NULL);
- Py_DECREF(fileno);
- Py_DECREF(length);
- if(PyErr_Occurred())
- {
- return -1;
- }
- }
- else
- {
- if(!PyObject_TypeCheck(mmap_obj, (PyTypeObject*)mmap_cls))
- {
- PyErr_SetString(PyExc_TypeError,
- "The mmap argument MUST be an instance \
- of mmap.mmap");
- return -1;
- }
- /**@todo check if mmap is shared & writable ? */
- if(PyObject_Length(mmap_obj) != (Py_ssize_t) expt_sz)
- {
- PyErr_Format(PyExc_ValueError,
- "Expected mmap length is %ld but mmap with length %ld provided",
- rif_params->mem_sz, PyObject_Length(mmap_obj));
- return -1;
- }
- }
-
-
- if(PyObject_GetBuffer(mmap_obj, &expr_self->mm_buff,
- PyBUF_CONTIG) == -1)
- {
- return -1;
- }
-
- expr_self->mmap = mmap_obj;
- expr_self->_mmap = expr_self->mm_buff.buf;
-
- // Creating rif with a new memory map
- expr_self->rif = rpn_if_new(rif_params, expr_self->mm_buff.buf, NULL);
- if(!expr_self->rif)
- {
- PyErr_Format(PyExc_RuntimeError,
- "Error initalizing if : %s", strerror(errno));
- return -1;
- }
-
- // Creating the tuple holding RPNExpr instances of expressions
- return _rpnif_init_expr_tuple(expr_self);
- }
-
-
- PyObject* rpnif_init_borrowed(rpn_if_t *borrowed_if, PyObject *mmap_obj)
- {
- PyObject *sz_lim, *const_val;
- PyObject *args, *ret;
-
-
- rpn_if_default_data_t *params;
- params = (rpn_if_default_data_t*)(borrowed_if->params->data);
-
- const size_t nsz = params->ndim + (params->pos_flag == RPN_IF_POSITION_XDIM?1:0);
- sz_lim = PyTuple_New(nsz);
- for(size_t i=0; i<nsz; i++)
- {
- PyObject *v = PyLong_FromLong(params->size_lim[i]);
- PyTuple_SET_ITEM(sz_lim, i, v);
- }
-
- const size_t const_val_sz = params->res_flag == RPN_IF_RES_CONST ? 1 : \
- (params->res_flag == RPN_IF_RES_CONST_RGBA ? 4 : 0);
-
- if(const_val_sz)
- {
- const_val = PyTuple_New(const_val_sz);
- for(size_t i=0; i<const_val_sz; i++)
- {
- PyObject *v = PyLong_FromLong(params->const_val[i]);
- PyTuple_SET_ITEM(const_val, i, v);
- }
- }
- else
- {
- const_val = Py_None;
- Py_INCREF(const_val);
- }
-
- // no mmap :/
- // It seems there is no elegant solutions for the moment
- // if we give None a new mmap is created
- // if we give a dummy mmap it has to have the expected size...
- // using None for the moment...
- /**@todo find a solution */
- PyObject *mmap_arg = Py_None;
- if(mmap_obj)
- {
- mmap_arg = mmap_obj;
- }
-
- args = Py_BuildValue("hhOOBO", params->pos_flag, params->res_flag,
- sz_lim, const_val,
- borrowed_if->params->rpn_stack_sz,
- mmap_arg);
- Py_DECREF(sz_lim);
- Py_DECREF(const_val);
- if(!args || PyErr_Occurred())
- {
- return NULL;
- }
-
- ret = PyObject_CallObject((PyObject*)&RPNIterExprType, args);
- Py_DECREF(args);
- if(!ret || PyErr_Occurred())
- {
- return NULL;
- }
-
- PyRPNIterExpr_t* instance = (PyRPNIterExpr_t*)ret;
-
- // changing if instance
- rpn_if_free(instance->rif);
- instance->rif = borrowed_if;
- // reseting expr tuple
- Py_DECREF(instance->expr);
- instance->expr = NULL;
-
- // mmap update
- PyBuffer_Release(&instance->mm_buff);
- if(!mmap_obj)
- {
- Py_DECREF(instance->mmap);
- instance->mmap = NULL;
- instance->mm_buff.buf = NULL;
- instance->_mmap = borrowed_if->mem;
- }
- instance->borrowed_if = 1;
- // someone else will take care to free the rif params
- if(instance->rif_params) { free(instance->rif_params); }
- instance->rif_params = NULL;
-
- if(_rpnif_init_expr_tuple(instance) < 0)
- {
- return NULL;
- }
- return ret;
- }
-
- /**@brief Returns the parameters in a named tuple */
- PyObject *rpnif_get_params(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- return _rpnif_params_to_tuple(expr_self->rif->params);
- }
-
- PyObject *rpnif_set_mmap(PyObject *self, PyObject *mm_obj)
- {
- if(!PyObject_TypeCheck(mm_obj, (PyTypeObject*)mmap_cls))
- {
- PyErr_Format(PyExc_TypeError,
- "Excpected instance of mmap.mmap");
- return NULL;
- }
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
-
- Py_buffer buff;
-
- /**@todo check mm size &writable ? */
- if(PyObject_GetBuffer(mm_obj, &buff, PyBUF_CONTIG) == -1)
- {
- return NULL;
- }
-
- // Release old mmap
- if(expr_self->mmap)
- {
- PyBuffer_Release(&expr_self->mm_buff);
- Py_DECREF(expr_self->mmap);
- }
-
- if(expr_self->rif->self_mem) // should never be true ?
- {
- const size_t mm_sz = expr_self->rif->params->mem_sz *\
- expr_self->rif->params->value_sz;
- munmap(expr_self->rif->mem, mm_sz);
- }
-
- // Set new mmap in python struct & rif struct
- expr_self->mm_buff = buff;
- expr_self->mmap = mm_obj;
- expr_self->_mmap = buff.buf;
-
- expr_self->rif->mem = buff.buf;
- expr_self->rif->self_mem = 0;
-
- Py_RETURN_NONE;
- }
-
- PyObject *rpnif_shape(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *params;
- params = (rpn_if_default_data_t*)(expr_self->rif->params->data);
-
- size_t res_sz;
-
- switch(params->res_flag)
- {
- case RPN_IF_RES_RGB:
- res_sz = 3;
- break;
- case RPN_IF_RES_RGBA:
- res_sz = 4;
- break;
- default:
- res_sz = 1;
- break;
- }
-
- const size_t shape_sz = params->ndim + (res_sz > 1 ?1:0);
-
- PyObject *ret = PyTuple_New(shape_sz);
- if(!ret)
- {
- return NULL;
- }
-
- size_t i;
- for(i = 0; i < params->ndim; i++)
- {
- size_t idx = params->pos_flag == RPN_IF_POSITION_XDIM ? i+1:i;
- PyObject *d = PyLong_FromLong(params->size_lim[idx]);
- if(!d)
- {
- goto item_err;
- }
- PyTuple_SET_ITEM(ret, i, d);
- }
- if(res_sz > 1)
- {
- PyObject *d = PyLong_FromLong(res_sz);
- if(!d)
- {
- goto item_err;
- }
- PyTuple_SET_ITEM(ret, i, d);
- }
- return ret;
-
- item_err:
- Py_DECREF(ret);
- return NULL;
- }
-
-
- PyObject *rpnif_step(PyObject *self, PyObject* opos)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- /** @todo allow tuple as argument !!!!! */
- if(!PyLong_Check(opos))
- {
- PyErr_SetString(PyExc_TypeError, "Expected position to be an int");
- return NULL;
- }
- size_t pos = PyLong_AsSize_t(opos);
- if(PyErr_Occurred())
- {
- return NULL;
- }
-
- pos = rpn_if_step(expr_self->rif, pos);
-
- return PyLong_FromSize_t(pos);
- }
-
-
- PyObject* rpnif_mutate(PyObject *self, PyObject *args, PyObject *kwargs)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- size_t rpn_sz = expr_self->rif->params->rpn_sz;
-
- char *str_args = "|IOO:RPNExpr.mutate";
- char *names[] = {"n_mutations", "params", "weights", NULL};
-
- PyObject *py_params = NULL, *py_weights = NULL;
- unsigned int n_mutations = 1;
- rpn_mutation_params_t params;
- rnd_t *weights;
- if(!if_mutation_alloc_weights(expr_self->rif, &weights))
- {
- PyErr_Format(PyExc_MemoryError,
- "Unable to allocate weights : %s\n",
- strerror(errno));
- return NULL;
- }
-
- if(!PyArg_ParseTupleAndKeywords(args, kwargs, str_args, names,
- &n_mutations, &py_params, &py_weights))
- {
- goto err;
- }
-
- if(!py_weights || py_weights == Py_None)
- {
- for(size_t i=0; i<rpn_sz; i++)
- {
- weights[i] = (rnd_t)((rnd_t_max / rpn_sz)*(i+1));
- }
- }
- else
- {
- // Parsing weights sequence into a weights array suitable
- // for rpn_mutate utility function
- PyObject *seq = PySequence_Fast(py_weights,
- "weights argument must be a sequence");
- if(!seq)
- {
- goto err;
- }
- if((size_t)PySequence_Fast_GET_SIZE(seq) != rpn_sz)
- {
- Py_DECREF(seq);
- char err[] = "expected weights to be a sequence of \
- %ld elements, but got %ld elements";
- PyErr_Format(PyExc_TypeError, err,
- rpn_sz,
- PySequence_Fast_GET_SIZE(seq));
- goto err;
-
- }
-
- float *fweights;
- if(!if_mutation_alloc_weights(expr_self->rif, &fweights))
- {
- PyErr_Format(PyExc_MemoryError,
- "Unable to allocate memory : %s",
- strerror(errno));
- goto err;
- }
- for(size_t i=0; i<rpn_sz; i++)
- {
- PyObject *elt = PySequence_Fast_GET_ITEM(seq, i);
- if(!PyNumber_Check(elt))
- {
- Py_DECREF(seq);
- free(fweights);
- PyErr_SetString(PyExc_TypeError,
- "weights must contains float values");
- goto err;
- }
- fweights[i] = (float)PyFloat_AsDouble(elt);
- if(PyErr_Occurred())
- {
- Py_DECREF(seq);
- free(fweights);
- goto err;
- }
- }
- rpnifs_fast_rnd_weights(rpn_sz, fweights, weights);
- free(fweights);
- Py_DECREF(seq);
- }
-
- if(!py_params || py_params == Py_None)
- {
- if(py_params == Py_None) { Py_DECREF(Py_None); }
- memcpy(¶ms, &rpn_mutation_params_default,
- sizeof(rpn_mutation_params_t));
- }
- else
- {
- if(pyrpn_pyobj_to_mutation_params(py_params, ¶ms) < 0)
- {
- if(!PyErr_Occurred())
- {
- PyErr_Format(PyExc_ValueError,
- "Bad value for params arguments : %s",
- strerror(errno));
- }
- goto err;
- }
- }
-
- if(if_mutation(expr_self->rif, weights, n_mutations, ¶ms) < 0)
- {
- free(weights);
- PyErr_Format(PyExc_RuntimeError,
- "Error during mutations : %s",
- strerror(errno));
- goto err;
- }
-
- free(weights);
- Py_RETURN_NONE;
-
- err:
- free(weights);
- return NULL;
- }
-
-
- PyObject *rpnif_to_pos(PyObject *self, PyObject** argv, Py_ssize_t argc)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
- return _rpnif_to_pos(rif_data, argv, argc);
- }
-
-
- PyObject *rpnif_from_pos(PyObject *self, PyObject* _pos)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
-
- return _rpnif_from_pos(rif_data, _pos);
- }
-
-
- PyObject *rpnif_keys(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
-
- Py_ssize_t ret_idx = 0;
- char xdim_key[64];
-
- PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
- if(PyErr_Occurred())
- {
- return NULL;
- }
-
- #define _ret_append(key) PyTuple_SET_ITEM(ret, ret_idx++, \
- PyUnicode_FromString(key))
-
- switch(rif_data->pos_flag)
- {
- case RPN_IF_POSITION_XY:
- _ret_append("X");
- _ret_append("Y");
- break;
- case RPN_IF_POSITION_LINEAR:
- _ret_append("X");
- break;
- case RPN_IF_POSITION_XDIM:
- for(size_t i=0; i<rif_data->size_lim[0];i++)
- {
- snprintf(xdim_key, 64, "D%ld", i);
- _ret_append(xdim_key);
- }
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError,
- "UNKOWN POS_FLAG3");
- return NULL;
- }
- switch(rif_data->res_flag)
- {
- case RPN_IF_RES_BOOL:
- case RPN_IF_RES_XFUN:
- _ret_append("R");
- break;
- case RPN_IF_RES_RGB:
- _ret_append("R");
- _ret_append("G");
- _ret_append("B");
- break;
- case RPN_IF_RES_RGBA:
- _ret_append("R");
- _ret_append("G");
- _ret_append("B");
- _ret_append("A");
- break;
- default:
- break;
- }
-
- if(PyErr_Occurred())
- {
- return NULL;
- }
-
- return ret;
-
- #undef _ret_append
- }
-
-
- PyObject *rpnif_values(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- Py_INCREF(expr_self->expr);
- return expr_self->expr;
- }
-
-
- PyObject *rpnif_items(PyObject *self)
- {
- size_t i;
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
- if(PyErr_Occurred())
- {
- return NULL;
- }
- PyObject *keys = rpnif_keys(self);
- for(i=0; i<expr_self->rif->params->rpn_sz; i++)
- {
- PyObject *tmp = PyTuple_New(2);
- if(PyErr_Occurred())
- {
- goto err_loop_newtuple;
- }
- PyObject *key = PyTuple_GET_ITEM(keys, i);
- PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
- Py_INCREF(key);
- Py_INCREF(value);
- PyTuple_SET_ITEM(tmp, 0, key);
- PyTuple_SET_ITEM(tmp, 1, value);
- PyTuple_SET_ITEM(ret, i, tmp);
- if(PyErr_Occurred())
- {
- goto err_loop_setitem;
- }
-
-
- }
-
- return ret;
-
- /** @todo cleanup seems wrong... */
- for(i=i; i>=0; i--)
- {
- err_loop_setitem:
- PyObject *key = PyTuple_GET_ITEM(keys, i);
- PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
- Py_DECREF(key);
- Py_DECREF(value);
- err_loop_newtuple:
- }
- Py_DECREF(ret);
- return NULL;
- }
-
-
- void rpnif_del(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- if((!expr_self->borrowed_if) && expr_self->rif)
- {
- rpn_if_free(expr_self->rif);
- expr_self->rif = NULL;
- }
- if(expr_self->mmap)
- {
- if(expr_self->mm_buff.buf)
- {
- PyBuffer_Release(&expr_self->mm_buff);
- expr_self->mm_buff.buf = NULL;
- }
- Py_DECREF(expr_self->mmap);
- expr_self->mmap = NULL;
- }
- if(expr_self->expr)
- {
- Py_DECREF(expr_self->expr);
- expr_self->expr = NULL;
- }
- if(expr_self->rif_params) { free(expr_self->rif_params); }
- }
-
-
- Py_ssize_t rpnif_len(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- return expr_self->rif->params->rpn_sz;
- }
-
- PyObject* rpnif_expr_item(PyObject *self, Py_ssize_t idx)
- {
- Py_ssize_t _idx = idx;
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
-
- if(idx < 0)
- {
- idx = expr_self->rif->params->rpn_sz - 1 + idx;
- }
- if(idx < 0 || (size_t) idx >= expr_self->rif->params->rpn_sz)
- {
- PyErr_Format(PyExc_IndexError,
- "No expression %ld with given options",
- _idx);
- return NULL;
- }
- PyObject *ret = PyTuple_GET_ITEM(expr_self->expr, idx);
- Py_INCREF(ret);
- return ret;
- }
-
-
- int rpnif_expr_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
-
- if(!PyUnicode_Check(elt))
- {
- PyErr_SetString(PyExc_TypeError, "RPNExpr expected");
- return -1;
- }
-
- PyObject *bytes_str = PyUnicode_AsASCIIString(elt);
- if(PyErr_Occurred())
- {
- return -1;
- }
- const char *code = PyBytes_AS_STRING(bytes_str);
-
- rpn_expr_t *expr = &(expr_self->rif->rpn[idx]);
-
- if(rpn_expr_recompile(expr, code) < 0)
- {
- PyErr_Format(PyExc_ValueError,
- "Error during expression '%s' compilation : %s",
- code, expr->err_reason);
- return -1;
- }
-
- return 0;
- }
-
- /** Convert key to integer index
- * @param self @ref PyRPNIterExpr_t instance
- * @param _key An expression name (str)
- * @return The expression index or -1 on error (raise python exception)
- */
- static Py_ssize_t _rpnif_subscript_idx(PyObject *self, PyObject *_key)
- {
- if(!PyUnicode_Check(_key))
- {
- PyErr_SetString(PyExc_TypeError, "Key should be a str");
- return -1;
- }
- PyObject *bytes_str = PyUnicode_AsASCIIString(_key);
- if(PyErr_Occurred())
- {
- return -1;
- }
- const char *key = PyBytes_AS_STRING(bytes_str);
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
-
- Py_ssize_t idx = -1;
- Py_ssize_t res_idx = -1;
-
- switch(rif_data->pos_flag)
- {
- case RPN_IF_POSITION_XY:
- res_idx = 2;
- if(key[1] != '\0') { break; }
- switch(key[0])
- {
- case 'X':
- idx=0;
- break;
- case 'Y':
- idx=1;
- break;
- }
- break;
- case RPN_IF_POSITION_LINEAR:
- res_idx = 1;
- if(!strcmp("X", key))
- {
- idx = 0;
- }
- break;
- case RPN_IF_POSITION_XDIM:
- size_t ndim = rif_data->size_lim[0];
- res_idx = ndim;
- char possible_key[64];
- for(size_t i=0; i<ndim; i++)
- {
- snprintf(possible_key, 64, "D%ld", i);
- if(!strcmp(possible_key, key))
- {
- idx = i;
- break;
- }
- }
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError,
- "UNKOWN POS_FLAG");
- return -1;
- }
- if(idx < 0)
- {
- // not found yet, looking for result key
- switch(rif_data->res_flag)
- {
- case RPN_IF_RES_BOOL:
- case RPN_IF_RES_XFUN:
- if(!strcmp("R", key))
- {
- idx = res_idx;
- }
- break;
- case RPN_IF_RES_RGBA:
- if(!strcmp("A", key))
- {
- idx = res_idx + 3;
- }
- case RPN_IF_RES_RGB:
- if(key[1] != '\0')
- {
- break;
- }
- switch(key[0])
- {
- case 'R':
- idx=res_idx;
- break;
- case 'G':
- idx=res_idx+1;
- break;
- case 'B':
- idx=res_idx+2;
- break;
- }
- break;
- default:
- // not implemented, not unknown....
- PyErr_SetString(PyExc_RuntimeError,
- "UNKOWN RES_FLAG");
- return -1;
- }
- }
- return idx;
- }
-
- PyObject* rpnif_subscript(PyObject *self, PyObject *key)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
-
- Py_ssize_t idx = _rpnif_subscript_idx(self, key);
- if(idx < 0)
- {
- PyErr_Format(PyExc_IndexError,
- "No expression '%R' with given parameters",
- key);
- return NULL;
- }
- PyObject *expr = PyTuple_GET_ITEM(expr_self->expr, idx);
- Py_INCREF(expr);
- return expr;
- }
-
- int rpnif_ass_subscript(PyObject *self, PyObject *key, PyObject *elt)
- {
- Py_ssize_t idx = _rpnif_subscript_idx(self, key);
- if(idx < 0)
- {
- PyErr_Format(PyExc_IndexError,
- "Cannot set expression '%R' that do not exists with this parameters",
- key);
- return -1;
- }
-
- return rpnif_expr_ass_item(self, idx, elt);
- }
-
- int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags)
- {
- PyRPNIterExpr_t *expr_self;
- expr_self = (PyRPNIterExpr_t*)self;
-
- if(expr_self->mmap)
- {
- return PyObject_GetBuffer(expr_self->mmap, view, flags);
- }
- return _rpnif_getbuffer_nopymap(self, expr_self->rif->params,
- expr_self->_mmap, view, flags);
- }
-
- void rpnif_releasebuffer(PyObject *self, Py_buffer *view)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- if(expr_self->mmap)
- {
- return PyBuffer_Release(view);
- }
- return _rpnif_releasebuffer_nopymap(self, view);
- }
-
- PyObject* rpnif_str(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = \
- (rpn_if_default_data_t*)expr_self->rif->params->data;
- const size_t rpn_sz = expr_self->rif->params->rpn_sz;
- const char pyfmt[] = "%VA%ld=%U=\"%S\";";
-
- size_t i;
- PyObject *buf, *tmp, *items;
-
- buf = NULL;
- items = rpnif_items(self);
- if(PyErr_Occurred()) { return NULL; }
-
-
- for(i=0; i<rpn_sz; i++)
- {
- PyObject *key, *value, *elt;
- elt = PyTuple_GET_ITEM(items, i);
- key = PyTuple_GET_ITEM(elt, 0);
- value = PyTuple_GET_ITEM(elt, 1);
-
- tmp = PyUnicode_FromFormat(pyfmt,
- buf, "",
- i, key, value);
- if(buf) { Py_DECREF(buf); }
- if(PyErr_Occurred()) { return NULL; }
- buf = tmp;
- }
-
-
- switch(rif_data->res_flag)
- {
- case RPN_IF_RES_CONST:
- tmp = PyUnicode_FromFormat("%U A%ld=C(*)=%lld",
- buf, i+1, rif_data->const_val[0]);
- Py_DECREF(buf);
- buf=tmp;
- break;
- case RPN_IF_RES_CONST_RGBA:
- tmp = PyUnicode_FromFormat("%U A%ld=R(*)=%lld A%ld=G(*)=%lld A%ld=B(*)=%lld A%ld=A(*)=%lld",
- buf,
- i+1, rif_data->const_val[0],
- i+2, rif_data->const_val[1],
- i+3, rif_data->const_val[2],
- i+4, rif_data->const_val[3]);
- Py_DECREF(buf);
- buf=tmp;
- break;
- }
-
- Py_INCREF(buf);
- return buf;
- }
-
- /** Return a string representation of expressions dict
- * @param self @ref PyRPNIterExpr_t instance
- * @return a str instance */
- static PyObject* _rpnif_expr_repr(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = \
- (rpn_if_default_data_t*)expr_self->rif->params->data;
-
- PyObject *buf, *tmp, *items, *const_res;
- const char pyfmt[] = "%V\"%U\":\"%S\"%V";
-
- buf = const_res = NULL;
-
- items = rpnif_items(self);
- if(PyErr_Occurred()) { return NULL; }
-
- #define _const_res_key ",\"const_res\":"
- switch(rif_data->res_flag)
- {
- case RPN_IF_RES_CONST:
- const_res = PyUnicode_FromFormat(
- _const_res_key "{\"r\":%llu}}",
- rif_data->const_val[0]);
- break;
- /*
- case RPN_IF_RES_CONST_RGB:
- const_res = PyUnicode_FromFormat(
- "\"const_res\": {\"r\":%llu, \"g\":%llu, \"b\":%llu}}",
- rif_data->const_val[0],
- rif_data->const_val[1],
- rif_data->const_val[2])
- break;
- */
- case RPN_IF_RES_CONST_RGBA:
- const_res = PyUnicode_FromFormat(
- _const_res_key \
- "{\"r\":%llu,\"g\":%llu,\"b\":%llu,\"a\":%llu}}",
- rif_data->const_val[0],
- rif_data->const_val[1],
- rif_data->const_val[2],
- rif_data->const_val[3]);
- break;
- default:
- const_res = PyUnicode_FromFormat("}");
- break;
- }
- #undef _const_res_key
-
- const size_t rpn_sz = expr_self->rif->params->rpn_sz;
-
- for(size_t i=0; i<rpn_sz; i++)
- {
- PyObject *key, *value, *elt;
- elt = PyTuple_GET_ITEM(items, i);
- key = PyTuple_GET_ITEM(elt, 0);
- value = PyTuple_GET_ITEM(elt, 1);
-
- tmp = PyUnicode_FromFormat(pyfmt,
- buf, "{", key, value,
- i==rpn_sz-1?const_res:NULL, ",");
- if(buf)
- {
- Py_DECREF(buf);
- }
- if(PyErr_Occurred())
- {
- return NULL;
- }
- buf = tmp;
- }
-
-
- return buf;
- }
-
- PyObject* rpnif_repr(PyObject *self)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
-
- char *str_pos, *str_res;
- char tmp[64];
-
- PyObject *expr_repr = _rpnif_expr_repr(self);
- if(PyErr_Occurred()) { return NULL; }
-
- switch(rif_data->pos_flag)
- {
- case RPN_IF_POSITION_XY:
- str_pos = "XY";
- break;
- case RPN_IF_POSITION_LINEAR:
- str_pos = "LINEAR";
- break;
- case RPN_IF_POSITION_XDIM:
- snprintf(tmp, 64, "XDIM%ld", rif_data->size_lim[0]);
- str_pos = tmp;
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError,
- "UNKOWN POS_FLAG2");
- return NULL;
- }
-
- PyObject *const_res = NULL;
-
- switch(rif_data->res_flag)
- {
- case RPN_IF_RES_BOOL:
- str_res = "BOOL";
- break;
- case RPN_IF_RES_CONST:
- str_res = "CONST";
- const_res = PyTuple_New(1);
- break;
- case RPN_IF_RES_CONST_RGBA:
- str_res = "CONST_RGBA";
- break;
- case RPN_IF_RES_COUNT:
- str_res = "COUNT";
- break;
- case RPN_IF_RES_XFUN:
- str_res = "XFUN";
- break;
- case RPN_IF_RES_RGB:
- str_res = "RGB";
- break;
- case RPN_IF_RES_RGBA:
- str_res = "RGBA";
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError,
- "UNKOWN RES_FLAG2");
- return NULL;
- }
-
- PyObject *res;
-
- const_res = const_res?const_res:Py_None;
-
- res = PyUnicode_FromFormat(
- "<RPNIterExpr pos_flag:%s res_flag:%s expr:'%U' const_res:%S>",
- str_pos, str_res, expr_repr, const_res);
- if(PyErr_Occurred()) { return NULL; }
- return res;
- }
-
- PyObject* rpnif_getstate(PyObject *self, PyObject *noargs)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
- const rpn_if_param_t *params = expr_self->rif->params;
- rpn_if_default_data_t *data = (rpn_if_default_data_t*)(params->data);
-
- const size_t const_val_sz = data->res_flag == RPN_IF_RES_CONST ? 1 : \
- (data->res_flag == RPN_IF_RES_CONST_RGBA ? 4 : 0);
-
- const size_t nszlim = data->ndim +
- (data->pos_flag == RPN_IF_POSITION_XDIM ?1:0);
-
-
- size_t buf_sz = sizeof(void*) + \
- sizeof(rpn_if_param_t) + \
- sizeof(rpn_if_default_data_t) + \
- sizeof(rpn_value_t) * ( \
- params->rpn_sz + params->rpn_argc) + \
- sizeof(size_t) * nszlim + \
- sizeof(rpn_value_t) * const_val_sz;
-
- // all stack allocation grouped here
- void *new_rpn[params->rpn_sz];
-
- size_t rpn_sz[params->rpn_sz];
-
- size_t sz_max = 0;
- for(size_t i=0; i<params->rpn_sz; i++)
- {
- rpn_sz[i] = rpn_expr_serialize(&expr_self->rif->rpn[i],
- NULL, 0);
- // each expression stores a size and a picled repr
- buf_sz += rpn_sz[i] + sizeof(size_t);
- if(rpn_sz[i] > sz_max) { sz_max = rpn_sz[i]; }
- }
-
- void *buf = malloc(buf_sz);
- if(!buf)
- {
- PyErr_Format(PyExc_MemoryError,
- "Unable to allocate pickled representation : ",
- strerror(errno));
- return NULL;
- }
-
- bzero(buf, buf_sz);
- bzero(new_rpn, sizeof(*new_rpn));
-
- void **ptr = buf; // mmap ptr
- rpn_if_param_t *new_params = (void*)(ptr+1);
- rpn_if_default_data_t *new_data = (void*)(new_params + 1);
- size_t *new_size_lim = (void*)(new_data+1);
- rpn_value_t *new_const_val = (void*)(new_size_lim + nszlim);
- size_t *new_rpn_sz = (void*)(new_const_val + const_val_sz);
- size_t cur_offset = sizeof(size_t)*params->rpn_sz;
-
- *ptr = expr_self->_mmap;
-
- new_params->mem_sz = params->mem_sz;
- new_params->value_sz = params->value_sz;
- new_params->rpn_sz = params->rpn_sz;
- new_params->rpn_argc = params->rpn_argc;
- new_params->rpn_stack_sz = params->rpn_stack_sz;
- // The following should be more efficient, but result
- // in some badly initialized bytes in new_params struct
- // padding...
- //*new_params = *params;
-
- new_params->getarg_f = NULL;
- new_params->setres_f = NULL;
- new_params->data = NULL;
-
- new_data->pos_flag = data->pos_flag;
- new_data->res_flag = data->res_flag;
- new_data->ndim = data->ndim;
- // Same as above
- //*new_data = *data;
-
- new_data->size_lim = NULL;
- new_data->const_val = NULL;
-
- memcpy(new_size_lim, data->size_lim, sizeof(size_t)*nszlim);
- if(const_val_sz)
- {
- memcpy(new_const_val, data->const_val, sizeof(rpn_value_t)*const_val_sz);
- }
-
- // set sizes & rpn expressions
- for(size_t i=0; i<params->rpn_sz; i++)
- {
- new_rpn[i] = ((void*)new_rpn_sz)+cur_offset;
- new_rpn_sz[i] = rpn_sz[i];
- bzero(new_rpn[i], rpn_sz[i]);
- cur_offset += rpn_sz[i];
- if(!rpn_expr_serialize(&expr_self->rif->rpn[i],
- new_rpn[i], rpn_sz[i]))
- {
- goto err_rpn;
- }
- }
-
- PyObject *res = PyBytes_FromStringAndSize(buf, buf_sz);
- return res;
-
- err_rpn:
- /**@todo handle error */
- free(buf);
- return NULL;
- }
-
- PyObject* rpnif_setstate(PyObject *self, PyObject *state_bytes)
- {
- PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
-
- if(!PyBytes_Check(state_bytes)) /* Arg check */
- {
- PyErr_SetString(PyExc_TypeError, "Expected bytes");
- return NULL;
- }
-
- size_t bsize = PyBytes_GET_SIZE(state_bytes);
- const void *data = (void*)PyBytes_AS_STRING(state_bytes);
-
- if(bsize < sizeof(void*))
- {
- PyErr_SetString(PyExc_ValueError, "Smaller than expected given");
- return NULL;
- }
-
- rpn_if_param_t *params, *ser_params;
- rpn_if_default_data_t *ser_data;
- size_t *ser_size_lim;
- rpn_value_t *ser_const_val;
-
- expr_self->mmap = NULL;
- expr_self->_mmap = *(void**)data;
-
- ser_params = (void*)((void**)data+1);
- ser_data = (void*)(ser_params+1);
- ser_size_lim = (void*)(ser_data+1);
-
- const size_t nszlim = ser_data->ndim + \
- (ser_data->pos_flag == RPN_IF_POSITION_XDIM ?1:0);
-
- ser_const_val = (void*)(ser_size_lim + nszlim);
-
- params = rpn_if_default_params(ser_data->pos_flag, ser_data->res_flag,
- ser_size_lim, ser_const_val,
- ser_params->rpn_stack_sz);
-
- const size_t const_val_sz = ser_data->res_flag == RPN_IF_RES_CONST?1:\
- (ser_data->res_flag == RPN_IF_RES_CONST_RGBA?4:0);
-
- rpn_expr_t *ser_rpn = malloc(sizeof(*ser_rpn) * ser_params->rpn_sz);
- if(!ser_rpn)
- {
- PyErr_Format(PyExc_MemoryError,
- "Unable to alloc rpn expressions : %s",
- strerror(errno));
- return NULL;
- }
- size_t *ser_rpn_sz = (void*)(ser_const_val + const_val_sz);
- void *ser_rpn_buf = (void*)(ser_rpn_sz + ser_params->rpn_sz);
-
-
- for(size_t i=0; i<ser_params->rpn_sz; i++)
- {
- if(rpn_expr_deserialize(&ser_rpn[i], ser_rpn_buf, ser_rpn_sz[i]) < 0)
- {
- PyErr_Format(PyExc_ValueError,
- "Unable to deserialize expr#%ld : %s",
- i, ser_rpn[i].err_reason);
- return NULL;
- }
- ser_rpn_buf = (void*)ser_rpn_buf + ser_rpn_sz[i];
- }
-
- expr_self->rif = rpn_if_new(params, expr_self->_mmap, ser_rpn);
- if(!expr_self->rif)
- {
- PyErr_SetString(PyExc_ValueError,
- "Unable to initialize rif expression");
- return NULL;
- }
- expr_self->rif_params = params;
- expr_self->ndim = ser_data->ndim;
- if(_rpnif_init_expr_tuple(expr_self) < 0)
- {
- return NULL;
- }
- expr_self->borrowed_if = 0; // explicitly not borrowed
-
- Py_RETURN_NONE;
- }
-
- rpn_if_param_t *_rpnif_get_params(unsigned short pos_flag, unsigned short res_flag,
- PyObject *lim_obj, PyObject *const_values_obj,
- unsigned short stack_size)
- {
- char err_str[256];
- int ndim;
-
- // Args checking
- if(stack_size < 4 || stack_size > 255)
- {
- snprintf(err_str, 128,
- "Stack size should be in [0..255] but %u given",
- stack_size);
- PyErr_SetString(PyExc_ValueError, err_str);
- return NULL;
- }
-
- // Checks flags & fetch expected sizes for size_lim & const_values
- short expt_sizes[2];
- if(rpn_if_sizes_from_flag(pos_flag, res_flag, expt_sizes) < 0)
- {
- if(expt_sizes[0] < 0)
- {
- PyErr_SetString(PyExc_ValueError,
- "Invalid position flag given");
- }
- else
- {
- PyErr_SetString(PyExc_ValueError,
- "Invalid result flag given");
- }
- return NULL;
- }
-
- //Check & convert lim
- PyObject *tmp;
- tmp = PySequence_Fast(lim_obj, "Sequence expected for size_lim argument");
- if(PyErr_Occurred())
- {
- return NULL;
- }
- Py_ssize_t lim_obj_sz = PySequence_Fast_GET_SIZE(tmp);
- ndim = lim_obj_sz;
- if(PyErr_Occurred())
- {
- Py_DECREF(tmp);
- return NULL;
- }
- if(lim_obj_sz < 1)
- {
- Py_DECREF(tmp);
- PyErr_SetString(PyExc_ValueError,
- "Size limits cannot be empty");
- return NULL;
- }
-
- if(pos_flag == RPN_IF_POSITION_XDIM)
- {
- PyObject *item = PySequence_Fast_GET_ITEM(tmp, 0);
- Py_ssize_t tmp = PyLong_AsSsize_t(item);
- if(PyErr_Occurred())
- {
- PyErr_SetString(PyExc_ValueError,
- "Unable to convert size_lim[0] to int");
- Py_DECREF(tmp);
- return NULL;
- }
- if(lim_obj_sz != tmp + 1)
- {
- PyErr_Format(PyExc_ValueError,
- "Xdim indicate %d size_lim but len(size_lim)=%d",
- tmp+1, lim_obj_sz);
- Py_DECREF(tmp);
- return NULL;
- }
- expt_sizes[0] = ndim = tmp;
- }
- else
- {
- if(lim_obj_sz != expt_sizes[0])
- {
- PyErr_Format(PyExc_ValueError,
- "Expected %d size_lim but len(size_lim)=%d",
- expt_sizes[0], lim_obj_sz);
- Py_DECREF(tmp);
- return NULL;
- }
- }
-
- size_t sz_limits[lim_obj_sz];
- for(Py_ssize_t i = 0; i<lim_obj_sz; i++)
- {
- PyObject *item = PySequence_Fast_GET_ITEM(tmp, i);
- sz_limits[i] = PyLong_AsSize_t(item);
- if(PyErr_Occurred())
- {
- PyErr_Format(PyExc_ValueError,
- "Unable to convert size_lim[%d] to unsigned int",
- i);
- Py_DECREF(tmp);
- return NULL;
- }
- }
- Py_DECREF(tmp);
- tmp = NULL;
-
- //Check & convert const values
- Py_ssize_t values_obj_sz = 0;
- if(expt_sizes[1] > 0)
- {
- tmp = const_values_obj;
- if(!PyTuple_Check(tmp))
- {
- PyErr_SetString(PyExc_ValueError,
- "Invalid type for const_values argument");
- return NULL;
- }
- values_obj_sz = PyTuple_Size(tmp);
- if(values_obj_sz != expt_sizes[1])
- {
- PyErr_Format(PyExc_ValueError,
- "Expected %d const_values but len(const_values)=%d",
- expt_sizes[1], values_obj_sz);
- return NULL;
- }
- }
-
- rpn_value_t const_values[values_obj_sz];
- for(Py_ssize_t i = 0; i<values_obj_sz; i++)
- {
- PyObject *item = PyTuple_GET_ITEM(tmp, i);
- const_values[i] = PyLong_AsRpnValue_t(item);
- if(PyErr_Occurred())
- {
- PyErr_Format(PyExc_ValueError,
- "Unable to convert size_lim[%d] to unsigned int",
- i);
- return NULL;
- }
- }
-
-
- // Creating rif params
- rpn_if_param_t *rif_params;
-
- if(!(rif_params = rpn_if_default_params(pos_flag, res_flag,
- sz_limits, const_values, stack_size)))
- {
- PyErr_SetString(PyExc_ValueError, "Unable to create parameters \
- with given arguments");
- return NULL;
- }
-
- return rif_params;
- }
-
- PyObject *_rpnif_params_to_tuple(const rpn_if_param_t *_params)
- {
- PyObject *res, *val;
- short expt_sizes[2];
- rpn_if_default_data_t *params;
- params = (rpn_if_default_data_t*)(_params->data);
-
- if(rpn_if_sizes_from_flag(params->pos_flag, params->res_flag, expt_sizes) < 0)
- {
- PyErr_SetString(PyExc_RuntimeError, "Invalid internal state");
- return NULL;
- }
-
- res = PyStructSequence_New(&rpnif_params_SeqDesc);
- if(!res)
- {
- return NULL;
- }
- val = PyLong_FromLong(_params->rpn_argc);
- PyStructSequence_SET_ITEM(res, 0, val);
-
- val = PyLong_FromLong(params->pos_flag);
- PyStructSequence_SET_ITEM(res, 1, val);
-
- val = PyLong_FromLong(params->res_flag);
- PyStructSequence_SET_ITEM(res, 2, val);
-
- if(params->pos_flag == RPN_IF_POSITION_XDIM)
- {
- expt_sizes[0] = params->size_lim[0] + 1;
- }
-
- PyObject *lim = PyTuple_New(expt_sizes[0]);
- if(!lim)
- {
- Py_DECREF(res);
- return NULL;
- }
- PyStructSequence_SET_ITEM(res, 3, lim);
-
- for(Py_ssize_t i=0; i<expt_sizes[0]; i++)
- {
- val = PyLong_FromSize_t(params->size_lim[i]);
- PyTuple_SET_ITEM(lim, i, val);
- }
-
- if(!params->const_val)
- {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(res, 4, Py_None);
- }
- else
- {
- PyObject *values = PyTuple_New(expt_sizes[1]);
- if(!values)
- {
- Py_DECREF(res);
- return NULL;
- }
- PyStructSequence_SET_ITEM(res, 4, values);
- for(Py_ssize_t i=0; i<expt_sizes[1]; i++)
- {
- val = PyLong_FromRpnValue_t(params->const_val[i]);
- PyTuple_SET_ITEM(values, i, val);
- }
- }
- val = PyLong_FromUnsignedLong(_params->mem_sz * _params->value_sz);
- PyStructSequence_SET_ITEM(res, 5, val);
- return res;
- }
-
-
- PyObject *_rpnif_to_pos(rpn_if_default_data_t *rif_data, PyObject** argv, Py_ssize_t argc)
- {
- const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
- long long value;
-
- if((size_t)argc != rif_data->ndim)
- {
- PyErr_Format(PyExc_IndexError,
- "Expression expect %lu dimentions coordinates,"
- " but %ld arguments given.",
- rif_data->ndim, argc);
- return NULL;
- }
-
- rpn_value_t result=0;
- size_t cur_dim_sz = 1;
-
- for(size_t i=0; i<rif_data->ndim; i++)
- {
- if(!PyLong_Check(argv[i]))
- {
- PyErr_SetString(PyExc_TypeError,
- "coordinates must be integers");
- return NULL;
- }
- value = PyLong_AsLongLong(argv[i]);
- if(value < 0)
- {
- value = (-(rpn_value_t)-value)%rif_data->size_lim[i+idx_off];
- }
- if((size_t)value >= rif_data->size_lim[i+idx_off])
- {
- PyErr_Format(PyExc_IndexError,
- "Coordinate %ld overflows : %R/%lu",
- i, argv[i],
- rif_data->size_lim[i+idx_off]);
- return NULL;
- }
- result += value * cur_dim_sz;
- cur_dim_sz *= rif_data->size_lim[i+idx_off];
- }
-
- return PyLong_FromUnsignedLongLong(result);
- }
-
-
- PyObject *_rpnif_from_pos(rpn_if_default_data_t *rif_data, PyObject* _pos)
- {
- const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
-
- if(!PyLong_Check(_pos))
- {
- PyErr_SetString(PyExc_TypeError,
- "Expected position to be an integer");
- return NULL;
- }
-
- size_t pos = PyLong_AsUnsignedLong(_pos);
- if(PyErr_Occurred())
- {
- return NULL;
- }
-
- PyObject *res = PyTuple_New(rif_data->ndim);
- if(PyErr_Occurred())
- {
- return NULL;
- }
-
- for(size_t i=0; i<rif_data->ndim; i++)
- {
- size_t val;
- size_t lim = rif_data->size_lim[i+idx_off];
-
- val = pos % lim;
- pos /= lim;
-
- PyObject *elt = PyLong_FromUnsignedLong(val);
- if(PyErr_Occurred())
- {
- goto err;
- }
- PyTuple_SET_ITEM(res, i, elt);
- }
-
- return res;
-
- err:
- Py_DECREF(res);
- return NULL;
- }
-
-
- int _rpnif_getbuffer_nopymap(PyObject *self, const rpn_if_param_t *params,
- void *buf, Py_buffer *view, int flags)
- {
- rpn_if_default_data_t *data = (rpn_if_default_data_t*)params->data;
-
- view->buf = buf;
- view->obj = self;
- view->len = params->mem_sz * params->value_sz;
- view->readonly = 0;
- view->itemsize = sizeof(rpn_value_t);
- view->format = (flags & PyBUF_FORMAT)?"L":NULL;
- view->ndim = 1;
- view->shape = NULL;
- if(flags & PyBUF_ND)
- {
- short nval;
- switch(data->res_flag)
- {
- case RPN_IF_RES_BOOL:
- case RPN_IF_RES_CONST:
- case RPN_IF_RES_COUNT:
- nval = 1;
- break;
- case RPN_IF_RES_RGBA:
- case RPN_IF_RES_CONST_RGBA:
- nval = 4;
- break;
- case RPN_IF_RES_RGB:
- nval = 3;
- break;
- default:
- PyErr_SetString(PyExc_BufferError,
- "Unsupported result flag");
- return -1;
- }
- view->ndim += (nval>1)?1:0;
- if(!(view->shape = malloc(sizeof(Py_ssize_t) * view->ndim)))
- {
- PyErr_Format(PyExc_BufferError,
- "Buffer's shape allocation error : %s",
- strerror(errno));
- return -1;
- }
- for(size_t i=0; i<data->ndim; i++)
- {
- const int idx = i + \
- (data->pos_flag == RPN_IF_POSITION_XDIM)?1:0;
- view->shape[i] = data->size_lim[idx];
- }
- if(nval>1)
- {
- view->shape[data->ndim] = nval;
- }
-
- }
- view->strides = NULL;
- view->suboffsets = NULL;
- Py_INCREF(self);
- return 0;
- }
-
-
- void _rpnif_releasebuffer_nopymap(PyObject *self, Py_buffer *view)
- {
- if(view->shape) { free(view->shape); }
- view->buf = NULL;
- Py_DECREF(self);
- }
-
-
- int _rpnif_init_expr_tuple(PyRPNIterExpr_t *expr_self)
- {
- expr_self->expr = PyTuple_New(expr_self->rif->params->rpn_sz);
- for(size_t i=0; i<expr_self->rif->params->rpn_sz;i++)
- {
- rpn_expr_t *expr = &expr_self->rif->rpn[i];
- PyObject *instance = rpnexpr_init_borrowing(expr);
- if(!instance)
- {
- //! @todo set exception
- return -1;
- }
- PyTuple_SET_ITEM(expr_self->expr, i, instance);
- }
- return 0;
- }
-
-
- /**@def _ret_append(key)
- * @hiderefs
- * local macro */
- /**@def _const_res_key()
- * @hiderefs
- * local macro*/
|