|
@@ -2,8 +2,9 @@ |
|
|
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION |
|
|
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION |
|
|
#include <Python.h> |
|
|
#include <Python.h> |
|
|
#include <numpy/arrayobject.h> |
|
|
#include <numpy/arrayobject.h> |
|
|
#include "bithacks.h" |
|
|
|
|
|
#include "npy_util.h" |
|
|
#include "npy_util.h" |
|
|
|
|
|
#include "bithacks.h" |
|
|
|
|
|
#include "permanents.h" |
|
|
|
|
|
|
|
|
// Forward function declaration |
|
|
// Forward function declaration |
|
|
static PyObject *permanent(PyObject *self, PyObject *args); |
|
|
static PyObject *permanent(PyObject *self, PyObject *args); |
|
@@ -20,28 +21,6 @@ PyMODINIT_FUNC initpermanent(void) { |
|
|
import_array(); |
|
|
import_array(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Ryser's algorithm |
|
|
|
|
|
static npy_complex128 perm_ryser(PyArrayObject *submatrix) { |
|
|
|
|
|
int n = (int) PyArray_DIM(submatrix, 0); |
|
|
|
|
|
npy_complex128 rowsum, rowsumprod; |
|
|
|
|
|
npy_complex128 perm = complex_zero; |
|
|
|
|
|
int exp = 1 << n; |
|
|
|
|
|
int i, y, z; |
|
|
|
|
|
for (i=0; i<exp; ++i) { |
|
|
|
|
|
rowsumprod = complex_one; |
|
|
|
|
|
for (y=0; y<n; ++y) { |
|
|
|
|
|
rowsum = complex_zero; |
|
|
|
|
|
for (z=0; z<n; ++z) { |
|
|
|
|
|
if ((i & (1 << z)) != 0) { complex_inc(&rowsum, SM(z, y)); } |
|
|
|
|
|
} |
|
|
|
|
|
complex_multiply(&rowsumprod, rowsum); |
|
|
|
|
|
} |
|
|
|
|
|
complex_inc(&perm, complex_float_prod(rowsumprod, bitparity(i))); |
|
|
|
|
|
} |
|
|
|
|
|
if (n%2 == 1) {perm=complex_float_prod(perm, -1);} |
|
|
|
|
|
return perm; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// This is a wrapper which chooses the optimal permanent function |
|
|
// This is a wrapper which chooses the optimal permanent function |
|
|
static PyObject *permanent(PyObject *self, PyObject *args) { |
|
|
static PyObject *permanent(PyObject *self, PyObject *args) { |
|
|
// Parse the input |
|
|
// Parse the input |
|
|