summaryrefslogtreecommitdiff
path: root/numpy/lib/src/_compiled_base.c
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2007-12-30 09:32:31 +0000
committerTravis Oliphant <oliphant@enthought.com>2007-12-30 09:32:31 +0000
commitfdeac7465818652d5fb31e7e0e27f9debd0f54b8 (patch)
tree4d3146fdb9fb8f78eb6bf68891550e9b77b3ad44 /numpy/lib/src/_compiled_base.c
parent083ca64099268bc5967d25a15f9a4d26d750eb69 (diff)
parent50b26d2464f607566bf66986832636816eaa6d05 (diff)
downloadnumpy-fdeac7465818652d5fb31e7e0e27f9debd0f54b8.tar.gz
Merge the lib_for_io branch back into the trunk.
Diffstat (limited to 'numpy/lib/src/_compiled_base.c')
-rw-r--r--numpy/lib/src/_compiled_base.c272
1 files changed, 271 insertions, 1 deletions
diff --git a/numpy/lib/src/_compiled_base.c b/numpy/lib/src/_compiled_base.c
index 42c0183e8..654e7d95b 100644
--- a/numpy/lib/src/_compiled_base.c
+++ b/numpy/lib/src/_compiled_base.c
@@ -9,6 +9,9 @@ static PyObject *ErrorObject;
goto fail;} \
}
+#define PYSETERROR(message) \
+{ PyErr_SetString(ErrorObject, message); goto fail; }
+
static intp
incr_slot_ (double x, double *bins, intp lbins)
{
@@ -526,6 +529,269 @@ arr_add_docstring(PyObject *dummy, PyObject *args)
return Py_None;
}
+
+static char packbits_doc[] =
+ "out = numpy.packbits(myarray, axis=None)\n\n"
+ " myarray : an integer type array whose elements should be packed to bits\n\n"
+ " This routine packs the elements of a binary-valued dataset into a\n"
+ " NumPy array of type uint8 ('B') whose bits correspond to\n"
+ " the logical (0 or nonzero) value of the input elements.\n"
+ " The dimension over-which bit-packing is done is given by axis.\n"
+ " The shape of the output has the same number of dimensions as the input\n"
+ " (unless axis is None, in which case the output is 1-d).\n"
+ "\n"
+ " Example:\n"
+ " >>> a = array([[[1,0,1],\n"
+ " ... [0,1,0]],\n"
+ " ... [[1,1,0],\n"
+ " ... [0,0,1]]])\n"
+ " >>> b = numpy.packbits(a,axis=-1)\n"
+ " >>> b\n"
+ " array([[[160],[64]],[[192],[32]]], dtype=uint8)\n\n"
+ " Note that 160 = 128 + 32\n"
+ " 192 = 128 + 64\n";
+
+static char unpackbits_doc[] =
+ "out = numpy.unpackbits(myarray, axis=None)\n\n"
+ " myarray - array of uint8 type where each element represents a bit-field\n"
+ " that should be unpacked into a boolean output array\n\n"
+ " The shape of the output array is either 1-d (if axis is None) or\n"
+ " the same shape as the input array with unpacking done along the\n"
+ " axis specified.";
+
+/* PACKBITS
+
+ This function packs binary (0 or 1) 1-bit per pixel arrays
+ into contiguous bytes.
+
+*/
+
+static void
+_packbits(
+ void *In,
+ int element_size, /* in bytes */
+ npy_intp in_N,
+ npy_intp in_stride,
+ void *Out,
+ npy_intp out_N,
+ npy_intp out_stride
+ )
+{
+ char build;
+ int i, index;
+ npy_intp out_Nm1;
+ int maxi, remain, nonzero, j;
+ char *outptr,*inptr;
+
+ outptr = Out; /* pointer to output buffer */
+ inptr = In; /* pointer to input buffer */
+
+ /* Loop through the elements of In */
+ /* Determine whether or not it is nonzero.
+ Yes: set correspdoning bit (and adjust build value)
+ No: move on
+ /* Every 8th value, set the value of build and increment the outptr */
+
+ remain = in_N % 8; /* uneven bits */
+ if (remain == 0) remain = 8;
+ out_Nm1 = out_N - 1;
+ for (index = 0; index < out_N; index++) {
+ build = 0;
+ maxi = (index != out_Nm1 ? 8 : remain);
+ for (i = 0; i < maxi ; i++) {
+ build <<= 1; /* shift bits left one bit */
+ nonzero = 0;
+ for (j = 0; j < element_size; j++) /* determine if this number is non-zero */
+ nonzero += (*(inptr++) != 0);
+ inptr += (in_stride - element_size); /* advance to next input */
+ build += (nonzero != 0); /* add to this bit if the input value is non-zero */
+ }
+ if (index == out_Nm1) build <<= (8-remain);
+ /* printf("Here: %d %d %d %d\n",build,slice,index,maxi);
+ */
+ *outptr = build;
+ outptr += out_stride;
+ }
+ return;
+}
+
+
+static void
+_unpackbits(
+ void *In,
+ int el_size, /* unused */
+ npy_intp in_N,
+ npy_intp in_stride,
+ void *Out,
+ npy_intp out_N,
+ npy_intp out_stride
+ )
+{
+ unsigned char mask;
+ int i,index;
+ char *inptr, *outptr;
+
+ /* Loop through the elements of out
+ */
+ outptr = Out;
+ inptr = In;
+ for (index = 0; index < in_N; index++) {
+ mask = 128;
+ for (i = 0; i < 8 ; i++) {
+ *outptr = ((mask & (unsigned char)(*inptr)) != 0);
+ outptr += out_stride;
+ mask >>= 1;
+ }
+ inptr += in_stride;
+ }
+ return;
+}
+
+static PyObject *
+pack_or_unpack_bits(PyObject *input, int axis, int unpack)
+{
+ PyArrayObject *inp;
+ PyObject *new=NULL;
+ PyObject *out=NULL;
+ npy_intp outdims[MAX_DIMS];
+ int i;
+ void (*thefunc)(void *, int, npy_intp, npy_intp, void *, npy_intp, npy_intp);
+ PyArrayIterObject *it, *ot;
+
+ inp = (PyArrayObject *)PyArray_FROM_O(input);
+
+ if (inp == NULL) return NULL;
+
+ if (unpack) {
+ if (PyArray_TYPE(inp) != NPY_UBYTE)
+ PYSETERROR("Expecting an input array of unsigned byte data type");
+ }
+ else {
+ if (!PyArray_ISINTEGER(inp))
+ PYSETERROR("Expecting an input array of integer data type");
+ }
+
+ new = PyArray_CheckAxis(inp, &axis, 0);
+ Py_DECREF(inp);
+ if (new == NULL) return NULL;
+
+ /* Handle zero-dim array separately */
+ if (PyArray_SIZE(new) == 0) {
+ return PyArray_Copy((PyArrayObject *)new);
+ }
+
+ if (PyArray_NDIM(new) == 0) {
+ if (unpack) {
+ /* Handle 0-d array by converting it to a 1-d array */
+ PyObject *temp;
+ PyArray_Dims newdim = {NULL, 1};
+ npy_intp shape=1;
+ newdim.ptr = &shape;
+ temp = PyArray_Newshape((PyArrayObject *)new, &newdim, NPY_CORDER);
+ if (temp == NULL) goto fail;
+ Py_DECREF(new);
+ new = temp;
+ }
+ else {
+ ubyte *optr, *iptr;
+ out = PyArray_New(new->ob_type, 0, NULL, NPY_UBYTE,
+ NULL, NULL, 0, 0, NULL);
+ if (out == NULL) goto fail;
+ optr = PyArray_DATA(out);
+ iptr = PyArray_DATA(new);
+ *optr = 0;
+ for (i=0; i<PyArray_ITEMSIZE(new); i++) {
+ if (*iptr != 0) {
+ *optr = 1;
+ break;
+ }
+ iptr++;
+ }
+ goto finish;
+ }
+ }
+
+
+ /* Setup output shape */
+ for (i=0; i<PyArray_NDIM(new); i++) {
+ outdims[i] = PyArray_DIM(new, i);
+ }
+
+ if (unpack) {
+ /* Multiply axis dimension by 8 */
+ outdims[axis] <<= 3;
+ thefunc = _unpackbits;
+ }
+ else {
+ /* Divide axis dimension by 8 */
+ /* 8 -> 1, 9 -> 2, 16 -> 2, 17 -> 3 etc.. */
+ outdims[axis] = ((outdims[axis] - 1) >> 3) + 1;
+ thefunc = _packbits;
+ }
+
+ /* Create output array */
+ out = PyArray_New(new->ob_type, PyArray_NDIM(new), outdims, PyArray_UBYTE,
+ NULL, NULL, 0, PyArray_ISFORTRAN(new), NULL);
+ if (out == NULL) goto fail;
+
+ /* Setup iterators to iterate over all but given axis */
+ it = (PyArrayIterObject *)PyArray_IterAllButAxis((PyObject *)new, &axis);
+ ot = (PyArrayIterObject *)PyArray_IterAllButAxis((PyObject *)out, &axis);
+ if (it == NULL || ot == NULL) {
+ Py_XDECREF(it);
+ Py_XDECREF(ot);
+ goto fail;
+ }
+
+ while(PyArray_ITER_NOTDONE(it)) {
+ thefunc(PyArray_ITER_DATA(it), PyArray_ITEMSIZE(new),
+ PyArray_DIM(new, axis), PyArray_STRIDE(new, axis),
+ PyArray_ITER_DATA(ot), PyArray_DIM(out, axis),
+ PyArray_STRIDE(out, axis));
+ PyArray_ITER_NEXT(it);
+ PyArray_ITER_NEXT(ot);
+ }
+ Py_DECREF(it);
+ Py_DECREF(ot);
+
+ finish:
+ Py_DECREF(new);
+ return out;
+
+ fail:
+ Py_XDECREF(new);
+ Py_XDECREF(out);
+ return NULL;
+}
+
+
+
+static PyObject *
+io_pack(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+ int axis=NPY_MAXDIMS;
+ static char *kwlist[] = {"in", "axis", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&" , kwlist,
+ &obj, PyArray_AxisConverter, &axis))
+ return NULL;
+ return pack_or_unpack_bits(obj, axis, 0);
+}
+
+static PyObject *
+io_unpack(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+ int axis=NPY_MAXDIMS;
+ static char *kwlist[] = {"in", "axis", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&" , kwlist,
+ &obj, PyArray_AxisConverter, &axis))
+ return NULL;
+ return pack_or_unpack_bits(obj, axis, 1);
+}
+
static struct PyMethodDef methods[] = {
{"_insert", (PyCFunction)arr_insert, METH_VARARGS | METH_KEYWORDS,
arr_insert__doc__},
@@ -537,6 +803,10 @@ static struct PyMethodDef methods[] = {
NULL},
{"add_docstring", (PyCFunction)arr_add_docstring, METH_VARARGS,
NULL},
+ {"packbits", (PyCFunction)io_pack, METH_VARARGS | METH_KEYWORDS,
+ packbits_doc},
+ {"unpackbits", (PyCFunction)io_unpack, METH_VARARGS | METH_KEYWORDS,
+ unpackbits_doc},
{NULL, NULL} /* sentinel */
};
@@ -578,7 +848,7 @@ PyMODINIT_FUNC init_compiled_base(void) {
PyDict_SetItemString(d, "__version__", s);
Py_DECREF(s);
- ErrorObject = PyString_FromString("numpy.lib._compiled_base.error");
+ ErrorObject = PyString_FromString("numpy.lib.error");
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);