Source

Numpy Toy Box / getsetcarray / getsetcarraymodule.c.src

Full commit
/* -*- c -*- */
#include <Python.h>
#include "structmember.h"
#include <numpy/arrayobject.h>

#define GETSETCARRAY_VERBOSE
#ifdef GETSETCARRAY_VERBOSE
#define GETSETCARRAY_DEBUGFUNCCALL \
  printf("'%s' called\n", __func__)
#else
#define GETSETCARRAY_DEBUGFUNCCALL
#endif

typedef struct getsetcarray_{
  PyObject_HEAD
  PyObject *np1d, *np2d, *np3d;
  int *i1d, **i2d, ***i3d;
} GetSetCArray;

/* -------------------- int 1D array -------------------- */
static void i1d_dealloc(int *i1d)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  return;
}

static int i1d_new(int *i1d, PyObject *np1d)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  i1d = (int*)PyArray_DATA(np1d);
  return 0;
}

static int i1d_check_pointer(int *i1d, PyObject *np1d)
{
  int i,*dims;
  GETSETCARRAY_DEBUGFUNCCALL;

  dims = PyArray_DIMS(np1d);
  for (i = 0; i < dims[0]; ++i){
    printf("%d", i);
    if (PyArray_GETPTR1(np1d,i) != (void*)&i1d[i]){
      return -1;
    }
  }
  return 0;
}

/* -------------------- int 2D array -------------------- */
static void i2d_dealloc(int **i2d)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  free(i2d);
  return;
}

static int i2d_new(int **i2d, PyObject *np2d)
{
  int i,*dims;
  GETSETCARRAY_DEBUGFUNCCALL;

  dims = PyArray_DIMS(np2d);
  i2d = (int**)malloc(dims[0]*sizeof(int*));
  if (i2d == NULL){
    return -1;
  }

  i2d[0] = (int*)PyArray_DATA(np2d);
  for (i = 1; i < dims[0]; i++){
    i2d[i] = i2d[0] + i * dims[1];
  }
  return 0;
}

static int i2d_check_pointer(int **i2d, PyObject *np2d)
{
  int i,j,*dims;
  GETSETCARRAY_DEBUGFUNCCALL;

  dims = PyArray_DIMS(np2d);
  for (i = 0; i < dims[0]; ++i){
    for (j = 0; j < dims[1]; ++j){
      if (PyArray_GETPTR2(np2d,i,j) != (void*)&i2d[i][j]){
	return -1;
      }
    }
  }
  return 0;
}

/* -------------------- int 3D array -------------------- */
static void i3d_dealloc(int ***i3d)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  free(i3d[0]);
  free(i3d);
  return;
}

static int i3d_new(int ***i3d, PyObject *np3d)
{
  int i,j,*dims;
  GETSETCARRAY_DEBUGFUNCCALL;

  dims = PyArray_DIMS(np3d);
  i3d = (int***)malloc(dims[0]*sizeof(int**));
  if (i3d == NULL){
    return -1;
  }

  i3d[0] = (int**)malloc(dims[0]*dims[1]*sizeof(int*));
  if (i3d[0] == NULL){
    free(i3d);
    return -1;
  }

  i3d[0][0] = (int*)PyArray_DATA(np3d);
  for (i = 0; i < dims[0]; i++) {
    i3d[i] = i3d[0] + i * dims[1];
    for (j = 0; j < dims[1]; j++){
      i3d[i][j] = i3d[0][0] + i * dims[1]*dims[2] + j * dims[2];
    }
  }
  return 0;
}

static int i3d_check_pointer(int ***i3d, PyObject *np3d)
{
  int i,j,k,*dims;
  GETSETCARRAY_DEBUGFUNCCALL;

  dims = PyArray_DIMS(np3d);
  for (i = 0; i < dims[0]; ++i){
    for (j = 0; j < dims[1]; ++j){
      for (k = 0; k < dims[2]; ++k){
	if (PyArray_GETPTR3(np3d,i,j,k) != (void*)&i3d[i][j][k]){
	  return -1;
	}
      }
    }
  }
  return 0;
}

/* -------------------- GetSetCArray -------------------- */
static void
GetSetCArray_dealloc(GetSetCArray* self)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  Py_XDECREF(self->np1d);
  Py_XDECREF(self->np2d);
  Py_XDECREF(self->np3d);
  i1d_dealloc(self->i1d);
  i2d_dealloc(self->i2d);
  i3d_dealloc(self->i3d);
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
GetSetCArray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  GetSetCArray *self;
  GETSETCARRAY_DEBUGFUNCCALL;

  self = (GetSetCArray *)type->tp_alloc(type, 0);
  if (self == NULL){
    return NULL;
  }
  self->i1d = NULL;
  self->i2d = NULL;
  self->i3d = NULL;
  self->np1d = NULL;
  self->np2d = NULL;
  self->np3d = NULL;

  return (PyObject *)self;
}

