Fast IFS using RPN notation
python
c
x86-64
nasm
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

python_if.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. #ifndef _PYTHON_IF_H__
  20. #define _PYTHON_IF_H__
  21. #include "config.h"
  22. #include <errno.h>
  23. #define PY_SSIZE_T_CLEAN
  24. #include <Python.h>
  25. #include "structmember.h"
  26. #include "rpn_if.h"
  27. #include "rpn_if_default.h"
  28. #include "rpn_if_mutate.h"
  29. #include "python_mutation.h"
  30. #include "python_rpnexpr.h"
  31. #include "python_const.h"
  32. /**@file python_if.h
  33. * @brief Python RPNIterExpr type headers
  34. * @ingroup python_ext
  35. * @ingroup pymod_pyrpn_RPNExprIter
  36. *
  37. * This file is the header of the RPNIterExpr Python class
  38. */
  39. /**@defgroup pymod_pyrpn_RPNExprIter class pyrpn.RPNExprIter
  40. * @ingroup pymod_pyrpn
  41. * @brief Exposed Python class : RPNIterExpr
  42. *
  43. * Iterated expression are composed of RPN expressions, they are able to
  44. * iterate taking their parameters from a memory array and setting back values
  45. * in it on each iteration.
  46. *
  47. * @see ifs_if
  48. */
  49. /**@brief RPNIterExpr Python class type definition
  50. * @ingroup pymod_pyrpn_RPNExprIter */
  51. extern PyTypeObject RPNIterExprType;
  52. /**@brief Points on Python's std mmap module */
  53. extern PyObject *mmap_module;
  54. /**@brief Python's mmap.mmap class */
  55. extern PyObject *mmap_cls;
  56. /**@brief Structure holding RPNIterExpr objects
  57. *
  58. * @warning Pickling methods are implemented for a limited usage.
  59. * The mmap.mmap instance olded by the structure (sadly) cannot be
  60. * pickled... In order to allow using RPNExprIter instances in
  61. * multiprocessing stuffs, the piclking method will "export" only
  62. * a pointer on the shared mmap. This implies that if the GC pops out
  63. * on the mmap, the unpickled instance will segfault...
  64. * This implies that unpickled instances has limited capabilities (no
  65. * way to get back the mmap.mmap instance).
  66. * There is a way (using another shared mmap at module level ?) to
  67. * implement a custom reference count on the mmap pointer in order
  68. * to determine when to DECREF the mmap.mmap instance.
  69. *
  70. * @todo think about implementing a safe pickle/unpickle method
  71. * @ingroup pymod_pyrpn_RPNExprIter */
  72. typedef struct
  73. {
  74. /** Python's type definition */
  75. PyObject_VAR_HEAD;
  76. /** @brief Number of dimention in map */
  77. size_t ndim;
  78. /**@brief Pointer on @ref rpn_if_s */
  79. rpn_if_t *rif;
  80. /**@brief Python tuple with instances of RPNExpr */
  81. PyObject *expr;
  82. /**@brief Python mmap.mmap instance representing rif memory map
  83. * @note NULL if unpickled instance */
  84. PyObject *mmap;
  85. /**@brief Memory map buffer allowing acces to underlying pointer
  86. * @note unrelevant if unpickled instance */
  87. Py_buffer mm_buff;
  88. /**@brief Memory map buffer pointer */
  89. void *_mmap;
  90. /**@brief Pointer on params to free at del */
  91. rpn_if_param_t *rif_params;
  92. /**@brief If true, someone else (an ifs ?) will take care of freeing
  93. * the if at deletion */
  94. short borrowed_if;
  95. } PyRPNIterExpr_t;
  96. /**@brief RPNIterExpr.params static method
  97. * @param args Position arguments
  98. * @param kwds Keyword arguments
  99. * @return A new rpnif_params_SeqDesc instance
  100. */
  101. PyObject* rpnif_params(PyObject *cls, PyObject *args, PyObject *kwds);
  102. /**@brief RpnIterExpr __new__ method
  103. * @param subtype Type of object being created (pyrpn.RPNIterExpr)
  104. * @param args positional arguments for subtype
  105. * @param kwds keyword argumenrs for subtype
  106. * @return The new Python RPNIterExpr object
  107. * @ingroup pymod_pyrpn_RPNExprIter
  108. */
  109. PyObject* rpnif_new(PyTypeObject *subtype, PyObject* args, PyObject* kwds);
  110. /**@brief RpnIterExpr constructor
  111. * @param self New RPNIterExpr instance
  112. * @param args Positional arguments list
  113. * @param kwds Keywords arguments dict
  114. * @return 0 if no error else -1
  115. * @ingroup pymod_pyrpn_RPNExprIter
  116. */
  117. int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds);
  118. /**@brief RPNIterExpr constructor with a borrowed expression
  119. * @param borrowed_if Pointer on borrowed instance
  120. * @param mmap Pointer on borrowed python mmap object (NULL if deserialized instance)
  121. * @return 0 if no error else -1
  122. */
  123. PyObject* rpnif_init_borrowed(rpn_if_t *borrowed_if, PyObject *mmap);
  124. /**@brief RPNIterExpr __del__ method
  125. * @param self RPNExpr instance
  126. * @ingroup pymod_pyrpn_RPNExprIter
  127. */
  128. void rpnif_del(PyObject *self);
  129. /**@brief Buffer protocol request handler method
  130. * @param self RPNIterExpr instance
  131. * @param view A memoryview to fill depending on flags
  132. * @param flags Indicates the request type
  133. * @return -1 on error
  134. * @note Used by RPNIterExpr and RPNIFS (proper way to implement it is base class)
  135. * See python documentation at
  136. * https://docs.python.org/3/c-api/buffer.html#buffer-request-types
  137. * @ingroup pymod_pyrpn_RPNExprIter
  138. */
  139. int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags);
  140. /**@brief Buffer protocol request release method
  141. * @param self RPNIterExppr instance
  142. * @param view The memoryview to release (free what we filled)
  143. * See python documentation at
  144. * https://docs.python.org/3/c-api/buffer.html#buffer-request-types
  145. * @ingroup pymod_pyrpn_RPNExprIter
  146. */
  147. void rpnif_releasebuffer(PyObject *self, Py_buffer *view);
  148. /**@brief Return a named tuple of custom rif data
  149. * @param self RPNIterExpr instance
  150. * @return A RPNIterParams named tuple
  151. * @ingroup pymod_pyrpn_RPNExprIter
  152. */
  153. PyObject *rpnif_get_params(PyObject *self);
  154. /**@brief Set the mmap object used for data storage
  155. * @param self RPNIterExpr instance
  156. * @return None
  157. * @ingroup pymod_pyrpn_RPNExprIter
  158. */
  159. PyObject *rpnif_set_mmap(PyObject *self, PyObject *mm_obj);
  160. /**@brief Return a tuple with data buffer's shape
  161. * @param self RPNIterExpr instance
  162. * @return A new ref on a tuple
  163. * @ingroup pymod_pyrpn_RPNExprIter
  164. */
  165. PyObject *rpnif_shape(PyObject *self);
  166. /**@brief Runs an IF on given position
  167. * @param self RPNInterExpr instance
  168. * @param pos The start position
  169. * @return A new position
  170. * @ingroup pymod_pyrpn_RPNExprIter
  171. */
  172. PyObject *rpnif_step(PyObject *self, PyObject* pos);
  173. /**@brief Mutate the expressions in the IF
  174. * @note For X mutations, an expression will be choosen randomly and mutate between
  175. * 1 and X times, if mutations left to do we loop on expression choice.
  176. * @param self
  177. * @param args
  178. * @param kwargs
  179. * @return None
  180. */
  181. PyObject* rpnif_mutate(PyObject *self, PyObject *args, PyObject *kwargs);
  182. /**@brief Convert given arguments coordinates to position
  183. * @param self RPNIterExpr instance
  184. * @param argv Pointer on the array of arguments
  185. * @param argc Argument count
  186. * @return An integer
  187. */
  188. PyObject *rpnif_to_pos(PyObject *self, PyObject** argv, Py_ssize_t argc);
  189. /**@brief Convert given position to coordinates tuple
  190. * @param self RPNIterExpr instance
  191. * @param pos Position, as integer, to convert
  192. * @return A tuple
  193. */
  194. PyObject *rpnif_from_pos(PyObject *self, PyObject* pos);
  195. /**@brief RPNIterExpr __getstate__ method for pickling
  196. * @param cls RPNIterExpr type object
  197. * @param noargs Not an argument...
  198. * @return A bytes Python instance suitable as argument for
  199. * @ref rpnexpr_setstate
  200. * @ingroup pymod_pyrpn_RPNExprIter
  201. */
  202. PyObject* rpnif_getstate(PyObject *cls, PyObject *noargs);
  203. /**@brief RPNIterExpr __setstate__ method for pickling
  204. * @param cls RPNIterExpr type object
  205. * @param state Should by a bytes Python instance returned by @ref
  206. * rpnexpr_getstate
  207. * @return A bytes Python instance suitable as argument for
  208. * @ref rpnexpr_setstate
  209. * @ingroup pymod_pyrpn_RPNExprIter
  210. */
  211. PyObject* rpnif_setstate(PyObject *cls, PyObject *state);
  212. /**@brief RPNIterExpr.__repr__()
  213. * @param self RPNIterExpr instance
  214. * @return A string representation of the instance
  215. * @ingroup pymod_pyrpn_RPNExprIter
  216. */
  217. PyObject* rpnif_repr(PyObject *self);
  218. /**@brief RPNIterExpr.__str__()
  219. * @param self RPNIterExpr instance
  220. * @return A string representation of the instance
  221. * @ingroup pymod_pyrpn_RPNExprIter
  222. */
  223. PyObject* rpnif_str(PyObject *self);
  224. /**@brief RPNExpr.__len__() method
  225. * @param self RPNIterExpr instance
  226. * @return A integer with the number of tokens in expression
  227. * @ingroup pymod_pyrpn_RPNExprIter
  228. */
  229. Py_ssize_t rpnif_len(PyObject *self);
  230. /**@brief Sequence method for __getitem__ method
  231. *
  232. * Allow expressions access with integer indexes
  233. * @param self RPNIterExpr instance
  234. * @param idx Item index
  235. * @return Corresponding RPNExpr or raise IndexError
  236. * @ingroup pymod_pyrpn_RPNExprIter
  237. */
  238. PyObject* rpnif_expr_item(PyObject *self, Py_ssize_t idx);
  239. /**@brief Sequence method for __setitem__ method
  240. *
  241. * Allow to recompile an expressions using a str with integer indexes
  242. * @param self RPNIterExpr instance
  243. * @param idx Item index
  244. * @param elt The code (str) to compile in indicated expression
  245. * @return 0 if no error else -1
  246. * @ingroup pymod_pyrpn_RPNExprIter
  247. */
  248. int rpnif_expr_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt);
  249. /**@brief Mapping method to access expressions by name
  250. * @param self RPNIterExpr instance
  251. * @param key An expression name (depending on parameters)
  252. * @return The corresponding RPNExpr of raise KeyError
  253. * @ingroup pymod_pyrpn_RPNExprIter
  254. */
  255. PyObject* rpnif_subscript(PyObject *self, PyObject *key);
  256. /**@brief Mapping method to recompile an expression by name
  257. * @param self RPNIterExpr instance
  258. * @param key An expression name (depending on parameters)
  259. * @param elt The code (str) to compile in indicated expression
  260. * @return 0 if no error else -1
  261. * @ingroup pymod_pyrpn_RPNExprIter
  262. */
  263. int rpnif_ass_subscript(PyObject *self, PyObject *key, PyObject *elt);
  264. /**@brief Mimics dict.keys() method
  265. * @param self RPNIterExpr instance
  266. * @return A tuple with expressions name
  267. * @ingroup pymod_pyrpn_RPNExprIter */
  268. PyObject *rpnif_keys(PyObject *self);
  269. /**@brief Mimics dict.values() method
  270. * @param self RPNIterExpr instance
  271. * @return A tuple with RPNExpr instances
  272. * @ingroup pymod_pyrpn_RPNExprIter */
  273. PyObject *rpnif_values(PyObject *self);
  274. /**@brief Mimics dict.items() method
  275. * @param self RPNIterExpr instance
  276. * @return A tuple with tuples(key, value)
  277. * @ingroup pymod_pyrpn_RPNExprIter */
  278. PyObject *rpnif_items(PyObject *self);
  279. /**@brief Returns rpn_if_params given arguments
  280. * @param pos_flag a position flag
  281. * @param res_flag a result flag
  282. * @param size_lim a tuple with size limits
  283. * @param const_values a tuple wiith constant values
  284. * @param stack_size a stack size
  285. */
  286. rpn_if_param_t *_rpnif_get_params(unsigned short pos_flag, unsigned short res_flag,
  287. PyObject *size_lim, PyObject *const_values,
  288. unsigned short stack_size);
  289. /**@brief Converts rpn_if_params to named tuple
  290. * @param params The rpnif params
  291. * @return A named tuple
  292. */
  293. PyObject *_rpnif_params_to_tuple(const rpn_if_param_t *params);
  294. /**@brief Implementation of both RPNIterExpr.to_pos and RPNIFS.to_pos */
  295. PyObject *_rpnif_to_pos(rpn_if_default_data_t *rif_data, PyObject** argv, Py_ssize_t argc);
  296. /**@brief Implementation of bot RPNIterExpr.to_pos and RPNIFS.from_pos */
  297. PyObject *_rpnif_from_pos(rpn_if_default_data_t *rif_data, PyObject* _pos);
  298. /**@brief Buffer protocol request handler method when no python mmap exist
  299. * (deserialized instance)
  300. * @param self RPNIterExpr instance
  301. * @param view A memoryview to fill depending on flags
  302. * @param flags Indicates the request type
  303. * @return -1 on error
  304. * @note Used by RPNIterExpr and RPNIFS (proper way to implement it is base class)
  305. * See python documentation at
  306. * https://docs.python.org/3/c-api/buffer.html#buffer-request-types
  307. * @ingroup pymod_pyrpn_RPNExprIter
  308. */
  309. int _rpnif_getbuffer_nopymap(PyObject *self, const rpn_if_param_t *params,
  310. void *buf, Py_buffer *view, int flags);
  311. void _rpnif_releasebuffer_nopymap(PyObject *self, Py_buffer *view);
  312. /**@todo doc */
  313. int _rpnif_init_expr_tuple(PyRPNIterExpr_t *expr_self);
  314. #endif