| @@ -0,0 +1,57 @@ | |||||
| # Byte-compiled / optimized / DLL files | |||||
| __pycache__/ | |||||
| *.py[cod] | |||||
| # C extensions | |||||
| *.so | |||||
| # Distribution / packaging | |||||
| .Python | |||||
| env/ | |||||
| build/ | |||||
| develop-eggs/ | |||||
| dist/ | |||||
| downloads/ | |||||
| eggs/ | |||||
| lib/ | |||||
| lib64/ | |||||
| parts/ | |||||
| sdist/ | |||||
| var/ | |||||
| *.egg-info/ | |||||
| .installed.cfg | |||||
| *.egg | |||||
| # PyInstaller | |||||
| # Usually these files are written by a python script from a template | |||||
| # before PyInstaller builds the exe, so as to inject date/other infos into it. | |||||
| *.manifest | |||||
| *.spec | |||||
| # Installer logs | |||||
| pip-log.txt | |||||
| pip-delete-this-directory.txt | |||||
| # Unit test / coverage reports | |||||
| htmlcov/ | |||||
| .tox/ | |||||
| .coverage | |||||
| .cache | |||||
| nosetests.xml | |||||
| coverage.xml | |||||
| # Translations | |||||
| *.mo | |||||
| *.pot | |||||
| # Django stuff: | |||||
| *.log | |||||
| # Sphinx documentation | |||||
| docs/_build/ | |||||
| # PyBuilder | |||||
| target/ | |||||
| # PYC | |||||
| *.pyc | |||||
| @@ -0,0 +1,22 @@ | |||||
| The MIT License (MIT) | |||||
| Copyright (c) 2014 J. 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 | |||||
| in the Software without restriction, including without limitation the rights | |||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
| copies of the Software, and to permit persons to whom the Software is | |||||
| furnished to do so, subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in all | |||||
| copies or substantial portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| SOFTWARE. | |||||
| @@ -0,0 +1,3 @@ | |||||
| # Fast functions for LOQC | |||||
| - Permanent (hardcoded up to 4x4 and Ryser) | |||||
| - Parallel permanent | |||||
| @@ -0,0 +1,35 @@ | |||||
| import os | |||||
| import time | |||||
| import multiprocessing as mp | |||||
| import numpy as np | |||||
| import lib | |||||
| def test_fn(perm_fn, name, dimension=6, steps=1000, dt=1e-3, bodies=101, threads=1): | |||||
| # Test the speed of the evolution function. | |||||
| sreal=np.random.uniform(0,1,(dimension, dimension)) | |||||
| scomp=np.random.uniform(0,1,(dimension, dimension)) | |||||
| submatrix=sreal+1j*scomp | |||||
| t0 = time.time() | |||||
| for i in range(steps): | |||||
| p=perm_fn(submatrix) | |||||
| t1 = time.time() | |||||
| print "{0} ({1}): {2} steps/sec".format(name, threads, int(steps / (t1 - t0))) | |||||
| if __name__ == "__main__": | |||||
| d=4 | |||||
| steps=1000 | |||||
| # Test on one core | |||||
| test_fn(lib.perm_python, "1 core, C", steps=steps, threads=1) | |||||
| # Test on one core | |||||
| test_fn(lib.perm_c, "1 core, C", steps=steps, threads=1) | |||||
| # Test on four cores | |||||
| test_fn(lib.perm_c, "All cores, C", steps=steps/threads, threads=threads) | |||||
| @@ -0,0 +1,5 @@ | |||||
| #!/bin/bash | |||||
| rm lib/*.so | |||||
| python ./setup.py build_ext --inplace && | |||||
| python ./run-tests.py | |||||
| @@ -0,0 +1,18 @@ | |||||
| #!/usr/bin/env python | |||||
| from distutils.core import setup, Extension | |||||
| setup(name = "loqcmath", | |||||
| version = "1.0", | |||||
| description = "Fast maths for LOQC", | |||||
| author = "Pete Shadbolt", | |||||
| author_email = "pete.shadbolt@gmail.com", | |||||
| maintainer = "pete.shadbolt@gmail.com", | |||||
| url = "https://www.peteshadbolt.co.uk", | |||||
| ext_modules = [ | |||||
| Extension( | |||||
| 'perm_c', ['src/perm_c'], | |||||
| extra_compile_args=["-Ofast", "-march=native"]), | |||||
| ], | |||||
| ) | |||||
| @@ -0,0 +1,106 @@ | |||||
| /* Computes the permanent, given a numpy array */ | |||||
| #include <Python.h> | |||||
| #include <numpy/arrayobject.h> | |||||
| #include <math.h> | |||||
| // Forward function declaration. | |||||
| static PyObject *permanent(PyObject *self, PyObject *args); | |||||
| // Boilerplate: method list. | |||||
| static PyMethodDef methods[] = { | |||||
| { "permanent", permanent, METH_VARARGS, "Compute the permanent"}, | |||||
| { NULL, NULL, 0, NULL } /* Sentinel */ | |||||
| }; | |||||
| // Boilerplate: Module initialization. | |||||
| PyMODINIT_FUNC initpermanent(void) { | |||||
| (void) Py_InitModule("permanent", methods); | |||||
| import_array(); | |||||
| } | |||||
| /***************************************************************************** | |||||
| * Array access macros. * | |||||
| *****************************************************************************/ | |||||
| #define m(x0) (*(npy_float64*)((PyArray_DATA(py_m) + \ | |||||
| (x0) * PyArray_STRIDES(py_m)[0]))) | |||||
| #define m_shape(i) (py_m->dimensions[(i)]) | |||||
| #define r(x0, x1) (*(npy_float64*)((PyArray_DATA(py_r) + \ | |||||
| (x0) * PyArray_STRIDES(py_r)[0] + \ | |||||
| (x1) * PyArray_STRIDES(py_r)[1]))) | |||||
| #define r_shape(i) (py_r->dimensions[(i)]) | |||||
| #define v(x0, x1) (*(npy_float64*)((PyArray_DATA(py_v) + \ | |||||
| (x0) * PyArray_STRIDES(py_v)[0] + \ | |||||
| (x1) * PyArray_STRIDES(py_v)[1]))) | |||||
| #define v_shape(i) (py_v->dimensions[(i)]) | |||||
| #define F(x0, x1) (*(npy_float64*)((PyArray_DATA(py_F) + \ | |||||
| (x0) * PyArray_STRIDES(py_F)[0] + \ | |||||
| (x1) * PyArray_STRIDES(py_F)[1]))) | |||||
| #define F_shape(i) (py_F->dimensions[(i)]) | |||||
| /***************************************************************************** | |||||
| * compute_F * | |||||
| *****************************************************************************/ | |||||
| static inline void compute_F(npy_int64 N, | |||||
| PyArrayObject *py_m, | |||||
| PyArrayObject *py_r, | |||||
| PyArrayObject *py_F) { | |||||
| npy_int64 i, j; | |||||
| npy_float64 sx, sy, Fx, Fy, s3, tmp; | |||||
| // Set all forces to zero. | |||||
| for(i = 0; i < N; ++i) { | |||||
| F(i, 0) = F(i, 1) = 0; | |||||
| } | |||||
| // Compute forces between pairs of bodies. | |||||
| for(i = 0; i < N; ++i) { | |||||
| for(j = i + 1; j < N; ++j) { | |||||
| sx = r(j, 0) - r(i, 0); | |||||
| sy = r(j, 1) - r(i, 1); | |||||
| s3 = sqrt(sx*sx + sy*sy); | |||||
| s3 *= s3 * s3; | |||||
| tmp = m(i) * m(j) / s3; | |||||
| Fx = tmp * sx; | |||||
| Fy = tmp * sy; | |||||
| F(i, 0) += Fx; | |||||
| F(i, 1) += Fy; | |||||
| F(j, 0) -= Fx; | |||||
| F(j, 1) -= Fy; | |||||
| } | |||||
| } | |||||
| } | |||||
| static PyObject *permanent(PyObject *self, PyObject *args) { | |||||
| // Declare variables. | |||||
| npy_int64 d, i, j; | |||||
| npy_float64 output; | |||||
| PyArrayObject *submatrix; | |||||
| // Parse variables. | |||||
| if (!PyArg_ParseTuple(args, "ldllO!O!O!O!", | |||||
| &threads, | |||||
| &dt, | |||||
| &steps, | |||||
| &N, | |||||
| &PyArray_Type, &submatrix)) { | |||||
| return NULL; | |||||
| } | |||||
| // Compute the permanent | |||||
| for(i = 0; i < d; ++i) { | |||||
| for(j = 0; j<d; ++j) { | |||||
| } | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | |||||