@@ -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; | |||||
} |