@@ -2696,6 +2696,53 @@ npyiter_check_casting(npy_intp niter, PyArrayObject **op,
2696
2696
return 1;
2697
2697
}
2698
2698
2699
+ static PyObject *
2700
+ npyiter_shape_string(npy_intp n, npy_intp *vals, char *ending)
2701
+ {
2702
+ npy_intp i;
2703
+ PyObject *ret, *tmp;
2704
+
2705
+ if (n <= 0) {
2706
+ return PyString_FromString("()");
2707
+ }
2708
+
2709
+ switch (n) {
2710
+ case 1:
2711
+ return PyString_FromFormat("(%zd)%s",
2712
+ vals[0], ending);
2713
+ case 2:
2714
+ return PyString_FromFormat("(%zd,%zd)%s",
2715
+ vals[0], vals[1], ending);
2716
+ case 3:
2717
+ return PyString_FromFormat("(%zd,%zd,%zd)%s",
2718
+ vals[0], vals[1], vals[2], ending);
2719
+ case 4:
2720
+ return PyString_FromFormat("(%zd,%zd,%zd,%zd)%s",
2721
+ vals[0], vals[1], vals[2], vals[3], ending);
2722
+ }
2723
+
2724
+ ret = PyString_FromFormat("(%zd,%zd,%zd,%zd,%zd",
2725
+ vals[0], vals[1], vals[2], vals[3], vals[4]);
2726
+ if (ret == NULL) {
2727
+ return NULL;
2728
+ }
2729
+ for (i = 5; i < n; ++i) {
2730
+ tmp = PyString_FromFormat(",%zd", vals[i]);
2731
+ if (tmp == NULL) {
2732
+ Py_DECREF(ret);
2733
+ return NULL;
2734
+ }
2735
+
2736
+ PyString_ConcatAndDel(&ret, tmp);
2737
+ if (ret == NULL) {
2738
+ return NULL;
2739
+ }
2740
+ }
2741
+ tmp = PyString_FromFormat(")%s", ending);
2742
+ PyString_ConcatAndDel(&ret, tmp);
2743
+ return ret;
2744
+ }
2745
+
2699
2746
/*
2700
2747
* Fills in the AXISDATA for the 'niter' operands, broadcasting
2701
2748
* the dimensionas as necessary. Also fills
@@ -2840,10 +2887,7 @@ npyiter_fill_axisdata(NpyIter *iter, char **op_dataptr,
2840
2887
NAD_SHAPE(axisdata) = shape;
2841
2888
}
2842
2889
else if (NAD_SHAPE(axisdata) != shape) {
2843
- PyErr_SetString(PyExc_ValueError,
2844
- "operands cannot be broadcast "
2845
- "to a single shape");
2846
- return 0;
2890
+ goto broadcast_error;
2847
2891
}
2848
2892
NAD_STRIDES(axisdata)[iiter] = PyArray_STRIDE(
2849
2893
op[iiter], ondim-idim-1);
@@ -2890,10 +2934,7 @@ npyiter_fill_axisdata(NpyIter *iter, char **op_dataptr,
2890
2934
NAD_SHAPE(axisdata) = shape;
2891
2935
}
2892
2936
else if (NAD_SHAPE(axisdata) != shape) {
2893
- PyErr_SetString(PyExc_ValueError,
2894
- "operands cannot be broadcast "
2895
- "to a single shape");
2896
- return 0;
2937
+ goto broadcast_error;
2897
2938
}
2898
2939
NAD_STRIDES(axisdata)[iiter] =
2899
2940
PyArray_STRIDE(op[iiter], i);
@@ -2929,14 +2970,16 @@ npyiter_fill_axisdata(NpyIter *iter, char **op_dataptr,
2929
2970
else {
2930
2971
i = ndim-idim-1;
2931
2972
}
2932
- if (i < PyArray_NDIM(op[iiter])) {
2973
+ if (i >= 0 && i < PyArray_NDIM(op[iiter])) {
2933
2974
if (PyArray_DIM(op[iiter], i) != NAD_SHAPE(axisdata)) {
2934
2975
if (op_flags[iiter]&NPY_ITER_WRITEONLY) {
2935
2976
PyErr_SetString(PyExc_ValueError,
2936
- "output operand cannot be broadcasted");
2977
+ "output operand is smaller "
2978
+ "than the broadcast dimensions");
2937
2979
} else {
2938
2980
PyErr_SetString(PyExc_ValueError,
2939
- "operand cannot be broadcasted");
2981
+ "operand is smaller "
2982
+ "than the broadcast dimensions");
2940
2983
}
2941
2984
return 0;
2942
2985
}
@@ -2956,10 +2999,12 @@ npyiter_fill_axisdata(NpyIter *iter, char **op_dataptr,
2956
2999
else { /*if (NAD_SHAPE(axisdata) != 1) {*/
2957
3000
if (op_flags[iiter]&NPY_ITER_WRITEONLY) {
2958
3001
PyErr_SetString(PyExc_ValueError,
2959
- "output operand cannot be broadcasted");
3002
+ "output operand is smaller "
3003
+ "than the broadcast dimensions");
2960
3004
} else {
2961
3005
PyErr_SetString(PyExc_ValueError,
2962
- "operand cannot be broadcasted");
3006
+ "operand is smaller "
3007
+ "than the broadcast dimensions");
2963
3008
}
2964
3009
return 0;
2965
3010
}
@@ -2982,6 +3027,78 @@ npyiter_fill_axisdata(NpyIter *iter, char **op_dataptr,
2982
3027
NIT_ITEREND(iter) = NIT_ITERSIZE(iter);
2983
3028
2984
3029
return 1;
3030
+
3031
+ broadcast_error: {
3032
+ PyObject *errmsg, *tmp;
3033
+ npy_intp remdims[NPY_MAXDIMS];
3034
+ char *tmpstr;
3035
+
3036
+ if (op_axes == NULL) {
3037
+ errmsg = PyString_FromString("operands could not be broadcast "
3038
+ "together with shapes ");
3039
+ for (iiter = 0; iiter < niter; ++iiter) {
3040
+ if (op[iiter] != NULL) {
3041
+ tmp = npyiter_shape_string(PyArray_NDIM(op[iiter]),
3042
+ PyArray_DIMS(op[iiter]),
3043
+ " ");
3044
+ if (tmp == NULL) {
3045
+ return 0;
3046
+ }
3047
+ PyString_ConcatAndDel(&errmsg, tmp);
3048
+ if (errmsg == NULL) {
3049
+ return 0;
3050
+ }
3051
+ }
3052
+ }
3053
+ PyErr_SetObject(PyExc_ValueError, errmsg);
3054
+ }
3055
+ else {
3056
+ errmsg = PyString_FromString("operands could not be broadcast "
3057
+ "together with remapped shapes "
3058
+ "[original->remapped]: ");
3059
+ for (iiter = 0; iiter < niter; ++iiter) {
3060
+ if (op[iiter] != NULL) {
3061
+ npy_intp *axes = op_axes[iiter];
3062
+
3063
+ tmpstr = (axes == NULL) ? " " : "->";
3064
+ tmp = npyiter_shape_string(PyArray_NDIM(op[iiter]),
3065
+ PyArray_DIMS(op[iiter]),
3066
+ tmpstr);
3067
+ if (tmp == NULL) {
3068
+ return 0;
3069
+ }
3070
+ PyString_ConcatAndDel(&errmsg, tmp);
3071
+ if (errmsg == NULL) {
3072
+ return 0;
3073
+ }
3074
+
3075
+ if (axes != NULL) {
3076
+ for (idim = 0; idim < ndim; ++idim) {
3077
+ npy_intp i = axes[ndim-idim-1];
3078
+
3079
+ if (i >= 0 && i < PyArray_NDIM(op[iiter])) {
3080
+ remdims[idim] = PyArray_DIM(op[iiter], i);
3081
+ }
3082
+ else {
3083
+ remdims[idim] = 1;
3084
+ }
3085
+ }
3086
+ tmp = npyiter_shape_string(ndim, remdims, " ");
3087
+ if (tmp == NULL) {
3088
+ return 0;
3089
+ }
3090
+ PyString_ConcatAndDel(&errmsg, tmp);
3091
+ if (errmsg == NULL) {
3092
+ return 0;
3093
+ }
3094
+ }
3095
+ }
3096
+ }
3097
+ PyErr_SetObject(PyExc_ValueError, errmsg);
3098
+ }
3099
+
3100
+ return 0;
3101
+ }
2985
3102
}
2986
3103
2987
3104
/*
0 commit comments