Python C extension to compute the permanent.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

permanent.c 3.2KB

6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* Computes the permanent, given a numpy array */
  2. #include <Python.h>
  3. #include <numpy/arrayobject.h>
  4. #include <math.h>
  5. // Forward function declaration.
  6. static PyObject *permanent(PyObject *self, PyObject *args);
  7. // Boilerplate: method list.
  8. static PyMethodDef methods[] = {
  9. { "permanent", permanent, METH_VARARGS, "Compute the permanent"},
  10. { NULL, NULL, 0, NULL } /* Sentinel */
  11. };
  12. // Boilerplate: Module initialization.
  13. PyMODINIT_FUNC initpermanent(void) {
  14. (void) Py_InitModule("permanent", methods);
  15. import_array();
  16. }
  17. /*****************************************************************************
  18. * Array access macros. *
  19. *****************************************************************************/
  20. #define m(x0) (*(npy_float64*)((PyArray_DATA(py_m) + \
  21. (x0) * PyArray_STRIDES(py_m)[0])))
  22. #define m_shape(i) (py_m->dimensions[(i)])
  23. #define r(x0, x1) (*(npy_float64*)((PyArray_DATA(py_r) + \
  24. (x0) * PyArray_STRIDES(py_r)[0] + \
  25. (x1) * PyArray_STRIDES(py_r)[1])))
  26. #define r_shape(i) (py_r->dimensions[(i)])
  27. #define v(x0, x1) (*(npy_float64*)((PyArray_DATA(py_v) + \
  28. (x0) * PyArray_STRIDES(py_v)[0] + \
  29. (x1) * PyArray_STRIDES(py_v)[1])))
  30. #define v_shape(i) (py_v->dimensions[(i)])
  31. #define F(x0, x1) (*(npy_float64*)((PyArray_DATA(py_F) + \
  32. (x0) * PyArray_STRIDES(py_F)[0] + \
  33. (x1) * PyArray_STRIDES(py_F)[1])))
  34. #define F_shape(i) (py_F->dimensions[(i)])
  35. /*****************************************************************************
  36. * compute_F *
  37. *****************************************************************************/
  38. static inline void compute_F(npy_int64 N,
  39. PyArrayObject *py_m,
  40. PyArrayObject *py_r,
  41. PyArrayObject *py_F) {
  42. npy_int64 i, j;
  43. npy_float64 sx, sy, Fx, Fy, s3, tmp;
  44. // Set all forces to zero.
  45. for(i = 0; i < N; ++i) {
  46. F(i, 0) = F(i, 1) = 0;
  47. }
  48. // Compute forces between pairs of bodies.
  49. for(i = 0; i < N; ++i) {
  50. for(j = i + 1; j < N; ++j) {
  51. sx = r(j, 0) - r(i, 0);
  52. sy = r(j, 1) - r(i, 1);
  53. s3 = sqrt(sx*sx + sy*sy);
  54. s3 *= s3 * s3;
  55. tmp = m(i) * m(j) / s3;
  56. Fx = tmp * sx;
  57. Fy = tmp * sy;
  58. F(i, 0) += Fx;
  59. F(i, 1) += Fy;
  60. F(j, 0) -= Fx;
  61. F(j, 1) -= Fy;
  62. }
  63. }
  64. }
  65. static PyObject *permanent(PyObject *self, PyObject *args) {
  66. // Declare variables.
  67. npy_int64 d, i, j;
  68. npy_float64 output;
  69. PyArrayObject *submatrix;
  70. // Parse variables.
  71. if (!PyArg_ParseTuple(args, "ldllO!O!O!O!",
  72. &threads,
  73. &dt,
  74. &steps,
  75. &N,
  76. &PyArray_Type, &submatrix)) {
  77. return NULL;
  78. }
  79. // Compute the permanent
  80. for(i = 0; i < d; ++i) {
  81. for(j = 0; j<d; ++j) {
  82. }
  83. }
  84. Py_RETURN_NONE;
  85. }