expression.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) 2013-2017, Nucleic Development Team.
  3. |
  4. | Distributed under the terms of the Modified BSD License.
  5. |
  6. | The full license is in the file COPYING.txt, distributed with this software.
  7. |----------------------------------------------------------------------------*/
  8. #include <sstream>
  9. #include <Python.h>
  10. #include "pythonhelpers.h"
  11. #include "symbolics.h"
  12. #include "types.h"
  13. #include "util.h"
  14. using namespace PythonHelpers;
  15. static PyObject*
  16. Expression_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
  17. {
  18. static const char *kwlist[] = { "terms", "constant", 0 };
  19. PyObject* pyterms;
  20. PyObject* pyconstant = 0;
  21. if( !PyArg_ParseTupleAndKeywords(
  22. args, kwargs, "O|O:__new__", const_cast<char**>( kwlist ),
  23. &pyterms, &pyconstant ) )
  24. return 0;
  25. PyObjectPtr terms( PySequence_Tuple( pyterms ) );
  26. if( !terms )
  27. return 0;
  28. Py_ssize_t end = PyTuple_GET_SIZE( terms.get() );
  29. for( Py_ssize_t i = 0; i < end; ++i )
  30. {
  31. PyObject* item = PyTuple_GET_ITEM( terms.get(), i );
  32. if( !Term::TypeCheck( item ) )
  33. return py_expected_type_fail( item, "Term" );
  34. }
  35. double constant = 0.0;
  36. if( pyconstant && !convert_to_double( pyconstant, constant ) )
  37. return 0;
  38. PyObject* pyexpr = PyType_GenericNew( type, args, kwargs );
  39. if( !pyexpr )
  40. return 0;
  41. Expression* self = reinterpret_cast<Expression*>( pyexpr );
  42. self->terms = terms.release();
  43. self->constant = constant;
  44. return pyexpr;
  45. }
  46. static void
  47. Expression_clear( Expression* self )
  48. {
  49. Py_CLEAR( self->terms );
  50. }
  51. static int
  52. Expression_traverse( Expression* self, visitproc visit, void* arg )
  53. {
  54. Py_VISIT( self->terms );
  55. return 0;
  56. }
  57. static void
  58. Expression_dealloc( Expression* self )
  59. {
  60. PyObject_GC_UnTrack( self );
  61. Expression_clear( self );
  62. Py_TYPE( self )->tp_free( pyobject_cast( self ) );
  63. }
  64. static PyObject*
  65. Expression_repr( Expression* self )
  66. {
  67. std::stringstream stream;
  68. Py_ssize_t end = PyTuple_GET_SIZE( self->terms );
  69. for( Py_ssize_t i = 0; i < end; ++i )
  70. {
  71. PyObject* item = PyTuple_GET_ITEM( self->terms, i );
  72. Term* term = reinterpret_cast<Term*>( item );
  73. stream << term->coefficient << " * ";
  74. stream << reinterpret_cast<Variable*>( term->variable )->variable.name();
  75. stream << " + ";
  76. }
  77. stream << self->constant;
  78. return FROM_STRING( stream.str().c_str() );
  79. }
  80. static PyObject*
  81. Expression_terms( Expression* self )
  82. {
  83. return newref( self->terms );
  84. }
  85. static PyObject*
  86. Expression_constant( Expression* self )
  87. {
  88. return PyFloat_FromDouble( self->constant );
  89. }
  90. static PyObject*
  91. Expression_value( Expression* self )
  92. {
  93. double result = self->constant;
  94. Py_ssize_t size = PyTuple_GET_SIZE( self->terms );
  95. for( Py_ssize_t i = 0; i < size; ++i )
  96. {
  97. PyObject* item = PyTuple_GET_ITEM( self->terms, i );
  98. Term* term = reinterpret_cast<Term*>( item );
  99. Variable* pyvar = reinterpret_cast<Variable*>( term->variable );
  100. result += term->coefficient * pyvar->variable.value();
  101. }
  102. return PyFloat_FromDouble( result );
  103. }
  104. static PyObject*
  105. Expression_add( PyObject* first, PyObject* second )
  106. {
  107. return BinaryInvoke<BinaryAdd, Expression>()( first, second );
  108. }
  109. static PyObject*
  110. Expression_sub( PyObject* first, PyObject* second )
  111. {
  112. return BinaryInvoke<BinarySub, Expression>()( first, second );
  113. }
  114. static PyObject*
  115. Expression_mul( PyObject* first, PyObject* second )
  116. {
  117. return BinaryInvoke<BinaryMul, Expression>()( first, second );
  118. }
  119. static PyObject*
  120. Expression_div( PyObject* first, PyObject* second )
  121. {
  122. return BinaryInvoke<BinaryDiv, Expression>()( first, second );
  123. }
  124. static PyObject*
  125. Expression_neg( PyObject* value )
  126. {
  127. return UnaryInvoke<UnaryNeg, Expression>()( value );
  128. }
  129. static PyObject*
  130. Expression_richcmp( PyObject* first, PyObject* second, int op )
  131. {
  132. switch( op )
  133. {
  134. case Py_EQ:
  135. return BinaryInvoke<CmpEQ, Expression>()( first, second );
  136. case Py_LE:
  137. return BinaryInvoke<CmpLE, Expression>()( first, second );
  138. case Py_GE:
  139. return BinaryInvoke<CmpGE, Expression>()( first, second );
  140. default:
  141. break;
  142. }
  143. PyErr_Format(
  144. PyExc_TypeError,
  145. "unsupported operand type(s) for %s: "
  146. "'%.100s' and '%.100s'",
  147. pyop_str( op ),
  148. first->ob_type->tp_name,
  149. second->ob_type->tp_name
  150. );
  151. return 0;
  152. }
  153. static PyMethodDef
  154. Expression_methods[] = {
  155. { "terms", ( PyCFunction )Expression_terms, METH_NOARGS,
  156. "Get the tuple of terms for the expression." },
  157. { "constant", ( PyCFunction )Expression_constant, METH_NOARGS,
  158. "Get the constant for the expression." },
  159. { "value", ( PyCFunction )Expression_value, METH_NOARGS,
  160. "Get the value for the expression." },
  161. { 0 } // sentinel
  162. };
  163. static PyNumberMethods
  164. Expression_as_number = {
  165. (binaryfunc)Expression_add, /* nb_add */
  166. (binaryfunc)Expression_sub, /* nb_subtract */
  167. (binaryfunc)Expression_mul, /* nb_multiply */
  168. #if PY_MAJOR_VERSION < 3
  169. (binaryfunc)Expression_div, /* nb_divide */
  170. #endif
  171. 0, /* nb_remainder */
  172. 0, /* nb_divmod */
  173. 0, /* nb_power */
  174. (unaryfunc)Expression_neg, /* nb_negative */
  175. 0, /* nb_positive */
  176. 0, /* nb_absolute */
  177. #if PY_MAJOR_VERSION >= 3
  178. 0, /* nb_bool */
  179. #else
  180. 0, /* nb_nonzero */
  181. #endif
  182. 0, /* nb_invert */
  183. 0, /* nb_lshift */
  184. 0, /* nb_rshift */
  185. 0, /* nb_and */
  186. 0, /* nb_xor */
  187. (binaryfunc)0, /* nb_or */
  188. #if PY_MAJOR_VERSION < 3
  189. 0, /* nb_coerce */
  190. #endif
  191. 0, /* nb_int */
  192. #if PY_MAJOR_VERSION >= 3
  193. (void *)0, /* nb_reserved */
  194. #else
  195. 0, /* nb_long */
  196. #endif
  197. 0, /* nb_float */
  198. #if PY_MAJOR_VERSION < 3
  199. 0, /* nb_oct */
  200. 0, /* nb_hex */
  201. #endif
  202. 0, /* nb_inplace_add */
  203. 0, /* nb_inplace_subtract */
  204. 0, /* nb_inplace_multiply */
  205. #if PY_MAJOR_VERSION < 3
  206. 0, /* nb_inplace_divide */
  207. #endif
  208. 0, /* nb_inplace_remainder */
  209. 0, /* nb_inplace_power */
  210. 0, /* nb_inplace_lshift */
  211. 0, /* nb_inplace_rshift */
  212. 0, /* nb_inplace_and */
  213. 0, /* nb_inplace_xor */
  214. 0, /* nb_inplace_or */
  215. (binaryfunc)0, /* nb_floor_divide */
  216. (binaryfunc)Expression_div, /* nb_true_divide */
  217. 0, /* nb_inplace_floor_divide */
  218. 0, /* nb_inplace_true_divide */
  219. #if PY_VERSION_HEX >= 0x02050000
  220. (unaryfunc)0, /* nb_index */
  221. #endif
  222. #if PY_VERSION_HEX >= 0x03050000
  223. (binaryfunc)0, /* nb_matrix_multiply */
  224. (binaryfunc)0, /* nb_inplace_matrix_multiply */
  225. #endif
  226. };
  227. PyTypeObject Expression_Type = {
  228. PyVarObject_HEAD_INIT( &PyType_Type, 0 )
  229. "kiwisolver.Expression", /* tp_name */
  230. sizeof( Expression ), /* tp_basicsize */
  231. 0, /* tp_itemsize */
  232. (destructor)Expression_dealloc, /* tp_dealloc */
  233. (printfunc)0, /* tp_print */
  234. (getattrfunc)0, /* tp_getattr */
  235. (setattrfunc)0, /* tp_setattr */
  236. #if PY_VERSION_HEX >= 0x03050000
  237. ( PyAsyncMethods* )0, /* tp_as_async */
  238. #elif PY_VERSION_HEX >= 0x03000000
  239. ( void* ) 0, /* tp_reserved */
  240. #else
  241. ( cmpfunc )0, /* tp_compare */
  242. #endif
  243. (reprfunc)Expression_repr, /* tp_repr */
  244. (PyNumberMethods*)&Expression_as_number,/* tp_as_number */
  245. (PySequenceMethods*)0, /* tp_as_sequence */
  246. (PyMappingMethods*)0, /* tp_as_mapping */
  247. (hashfunc)0, /* tp_hash */
  248. (ternaryfunc)0, /* tp_call */
  249. (reprfunc)0, /* tp_str */
  250. (getattrofunc)0, /* tp_getattro */
  251. (setattrofunc)0, /* tp_setattro */
  252. (PyBufferProcs*)0, /* tp_as_buffer */
  253. #if PY_MAJOR_VERSION >= 3
  254. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE,
  255. #else
  256. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */
  257. #endif
  258. 0, /* Documentation string */
  259. (traverseproc)Expression_traverse, /* tp_traverse */
  260. (inquiry)Expression_clear, /* tp_clear */
  261. (richcmpfunc)Expression_richcmp, /* tp_richcompare */
  262. 0, /* tp_weaklistoffset */
  263. (getiterfunc)0, /* tp_iter */
  264. (iternextfunc)0, /* tp_iternext */
  265. (struct PyMethodDef*)Expression_methods,/* tp_methods */
  266. (struct PyMemberDef*)0, /* tp_members */
  267. 0, /* tp_getset */
  268. 0, /* tp_base */
  269. 0, /* tp_dict */
  270. (descrgetfunc)0, /* tp_descr_get */
  271. (descrsetfunc)0, /* tp_descr_set */
  272. 0, /* tp_dictoffset */
  273. (initproc)0, /* tp_init */
  274. (allocfunc)PyType_GenericAlloc, /* tp_alloc */
  275. (newfunc)Expression_new, /* tp_new */
  276. (freefunc)PyObject_GC_Del, /* tp_free */
  277. (inquiry)0, /* tp_is_gc */
  278. 0, /* tp_bases */
  279. 0, /* tp_mro */
  280. 0, /* tp_cache */
  281. 0, /* tp_subclasses */
  282. 0, /* tp_weaklist */
  283. (destructor)0 /* tp_del */
  284. };
  285. int import_expression()
  286. {
  287. return PyType_Ready( &Expression_Type );
  288. }