diff options
author | Lars Buitinck <larsmans@gmail.com> | 2014-08-23 22:30:07 +0200 |
---|---|---|
committer | Lars Buitinck <larsmans@gmail.com> | 2014-08-24 13:27:49 +0200 |
commit | d07c4c72793fc120bf4cc807857567517e775c5b (patch) | |
tree | 2313c12b7c999da0765b14a90139335a2e2b5bb9 /numpy | |
parent | d8af083f3873da3fa041f20d1b981709cc61d972 (diff) | |
download | numpy-d07c4c72793fc120bf4cc807857567517e775c5b.tar.gz |
ENH: include shapes in "matrices not aligned" msg
I had to move convert_shape_to_string to common.h so that _dotblas.c
can access it.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/blasdot/_dotblas.c | 10 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.c | 61 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.h | 119 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 6 |
4 files changed, 117 insertions, 79 deletions
diff --git a/numpy/core/blasdot/_dotblas.c b/numpy/core/blasdot/_dotblas.c index a16cbe5d0..0679e38f8 100644 --- a/numpy/core/blasdot/_dotblas.c +++ b/numpy/core/blasdot/_dotblas.c @@ -530,8 +530,7 @@ dotblas_matrixproduct(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject* kwa l = PyArray_DIM(oap1, PyArray_NDIM(oap1) - 1); if (PyArray_DIM(oap2, 0) != l) { - not_aligned(PyArray_NDIM(oap1) - 1, 0, - l, PyArray_DIM(oap2, 0)); + not_aligned(oap1, PyArray_NDIM(oap1) - 1, oap2, 0); goto fail; } nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2; @@ -581,8 +580,7 @@ dotblas_matrixproduct(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject* kwa l = PyArray_DIM(ap1, PyArray_NDIM(ap1) - 1); if (PyArray_DIM(ap2, 0) != l) { - not_aligned(PyArray_NDIM(ap1) - 1, 0, - l, PyArray_DIM(ap2, 0)); + not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, 0); goto fail; } nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2; @@ -1010,8 +1008,8 @@ dotblas_innerproduct(PyObject *NPY_UNUSED(dummy), PyObject *args) l = PyArray_DIM(ap1, PyArray_NDIM(ap1)-1); if (PyArray_DIM(ap2, PyArray_NDIM(ap2)-1) != l) { - not_aligned(PyArray_NDIM(ap1) - 1, PyArray_NDIM(ap2) - 1, - l, PyArray_DIM(ap2, PyArray_NDIM(ap2) - 1)); + not_aligned(ap1, PyArray_NDIM(ap1) - 1, + ap2, PyArray_NDIM(ap2) - 1); goto fail; } nd = PyArray_NDIM(ap1)+PyArray_NDIM(ap2)-2; diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 54b9e3c1a..02f16b9bc 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -779,64 +779,3 @@ offset_bounds_from_strides(const int itemsize, const int nd, *lower_offset = lower; *upper_offset = upper; } - - -/** - * Convert an array shape to a string such as "(1, 2)". - * - * @param Dimensionality of the shape - * @param npy_intp pointer to shape array - * @param String to append after the shape `(1, 2)%s`. - * - * @return Python unicode string - */ -NPY_NO_EXPORT PyObject * -convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending) -{ - npy_intp i; - PyObject *ret, *tmp; - - /* - * Negative dimension indicates "newaxis", which can - * be discarded for printing if it's a leading dimension. - * Find the first non-"newaxis" dimension. - */ - for (i = 0; i < n && vals[i] < 0; i++); - - if (i == n) { - return PyUString_FromFormat("()%s", ending); - } - else { - ret = PyUString_FromFormat("(%" NPY_INTP_FMT, vals[i++]); - if (ret == NULL) { - return NULL; - } - } - - for (; i < n; ++i) { - if (vals[i] < 0) { - tmp = PyUString_FromString(",newaxis"); - } - else { - tmp = PyUString_FromFormat(",%" NPY_INTP_FMT, vals[i]); - } - if (tmp == NULL) { - Py_DECREF(ret); - return NULL; - } - - PyUString_ConcatAndDel(&ret, tmp); - if (ret == NULL) { - return NULL; - } - } - - if (i == 1) { - tmp = PyUString_FromFormat(",)%s", ending); - } - else { - tmp = PyUString_FromFormat(")%s", ending); - } - PyUString_ConcatAndDel(&ret, tmp); - return ret; -} diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index 5edf4e6ba..2de31e467 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -3,6 +3,7 @@ #include <numpy/npy_common.h> #include <numpy/npy_cpu.h> #include <numpy/ndarraytypes.h> +#include <numpy/npy_3kcompat.h> #define error_converting(x) (((x) == -1) && PyErr_Occurred()) @@ -69,9 +70,6 @@ offset_bounds_from_strides(const int itemsize, const int nd, const npy_intp *dims, const npy_intp *strides, npy_intp *lower_offset, npy_intp *upper_offset); -NPY_NO_EXPORT PyObject * -convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending); - /* * Returns -1 and sets an exception if *index is an invalid index for @@ -208,16 +206,121 @@ _is_basic_python_type(PyObject * obj) return 0; } + +/** + * Convert an array shape to a string such as "(1, 2)". + * + * @param Dimensionality of the shape + * @param npy_intp pointer to shape array + * @param String to append after the shape `(1, 2)%s`. + * + * @return Python unicode string + */ +static NPY_INLINE PyObject * +convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending) +{ + npy_intp i; + PyObject *ret, *tmp; + + /* + * Negative dimension indicates "newaxis", which can + * be discarded for printing if it's a leading dimension. + * Find the first non-"newaxis" dimension. + */ + for (i = 0; i < n && vals[i] < 0; i++); + + if (i == n) { + return PyUString_FromFormat("()%s", ending); + } + else { + ret = PyUString_FromFormat("(%" NPY_INTP_FMT, vals[i++]); + if (ret == NULL) { + return NULL; + } + } + + for (; i < n; ++i) { + if (vals[i] < 0) { + tmp = PyUString_FromString(",newaxis"); + } + else { + tmp = PyUString_FromFormat(",%" NPY_INTP_FMT, vals[i]); + } + if (tmp == NULL) { + Py_DECREF(ret); + return NULL; + } + + PyUString_ConcatAndDel(&ret, tmp); + if (ret == NULL) { + return NULL; + } + } + + if (i == 1) { + tmp = PyUString_FromFormat(",)%s", ending); + } + else { + tmp = PyUString_FromFormat(")%s", ending); + } + PyUString_ConcatAndDel(&ret, tmp); + return ret; +} + + /* * Sets ValueError with "matrices not aligned" message for np.dot and friends - * when shape[i] = m doesn't match shape[j] = n. + * when a.shape[i] should match b.shape[j], but doesn't. */ static NPY_INLINE void -not_aligned(int i, int j, Py_ssize_t m, Py_ssize_t n) +not_aligned(PyArrayObject *a, int i, PyArrayObject *b, int j) { - PyErr_Format(PyExc_ValueError, - "matrices are not aligned: shape[%d] (%zd) != shape[%d] (%zd)", - i, m, j, n); + PyObject *errmsg = NULL, *format = NULL, *fmt_args = NULL, + *i_obj = NULL, *j_obj = NULL, + *shape1 = NULL, *shape2 = NULL, + *shape1_i = NULL, *shape2_j = NULL; + + format = PyUString_FromString("shapes %s and %s not aligned:" + " %d (dim %d) != %d (dim %d)"); + + shape1 = convert_shape_to_string(PyArray_NDIM(a), PyArray_DIMS(a), ""); + shape2 = convert_shape_to_string(PyArray_NDIM(b), PyArray_DIMS(b), ""); + + i_obj = PyLong_FromLong(i); + j_obj = PyLong_FromLong(j); + + shape1_i = PyLong_FromSsize_t(PyArray_DIM(a, i)); + shape2_j = PyLong_FromSsize_t(PyArray_DIM(b, j)); + + if (!format || !shape1 || !shape2 || !i_obj || !j_obj || + !shape1_i || !shape2_j) { + goto end; + } + + fmt_args = PyTuple_Pack(6, shape1, shape2, + shape1_i, i_obj, shape2_j, j_obj); + if (fmt_args == NULL) { + goto end; + } + + errmsg = PyUString_Format(format, fmt_args); + if (errmsg != NULL) { + PyErr_SetObject(PyExc_ValueError, errmsg); + } + else { + PyErr_SetString(PyExc_ValueError, "shapes are not aligned"); + } + +end: + Py_XDECREF(errmsg); + Py_XDECREF(fmt_args); + Py_XDECREF(format); + Py_XDECREF(i_obj); + Py_XDECREF(j_obj); + Py_XDECREF(shape1); + Py_XDECREF(shape2); + Py_XDECREF(shape1_i); + Py_XDECREF(shape2_j); } #include "ucsnarrow.h" diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index a3165b67c..8f5bb6d4a 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -841,8 +841,7 @@ PyArray_InnerProduct(PyObject *op1, PyObject *op2) l = PyArray_DIMS(ap1)[PyArray_NDIM(ap1) - 1]; if (PyArray_DIMS(ap2)[PyArray_NDIM(ap2) - 1] != l) { - not_aligned(PyArray_NDIM(ap1) - 1, PyArray_NDIM(ap2) - 1, - l, PyArray_DIMS(ap2)[PyArray_NDIM(ap2) - 1]); + not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, PyArray_NDIM(ap2) - 1); goto fail; } @@ -962,8 +961,7 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out) matchDim = 0; } if (PyArray_DIMS(ap2)[matchDim] != l) { - not_aligned(PyArray_NDIM(ap1) - 1, matchDim, - l, PyArray_DIMS(ap2)[matchDim]); + not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, matchDim); goto fail; } nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2; |