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.

59 lines
1.6KB

  1. /* Computes the permanent, given a numpy array */
  2. #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
  3. #include <Python.h>
  4. #include <numpy/arrayobject.h>
  5. #include <math.h>
  6. #include <complex.h>
  7. // Boilerplate: Forward function declaration.
  8. static PyObject *permanent(PyObject *self, PyObject *args);
  9. // Boilerplate: method list.
  10. static PyMethodDef methods[] = {
  11. { "permanent", permanent, METH_VARARGS, "Compute the permanent"},
  12. { NULL, NULL, 0, NULL } /* Sentinel */
  13. };
  14. // Boilerplate: Module initialization.
  15. PyMODINIT_FUNC initpermanent(void) {
  16. (void) Py_InitModule("permanent", methods);
  17. import_array();
  18. }
  19. // Array access macros.
  20. #define SM(x0, x1) (*(npy_complex128*)((PyArray_DATA(submatrix) + \
  21. (x0) * PyArray_STRIDES(submatrix)[0] + \
  22. (x1) * PyArray_STRIDES(submatrix)[1])))
  23. #define SM_shape(x0) (int) PyArray_DIM(submatrix, x0)
  24. static PyObject *permanent(PyObject *self, PyObject *args) {
  25. // Parse input
  26. PyArrayObject *submatrix;
  27. if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {
  28. return NULL;
  29. }
  30. // Check for stupid mistakes
  31. if ((int) PyArray_NDIM(submatrix) != 2) {return NULL;}
  32. int d = (int) PyArray_DIM(submatrix, 0);
  33. if ((int) PyArray_DIM(submatrix, 1) != d) {return NULL;}
  34. // This number ends up being the permanent
  35. npy_complex64 p;
  36. p.real=0; p.imag=0;
  37. int i, j;
  38. for (i = 0; i < d; ++i) {
  39. for (j = 0; j<d; ++j) {
  40. npy_complex128 q = SM(0,0);
  41. p.real += q.real;
  42. p.imag += q.imag;
  43. }
  44. }
  45. // Convert to a python complex number and return
  46. PyObject *output=PyComplex_FromDoubles(p.real,p.imag);
  47. return output;
  48. }