* Creates a sorted stride perm matching the KEEPORDER behavior * of the NpyIter object. Because this operates based on multiple * input strides, the 'stride' member of the npy_stride_sort_item * would be useless and we simply argsort a list of indices instead. * * The caller should have already validated that 'ndim' matches for * every array in the arrays list. */
| 805 | * every array in the arrays list. |
| 806 | */ |
| 807 | NPY_NO_EXPORT void |
| 808 | PyArray_CreateMultiSortedStridePerm(int narrays, PyArrayObject **arrays, |
| 809 | int ndim, int *out_strideperm) |
| 810 | { |
| 811 | int i0, i1, ipos, ax_j0, ax_j1, iarrays; |
| 812 | |
| 813 | /* Initialize the strideperm values to the identity. */ |
| 814 | for (i0 = 0; i0 < ndim; ++i0) { |
| 815 | out_strideperm[i0] = i0; |
| 816 | } |
| 817 | |
| 818 | /* |
| 819 | * This is the same as the custom stable insertion sort in |
| 820 | * the NpyIter object, but sorting in the reverse order as |
| 821 | * in the iterator. The iterator sorts from smallest stride |
| 822 | * to biggest stride (Fortran order), whereas here we sort |
| 823 | * from biggest stride to smallest stride (C order). |
| 824 | */ |
| 825 | for (i0 = 1; i0 < ndim; ++i0) { |
| 826 | |
| 827 | ipos = i0; |
| 828 | ax_j0 = out_strideperm[i0]; |
| 829 | |
| 830 | for (i1 = i0 - 1; i1 >= 0; --i1) { |
| 831 | int ambig = 1, shouldswap = 0; |
| 832 | |
| 833 | ax_j1 = out_strideperm[i1]; |
| 834 | |
| 835 | for (iarrays = 0; iarrays < narrays; ++iarrays) { |
| 836 | if (PyArray_SHAPE(arrays[iarrays])[ax_j0] != 1 && |
| 837 | PyArray_SHAPE(arrays[iarrays])[ax_j1] != 1) { |
| 838 | if (s_intp_abs(PyArray_STRIDES(arrays[iarrays])[ax_j0]) <= |
| 839 | s_intp_abs(PyArray_STRIDES(arrays[iarrays])[ax_j1])) { |
| 840 | /* |
| 841 | * Set swap even if it's not ambiguous already, |
| 842 | * because in the case of conflicts between |
| 843 | * different operands, C-order wins. |
| 844 | */ |
| 845 | shouldswap = 0; |
| 846 | } |
| 847 | else { |
| 848 | /* Only set swap if it's still ambiguous */ |
| 849 | if (ambig) { |
| 850 | shouldswap = 1; |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | /* |
| 855 | * A comparison has been done, so it's |
| 856 | * no longer ambiguous |
| 857 | */ |
| 858 | ambig = 0; |
| 859 | } |
| 860 | } |
| 861 | /* |
| 862 | * If the comparison was unambiguous, either shift |
| 863 | * 'ipos' to 'i1' or stop looking for an insertion point |
| 864 | */ |
no test coverage detected