static PyObject * unitRowVectors(PyObject *self, PyObject *args) { PyArrayObject *vecIn, *vecOut; double *cIn, *cOut; int d; npy_intp m,n; if ( !PyArg_ParseTuple(args,"O", &vecIn)) return(NULL); if ( vecIn == NULL ) return(NULL); assert( PyArray_ISCONTIGUOUS(vecIn) ); assert( PyArray_ISALIGNED(vecIn) ); d = PyArray_NDIM(vecIn); assert(d == 2); m = PyArray_DIMS(vecIn)[0]; n = PyArray_DIMS(vecIn)[1]; vecOut = (PyArrayObject*)PyArray_EMPTY(d,PyArray_DIMS(vecIn),NPY_DOUBLE,0); cIn = (double*)PyArray_DATA(vecIn); cOut = (double*)PyArray_DATA(vecOut); unitRowVectors_cfunc(m,n,cIn,cOut); return((PyObject*)vecOut); }
fff_array* fff_array_fromPyArray(const PyArrayObject* x) { fff_array* y; fff_datatype datatype; unsigned int nbytes; size_t dimX = 1, dimY = 1, dimZ = 1, dimT = 1; size_t offX = 0, offY = 0, offZ = 0, offT = 0; size_t ndims = (size_t)PyArray_NDIM(x); /* Check that the input array has less than four dimensions */ if (ndims > 4) { FFF_ERROR("Input array has more than four dimensions", EINVAL); return NULL; } /* Check that the input array is aligned */ if (! PyArray_ISALIGNED(x)) { FFF_ERROR("Input array is not aligned", EINVAL); return NULL; } /* Match the data type */ datatype = fff_datatype_fromNumPy(PyArray_TYPE(x)); if (datatype == FFF_UNKNOWN_TYPE) { FFF_ERROR("Unrecognized data type", EINVAL); return NULL; } /* Dimensions and offsets */ nbytes = fff_nbytes(datatype); dimX = PyArray_DIM(x, 0); offX = PyArray_STRIDE(x, 0)/nbytes; if (ndims > 1) { dimY = PyArray_DIM(x, 1); offY = PyArray_STRIDE(x, 1)/nbytes; if (ndims > 2) { dimZ = PyArray_DIM(x, 2); offZ = PyArray_STRIDE(x, 2)/nbytes; if (ndims > 3) { dimT = PyArray_DIM(x, 3); offT = PyArray_STRIDE(x, 3)/nbytes; } } } /* Create array (not owner) */ y = (fff_array*)malloc(sizeof(fff_array)); *y = fff_array_view(datatype, (void*) PyArray_DATA(x), dimX, dimY, dimZ, dimT, offX, offY, offZ, offT); return y; }
T ndarray_cast(PyArrayObject* a) { typedef typename no_ptr<T>::type base_type; assert(check_type<base_type>(a)); assert(PyArray_ISALIGNED(a)); // The reason for the intermediate ``as_voidp`` variable is the following: // around version 1.7.0, numpy played with having ``PyArray_DATA`` return // ``char*`` as opposed to ``void*``. ``reinterpret_cast`` from void* was // actually against the standard in C++ pre C++11 (although G++ accepts // it). // // This roundabout way works on all these versions. void* as_voidp = PyArray_DATA(a); return const_cast<T>(static_cast<T>(as_voidp)); }
void throw_array_conversion_error(PyObject* object, int flags, int rank_range, PyArray_Descr* descr) { if (!PyArray_Check(object)) PyErr_Format(PyExc_TypeError, "expected numpy array, got %s", object->ob_type->tp_name); else if (!PyArray_EquivTypes(PyArray_DESCR((PyArrayObject*)object), descr)) PyErr_Format(PyExc_TypeError, "expected array type %s, got %s", descr->typeobj->tp_name, PyArray_DESCR((PyArrayObject*)object)->typeobj->tp_name); else if (!PyArray_CHKFLAGS((PyArrayObject*)object,flags)){ if (flags&NPY_ARRAY_WRITEABLE && !PyArray_ISWRITEABLE((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "unwriteable array"); else if (flags&NPY_ARRAY_ALIGNED && !PyArray_ISALIGNED((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "unaligned array"); else if (flags&NPY_ARRAY_C_CONTIGUOUS && !PyArray_ISCONTIGUOUS((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "noncontiguous array"); else PyErr_SetString(PyExc_TypeError, "unknown array flag mismatch");} else if (rank_range>=0) PyErr_Format(PyExc_ValueError, "expected rank %d, got %d", rank_range, PyArray_NDIM((PyArrayObject*)object)); else PyErr_Format(PyExc_ValueError, "expected rank at least %d, got %d", -rank_range-1, PyArray_NDIM((PyArrayObject*)object)); throw PythonError(); }
/* Get a fff_matrix from an input PyArray. This function acts as a fff_vector constructor that is compatible with fff_vector_delete. */ fff_matrix* fff_matrix_fromPyArray(const PyArrayObject* x) { fff_matrix* y; npy_intp dim[2]; PyArrayObject* xd; /* Check that the input object is a two-dimensional array */ if (PyArray_NDIM(x) != 2) { FFF_ERROR("Input array is not a matrix", EINVAL); return NULL; } /* If the PyArray is double, contiguous and aligned just wrap without copying */ if ((PyArray_TYPE(x) == NPY_DOUBLE) && (PyArray_ISCONTIGUOUS(x)) && (PyArray_ISALIGNED(x))) { y = (fff_matrix*) malloc(sizeof(fff_matrix)); y->size1 = (size_t) PyArray_DIM(x,0); y->size2 = (size_t) PyArray_DIM(x,1); y->tda = y->size2; y->data = (double*) PyArray_DATA(x); y->owner = 0; } /* Otherwise, output a owner (contiguous) matrix with copied data */ else { size_t dim0 = PyArray_DIM(x,0), dim1 = PyArray_DIM(x,1); y = fff_matrix_new((size_t)dim0, (size_t)dim1); dim[0] = dim0; dim[1] = dim1; xd = (PyArrayObject*) PyArray_SimpleNewFromData(2, dim, NPY_DOUBLE, (void*)y->data); PyArray_CastTo(xd, (PyArrayObject*)x); Py_XDECREF(xd); } return y; }
bool is_aligned() const { return PyArray_ISALIGNED(array_); }
aligned_iterator_type(PyArrayObject* array) :iterator_base<BaseType>(array) { assert(PyArray_ISALIGNED(array)); }
static PyObject * PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out, int axis, int otype) { PyArrayObject *op[2]; PyArray_Descr *op_dtypes[2] = {NULL, NULL}; int op_axes_arrays[2][NPY_MAXDIMS]; int *op_axes[2] = {op_axes_arrays[0], op_axes_arrays[1]}; npy_uint32 op_flags[2]; int idim, ndim, otype_final; int needs_api, need_outer_iterator; NpyIter *iter = NULL, *iter_inner = NULL; /* The selected inner loop */ PyUFuncGenericFunction innerloop = NULL; void *innerloopdata = NULL; const char *ufunc_name = ufunc->name ? ufunc->name : "(unknown)"; /* These parameters come from extobj= or from a TLS global */ int buffersize = 0, errormask = 0; NPY_BEGIN_THREADS_DEF; NPY_UF_DBG_PRINT1("\nEvaluating ufunc %s.accumulate\n", ufunc_name); #if 0 printf("Doing %s.accumulate on array with dtype : ", ufunc_name); PyObject_Print((PyObject *)PyArray_DESCR(arr), stdout, 0); printf("\n"); #endif if (_get_bufsize_errmask(NULL, "accumulate", &buffersize, &errormask) < 0) { return NULL; } /* Take a reference to out for later returning */ Py_XINCREF(out); otype_final = otype; if (get_binary_op_function(ufunc, &otype_final, &innerloop, &innerloopdata) < 0) { PyArray_Descr *dtype = PyArray_DescrFromType(otype); PyErr_Format(PyExc_ValueError, "could not find a matching type for %s.accumulate, " "requested type has type code '%c'", ufunc_name, dtype ? dtype->type : '-'); Py_XDECREF(dtype); goto fail; } ndim = PyArray_NDIM(arr); /* * Set up the output data type, using the input's exact * data type if the type number didn't change to preserve * metadata */ if (PyArray_DESCR(arr)->type_num == otype_final) { if (PyArray_ISNBO(PyArray_DESCR(arr)->byteorder)) { op_dtypes[0] = PyArray_DESCR(arr); Py_INCREF(op_dtypes[0]); } else { op_dtypes[0] = PyArray_DescrNewByteorder(PyArray_DESCR(arr), NPY_NATIVE); } } else { op_dtypes[0] = PyArray_DescrFromType(otype_final); } if (op_dtypes[0] == NULL) { goto fail; } #if NPY_UF_DBG_TRACING printf("Found %s.accumulate inner loop with dtype : ", ufunc_name); PyObject_Print((PyObject *)op_dtypes[0], stdout, 0); printf("\n"); #endif /* Set up the op_axes for the outer loop */ for (idim = 0; idim < ndim; ++idim) { op_axes_arrays[0][idim] = idim; op_axes_arrays[1][idim] = idim; } /* The per-operand flags for the outer loop */ op_flags[0] = NPY_ITER_READWRITE | NPY_ITER_NO_BROADCAST | NPY_ITER_ALLOCATE | NPY_ITER_NO_SUBTYPE; op_flags[1] = NPY_ITER_READONLY; op[0] = out; op[1] = arr; need_outer_iterator = (ndim > 1); /* We can't buffer, so must do UPDATEIFCOPY */ if (!PyArray_ISALIGNED(arr) || (out && !PyArray_ISALIGNED(out)) || !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(arr)) || (out && !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(out)))) { need_outer_iterator = 1; } if (need_outer_iterator) { int ndim_iter = 0; npy_uint32 flags = NPY_ITER_ZEROSIZE_OK| NPY_ITER_REFS_OK; PyArray_Descr **op_dtypes_param = NULL; /* * The way accumulate is set up, we can't do buffering, * so make a copy instead when necessary. */ ndim_iter = ndim; flags |= NPY_ITER_MULTI_INDEX; /* Add some more flags */ op_flags[0] |= NPY_ITER_UPDATEIFCOPY|NPY_ITER_ALIGNED; op_flags[1] |= NPY_ITER_COPY|NPY_ITER_ALIGNED; op_dtypes_param = op_dtypes; op_dtypes[1] = op_dtypes[0]; NPY_UF_DBG_PRINT("Allocating outer iterator\n"); iter = NpyIter_AdvancedNew(2, op, flags, NPY_KEEPORDER, NPY_UNSAFE_CASTING, op_flags, op_dtypes_param, ndim_iter, op_axes, NULL, 0); if (iter == NULL) { goto fail; } /* In case COPY or UPDATEIFCOPY occurred */ op[0] = NpyIter_GetOperandArray(iter)[0]; op[1] = NpyIter_GetOperandArray(iter)[1]; if (PyArray_SIZE(op[0]) == 0) { if (out == NULL) { out = op[0]; Py_INCREF(out); } goto finish; } if (NpyIter_RemoveAxis(iter, axis) != NPY_SUCCEED) { goto fail; } if (NpyIter_RemoveMultiIndex(iter) != NPY_SUCCEED) { goto fail; } } /* Get the output */ if (out == NULL) { if (iter) { op[0] = out = NpyIter_GetOperandArray(iter)[0]; Py_INCREF(out); } else { PyArray_Descr *dtype = op_dtypes[0]; Py_INCREF(dtype); op[0] = out = (PyArrayObject *)PyArray_NewFromDescr( &PyArray_Type, dtype, ndim, PyArray_DIMS(op[1]), NULL, NULL, 0, NULL); if (out == NULL) { goto fail; } } } /* * If the reduction axis has size zero, either return the reduction * unit for UFUNC_REDUCE, or return the zero-sized output array * for UFUNC_ACCUMULATE. */ if (PyArray_DIM(op[1], axis) == 0) { goto finish; } else if (PyArray_SIZE(op[0]) == 0) { goto finish; } if (iter && NpyIter_GetIterSize(iter) != 0) { char *dataptr_copy[3]; npy_intp stride_copy[3]; npy_intp count_m1, stride0, stride1; NpyIter_IterNextFunc *iternext; char **dataptr; int itemsize = op_dtypes[0]->elsize; /* Get the variables needed for the loop */ iternext = NpyIter_GetIterNext(iter, NULL); if (iternext == NULL) { goto fail; } dataptr = NpyIter_GetDataPtrArray(iter); /* Execute the loop with just the outer iterator */ count_m1 = PyArray_DIM(op[1], axis)-1; stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis); NPY_UF_DBG_PRINT("UFunc: Reduce loop with just outer iterator\n"); stride0 = PyArray_STRIDE(op[0], axis); stride_copy[0] = stride0; stride_copy[1] = stride1; stride_copy[2] = stride0; needs_api = NpyIter_IterationNeedsAPI(iter); NPY_BEGIN_THREADS_NDITER(iter); do { dataptr_copy[0] = dataptr[0]; dataptr_copy[1] = dataptr[1]; dataptr_copy[2] = dataptr[0]; /* * Copy the first element to start the reduction. * * Output (dataptr[0]) and input (dataptr[1]) may point to * the same memory, e.g. np.add.accumulate(a, out=a). */ if (otype == NPY_OBJECT) { /* * Incref before decref to avoid the possibility of the * reference count being zero temporarily. */ Py_XINCREF(*(PyObject **)dataptr_copy[1]); Py_XDECREF(*(PyObject **)dataptr_copy[0]); *(PyObject **)dataptr_copy[0] = *(PyObject **)dataptr_copy[1]; } else { memmove(dataptr_copy[0], dataptr_copy[1], itemsize); } if (count_m1 > 0) { /* Turn the two items into three for the inner loop */ dataptr_copy[1] += stride1; dataptr_copy[2] += stride0; NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count_m1); innerloop(dataptr_copy, &count_m1, stride_copy, innerloopdata); } } while (iternext(iter)); NPY_END_THREADS; } else if (iter == NULL) { char *dataptr_copy[3]; npy_intp stride_copy[3]; int itemsize = op_dtypes[0]->elsize; /* Execute the loop with no iterators */ npy_intp count = PyArray_DIM(op[1], axis); npy_intp stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis); NPY_UF_DBG_PRINT("UFunc: Reduce loop with no iterators\n"); if (PyArray_NDIM(op[0]) != PyArray_NDIM(op[1]) || !PyArray_CompareLists(PyArray_DIMS(op[0]), PyArray_DIMS(op[1]), PyArray_NDIM(op[0]))) { PyErr_SetString(PyExc_ValueError, "provided out is the wrong size " "for the reduction"); goto fail; } stride0 = PyArray_STRIDE(op[0], axis); stride_copy[0] = stride0; stride_copy[1] = stride1; stride_copy[2] = stride0; /* Turn the two items into three for the inner loop */ dataptr_copy[0] = PyArray_BYTES(op[0]); dataptr_copy[1] = PyArray_BYTES(op[1]); dataptr_copy[2] = PyArray_BYTES(op[0]); /* * Copy the first element to start the reduction. * * Output (dataptr[0]) and input (dataptr[1]) may point to the * same memory, e.g. np.add.accumulate(a, out=a). */ if (otype == NPY_OBJECT) { /* * Incref before decref to avoid the possibility of the * reference count being zero temporarily. */ Py_XINCREF(*(PyObject **)dataptr_copy[1]); Py_XDECREF(*(PyObject **)dataptr_copy[0]); *(PyObject **)dataptr_copy[0] = *(PyObject **)dataptr_copy[1]; } else { memmove(dataptr_copy[0], dataptr_copy[1], itemsize); } if (count > 1) { --count; dataptr_copy[1] += stride1; dataptr_copy[2] += stride0; NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count); needs_api = PyDataType_REFCHK(op_dtypes[0]); if (!needs_api) { NPY_BEGIN_THREADS_THRESHOLDED(count); } innerloop(dataptr_copy, &count, stride_copy, innerloopdata); NPY_END_THREADS; } } finish: Py_XDECREF(op_dtypes[0]); NpyIter_Deallocate(iter); NpyIter_Deallocate(iter_inner); return (PyObject *)out; fail: Py_XDECREF(out); Py_XDECREF(op_dtypes[0]); NpyIter_Deallocate(iter); NpyIter_Deallocate(iter_inner); return NULL; }
PyObject * save_png_fast_progressive (char *filename, int w, int h, bool has_alpha, PyObject *data_generator, bool write_legacy_png) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; PyObject * result = NULL; int bpc; FILE * fp = NULL; PyObject *iterator = NULL; /* TODO: try if this silliness helps #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif */ bpc = 8; fp = fopen(filename, "wb"); if (!fp) { PyErr_SetFromErrno(PyExc_IOError); //PyErr_Format(PyExc_IOError, "Could not open PNG file for writing: %s", filename); goto cleanup; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_write_error_callback, NULL); if (!png_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_write_struct() failed"); goto cleanup; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_info_struct() failed"); goto cleanup; } if (setjmp(png_jmpbuf(png_ptr))) { goto cleanup; } png_init_io(png_ptr, fp); png_set_IHDR (png_ptr, info_ptr, w, h, bpc, has_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (! write_legacy_png) { // Internal data is sRGB by the time it gets here. // Explicitly save with the recommended chunks to advertise that fact. png_set_sRGB_gAMA_and_cHRM (png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); } // default (all filters enabled): 1350ms, 3.4MB //png_set_filter(png_ptr, 0, PNG_FILTER_NONE); // 790ms, 3.8MB //png_set_filter(png_ptr, 0, PNG_FILTER_PAETH); // 980ms, 3.5MB png_set_filter(png_ptr, 0, PNG_FILTER_SUB); // 760ms, 3.4MB //png_set_compression_level(png_ptr, 0); // 0.49s, 32MB //png_set_compression_level(png_ptr, 1); // 0.98s, 9.6MB png_set_compression_level(png_ptr, 2); // 1.08s, 9.4MB //png_set_compression_level(png_ptr, 9); // 18.6s, 9.3MB png_write_info(png_ptr, info_ptr); if (!has_alpha) { // input array format format is rgbu png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); } { iterator = PyObject_GetIter(data_generator); if (!iterator) goto cleanup; int y = 0; while (y < h) { int rows; PyObject * arr = PyIter_Next(iterator); if (PyErr_Occurred()) goto cleanup; assert(arr); // iterator should have data assert(PyArray_ISALIGNED(arr)); assert(PyArray_NDIM(arr) == 3); assert(PyArray_DIM(arr, 1) == w); assert(PyArray_DIM(arr, 2) == 4); // rgbu assert(PyArray_TYPE(arr) == NPY_UINT8); assert(PyArray_STRIDE(arr, 1) == 4); assert(PyArray_STRIDE(arr, 2) == 1); rows = PyArray_DIM(arr, 0); assert(rows > 0); y += rows; png_bytep p = (png_bytep)PyArray_DATA(arr); for (int row=0; row<rows; row++) { png_write_row (png_ptr, p); p += PyArray_STRIDE(arr, 0); } Py_DECREF(arr); } assert(y == h); PyObject * obj = PyIter_Next(iterator); assert(!obj); // iterator should be finished if (PyErr_Occurred()) goto cleanup; } png_write_end (png_ptr, NULL); result = Py_BuildValue("{}"); cleanup: if (iterator) Py_DECREF(iterator); if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) fclose(fp); return result; }
aligned_array(PyArrayObject* array) :array_base<BaseType>(array) ,is_carray_(PyArray_ISCARRAY(array)) { assert(PyArray_ISALIGNED(array)); }