term.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. Term_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
  17. {
  18. static const char *kwlist[] = { "variable", "coefficient", 0 };
  19. PyObject* pyvar;
  20. PyObject* pycoeff = 0;
  21. if( !PyArg_ParseTupleAndKeywords(
  22. args, kwargs, "O|O:__new__", const_cast<char**>( kwlist ),
  23. &pyvar, &pycoeff ) )
  24. return 0;
  25. if( !Variable::TypeCheck( pyvar ) )
  26. return py_expected_type_fail( pyvar, "Variable" );
  27. double coefficient = 1.0;
  28. if( pycoeff && !convert_to_double( pycoeff, coefficient ) )
  29. return 0;
  30. PyObject* pyterm = PyType_GenericNew( type, args, kwargs );
  31. if( !pyterm )
  32. return 0;
  33. Term* self = reinterpret_cast<Term*>( pyterm );
  34. self->variable = newref( pyvar );
  35. self->coefficient = coefficient;
  36. return pyterm;
  37. }
  38. static void
  39. Term_clear( Term* self )
  40. {
  41. Py_CLEAR( self->variable );
  42. }
  43. static int
  44. Term_traverse( Term* self, visitproc visit, void* arg )
  45. {
  46. Py_VISIT( self->variable );
  47. return 0;
  48. }
  49. static void
  50. Term_dealloc( Term* self )
  51. {
  52. PyObject_GC_UnTrack( self );
  53. Term_clear( self );
  54. Py_TYPE( self )->tp_free( pyobject_cast( self ) );
  55. }
  56. static PyObject*
  57. Term_repr( Term* self )
  58. {
  59. std::stringstream stream;
  60. stream << self->coefficient << " * ";
  61. stream << reinterpret_cast<Variable*>( self->variable )->variable.name();
  62. return FROM_STRING( stream.str().c_str() );
  63. }
  64. static PyObject*
  65. Term_variable( Term* self )
  66. {
  67. return newref( self->variable );
  68. }
  69. static PyObject*
  70. Term_coefficient( Term* self )
  71. {
  72. return PyFloat_FromDouble( self->coefficient );
  73. }
  74. static PyObject*
  75. Term_value( Term* self )
  76. {
  77. Variable* pyvar = reinterpret_cast<Variable*>( self->variable );
  78. return PyFloat_FromDouble( self->coefficient * pyvar->variable.value() );
  79. }
  80. static PyObject*
  81. Term_add( PyObject* first, PyObject* second )
  82. {
  83. return BinaryInvoke<BinaryAdd, Term>()( first, second );
  84. }
  85. static PyObject*
  86. Term_sub( PyObject* first, PyObject* second )
  87. {
  88. return BinaryInvoke<BinarySub, Term>()( first, second );
  89. }
  90. static PyObject*
  91. Term_mul( PyObject* first, PyObject* second )
  92. {
  93. return BinaryInvoke<BinaryMul, Term>()( first, second );
  94. }
  95. static PyObject*
  96. Term_div( PyObject* first, PyObject* second )
  97. {
  98. return BinaryInvoke<BinaryDiv, Term>()( first, second );
  99. }
  100. static PyObject*
  101. Term_neg( PyObject* value )
  102. {
  103. return UnaryInvoke<UnaryNeg, Term>()( value );
  104. }
  105. static PyObject*
  106. Term_richcmp( PyObject* first, PyObject* second, int op )
  107. {
  108. switch( op )
  109. {
  110. case Py_EQ:
  111. return BinaryInvoke<CmpEQ, Term>()( first, second );
  112. case Py_LE:
  113. return BinaryInvoke<CmpLE, Term>()( first, second );
  114. case Py_GE:
  115. return BinaryInvoke<CmpGE, Term>()( first, second );
  116. default:
  117. break;
  118. }
  119. PyErr_Format(
  120. PyExc_TypeError,
  121. "unsupported operand type(s) for %s: "
  122. "'%.100s' and '%.100s'",
  123. pyop_str( op ),
  124. first->ob_type->tp_name,
  125. second->ob_type->tp_name
  126. );
  127. return 0;
  128. }
  129. static PyMethodDef
  130. Term_methods[] = {
  131. { "variable", ( PyCFunction )Term_variable, METH_NOARGS,
  132. "Get the variable for the term." },
  133. { "coefficient", ( PyCFunction )Term_coefficient, METH_NOARGS,
  134. "Get the coefficient for the term." },
  135. { "value", ( PyCFunction )Term_value, METH_NOARGS,
  136. "Get the value for the term." },
  137. { 0 } // sentinel
  138. };
  139. static PyNumberMethods
  140. Term_as_number = {
  141. (binaryfunc)Term_add, /* nb_add */
  142. (binaryfunc)Term_sub, /* nb_subtract */
  143. (binaryfunc)Term_mul, /* nb_multiply */
  144. #if PY_MAJOR_VERSION < 3
  145. (binaryfunc)Term_div, /* nb_divide */
  146. #endif
  147. 0, /* nb_remainder */
  148. 0, /* nb_divmod */
  149. 0, /* nb_power */
  150. (unaryfunc)Term_neg, /* nb_negative */
  151. 0, /* nb_positive */
  152. 0, /* nb_absolute */
  153. #if PY_MAJOR_VERSION >= 3
  154. 0, /* nb_bool */
  155. #else
  156. 0, /* nb_nonzero */
  157. #endif
  158. 0, /* nb_invert */
  159. 0, /* nb_lshift */
  160. 0, /* nb_rshift */
  161. 0, /* nb_and */
  162. 0, /* nb_xor */
  163. (binaryfunc)0, /* nb_or */
  164. #if PY_MAJOR_VERSION < 3
  165. 0, /* nb_coerce */
  166. #endif
  167. 0, /* nb_int */
  168. 0, /* nb_long */
  169. 0, /* nb_float */
  170. #if PY_MAJOR_VERSION < 3
  171. 0, /* nb_oct */
  172. 0, /* nb_hex */
  173. #endif
  174. 0, /* nb_inplace_add */
  175. 0, /* nb_inplace_subtract */
  176. 0, /* nb_inplace_multiply */
  177. #if PY_MAJOR_VERSION < 3
  178. 0, /* nb_inplace_divide */
  179. #endif
  180. 0, /* nb_inplace_remainder */
  181. 0, /* nb_inplace_power */
  182. 0, /* nb_inplace_lshift */
  183. 0, /* nb_inplace_rshift */
  184. 0, /* nb_inplace_and */
  185. 0, /* nb_inplace_xor */
  186. 0, /* nb_inplace_or */
  187. (binaryfunc)0, /* nb_floor_divide */
  188. (binaryfunc)Term_div, /* nb_true_divide */
  189. 0, /* nb_inplace_floor_divide */
  190. 0, /* nb_inplace_true_divide */
  191. #if PY_VERSION_HEX >= 0x02050000
  192. (unaryfunc)0, /* nb_index */
  193. #endif
  194. #if PY_VERSION_HEX >= 0x03050000
  195. (binaryfunc)0, /* nb_matrix_multiply */
  196. (binaryfunc)0, /* nb_inplace_matrix_multiply */
  197. #endif
  198. };
  199. PyTypeObject Term_Type = {
  200. PyVarObject_HEAD_INIT( &PyType_Type, 0 )
  201. "kiwisolver.Term", /* tp_name */
  202. sizeof( Term ), /* tp_basicsize */
  203. 0, /* tp_itemsize */
  204. (destructor)Term_dealloc, /* tp_dealloc */
  205. (printfunc)0, /* tp_print */
  206. (getattrfunc)0, /* tp_getattr */
  207. (setattrfunc)0, /* tp_setattr */
  208. #if PY_VERSION_HEX >= 0x03050000
  209. ( PyAsyncMethods* )0, /* tp_as_async */
  210. #elif PY_VERSION_HEX >= 0x03000000
  211. ( void* ) 0, /* tp_reserved */
  212. #else
  213. ( cmpfunc )0, /* tp_compare */
  214. #endif
  215. (reprfunc)Term_repr, /* tp_repr */
  216. (PyNumberMethods*)&Term_as_number, /* tp_as_number */
  217. (PySequenceMethods*)0, /* tp_as_sequence */
  218. (PyMappingMethods*)0, /* tp_as_mapping */
  219. (hashfunc)0, /* tp_hash */
  220. (ternaryfunc)0, /* tp_call */
  221. (reprfunc)0, /* tp_str */
  222. (getattrofunc)0, /* tp_getattro */
  223. (setattrofunc)0, /* tp_setattro */
  224. (PyBufferProcs*)0, /* tp_as_buffer */
  225. #if PY_MAJOR_VERSION >= 3
  226. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE, /* tp_flags */
  227. #else
  228. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */
  229. #endif
  230. 0, /* Documentation string */
  231. (traverseproc)Term_traverse, /* tp_traverse */
  232. (inquiry)Term_clear, /* tp_clear */
  233. (richcmpfunc)Term_richcmp, /* tp_richcompare */
  234. 0, /* tp_weaklistoffset */
  235. (getiterfunc)0, /* tp_iter */
  236. (iternextfunc)0, /* tp_iternext */
  237. (struct PyMethodDef*)Term_methods, /* tp_methods */
  238. (struct PyMemberDef*)0, /* tp_members */
  239. 0, /* tp_getset */
  240. 0, /* tp_base */
  241. 0, /* tp_dict */
  242. (descrgetfunc)0, /* tp_descr_get */
  243. (descrsetfunc)0, /* tp_descr_set */
  244. 0, /* tp_dictoffset */
  245. (initproc)0, /* tp_init */
  246. (allocfunc)PyType_GenericAlloc, /* tp_alloc */
  247. (newfunc)Term_new, /* tp_new */
  248. (freefunc)PyObject_GC_Del, /* tp_free */
  249. (inquiry)0, /* tp_is_gc */
  250. 0, /* tp_bases */
  251. 0, /* tp_mro */
  252. 0, /* tp_cache */
  253. 0, /* tp_subclasses */
  254. 0, /* tp_weaklist */
  255. (destructor)0 /* tp_del */
  256. };
  257. int import_term()
  258. {
  259. return PyType_Ready( &Term_Type );
  260. }