| 
																	
																	
																		
																	
																	
																 | 
																@@ -9,6 +9,21 @@ | 
															
														
														
													
														
															
																 | 
																 | 
																                    (x1) * PyArray_STRIDES(submatrix)[1]))) | 
																 | 
																 | 
																                    (x1) * PyArray_STRIDES(submatrix)[1]))) | 
															
														
														
													
														
															
																 | 
																 | 
																#define SM_shape(x0) (int) PyArray_DIM(submatrix, x0) | 
																 | 
																 | 
																#define SM_shape(x0) (int) PyArray_DIM(submatrix, x0) | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																int countbits(unsigned int n)  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int q=n; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x5555555555555555) + ((q & 0xAAAAAAAAAAAAAAAA) >> 1); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x3333333333333333) + ((q & 0xCCCCCCCCCCCCCCCC) >> 2); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x0F0F0F0F0F0F0F0F) + ((q & 0xF0F0F0F0F0F0F0F0) >> 4); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x00FF00FF00FF00FF) + ((q & 0xFF00FF00FF00FF00) >> 8); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x0000FFFF0000FFFF) + ((q & 0xFFFF0000FFFF0000) >> 16); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    q = (q & 0x00000000FFFFFFFF) + ((q & 0xFFFFFFFF00000000) >> 32); // This last & isq't strictly qecessary. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return q; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																int bitparity (unsigned int n) { return 1 - (countbits(n) & 1)*2; } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																// Complex numbers | 
																 | 
																 | 
																// Complex numbers | 
															
														
														
													
														
															
																 | 
																 | 
																static const npy_complex128 complex_one = {.real=1, .imag=0}; | 
																 | 
																 | 
																static const npy_complex128 complex_one = {.real=1, .imag=0}; | 
															
														
														
													
														
															
																 | 
																 | 
																static const npy_complex128 complex_zero = {.real=0, .imag=0}; | 
																 | 
																 | 
																static const npy_complex128 complex_zero = {.real=0, .imag=0}; | 
															
														
														
													
												
													
														
															
																| 
																	
																	
																	
																		
																	
																 | 
																@@ -20,8 +35,8 @@ static npy_complex128 complex_add(npy_complex128 a, npy_complex128 b) { | 
															
														
														
													
														
															
																 | 
																 | 
																} | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																static npy_complex128 complex_prod(npy_complex128 a, npy_complex128 b) {  | 
																 | 
																 | 
																static npy_complex128 complex_prod(npy_complex128 a, npy_complex128 b) {  | 
															
														
														
													
														
															
																 | 
																 | 
																    npy_complex128 x; | 
																 | 
																 | 
																    npy_complex128 x; | 
															
														
														
													
														
															
																 | 
																 | 
																    x.real = a.real*b.real+a.imag*b.imag; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    x.imag = a.real*b.imag+a.imag*b.real; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    x.real = a.real*b.real - a.imag*b.imag; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    x.imag = a.imag*b.real + a.real*b.imag; | 
															
														
														
													
														
															
																 | 
																 | 
																    return x; | 
																 | 
																 | 
																    return x; | 
															
														
														
													
														
															
																 | 
																 | 
																} | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																
  | 
															
														
														
													
												
													
														
															
																| 
																	
																	
																	
																		
																	
																 | 
																@@ -36,46 +51,28 @@ PyMODINIT_FUNC initpermanent(void) {                            // Module initia | 
															
														
														
													
														
															
																 | 
																 | 
																  import_array(); | 
																 | 
																 | 
																  import_array(); | 
															
														
														
													
														
															
																 | 
																 | 
																} | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																inline int* dec2binarr(long n, int dim) | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																{ | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    // note: res[dim] will save the sum res[0]+...+res[dim-1] | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    int* res = (int*)calloc(dim + 1, sizeof(int));    | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    int pos = dim - 1; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    // note: this will crash if dim < log_2(n)... | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    while (n > 0) | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    { | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																        res[pos] = n % 2; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																        res[dim] += res[pos]; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																        n = n / 2; // integer division         | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																        pos--; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    } | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    return res; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																} | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																// Ryser's algorithm  | 
																 | 
																 | 
																// Ryser's algorithm  | 
															
														
														
													
														
															
																 | 
																 | 
																static npy_complex128 perm_ryser(PyArrayObject *submatrix) { | 
																 | 
																 | 
																static npy_complex128 perm_ryser(PyArrayObject *submatrix) { | 
															
														
														
													
														
															
																 | 
																 | 
																    int n = (int) PyArray_DIM(submatrix, 0); | 
																 | 
																 | 
																    int n = (int) PyArray_DIM(submatrix, 0); | 
															
														
														
													
														
															
																 | 
																 | 
																    int i = 0; int z = 0; int y = 0; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																    npy_complex128 sum, prod; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    npy_complex128 rowsum, rowsumprod; | 
															
														
														
													
														
															
																 | 
																 | 
																    npy_complex128 perm = complex_zero; | 
																 | 
																 | 
																    npy_complex128 perm = complex_zero; | 
															
														
														
													
														
															
																 | 
																 | 
																    int exp = 1 << n;  | 
																 | 
																 | 
																    int exp = 1 << n;  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int i, y, z; | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																    // Iterate over exponentially many index strings | 
																 | 
																 | 
																    // Iterate over exponentially many index strings | 
															
														
														
													
														
															
																 | 
																 | 
																    for (i=0; i<exp; ++i) { | 
																 | 
																 | 
																    for (i=0; i<exp; ++i) { | 
															
														
														
													
														
															
																 | 
																 | 
																        prod = complex_one; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        rowsumprod = complex_one; | 
															
														
														
													
														
															
																 | 
																 | 
																        for (y=0; y<n; ++y) {               // Rows | 
																 | 
																 | 
																        for (y=0; y<n; ++y) {               // Rows | 
															
														
														
													
														
															
																 | 
																 | 
																            sum = complex_zero; | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            rowsum = complex_zero; | 
															
														
														
													
														
															
																 | 
																 | 
																            for (z=0; z<n; ++z) {           // Columns | 
																 | 
																 | 
																            for (z=0; z<n; ++z) {           // Columns | 
															
														
														
													
														
															
																 | 
																 | 
																                if ((i && (1 << z)) != 0) {  | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																                    sum = complex_add(sum, SM(z,y));  | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																                } | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																                if ((i & (1 << z)) != 0) { rowsum = complex_add(rowsum, SM(z,y)); } | 
															
														
														
													
														
															
																 | 
																 | 
																            } | 
																 | 
																 | 
																            } | 
															
														
														
													
														
															
																 | 
																 | 
																            prod = complex_prod(prod, sum); | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            rowsumprod = complex_prod(rowsumprod, rowsum); | 
															
														
														
													
														
															
																 | 
																 | 
																        } | 
																 | 
																 | 
																        } | 
															
														
														
													
														
															
																 | 
																 | 
																        if (i%2 == 1) {prod.real*=-1; prod.imag*=-1;} | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																        perm = complex_add(perm, prod); | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        int sign = bitparity(i);  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        perm.real+=sign*rowsumprod.real; perm.imag+=sign*rowsumprod.imag; | 
															
														
														
													
														
															
																 | 
																 | 
																    } | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																    if (i%2 == 1) {perm.real*=-1; perm.imag*=-1;} | 
																 | 
																 | 
																 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (n%2 == 1) {perm.real*=-1; perm.imag*=-1;} | 
															
														
														
													
														
															
																 | 
																 | 
																    return perm; | 
																 | 
																 | 
																    return perm; | 
															
														
														
													
														
															
																 | 
																 | 
																} | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																
  | 
																 | 
																 | 
																
  | 
															
														
														
													
												
													
														
															
																| 
																	
																		
																	
																	
																	
																 | 
																
  |