Numpy Toy Box / carraywrap / carraywrapmodule.c

#include <Python.h>
#include "structmember.h"
#include <numpy/arrayobject.h>

#define CARRAYWRAP_VERBOSE
#define CARRAYWRAP_MAXDIM 3

typedef struct __CArrayWrap__{
  PyObject_HEAD
  char *data, *array;
  int ndim, dims[CARRAYWRAP_MAXDIM];
  PyObject *nparray;
} CArrayWrap;

static void       CArrayWrap_dealloc(CArrayWrap* self);
static PyObject * CArrayWrap_new(PyTypeObject *type,
				 PyObject *args, PyObject *kwds);
static int CArrayWrap_init(CArrayWrap *self, PyObject *args, PyObject *kwds);
static int CArrayWrap_traverse(CArrayWrap *self, visitproc visit, void *arg);
static int CArrayWrap_clear(CArrayWrap *self);

static void print_indent(int inum)
{
  int i;
  for (i = 0; i < inum; ++i){
    printf("  ");
  }
}

static void print_array_i1d(int *a1d, int *dims, int inum)
{
  int i;
  print_indent(inum);
  printf("[%d]", dims[0]);
  for (i = 0; i < dims[0]; ++i){
    printf(" %d", a1d[i]);
  }
  printf("\n");
}

static void print_array_i2d(int **a2d, int *dims, int inum)
{
  int i;
  print_indent(inum);
  printf("[%d]\n", dims[0]);
  for (i = 0; i < dims[0]; ++i){
    print_array_i1d(a2d[i], dims+1, inum+1);
  }
}

static void print_array_i3d(int ***a3d, int *dims, int inum)
{
  int i;
  print_indent(inum);
  printf("[%d]\n", dims[0]);
  for (i = 0; i < dims[0]; ++i){
    print_array_i2d(a3d[i], dims+1, inum+1);
  }
}

static PyObject *
CArrayWrap_print_array(CArrayWrap *self)
{
  switch(self->ndim){
  case 1:
    print_array_i1d((int *)self->array, self->dims, 0);
    break;
  case 2:
    print_array_i2d((int **)self->array, self->dims, 0);
    break;
  case 3:
    print_array_i3d((int ***)self->array, self->dims, 0);
    break;
  }

  return Py_BuildValue("");  /* return None */
}

static PyMemberDef CArrayWrap_members[] = {
  {"nparray", T_OBJECT_EX, offsetof(CArrayWrap, nparray), 0, "numpy array"},
  {NULL}  /* Sentinel */
};

static PyGetSetDef CArrayWrap_getseters[] = {
  {NULL}  /* Sentinel */
};

static PyMethodDef CArrayWrap_methods[] = {
  {"print_array",
   (PyCFunction)CArrayWrap_print_array, METH_VARARGS, "print array"},
  {NULL}  /* Sentinel */
};

static PyTypeObject CArrayWrapType = {
    PyObject_HEAD_INIT(NULL)
    0,				/*ob_size*/
    "CArrayWrap",	/*tp_name*/
    sizeof(CArrayWrap),		/*tp_basicsize*/
    0,				/*tp_itemsize*/
    (destructor)CArrayWrap_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 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
    /* Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/\*tp_flags*\/ */
    "CArrayWrap objects",		/* tp_doc */
    (traverseproc)CArrayWrap_traverse,   /* tp_traverse */
    (inquiry)CArrayWrap_clear,           /* tp_clear */
    0,				/* tp_richcompare */
    0,				/* tp_weaklistoffset */
    0,				/* tp_iter */
    0,				/* tp_iternext */
    CArrayWrap_methods,		/* tp_methods */
    CArrayWrap_members,		/* tp_members */
    CArrayWrap_getseters,		/* tp_getset */
    0,				/* tp_base */
    0,				/* tp_dict */
    0,				/* tp_descr_get */
    0,				/* tp_descr_set */
    0,				/* tp_dictoffset */
    (initproc)CArrayWrap_init,	/* tp_init */
    0,				/* tp_alloc */
    CArrayWrap_new,			/* tp_new */
};

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


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

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

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

static int
CArrayWrap_traverse(CArrayWrap *self, visitproc visit, void *arg)
{
  Py_VISIT(self->nparray);
  return 0;
}

