int check_and_fix_dimensions()

in source/predictive_maintenance/numpy/f2py/src/fortranobject.c [859:1018]


int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp *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.
     *
     * Returns 0 if the function is successful.
     *
     * If an error condition is detected, an exception is set and 1 is returned.
     */
    const npy_intp arr_size = (PyArray_NDIM(arr))?PyArray_Size((PyObject *)arr):1;
#ifdef DEBUG_COPY_ND_ARRAY
    dump_attrs(arr);
    printf("check_and_fix_dimensions:init: dims=");
    dump_dims(rank,dims);
#endif
    if (rank > PyArray_NDIM(arr)) { /* [1,2] -> [[1],[2]]; 1 -> [[1]]  */
        npy_intp new_size = 1;
        int free_axe = -1;
        int i;
        npy_intp d;
        /* Fill dims where -1 or 0; check dimensions; calc new_size; */
        for(i=0;i<PyArray_NDIM(arr);++i) {
            d = PyArray_DIM(arr,i);
            if (dims[i] >= 0) {
                if (d>1 && dims[i]!=d) {
                    PyErr_Format(PyExc_ValueError,
                                 "%d-th dimension must be fixed to %"
                                 NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n",
                                 i, dims[i], d);
                    return 1;
                }
                if (!dims[i]) dims[i] = 1;
            } else {
                dims[i] = d ? d : 1;
            }
            new_size *= dims[i];
        }
        for(i=PyArray_NDIM(arr);i<rank;++i)
            if (dims[i]>1) {
                PyErr_Format(PyExc_ValueError,
                             "%d-th dimension must be %" NPY_INTP_FMT
                             " 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) {
            PyErr_Format(PyExc_ValueError,
                         "unexpected array size: new_size=%" NPY_INTP_FMT
                         ", got array with arr_size=%" NPY_INTP_FMT
                         " (maybe too many free indices)\n",
                         new_size, arr_size);
            return 1;
        }
    } else if (rank==PyArray_NDIM(arr)) {
        npy_intp new_size = 1;
        int i;
        npy_intp d;
        for (i=0; i<rank; ++i) {
            d = PyArray_DIM(arr,i);
            if (dims[i]>=0) {
                if (d > 1 && d!=dims[i]) {
                    PyErr_Format(PyExc_ValueError,
                                 "%d-th dimension must be fixed to %"
                                 NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n",
                                 i, dims[i], d);
                    return 1;
                }
                if (!dims[i]) dims[i] = 1;
            } else dims[i] = d;
            new_size *= dims[i];
        }
        if (new_size != arr_size) {
            PyErr_Format(PyExc_ValueError,
                         "unexpected array size: new_size=%" NPY_INTP_FMT
                         ", got array with arr_size=%" NPY_INTP_FMT "\n",
                         new_size, arr_size);
            return 1;
        }
    } else { /* [[1,2]] -> [[1],[2]] */
        int i,j;
        npy_intp d;
        int effrank;
        npy_intp size;
        for (i=0,effrank=0;i<PyArray_NDIM(arr);++i)
            if (PyArray_DIM(arr,i)>1) ++effrank;
        if (dims[rank-1]>=0)
            if (effrank>rank) {
                PyErr_Format(PyExc_ValueError,
                             "too many axes: %d (effrank=%d), "
                             "expected rank=%d\n",
                             PyArray_NDIM(arr), effrank, rank);
                return 1;
            }

        for (i=0,j=0;i<rank;++i) {
            while (j<PyArray_NDIM(arr) && PyArray_DIM(arr,j)<2) ++j;
            if (j>=PyArray_NDIM(arr)) d = 1;
            else d = PyArray_DIM(arr,j++);
            if (dims[i]>=0) {
                if (d>1 && d!=dims[i]) {
                    PyErr_Format(PyExc_ValueError,
                                 "%d-th dimension must be fixed to %"
                                 NPY_INTP_FMT " but got %" NPY_INTP_FMT
                                 " (real index=%d)\n",
                                 i, dims[i], d, j-1);
                    return 1;
                }
                if (!dims[i]) dims[i] = 1;
            } else
                dims[i] = d;
        }

        for (i=rank;i<PyArray_NDIM(arr);++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
            while (j<PyArray_NDIM(arr) && PyArray_DIM(arr,j)<2) ++j;
            if (j>=PyArray_NDIM(arr)) d = 1;
            else d = PyArray_DIM(arr,j++);
            dims[rank-1] *= d;
        }
        for (i=0,size=1;i<rank;++i) size *= dims[i];
        if (size != arr_size) {
            char msg[200];
            int len;
            snprintf(msg, sizeof(msg),
                     "unexpected array size: size=%" NPY_INTP_FMT
                     ", arr_size=%" NPY_INTP_FMT
                     ", rank=%d, effrank=%d, arr.nd=%d, dims=[",
                     size, arr_size, rank, effrank, PyArray_NDIM(arr));
            for (i = 0; i < rank; ++i) {
                len = strlen(msg);
                snprintf(msg + len, sizeof(msg) - len,
                         " %" NPY_INTP_FMT, dims[i]);
            }
            len = strlen(msg);
            snprintf(msg + len, sizeof(msg) - len, " ], arr.dims=[");
            for (i = 0; i < PyArray_NDIM(arr); ++i) {
                len = strlen(msg);
                snprintf(msg + len, sizeof(msg) - len,
                         " %" NPY_INTP_FMT, PyArray_DIM(arr, i));
            }
            len = strlen(msg);
            snprintf(msg + len, sizeof(msg) - len, " ]\n");
            PyErr_SetString(PyExc_ValueError, msg);
            return 1;
        }
    }
#ifdef DEBUG_COPY_ND_ARRAY
    printf("check_and_fix_dimensions:end: dims=");
    dump_dims(rank,dims);
#endif
    return 0;
}