Revision: 8190
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at September 5, 2008 18:23 by tkf
Initial Code
/* dtlsmodule.c */
#include <math.h>
#include <stdio.h>
#include <Python.h>
#include "structmember.h"
#include <numpy/arrayobject.h>
/* ================================================================= MACROS */
#define QUOTE(s) # s /* turn s into string "s" */
#define NDIM_CHECK(a, expected_ndim, rt_error) \
if (PyArray_NDIM(a) != expected_ndim) { \
PyErr_Format(PyExc_ValueError, \
"%s array is %d-dimensional, but expected to be %d-dimensional", \
QUOTE(a), PyArray_NDIM(a), expected_ndim); \
return rt_error; \
}
#define DIM_CHECK(a, dim, expected_length, rt_error) \
if (dim > PyArray_NDIM(a)) { \
PyErr_Format(PyExc_ValueError, \
"%s array has no %d dimension (max dim. is %d)", \
QUOTE(a), dim, PyArray_NDIM(a)); \
return rt_error; \
} \
if (PyArray_DIM(a, dim) != expected_length) { \
PyErr_Format(PyExc_ValueError, \
"%s array has wrong %d-dimension=%d (expected %d)", \
QUOTE(a), dim, PyArray_DIM(a, dim), expected_length); \
return rt_error; \
}
#define TYPE_CHECK(a, tp, rt_error) \
if (PyArray_TYPE(a) != tp) { \
PyErr_Format(PyExc_TypeError, \
"%s array is not of correct type (%d)", QUOTE(a), tp); \
return rt_error; \
}
#define CALLABLE_CHECK(func, rt_error) \
if (!PyCallable_Check(func)) { \
PyErr_Format(PyExc_TypeError, \
"%s is not a callable function", QUOTE(func)); \
return rt_error; \
}
#define DIND1(a, i) *((double *) PyArray_GETPTR1(a, i))
#define DIND2(a, i, j) *((double *) PyArray_GETPTR2(a, i, j))
#define DIND3(a, i, j, k) *((double *) Py_Array_GETPTR3(a, i, j, k))
#define IIND1(a, i) *((int *) PyArray_GETPTR1(a, i))
#define IIND2(a, i, j) *((int *) PyArray_GETPTR2(a, i, j))
#define IIND3(a, i, j, k) *((int *) Py_Array_GETPTR3(a, i, j, k))
#define DEF_PYARRAY_GETTER(funcname, selftype, valname) \
static PyObject * \
funcname(selftype *self, void *closure) \
{ \
Py_INCREF(self->valname); \
return PyArray_Return(self->valname); \
}
#define DEF_PYARRAY_SETTER(funcname, selftype, valname, arraydim) \
static int \
funcname(selftype *self, PyObject *value, void *closure) \
{ \
if (value == NULL) { \
PyErr_SetString( PyExc_TypeError, \
"Cannot delete the last attribute"); \
return -1; \
} \
if ( PyArray_Check(value) != 1 ){ \
PyErr_Format( PyExc_ValueError, \
"value is not of type numpy array"); \
return -1; \
} \
if ( PyArray_NDIM(value) != arraydim ){ \
PyErr_Format( PyExc_ValueError, \
"value array's dimension %d != arraydim", \
PyArray_NDIM(value)); \
return -1; \
} \
if ( PyArray_TYPE(value) != NPY_DOUBLE ){ \
PyErr_Format( PyExc_ValueError, \
"value array is not of type 'Python float'"); \
return -1; \
} \
Py_DECREF(self->valname); \
Py_INCREF(value); \
self->valname = (PyArrayObject *) value; \
return 0; \
}
/* ========================================================== DTLSys struct */
typedef struct {
PyObject_HEAD
PyArrayObject *wt;
PyArrayObject *bs;
PyArrayObject *xt;
} DTLSys;
/* ============================================================ Declaration */
static void DTLSys_dealloc(DTLSys* self);
static PyObject * DTLSys_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static int DTLSys_init(DTLSys *self, PyObject *args, PyObject *kwds);
static PyMemberDef DTLSys_members[] = {
{NULL} /* Sentinel */
};
static PyObject * DTLSys_get_wt(DTLSys *self, void *closure);
static int DTLSys_set_wt(DTLSys *self, PyObject *value, void *closure);
static PyObject * DTLSys_get_bs(DTLSys *self, void *closure);
static int DTLSys_set_bs(DTLSys *self, PyObject *value, void *closure);
static PyObject * DTLSys_get_xt(DTLSys *self, void *closure);
static int DTLSys_set_xt(DTLSys *self, PyObject *value, void *closure);
static PyGetSetDef DTLSys_getseters[] = {
{"wt", (getter)DTLSys_get_wt, (setter)DTLSys_set_wt, "Matrix", NULL},
{"bs", (getter)DTLSys_get_bs, (setter)DTLSys_set_bs, "Vector", NULL},
{"xt", (getter)DTLSys_get_xt, (setter)DTLSys_set_xt, "Vector time sequence", NULL},
{NULL} /* Sentinel */
};
static int _DTLSys_check_sys_conf(DTLSys *self);
static PyObject * DTLSys_check_sys_conf(DTLSys *self);
static PyObject * DTLSys_make_tms(DTLSys *self, PyObject *args);
static PyMethodDef DTLSys_methods[] = {
{"check_sys_conf", (PyCFunction)DTLSys_check_sys_conf, METH_NOARGS, "Check if system config is correct"},
{"make_tms", (PyCFunction)DTLSys_make_tms, METH_VARARGS, "Make TiMe Series"},
{NULL} /* Sentinel */
};
static PyTypeObject DTLSysType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"dtls.DTLSys", /*tp_name*/
sizeof(DTLSys), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)DTLSys_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"DTLSys objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
DTLSys_methods, /* tp_methods */
DTLSys_members, /* tp_members */
DTLSys_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)DTLSys_init, /* tp_init */
0, /* tp_alloc */
DTLSys_new, /* tp_new */
};
static PyMethodDef module_methods[] = {
{NULL} /* Sentinel */
};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initdtls(void)
{
PyObject* m;
if (PyType_Ready(&DTLSysType) < 0){ return; }
m = Py_InitModule3("dtls", module_methods,
"Example module that creates an extension type.");
if (m == NULL){ return; }
Py_INCREF(&DTLSysType);
PyModule_AddObject(m, "DTLSys", (PyObject *)&DTLSysType);
import_array(); /* required NumPy initialization */
}
/* ================================================================= Define */
static void
DTLSys_dealloc(DTLSys* self)
{
Py_XDECREF(self->wt);
Py_XDECREF(self->bs);
Py_XDECREF(self->xt);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
DTLSys_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
DTLSys *self;
npy_intp wt_dims[2] = {0,0};
npy_intp bs_dims[1] = {0};
npy_intp xt_dims[2] = {0,0};
self = (DTLSys *)type->tp_alloc(type, 0);
if (self != NULL) {
self->wt = (PyArrayObject *) PyArray_SimpleNew(2, wt_dims, NPY_DOUBLE);
if (self->wt == NULL){ Py_DECREF(self); return NULL; }
self->bs = (PyArrayObject *) PyArray_SimpleNew(1, bs_dims, NPY_DOUBLE);
if (self->bs == NULL){ Py_DECREF(self); return NULL; }
self->xt = (PyArrayObject *) PyArray_SimpleNew(2, xt_dims, NPY_DOUBLE);
if (self->xt == NULL){ Py_DECREF(self); return NULL; }
}
return (PyObject *)self;
}
static int
DTLSys_init(DTLSys *self, PyObject *args, PyObject *kwds)
{
PyArrayObject *wt, *bs, *tmp;
int t_max;
npy_intp xt_dims[2] = {0,0};
if ( !PyArg_ParseTuple( args, "O!O!i:DTLSys.init",
&PyArray_Type, &wt,
&PyArray_Type, &bs,
&t_max)
) {
return -1; /* PyArg_ParseTuple has raised an exception */
}
if ( wt==NULL || bs==NULL ) {
printf("getting args failed\n"); return -1;
}
if ( t_max < 0 ) {
printf("t_max (3rd arg) must be positive int\n"); return -1;
}
xt_dims[0] = PyArray_DIM(wt,0);
xt_dims[1] = t_max;
self->xt = (PyArrayObject *) PyArray_SimpleNew(2, xt_dims, NPY_DOUBLE);
if (self->xt == NULL){
printf("creating %dx%d array failed\n", (int)xt_dims[0], (int)xt_dims[1]);
return -1;
}
tmp = self->wt; Py_INCREF(wt); self->wt = wt; Py_DECREF(tmp);
tmp = self->bs; Py_INCREF(bs); self->bs = bs; Py_DECREF(tmp);
if( _DTLSys_check_sys_conf(self) != 0 ){
PyErr_Clear();
printf("DTLSys config is not correct!\n");
}
return 0;
}
DEF_PYARRAY_GETTER( DTLSys_get_wt, DTLSys, wt )
DEF_PYARRAY_SETTER( DTLSys_set_wt, DTLSys, wt, 2 )
DEF_PYARRAY_GETTER( DTLSys_get_bs, DTLSys, bs )
DEF_PYARRAY_SETTER( DTLSys_set_bs, DTLSys, bs, 1 )
DEF_PYARRAY_GETTER( DTLSys_get_xt, DTLSys, xt )
DEF_PYARRAY_SETTER( DTLSys_set_xt, DTLSys, xt, 2 )
static int
_DTLSys_check_sys_conf(DTLSys *self)
{
int vecsize;
NDIM_CHECK(self->wt, 2, -1); TYPE_CHECK(self->wt, NPY_DOUBLE, -1);
NDIM_CHECK(self->bs, 1, -1); TYPE_CHECK(self->bs, NPY_DOUBLE, -1);
vecsize = PyArray_DIM(self->wt,0);
if (vecsize != PyArray_DIM(self->wt,1) ) {
PyErr_Format( PyExc_ValueError, "self.wt must be square");
return -1;
}
if (vecsize != PyArray_DIM(self->bs,0) ) {
PyErr_Format( PyExc_ValueError, "self.bs and self.wt[0] must be same shape");
return -1;
}
if (vecsize != PyArray_DIM(self->xt,0) ) {
PyErr_Format( PyExc_ValueError, "self.xt[,0] and self.wt[0] must be same shape");
return -1;
}
return 0;
}
static PyObject *
DTLSys_check_sys_conf(DTLSys *self)
{
if( _DTLSys_check_sys_conf(self) != 0 ){
PyErr_Clear();
Py_RETURN_FALSE;
}
Py_RETURN_TRUE;
}
static PyObject *
DTLSys_make_tms(DTLSys *self, PyObject *args)
{
int vecsize, t_max, i, j, t;
if( _DTLSys_check_sys_conf(self) != 0 ){
return NULL;
}
vecsize = PyArray_DIM(self->wt,0);
t_max = PyArray_DIM(self->xt,1);
for (t = 1; t < t_max; t++) {
for (i = 0; i < vecsize; i++) {
DIND2(self->xt,i,t) = DIND1(self->bs,i);
for (j = 0; j < vecsize; j++) {
DIND2(self->xt,i,t) += DIND2(self->wt,i,j) * DIND2(self->xt,j,t-1);
}
}
}
return Py_BuildValue(""); /* return None */
}
/*
# setup.py
# build command : python setup.py build build_ext --inplace
from numpy.distutils.core import setup, Extension
import os, numpy
name = 'dtls'
sources = ['dtlsmodule.c']
include_dirs = [
numpy.get_include()
]
setup( name = name,
include_dirs = include_dirs,
ext_modules = [Extension(name, sources)]
)
*/
/*
# test code
import scipy, pylab
import dtls
t_max = 200
rot = 5.0 * 2.0 * scipy.pi / t_max
wt = scipy.array([
[ scipy.cos(rot), scipy.sin(rot) ],
[ -scipy.sin(rot), scipy.cos(rot) ]
])
wt *= 0.99
bs = scipy.array([0.,0.])
a=dtls.DTLSys( wt, bs, t_max )
a.xt[0,0] = 0
a.xt[1,0] = 1
a.make_tms()
pylab.clf()
pylab.plot(a.xt[0],a.xt[1], 'o-')
# Check calculation
print (scipy.dot( a.wt, a.xt[:,0] ) + a.bs) - a.xt[:,1]
*/
Initial URL
Initial Description
Some macros are from the "Python Scripting for Computational Science" : http://folk.uio.no/hpl/scripting/
Initial Title
Example of Numpy/C API
Initial Tags
python, api
Initial Language
C