static int
CArrayWrap_clear(CArrayWrap *self)
{
  Py_CLEAR(self->nparray);
  return 0;
}

static void
CArrayWrap_dealloc(CArrayWrap* self)
{
#ifdef CARRAYWRAP_VERBOSE
  printf("'%s' called\n", __func__);
#endif
  CArrayWrap_clear(self);
  free(self->data);
  switch(self->ndim){
  case 2:
    free(self->array);
    break;
  case 3:
    free(((char **)self->array)[0]);
    free(self->array);
    break;
  }
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
CArrayWrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  CArrayWrap *self;
#ifdef CARRAYWRAP_VERBOSE
  printf("'%s' called\n", __func__);
#endif
  self = (CArrayWrap *)type->tp_alloc(type, 0);
  if (self == NULL){
    return NULL;
  }
  self->ndim = 0;
  self->nparray = Py_BuildValue("");
  if (self->nparray == NULL){
    Py_DECREF(self);
    return NULL;
  }
  return (PyObject *)self;
}

static int
CArrayWrap_init(CArrayWrap *self, PyObject *args, PyObject *kwds)
{
  PyObject *obj, *tmp;
  int i, elemnum;
#ifdef CARRAYWRAP_VERBOSE
  printf("'%s' called\n", __func__);
#endif

  if (!PyTuple_Check(args)){
    PyErr_SetString( PyExc_TypeError, "bad arguments");
    goto fail;
  }
  /* check ndims */
  self->ndim = PyTuple_Size(args);
  if (self->ndim > CARRAYWRAP_MAXDIM){
    PyErr_SetString( PyExc_ValueError, "too many arguments (ndim)");
    goto fail;
  }
  /* set self->dims */
  elemnum = 1;
  for (i = 0; i < self->ndim; ++i){
    obj = PyTuple_GetItem(args, i);
    if (!PyInt_Check(obj)){
      PyErr_Format( PyExc_ValueError, "value(%d) is not int", i);
      goto fail;
    }
    self->dims[i] = PyInt_AsLong(obj);
    if (self->dims[i] < 0){
      PyErr_Format( PyExc_ValueError,
		    "cannot get value(%d) or the value is not positive", i);
      goto fail;
    }
    elemnum *= self->dims[i];
  }
  /* alloc self->data */
  self->data = (char *)malloc(elemnum*sizeof(int));
  if (self->data == NULL){
    PyErr_SetString( PyExc_RuntimeError, "malloc for data fails");
    goto fail;
  }
  /* set pointer */
  switch(self->ndim){
  case 1:
    self->array = self->data;
    break;
  case 2:
    {
      int **a2d;
      a2d = (int**)malloc(self->dims[0]*sizeof(int*));
      a2d[0] = (int*)self->data;
      for (i = 1; i < self->dims[0]; i++){
	a2d[i] = a2d[0] + i * self->dims[1];
      }
      self->array = (char*)a2d;
    }
    break;
  case 3:
    {
      int ***a3d;
      int j;
      a3d = (int***)malloc(self->dims[0]*sizeof(int**));
      a3d[0] = (int**)malloc(self->dims[0]*self->dims[1]*sizeof(int*));
      a3d[0][0] = (int*)self->data;
      for (i = 0; i < self->dims[0]; i++) {
	a3d[i] = a3d[0] + i * self->dims[1];
	for (j = 0; j < self->dims[1]; j++){
	  a3d[i][j] = a3d[0][0]
	    + i * self->dims[1]*self->dims[2] + j * self->dims[2];
	}
      }
      self->array = (char*)a3d;
    }
    break;
  }

  tmp = self->nparray;
  self->nparray =
    PyArray_SimpleNewFromData( self->ndim, self->dims, NPY_LONG,
			       (void *)self->data );
  if (self->nparray == NULL){
    PyErr_SetString( PyExc_RuntimeError, "PyArray_SimpleNewFromData fails");
    goto fail;
  }
  Py_INCREF(self->nparray);
  Py_XDECREF(tmp);

/* #define CARRAYWRAP_TEST_OWNDATA_FAIL */
#ifndef CARRAYWRAP_TEST_OWNDATA_FAIL
  Py_INCREF(self);
  PyArray_BASE(self->nparray) = (PyObject *)self;
#endif

  return 0;
 fail:
  free(self->data);
  self->ndim = 0;
  return -1;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.