| 
				
				
					
				
				
				 | 
			
			 | 
			@@ -9,6 +9,21 @@ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    (x1) * PyArray_STRIDES(submatrix)[1]))) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#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 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static const npy_complex128 complex_one = {.real=1, .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) {  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    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; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -36,46 +51,28 @@ PyMODINIT_FUNC initpermanent(void) {                            // Module initia | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  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  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static npy_complex128 perm_ryser(PyArrayObject *submatrix) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    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; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int exp = 1 << n;  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int i, y, z; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Iterate over exponentially many index strings | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    for (i=0; i<exp; ++i) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        prod = complex_one; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        rowsumprod = complex_one; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        for (y=0; y<n; ++y) {               // Rows | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            sum = complex_zero; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            rowsum = complex_zero; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            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; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
	
		
			
				| 
				
					
				
				
				
				 | 
			
			 | 
			
  |