static int
GetSetCArray_init(GetSetCArray *self, PyObject *args, PyObject *kwds)
{
  GETSETCARRAY_DEBUGFUNCCALL;
  return 0;
}

/* -------------------- getter and setter -------------------- */

/**begin repeat
   #ndim=1,2,3#
*/
static PyObject *
GetSetCArray_getter_np@ndim@d(GetSetCArray *self, void *closure)
{
  if (self->np@ndim@d == NULL){
    return Py_BuildValue("");
  }
  Py_INCREF(self->np@ndim@d);
  return self->np@ndim@d;
}

static int
GetSetCArray_setter_np@ndim@d(GetSetCArray *self, PyObject *value, 
			      void *closure)
{
  if (value == NULL) {
    PyErr_SetString( PyExc_TypeError,"Cannot delete this attribute");
    return -1;
  }
  if ( PyArray_Check(value) != 1 ){
    PyErr_SetString( PyExc_ValueError,"got non-numpy array object");
    return -1;
  }
  if ( PyArray_NDIM(value) != @ndim@ ){
    PyErr_Format( PyExc_ValueError, "ndim(=%d) should be @ndim@",
		  PyArray_NDIM(value));
    return -1;
  }
  if ( PyArray_TYPE(value) != NPY_LONG ){
    PyErr_SetString( PyExc_ValueError, "array dtype is not numpy.int" );
    return -1;
  }
  if (i@ndim@d_new(self->i@ndim@d, value) < 0){
    PyErr_SetString( PyExc_RuntimeError, "fail while preparing c array" );
    return -1;
  }
  if (i@ndim@d_check_pointer(self->i@ndim@d, value) < 0){
    PyErr_SetString( PyExc_RuntimeError, "fail while checking pointer" );
    return -1;
  }

  Py_DECREF(self->np@ndim@d);
  Py_INCREF(value);
  self->np@ndim@d = (PyObject *) value;
  return 0;
}
/**end repeat**/


static PyMemberDef GetSetCArray_members[] = {
  {NULL}  /* Sentinel */
};

static PyGetSetDef GetSetCArray_getseters[] = {
/**begin repeat
   #ndim=1,2,3#
*/
  {"np@ndim@d", 
   (getter)GetSetCArray_getter_np@ndim@d,
   (setter)GetSetCArray_setter_np@ndim@d,
   "@ndim@-dim numpy-c array interface",
   NULL},
/**end repeat**/
  {NULL}  /* Sentinel */
};

static PyMethodDef GetSetCArray_methods[] = {
  {NULL}  /* Sentinel */
};

static PyTypeObject GetSetCArrayType = {
    PyObject_HEAD_INIT(NULL)
    0,				/*ob_size*/
    "GetSetCArray",	/*tp_name*/
    sizeof(GetSetCArray),		/*tp_basicsize*/
    0,				/*tp_itemsize*/
    (destructor)GetSetCArray_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*/
    "GetSetCArray objects",		/* tp_doc */
    0,				/* tp_traverse */
    0,				/* tp_clear */
    0,				/* tp_richcompare */
    0,				/* tp_weaklistoffset */
    0,				/* tp_iter */
    0,				/* tp_iternext */
    GetSetCArray_methods,		/* tp_methods */
    GetSetCArray_members,		/* tp_members */
    GetSetCArray_getseters,		/* tp_getset */
    0,				/* tp_base */
    0,				/* tp_dict */
    0,				/* tp_descr_get */
    0,				/* tp_descr_set */
    0,				/* tp_dictoffset */
    (initproc)GetSetCArray_init,	/* tp_init */
    0,				/* tp_alloc */
    GetSetCArray_new,			/* tp_new */
};

static PyMethodDef module_methods[] = {
  {NULL}  /* Sentinel */
};


#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initgetsetcarray(void)
{
  PyObject* m;
  if (PyType_Ready(&GetSetCArrayType) < 0){ return; }

  m = Py_InitModule3( "getsetcarray", module_methods, "" );
  if (m == NULL){ return; }

  Py_INCREF(&GetSetCArrayType);
  PyModule_AddObject(m, "GetSetCArray", (PyObject *)&GetSetCArrayType);
  import_array();   /* required NumPy initialization */
}