From 5ededa99988a5878feb86487899b315ee3ac07c8 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Wed, 26 Nov 2014 16:03:11 +0000 Subject: [PATCH] Compatible with PyPI, can be installed through pip --- .gitignore | 3 +++ LICENSE | 2 +- MANIFEST | 8 ++++++++ MANIFEST.in | 1 + README | 4 ++++ makefile | 21 --------------------- {lib => permanent}/__init__.py | 0 run-tests.py | 4 ++-- run-tests.sh | 5 +++++ setup.py | 11 ++++++----- src/permanent.c | 28 +++++++++++++++++++++++++--- 11 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 MANIFEST create mode 100644 MANIFEST.in create mode 100644 README delete mode 100644 makefile rename {lib => permanent}/__init__.py (100%) create mode 100755 run-tests.sh diff --git a/.gitignore b/.gitignore index 585129b..69f42a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.pypirc +*.pdf + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/LICENSE b/LICENSE index c63dcbc..bc73e98 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 J. Pete Shadbolt +Copyright (c) 2014 Pete Shadbolt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..e49d535 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,8 @@ +# file GENERATED by distutils, do NOT edit +README +setup.py +./src/permanent.c +permanent/__init__.py +src/bithacks.h +src/npy_util.h +src/permanent.c diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..a9042a5 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include src/* diff --git a/README b/README new file mode 100644 index 0000000..7f2862e --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +# Fast functions for LOQC +- Permanent (hardcoded up to 4x4 and Ryser) +- Parallel permanent +- No Cython dependency diff --git a/makefile b/makefile deleted file mode 100644 index 207db8f..0000000 --- a/makefile +++ /dev/null @@ -1,21 +0,0 @@ -srcdir = src -objdir = ./ - -target = permanent.so -setup = setup.py - -default : $(target) test - -# Compile -$(target): $(srcdir)/* - python $(setup) build_ext --inplace - -test : - python ./run-tests.py - -clean : - @ rm permanent.so - @ rm -rf build - -tar : - @ tar czf permanent.tar.gz $(srcdir) $(utils) diff --git a/lib/__init__.py b/permanent/__init__.py similarity index 100% rename from lib/__init__.py rename to permanent/__init__.py diff --git a/run-tests.py b/run-tests.py index 4099c8d..6079cb5 100644 --- a/run-tests.py +++ b/run-tests.py @@ -2,9 +2,9 @@ import os, sys import time import multiprocessing as mp import numpy as np -import lib import time from matplotlib import pyplot as plt +from permanent import permanent def perm_ryser(a): ''' the permanent calculated using the ryser formula. much faster than the naive approach ''' @@ -20,7 +20,7 @@ def perm_ryser(a): maxtime=1 dimensions=range(1,11) -for (function, label) in zip((lib.permanent, perm_ryser), ("C", "Python")): +for (function, label) in zip((permanent, perm_ryser), ("C", "Python")): counts=[] for dimension in dimensions: print dimension diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 0000000..19b6c35 --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +rm permanent/*.so +python ./setup.py build_ext --inplace && +python ./run-tests.py diff --git a/setup.py b/setup.py index 2ec325c..01b8bf8 100644 --- a/setup.py +++ b/setup.py @@ -2,16 +2,17 @@ from distutils.core import setup, Extension -setup(name = "loqcmath", - version = "1.0", - description = "Fast maths for LOQC", +setup(name = "permanent", + version = "0.1.2", + description = "Calculates the permanent of a Numpy matrix", author = "Pete Shadbolt", author_email = "pete.shadbolt@gmail.com", maintainer = "pete.shadbolt@gmail.com", - url = "https://www.peteshadbolt.co.uk", + url = "https://github.com/peteshadbolt/permanent", + packages = ["permanent"], ext_modules = [ Extension( - 'permanent', ['src/permanent.c'], + 'permanent.permanent', ['./src/permanent.c'], extra_compile_args=["-Ofast", "-march=native"]), ], diff --git a/src/permanent.c b/src/permanent.c index 782bce1..0093f7d 100644 --- a/src/permanent.c +++ b/src/permanent.c @@ -1,17 +1,16 @@ -/* Computes the permanent, given a numpy array */ +/* Functions to compute the permanent, given a numpy array */ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include #include "npy_util.h" #include "bithacks.h" -#include "ryser.h" // Forward function declaration static PyObject *permanent(PyObject *self, PyObject *args); // Method list static PyMethodDef methods[] = { - { "permanent", permanent, METH_VARARGS, "Compute the permanent"}, + { "permanent", permanent, METH_VARARGS, "Computes the permanent of a numpy using the most appropriate method available"}, { NULL, NULL, 0, NULL } // Sentinel }; @@ -21,6 +20,29 @@ PyMODINIT_FUNC initpermanent(void) { import_array(); } +// Ryser's algorithm +static npy_complex128 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