8000 ENH: np.dot: better "matrices not aligned" message by larsmans · Pull Request #4985 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: np.dot: better "matrices not aligned" message #4985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions numpy/core/blasdot/_dotblas.c
8000
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "numpy/arrayobject.h"
#include "npy_config.h"
#include "npy_pycompat.h"
#include "common.h"
#include "ufunc_override.h"
#ifndef CBLAS_HEADER
#define CBLAS_HEADER "cblas.h"
Expand Down Expand Up @@ -529,7 +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) {
PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
not_aligned(oap1, PyArray_NDIM(oap1) - 1, oap2, 0);
goto fail;
}
nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2;
Expand Down Expand Up @@ -579,7 +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) {
PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, 0);
goto fail;
}
nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2;
Expand Down Expand Up @@ -1007,7 +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) {
PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
not_aligned(ap1, PyArray_NDIM(ap1) - 1,
ap2, PyArray_NDIM(ap2) - 1);
goto fail;
}
nd = PyArray_NDIM(ap1)+PyArray_NDIM(ap2)-2;
Expand Down
61 changes: 0 additions & 61 deletions numpy/core/src/multiarray/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_ConcatAnd 8000 Del(&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;
}
121 changes: 118 additions & 3 deletions numpy/core/src/multiarray/common.h
8000 8000
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -208,6 +206,123 @@ _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 a.shape[i] should match b.shape[j], but doesn't.
*/
static NPY_INLINE void
not_aligned(PyArrayObject *a, int i, PyArrayObject *b, int j)
{
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"

#endif
4 changes: 2 additions & 2 deletions numpy/core/src/multiarray/multiarraymodule.c
6FA9
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +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) {
PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, PyArray_NDIM(ap2) - 1);
goto fail;
}

Expand Down Expand Up @@ -961,7 +961,7 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
matchDim = 0;
}
if (PyArray_DIMS(ap2)[matchDim] != l) {
PyErr_SetString(PyExc_ValueError, "objects are not aligned");
not_aligned(ap1, PyArray_NDIM(ap1) - 1, ap2, matchDim);
goto fail;
}
nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2;
Expand Down
0