diff options
Diffstat (limited to 'numpy/f2py/doc/multiarray/array_from_pyobj.c')
-rw-r--r-- | numpy/f2py/doc/multiarray/array_from_pyobj.c | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/numpy/f2py/doc/multiarray/array_from_pyobj.c b/numpy/f2py/doc/multiarray/array_from_pyobj.c deleted file mode 100644 index 237d16dbc..000000000 --- a/numpy/f2py/doc/multiarray/array_from_pyobj.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * File: array_from_pyobj.c - * - * Description: - * ------------ - * Provides array_from_pyobj function that returns a contigious array - * object with the given dimensions and required storage order, either - * in row-major (C) or column-major (Fortran) order. The function - * array_from_pyobj is very flexible about its Python object argument - * that can be any number, list, tuple, or array. - * - * array_from_pyobj is used in f2py generated Python extension - * modules. - * - * Author: Pearu Peterson <pearu@cens.ioc.ee> - * Created: 13-16 January 2002 - * $Id: array_from_pyobj.c,v 1.1 2002/01/16 18:57:33 pearu Exp $ - */ - - -#define ARR_IS_NULL(arr,mess) \ -if (arr==NULL) { \ - fprintf(stderr,"array_from_pyobj:" mess); \ - return NULL; \ -} - -#define CHECK_DIMS_DEFINED(rank,dims,mess) \ -if (count_nonpos(rank,dims)) { \ - fprintf(stderr,"array_from_pyobj:" mess); \ - return NULL; \ -} - -#define HAS_PROPER_ELSIZE(arr,type_num) \ - ((PyArray_DescrFromType(type_num)->elsize) == (arr)->descr->elsize) - -/* static */ -/* void f2py_show_args(const int type_num, */ -/* const int *dims, */ -/* const int rank, */ -/* const int intent) { */ -/* int i; */ -/* fprintf(stderr,"array_from_pyobj:\n\ttype_num=%d\n\trank=%d\n\tintent=%d\n",\ */ -/* type_num,rank,intent); */ -/* for (i=0;i<rank;++i) */ -/* fprintf(stderr,"\tdims[%d]=%d\n",i,dims[i]); */ -/* } */ - -static -int count_nonpos(const int rank, - const int *dims) { - int i=0,r=0; - while (i<rank) { - if (dims[i] <= 0) ++r; - ++i; - } - return r; -} - -static void lazy_transpose(PyArrayObject* arr); -static int check_and_fix_dimensions(const PyArrayObject* arr, - const int rank, - int *dims); -static -int array_has_column_major_storage(const PyArrayObject *ap); - -static -PyArrayObject* array_from_pyobj(const int type_num, - int *dims, - const int rank, - const int intent, - PyObject *obj) { - /* Note about reference counting - ----------------------------- - If the caller returns the array to Python, it must be done with - Py_BuildValue("N",arr). - Otherwise, if obj!=arr then the caller must call Py_DECREF(arr). - */ - -/* f2py_show_args(type_num,dims,rank,intent); */ - - if (intent & F2PY_INTENT_CACHE) { - /* Don't expect correct storage order or anything reasonable when - returning cache array. */ - if ((intent & F2PY_INTENT_HIDE) - || (obj==Py_None)) { - PyArrayObject *arr = NULL; - CHECK_DIMS_DEFINED(rank,dims,"optional,intent(cache) must" - " have defined dimensions.\n"); - arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); - ARR_IS_NULL(arr,"FromDims failed: optional,intent(cache)\n"); - if (intent & F2PY_INTENT_OUT) - Py_INCREF(arr); - return arr; - } - if (PyArray_Check(obj) - && ISCONTIGUOUS((PyArrayObject *)obj) - && HAS_PROPER_ELSIZE((PyArrayObject *)obj,type_num) - ) { - if (check_and_fix_dimensions((PyArrayObject *)obj,rank,dims)) - return NULL; /*XXX: set exception */ - if (intent & F2PY_INTENT_OUT) - Py_INCREF(obj); - return (PyArrayObject *)obj; - } - ARR_IS_NULL(NULL,"intent(cache) must be contiguous array with a proper elsize.\n"); - } - - if (intent & F2PY_INTENT_HIDE) { - PyArrayObject *arr = NULL; - CHECK_DIMS_DEFINED(rank,dims,"intent(hide) must have defined dimensions.\n"); - arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); - ARR_IS_NULL(arr,"FromDims failed: intent(hide)\n"); - if (intent & F2PY_INTENT_OUT) { - if ((!(intent & F2PY_INTENT_C)) && (rank>1)) { - lazy_transpose(arr); - arr->flags &= ~NPY_CONTIGUOUS; - } - Py_INCREF(arr); - } - return arr; - } - - if (PyArray_Check(obj)) { /* here we have always intent(in) or - intent(inout) */ - - PyArrayObject *arr = (PyArrayObject *)obj; - int is_cont = (intent & F2PY_INTENT_C) ? - (ISCONTIGUOUS(arr)) : (array_has_column_major_storage(arr)); - - if (check_and_fix_dimensions(arr,rank,dims)) - return NULL; /*XXX: set exception */ - - if ((intent & F2PY_INTENT_COPY) - || (! (is_cont - && HAS_PROPER_ELSIZE(arr,type_num) - && PyArray_CanCastSafely(arr->descr->type_num,type_num)))) { - PyArrayObject *tmp_arr = NULL; - if (intent & F2PY_INTENT_INOUT) { - ARR_IS_NULL(NULL,"intent(inout) array must be contiguous and" - " with a proper type and size.\n") - } - if ((rank>1) && (! (intent & F2PY_INTENT_C))) - lazy_transpose(arr); - if (PyArray_CanCastSafely(arr->descr->type_num,type_num)) { - tmp_arr = (PyArrayObject *)PyArray_CopyFromObject(obj,type_num,0,0); - ARR_IS_NULL(arr,"CopyFromObject failed: array.\n"); - } else { - tmp_arr = (PyArrayObject *)PyArray_FromDims(arr->nd, - arr->dimensions, - type_num); - ARR_IS_NULL(tmp_arr,"FromDims failed: array with unsafe cast.\n"); - if (copy_ND_array(arr,tmp_arr)) - ARR_IS_NULL(NULL,"copy_ND_array failed: array with unsafe cast.\n"); - } - if ((rank>1) && (! (intent & F2PY_INTENT_C))) { - lazy_transpose(arr); - lazy_transpose(tmp_arr); - tmp_arr->flags &= ~NPY_CONTIGUOUS; - } - arr = tmp_arr; - } - if (intent & F2PY_INTENT_OUT) - Py_INCREF(arr); - return arr; - } - - if ((obj==Py_None) && (intent & F2PY_OPTIONAL)) { - PyArrayObject *arr = NULL; - CHECK_DIMS_DEFINED(rank,dims,"optional must have defined dimensions.\n"); - arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); - ARR_IS_NULL(arr,"FromDims failed: optional.\n"); - if (intent & F2PY_INTENT_OUT) { - if ((!(intent & F2PY_INTENT_C)) && (rank>1)) { - lazy_transpose(arr); - arr->flags &= ~NPY_CONTIGUOUS; - } - Py_INCREF(arr); - } - return arr; - } - - if (intent & F2PY_INTENT_INOUT) { - ARR_IS_NULL(NULL,"intent(inout) argument must be an array.\n"); - } - - { - PyArrayObject *arr = (PyArrayObject *) \ - PyArray_ContiguousFromObject(obj,type_num,0,0); - ARR_IS_NULL(arr,"ContiguousFromObject failed: not a sequence.\n"); - if (check_and_fix_dimensions(arr,rank,dims)) - return NULL; /*XXX: set exception */ - if ((rank>1) && (! (intent & F2PY_INTENT_C))) { - PyArrayObject *tmp_arr = NULL; - lazy_transpose(arr); - arr->flags &= ~NPY_CONTIGUOUS; - tmp_arr = (PyArrayObject *) PyArray_CopyFromObject((PyObject *)arr,type_num,0,0); - Py_DECREF(arr); - arr = tmp_arr; - ARR_IS_NULL(arr,"CopyFromObject(Array) failed: intent(fortran)\n"); - lazy_transpose(arr); - arr->flags &= ~NPY_CONTIGUOUS; - } - if (intent & F2PY_INTENT_OUT) - Py_INCREF(arr); - return arr; - } - -} - - /*****************************************/ - /* Helper functions for array_from_pyobj */ - /*****************************************/ - -static -int array_has_column_major_storage(const PyArrayObject *ap) { - /* array_has_column_major_storage(a) is equivalent to - transpose(a).iscontiguous() but more efficient. - - This function can be used in order to decide whether to use a - Fortran or C version of a wrapped function. This is relevant, for - example, in choosing a clapack or flapack function depending on - the storage order of array arguments. - */ - int sd; - int i; - sd = ap->descr->elsize; - for (i=0;i<ap->nd;++i) { - if (ap->dimensions[i] == 0) return 1; - if (ap->strides[i] != sd) return 0; - sd *= ap->dimensions[i]; - } - return 1; -} - -static -void lazy_transpose(PyArrayObject* arr) { - /* - Changes the order of array strides and dimensions. This - corresponds to the lazy transpose of a Numeric array in-situ. - Note that this function is assumed to be used even times for a - given array. Otherwise, the caller should set flags &= ~NPY_CONTIGUOUS. - */ - int rank,i,s,j; - rank = arr->nd; - if (rank < 2) return; - - for(i=0,j=rank-1;i<rank/2;++i,--j) { - s = arr->strides[i]; - arr->strides[i] = arr->strides[j]; - arr->strides[j] = s; - s = arr->dimensions[i]; - arr->dimensions[i] = arr->dimensions[j]; - arr->dimensions[j] = s; - } -} - -static -int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,int *dims) { - /* - This function fills in blanks (that are -1's) in dims list using - the dimensions from arr. It also checks that non-blank dims will - match with the corresponding values in arr dimensions. - */ - const int arr_size = (arr->nd)?PyArray_Size((PyObject *)arr):1; - - if (rank > arr->nd) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */ - int new_size = 1; - int free_axe = -1; - int i; - /* Fill dims where -1 or 0; check dimensions; calc new_size; */ - for(i=0;i<arr->nd;++i) { - if (dims[i] >= 0) { - if (dims[i]!=arr->dimensions[i]) { - fprintf(stderr,"%d-th dimension must be fixed to %d but got %d\n", - i,dims[i],arr->dimensions[i]); - return 1; - } - if (!dims[i]) dims[i] = 1; - } else { - dims[i] = arr->dimensions[i] ? arr->dimensions[i] : 1; - } - new_size *= dims[i]; - } - for(i=arr->nd;i<rank;++i) - if (dims[i]>1) { - fprintf(stderr,"%d-th dimension must be %d but got 0 (not defined).\n", - i,dims[i]); - return 1; - } else if (free_axe<0) - free_axe = i; - else - dims[i] = 1; - if (free_axe>=0) { - dims[free_axe] = arr_size/new_size; - new_size *= dims[free_axe]; - } - if (new_size != arr_size) { - fprintf(stderr,"confused: new_size=%d, arr_size=%d (maybe too many free" - " indices)\n",new_size,arr_size); - return 1; - } - } else { - int i; - for (i=rank;i<arr->nd;++i) - if (arr->dimensions[i]>1) { - fprintf(stderr,"too many axes: %d, expected rank=%d\n",arr->nd,rank); - return 1; - } - for (i=0;i<rank;++i) - if (dims[i]>=0) { - if (arr->dimensions[i]!=dims[i]) { - fprintf(stderr,"%d-th dimension must be fixed to %d but got %d\n", - i,dims[i],arr->dimensions[i]); - return 1; - } - if (!dims[i]) dims[i] = 1; - } else - dims[i] = arr->dimensions[i]; - } - return 0; -} - -/* End of file: array_from_pyobj.c */ |