symbolics.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) 2013-2019, Nucleic Development Team.
  3. |
  4. | Distributed under the terms of the Modified BSD License.
  5. |
  6. | The full license is in the file LICENSE, distributed with this software.
  7. |----------------------------------------------------------------------------*/
  8. #pragma once
  9. #include <cppy/cppy.h>
  10. #include "types.h"
  11. #include "util.h"
  12. namespace kiwisolver
  13. {
  14. template<typename Op, typename T>
  15. struct UnaryInvoke
  16. {
  17. PyObject* operator()( PyObject* value )
  18. {
  19. return Op()( reinterpret_cast<T*>( value ) );
  20. }
  21. };
  22. template<typename Op, typename T>
  23. struct BinaryInvoke
  24. {
  25. PyObject* operator()( PyObject* first, PyObject* second )
  26. {
  27. if( T::TypeCheck( first ) )
  28. return invoke<Normal>( reinterpret_cast<T*>( first ), second );
  29. return invoke<Reverse>( reinterpret_cast<T*>( second ), first );
  30. }
  31. struct Normal
  32. {
  33. template<typename U>
  34. PyObject* operator()( T* primary, U secondary )
  35. {
  36. return Op()( primary, secondary );
  37. }
  38. };
  39. struct Reverse
  40. {
  41. template<typename U>
  42. PyObject* operator()( T* primary, U secondary )
  43. {
  44. return Op()( secondary, primary );
  45. }
  46. };
  47. template<typename Invk>
  48. PyObject* invoke( T* primary, PyObject* secondary )
  49. {
  50. if( Expression::TypeCheck( secondary ) )
  51. return Invk()( primary, reinterpret_cast<Expression*>( secondary ) );
  52. if( Term::TypeCheck( secondary ) )
  53. return Invk()( primary, reinterpret_cast<Term*>( secondary ) );
  54. if( Variable::TypeCheck( secondary ) )
  55. return Invk()( primary, reinterpret_cast<Variable*>( secondary ) );
  56. if( PyFloat_Check( secondary ) )
  57. return Invk()( primary, PyFloat_AS_DOUBLE( secondary ) );
  58. if( PyLong_Check( secondary ) )
  59. {
  60. double v = PyLong_AsDouble( secondary );
  61. if( v == -1 && PyErr_Occurred() )
  62. return 0;
  63. return Invk()( primary, v );
  64. }
  65. Py_RETURN_NOTIMPLEMENTED;
  66. }
  67. };
  68. struct BinaryMul
  69. {
  70. template<typename T, typename U>
  71. PyObject* operator()( T first, U second )
  72. {
  73. Py_RETURN_NOTIMPLEMENTED;
  74. }
  75. };
  76. template<> inline
  77. PyObject* BinaryMul::operator()( Variable* first, double second )
  78. {
  79. PyObject* pyterm = PyType_GenericNew( Term::TypeObject, 0, 0 );
  80. if( !pyterm )
  81. return 0;
  82. Term* term = reinterpret_cast<Term*>( pyterm );
  83. term->variable = cppy::incref( pyobject_cast( first ) );
  84. term->coefficient = second;
  85. return pyterm;
  86. }
  87. template<> inline
  88. PyObject* BinaryMul::operator()( Term* first, double second )
  89. {
  90. PyObject* pyterm = PyType_GenericNew( Term::TypeObject, 0, 0 );
  91. if( !pyterm )
  92. return 0;
  93. Term* term = reinterpret_cast<Term*>( pyterm );
  94. term->variable = cppy::incref( first->variable );
  95. term->coefficient = first->coefficient * second;
  96. return pyterm;
  97. }
  98. template<> inline
  99. PyObject* BinaryMul::operator()( Expression* first, double second )
  100. {
  101. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  102. if( !pyexpr )
  103. return 0;
  104. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  105. cppy::ptr terms( PyTuple_New( PyTuple_GET_SIZE( first->terms ) ) );
  106. if( !terms )
  107. return 0;
  108. Py_ssize_t end = PyTuple_GET_SIZE( first->terms );
  109. for( Py_ssize_t i = 0; i < end; ++i ) // memset 0 for safe error return
  110. PyTuple_SET_ITEM( terms.get(), i, 0 );
  111. for( Py_ssize_t i = 0; i < end; ++i )
  112. {
  113. PyObject* item = PyTuple_GET_ITEM( first->terms, i );
  114. PyObject* term = BinaryMul()( reinterpret_cast<Term*>( item ), second );
  115. if( !term )
  116. return 0;
  117. PyTuple_SET_ITEM( terms.get(), i, term );
  118. }
  119. expr->terms = terms.release();
  120. expr->constant = first->constant * second;
  121. return pyexpr.release();
  122. }
  123. template<> inline
  124. PyObject* BinaryMul::operator()( double first, Variable* second )
  125. {
  126. return operator()( second, first );
  127. }
  128. template<> inline
  129. PyObject* BinaryMul::operator()( double first, Term* second )
  130. {
  131. return operator()( second, first );
  132. }
  133. template<> inline
  134. PyObject* BinaryMul::operator()( double first, Expression* second )
  135. {
  136. return operator()( second, first );
  137. }
  138. struct BinaryDiv
  139. {
  140. template<typename T, typename U>
  141. PyObject* operator()( T first, U second )
  142. {
  143. Py_RETURN_NOTIMPLEMENTED;
  144. }
  145. };
  146. template<> inline
  147. PyObject* BinaryDiv::operator()( Variable* first, double second )
  148. {
  149. if( second == 0.0 )
  150. {
  151. PyErr_SetString( PyExc_ZeroDivisionError, "float division by zero" );
  152. return 0;
  153. }
  154. return BinaryMul()( first, 1.0 / second );
  155. }
  156. template<> inline
  157. PyObject* BinaryDiv::operator()( Term* first, double second )
  158. {
  159. if( second == 0.0 )
  160. {
  161. PyErr_SetString( PyExc_ZeroDivisionError, "float division by zero" );
  162. return 0;
  163. }
  164. return BinaryMul()( first, 1.0 / second );
  165. }
  166. template<> inline
  167. PyObject* BinaryDiv::operator()( Expression* first, double second )
  168. {
  169. if( second == 0.0 )
  170. {
  171. PyErr_SetString( PyExc_ZeroDivisionError, "float division by zero" );
  172. return 0;
  173. }
  174. return BinaryMul()( first, 1.0 / second );
  175. }
  176. struct UnaryNeg
  177. {
  178. template<typename T>
  179. PyObject* operator()( T value )
  180. {
  181. Py_RETURN_NOTIMPLEMENTED;
  182. }
  183. };
  184. template<> inline
  185. PyObject* UnaryNeg::operator()( Variable* value )
  186. {
  187. return BinaryMul()( value, -1.0 );
  188. }
  189. template<> inline
  190. PyObject* UnaryNeg::operator()( Term* value )
  191. {
  192. return BinaryMul()( value, -1.0 );
  193. }
  194. template<> inline
  195. PyObject* UnaryNeg::operator()( Expression* value )
  196. {
  197. return BinaryMul()( value, -1.0 );
  198. }
  199. struct BinaryAdd
  200. {
  201. template<typename T, typename U>
  202. PyObject* operator()( T first, U second )
  203. {
  204. Py_RETURN_NOTIMPLEMENTED;
  205. }
  206. };
  207. template<> inline
  208. PyObject* BinaryAdd::operator()( Expression* first, Expression* second )
  209. {
  210. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  211. if( !pyexpr )
  212. return 0;
  213. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  214. expr->constant = first->constant + second->constant;
  215. expr->terms = PySequence_Concat( first->terms, second->terms );
  216. if( !expr->terms )
  217. return 0;
  218. return pyexpr.release();
  219. }
  220. template<> inline
  221. PyObject* BinaryAdd::operator()( Expression* first, Term* second )
  222. {
  223. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  224. if( !pyexpr )
  225. return 0;
  226. PyObject* terms = PyTuple_New( PyTuple_GET_SIZE( first->terms ) + 1 );
  227. if( !terms )
  228. return 0;
  229. Py_ssize_t end = PyTuple_GET_SIZE( first->terms );
  230. for( Py_ssize_t i = 0; i < end; ++i )
  231. {
  232. PyObject* item = PyTuple_GET_ITEM( first->terms, i );
  233. PyTuple_SET_ITEM( terms, i, cppy::incref( item ) );
  234. }
  235. PyTuple_SET_ITEM( terms, end, cppy::incref( pyobject_cast( second ) ) );
  236. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  237. expr->terms = terms;
  238. expr->constant = first->constant;
  239. return pyexpr.release();
  240. }
  241. template<> inline
  242. PyObject* BinaryAdd::operator()( Expression* first, Variable* second )
  243. {
  244. cppy::ptr temp( BinaryMul()( second, 1.0 ) );
  245. if( !temp )
  246. return 0;
  247. return operator()( first, reinterpret_cast<Term*>( temp.get() ) );
  248. }
  249. template<> inline
  250. PyObject* BinaryAdd::operator()( Expression* first, double second )
  251. {
  252. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  253. if( !pyexpr )
  254. return 0;
  255. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  256. expr->terms = cppy::incref( first->terms );
  257. expr->constant = first->constant + second;
  258. return pyexpr.release();
  259. }
  260. template<> inline
  261. PyObject* BinaryAdd::operator()( Term* first, double second )
  262. {
  263. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  264. if( !pyexpr )
  265. return 0;
  266. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  267. expr->constant = second;
  268. expr->terms = PyTuple_Pack( 1, first );
  269. if( !expr->terms )
  270. return 0;
  271. return pyexpr.release();
  272. }
  273. template<> inline
  274. PyObject* BinaryAdd::operator()( Term* first, Expression* second )
  275. {
  276. return operator()( second, first );
  277. }
  278. template<> inline
  279. PyObject* BinaryAdd::operator()( Term* first, Term* second )
  280. {
  281. cppy::ptr pyexpr( PyType_GenericNew( Expression::TypeObject, 0, 0 ) );
  282. if( !pyexpr )
  283. return 0;
  284. Expression* expr = reinterpret_cast<Expression*>( pyexpr.get() );
  285. expr->constant = 0.0;
  286. expr->terms = PyTuple_Pack( 2, first, second );
  287. if( !expr->terms )
  288. return 0;
  289. return pyexpr.release();
  290. }
  291. template<> inline
  292. PyObject* BinaryAdd::operator()( Term* first, Variable* second )
  293. {
  294. cppy::ptr temp( BinaryMul()( second, 1.0 ) );
  295. if( !temp )
  296. return 0;
  297. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  298. }
  299. template<> inline
  300. PyObject* BinaryAdd::operator()( Variable* first, double second )
  301. {
  302. cppy::ptr temp( BinaryMul()( first, 1.0 ) );
  303. if( !temp )
  304. return 0;
  305. return operator()( reinterpret_cast<Term*>( temp.get() ), second );
  306. }
  307. template<> inline
  308. PyObject* BinaryAdd::operator()( Variable* first, Variable* second )
  309. {
  310. cppy::ptr temp( BinaryMul()( first, 1.0 ) );
  311. if( !temp )
  312. return 0;
  313. return operator()( reinterpret_cast<Term*>( temp.get() ), second );
  314. }
  315. template<> inline
  316. PyObject* BinaryAdd::operator()( Variable* first, Term* second )
  317. {
  318. cppy::ptr temp( BinaryMul()( first, 1.0 ) );
  319. if( !temp )
  320. return 0;
  321. return operator()( reinterpret_cast<Term*>( temp.get() ), second );
  322. }
  323. template<> inline
  324. PyObject* BinaryAdd::operator()( Variable* first, Expression* second )
  325. {
  326. cppy::ptr temp( BinaryMul()( first, 1.0 ) );
  327. if( !temp )
  328. return 0;
  329. return operator()( reinterpret_cast<Term*>( temp.get() ), second );
  330. }
  331. template<> inline
  332. PyObject* BinaryAdd::operator()( double first, Variable* second )
  333. {
  334. return operator()( second, first );
  335. }
  336. template<> inline
  337. PyObject* BinaryAdd::operator()( double first, Term* second )
  338. {
  339. return operator()( second, first );
  340. }
  341. template<> inline
  342. PyObject* BinaryAdd::operator()( double first, Expression* second )
  343. {
  344. return operator()( second, first );
  345. }
  346. struct BinarySub
  347. {
  348. template<typename T, typename U>
  349. PyObject* operator()( T first, U second )
  350. {
  351. Py_RETURN_NOTIMPLEMENTED;
  352. }
  353. };
  354. template<> inline
  355. PyObject* BinarySub::operator()( Variable* first, double second )
  356. {
  357. return BinaryAdd()( first, -second );
  358. }
  359. template<> inline
  360. PyObject* BinarySub::operator()( Variable* first, Variable* second )
  361. {
  362. cppy::ptr temp( UnaryNeg()( second ) );
  363. if( !temp )
  364. return 0;
  365. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  366. }
  367. template<> inline
  368. PyObject* BinarySub::operator()( Variable* first, Term* second )
  369. {
  370. cppy::ptr temp( UnaryNeg()( second ) );
  371. if( !temp )
  372. return 0;
  373. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  374. }
  375. template<> inline
  376. PyObject* BinarySub::operator()( Variable* first, Expression* second )
  377. {
  378. cppy::ptr temp( UnaryNeg()( second ) );
  379. if( !temp )
  380. return 0;
  381. return BinaryAdd()( first, reinterpret_cast<Expression*>( temp.get() ) );
  382. }
  383. template<> inline
  384. PyObject* BinarySub::operator()( Term* first, double second )
  385. {
  386. return BinaryAdd()( first, -second );
  387. }
  388. template<> inline
  389. PyObject* BinarySub::operator()( Term* first, Variable* second )
  390. {
  391. cppy::ptr temp( UnaryNeg()( second ) );
  392. if( !temp )
  393. return 0;
  394. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  395. }
  396. template<> inline
  397. PyObject* BinarySub::operator()( Term* first, Term* second )
  398. {
  399. cppy::ptr temp( UnaryNeg()( second ) );
  400. if( !temp )
  401. return 0;
  402. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  403. }
  404. template<> inline
  405. PyObject* BinarySub::operator()( Term* first, Expression* second )
  406. {
  407. cppy::ptr temp( UnaryNeg()( second ) );
  408. if( !temp )
  409. return 0;
  410. return BinaryAdd()( first, reinterpret_cast<Expression*>( temp.get() ) );
  411. }
  412. template<> inline
  413. PyObject* BinarySub::operator()( Expression* first, double second )
  414. {
  415. return BinaryAdd()( first, -second );
  416. }
  417. template<> inline
  418. PyObject* BinarySub::operator()( Expression* first, Variable* second )
  419. {
  420. cppy::ptr temp( UnaryNeg()( second ) );
  421. if( !temp )
  422. return 0;
  423. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  424. }
  425. template<> inline
  426. PyObject* BinarySub::operator()( Expression* first, Term* second )
  427. {
  428. cppy::ptr temp( UnaryNeg()( second ) );
  429. if( !temp )
  430. return 0;
  431. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  432. }
  433. template<> inline
  434. PyObject* BinarySub::operator()( Expression* first, Expression* second )
  435. {
  436. cppy::ptr temp( UnaryNeg()( second ) );
  437. if( !temp )
  438. return 0;
  439. return BinaryAdd()( first, reinterpret_cast<Expression*>( temp.get() ) );
  440. }
  441. template<> inline
  442. PyObject* BinarySub::operator()( double first, Variable* second )
  443. {
  444. cppy::ptr temp( UnaryNeg()( second ) );
  445. if( !temp )
  446. return 0;
  447. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  448. }
  449. template<> inline
  450. PyObject* BinarySub::operator()( double first, Term* second )
  451. {
  452. cppy::ptr temp( UnaryNeg()( second ) );
  453. if( !temp )
  454. return 0;
  455. return BinaryAdd()( first, reinterpret_cast<Term*>( temp.get() ) );
  456. }
  457. template<> inline
  458. PyObject* BinarySub::operator()( double first, Expression* second )
  459. {
  460. cppy::ptr temp( UnaryNeg()( second ) );
  461. if( !temp )
  462. return 0;
  463. return BinaryAdd()( first, reinterpret_cast<Expression*>( temp.get() ) );
  464. }
  465. template<typename T, typename U>
  466. PyObject* makecn( T first, U second, kiwi::RelationalOperator op )
  467. {
  468. cppy::ptr pyexpr( BinarySub()( first, second ) );
  469. if( !pyexpr )
  470. return 0;
  471. cppy::ptr pycn( PyType_GenericNew( Constraint::TypeObject, 0, 0 ) );
  472. if( !pycn )
  473. return 0;
  474. Constraint* cn = reinterpret_cast<Constraint*>( pycn.get() );
  475. cn->expression = reduce_expression( pyexpr.get() );
  476. if( !cn->expression )
  477. return 0;
  478. kiwi::Expression expr( convert_to_kiwi_expression( cn->expression ) );
  479. new( &cn->constraint ) kiwi::Constraint( expr, op, kiwi::strength::required );
  480. return pycn.release();
  481. }
  482. struct CmpEQ
  483. {
  484. template<typename T, typename U>
  485. PyObject* operator()( T first, U second )
  486. {
  487. return makecn( first, second, kiwi::OP_EQ );
  488. }
  489. };
  490. struct CmpLE
  491. {
  492. template<typename T, typename U>
  493. PyObject* operator()( T first, U second )
  494. {
  495. return makecn( first, second, kiwi::OP_LE );
  496. }
  497. };
  498. struct CmpGE
  499. {
  500. template<typename T, typename U>
  501. PyObject* operator()( T first, U second )
  502. {
  503. return makecn( first, second, kiwi::OP_GE );
  504. }
  505. };
  506. } // namespace kiwisolver