"""This module generates the "bytes" module which contains various byte munging C functions: copying, alignment, byteswapping, choosing, putting, taking. WARNING: This module exists solely as a mechanism to generate a portion of numarray and is not intended to provide any post-installation functionality. """ from basecode import CodeGenerator, template, _HEADER BYTES_HEADER = _HEADER + \ ''' #include #define NA_ACOPYN(i, o) memcpy(o, i, N) /* The following is used to copy nbytes of data for each element. ** ** As such it can be used to align any sort of data provided the ** ** output pointers used are aligned */ static int copyNbytes(long dim, long nbytes, maybelong *niters, void *input, long inboffset, maybelong *inbstrides, void *output, long outboffset, maybelong *outbstrides) { long i, j; char *tin = (char *) input + inboffset; char *tout = (char *) output + outboffset; if (dim == 0) { for (i=0; i=0; i--) { otemp = PySequence_GetItem(nitersObj, i); if (PyInt_Check(otemp)) ltemp = PyInt_AsLong(otemp); else if (PyLong_Check(otemp)) ltemp = PyLong_AsLong(otemp); else return PyErr_Format(PyExc_TypeError, "copyToString: non-integer shape element"); nelements *= ltemp; niters[nniters-i-1] = ltemp; Py_DECREF(otemp); otemp = PySequence_GetItem(inbstridesObj, i); if (PyInt_Check(otemp)) inbstrides[nniters-i-1] = PyInt_AsLong(otemp); else if (PyLong_Check(otemp)) inbstrides[nniters-i-1] = PyLong_AsLong(otemp); else return PyErr_Format(PyExc_TypeError, "copyToString: non-integer stride element"); Py_DECREF(otemp); } if (!nelements) return PyString_FromStringAndSize("", 0); outbstrides[0] = nbytes; for (i=1; i= max) \ i -= max; static int takeNbytes(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { maybelong i, cMode, N; maybelong *scatteredstrides, *scatteredshape, **indices; char *gathered, *scattered; maybelong nindices = ninargs-4, outi = ninargs+noutargs-1; if (NA_checkIo("takeNbytes", 4, 1, MIN(ninargs, 4), noutargs)) return -1; if (nindices == 0) return 0; if (NA_checkOneCBuffer("takeNbytes", 2, buffers[0], bsizes[0], sizeof(maybelong))) return -1; else { cMode = ((maybelong *) buffers[0])[0]; N = ((maybelong *) buffers[0])[1]; } if (NA_checkOneCBuffer("takeNbytes", nindices, buffers[2], bsizes[2], sizeof(maybelong))) return -1; else { scatteredstrides = (maybelong *) buffers[2]; } if (NA_checkOneCBuffer("takeNbytes", nindices, buffers[3], bsizes[3], sizeof(maybelong))) return -1; else { scatteredshape = (maybelong *) buffers[3]; } if (NA_checkOneStriding("takeNBytes", nindices, scatteredshape, 0, scatteredstrides, bsizes[1], N, 0)) return -1; else scattered = (char *) buffers[1]; for(i=4; i= scatteredshape[j]) k = scatteredshape[j]-1; index += scatteredstrides[j]*k; } memcpy( &gathered[i*N], scattered+index, N); } break; case RAISE: for(i=0; i= scatteredshape[j]) { PyErr_Format(PyExc_IndexError, "Index out of range"); return -1; } index += scatteredstrides[j]*k; } memcpy( &gathered[i*N], scattered+index, N); } break; } return 0; } SELF_CHECKED_CFUNC_DESCR(takeNbytes, CFUNC_UFUNC); static int putNbytes(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { maybelong i, cMode, N; maybelong *scatteredstrides, *scatteredshape, **indices; char *gathered, *scattered; long nindices = ninargs-4, outi = ninargs+noutargs-1; if (nindices == 0) return 0; if (NA_checkIo("putNbytes", 4, 1, MIN(ninargs, 4), noutargs)) return -1; if (NA_checkOneCBuffer("putNbytes", 2, buffers[0], bsizes[0], sizeof(maybelong))) return -1; else { cMode = ((maybelong *) buffers[0])[0]; N = ((maybelong *) buffers[0])[1]; } if (NA_checkOneCBuffer("putNbytes", niter*N, buffers[1], bsizes[1], 1)) return -1; else gathered = (char *) buffers[1]; if (NA_checkOneCBuffer("putNbytes", nindices, buffers[2], bsizes[2], sizeof(maybelong))) return -1; else { scatteredstrides = (maybelong *) buffers[2]; } if (NA_checkOneCBuffer("putNbytes", nindices, buffers[3], bsizes[3], sizeof(maybelong))) return -1; else { scatteredshape = (maybelong *) buffers[3]; } for(i=4; i= scatteredshape[j]) k = scatteredshape[j]-1; index += scatteredstrides[j]*k; } memcpy( scattered+index, &gathered[i*N], N); } break; case RAISE: for(i=0; i= scatteredshape[j]) { PyErr_Format(PyExc_IndexError, "Index out of range"); return -1; } index += scatteredstrides[j]*k; } memcpy( scattered+index, &gathered[i*N], N); } break; } return 0; } SELF_CHECKED_CFUNC_DESCR(putNbytes, CFUNC_UFUNC); ''' COPY_TEMPLATE = \ ''' /******************************************* * * * These copy data to a contiguous buffer. * * They do not handle non-aligned data. * * Offsets and Strides are in byte units * * * *******************************************/ static int copybytes(long dim, long dummy, maybelong *niters, void *input, long inboffset, maybelong *inbstrides, void *output, long outboffset, maybelong *outbstrides) { long i; char *tin = (char *) input + inboffset; char *tout = (char *) output + outboffset; if (dim == 0) { for (i=0; i(tin, tout); tin += inbstrides[dim]; tout += outbstrides[dim]; } } else { for (i=0; ibytes(dim-1, dummy, niters, input, inboffset + i*inbstrides[dim], inbstrides, output, outboffset + i*outbstrides[dim], outbstrides); } } return 0; } STRIDING_DESCR2(copybytes, CHECK_ALIGN, , ); ''' ALIGN_TEMPLATE = \ ''' static int alignbytes(long dim, long dummy, maybelong *niters, void *input, long inboffset, maybelong *inbstrides, void *output, long outboffset, maybelong *outbstrides) { return copyNbytes(dim, , niters, input, inboffset, inbstrides, output, outboffset, outbstrides); } STRIDING_DESCR2(alignbytes, !CHECK_ALIGN, , ); ''' BYTESWAP_TEMPLATE = \ ''' /******* byteswap *****/ static int byteswap(long dim, long dummy, maybelong *niters, void *input, long inboffset, maybelong *inbstrides, void *output, long outboffset, maybelong *outbstrides) { long i; char *tin = (char *) input + inboffset; char *tout = (char *) output + outboffset; if (dim == 0) { for (i=0; i]; NA_COPY(tin, t); (t, tout); tin += inbstrides[dim]; tout += outbstrides[dim]; } } else { for (i=0; i(dim-1, dummy, niters, input, inboffset + i*inbstrides[dim], inbstrides, output, outboffset + i*outbstrides[dim], outbstrides); } } return 0; } STRIDING_DESCR2(byteswap, !CHECK_ALIGN, , ); ''' CHOOSE_TEMPLATE = \ ''' static int choosebytes(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { maybelong i, cMode, maxP, N, *selector; char **population, *output; int outi = ninargs + noutargs - 1; if (NA_checkIo("choosebytes", 2, 1, MIN(ninargs,2), noutargs)) return -1; if (NA_checkOneCBuffer("choosebytes", 2, buffers[0], bsizes[0], sizeof(maybelong))) return -1; else { cMode = ((maybelong *) buffers[0])[0]; N = ((maybelong *) buffers[0])[1]; } if (NA_checkOneCBuffer("choosebytes", niter, buffers[1], bsizes[1], sizeof(maybelong))) return -1; else selector = (maybelong *) buffers[1]; if (ninargs-2 == 0) return 0; else maxP = ninargs-2; for(i=2; ibytes", niter, buffers[i], bsizes[i], )) return -1; population = (char **) &buffers[2]; if (NA_checkOneCBuffer("choosebytes", niter, buffers[outi], bsizes[outi], )) return -1; else output = (char *) buffers[outi]; if (maxP == 0) return 0; switch(cMode) { case WRAPPED: for(i=0; i(&population[j][i*], &output[i*]); } break; default: case CLIPPED: for(i=0; i= maxP) j = maxP-1; NA_ACOPY(&population[j][i*], &output[i*]); } break; case RAISE: for(i=0; i= maxP)) { PyErr_Format(PyExc_IndexError, "Index out of range"); return -1; } NA_ACOPY(&population[j][i*], &output[i*]); } break; } return 0; } SELF_CHECKED_CFUNC_DESCR(choosebytes, CFUNC_UFUNC); ''' BYTES_TEMPLATE = ( COPY_TEMPLATE + ALIGN_TEMPLATE + BYTESWAP_TEMPLATE + CHOOSE_TEMPLATE ) # ============================================================================ # IMPORTANT: no <>-sugared strings below this point # translate --> %(var)s in templates seen *so far* template.sugar_dict(globals()) # ============================================================================ bytesconfig = [ ["1", "Int8"], ["2", "Int16"], ["4", "Int32"], ["8", "Float64"], ["16", "Complex64"], ]; class BytesParams: def __init__(self, size, type): self.size = size self.sizename = str(size) + "bytes" self.typename = type self.swapkind = "NA_SWAP" NBytesParams = BytesParams("N","AnyType") class ComplexBytesParams: def __init__(self, size, type): self.size = size self.sizename = type self.typename = type self.swapkind = "NA_COMPLEX_SWAP" Complex32BytesCfg = ComplexBytesParams(8, "Complex32") Complex64BytesCfg = ComplexBytesParams(16, "Complex64") class BytesCodeGenerator(CodeGenerator): def __init__(self, *components): CodeGenerator.__init__(self, *components) self.module = "_bytes" self.qualified_module = "numarray._bytes" def gen_body(self): for cfg in bytesconfig: t = apply(BytesParams, cfg) self.codelist.append((self.separator + BYTES_TEMPLATE) % t.__dict__) self.addcfunc("copy"+ t.sizename) self.addcfunc("byteswap"+t.sizename) self.addcfunc("align"+t.sizename) self.addcfunc("choose"+t.sizename) self.codelist.append((self.separator + CHOOSE_TEMPLATE) % NBytesParams.__dict__) self.addcfunc("chooseNbytes") self.addcfunc("copyNbytes") self.addcfunc("putNbytes") self.addcfunc("takeNbytes") # Hack in the type based (not size based) methods for complex self.codelist.append((self.separator + BYTESWAP_TEMPLATE) % Complex32BytesCfg.__dict__) self.addcfunc("byteswapComplex32" ) self.codelist.append((self.separator + BYTESWAP_TEMPLATE) % Complex64BytesCfg.__dict__) self.addcfunc("byteswapComplex64" ) self.addmethod("copyToString") generate_bytes_code = BytesCodeGenerator(BYTES_HEADER)