* Determine whether an array has internal overlap. * * Returns: 0 (no overlap), 1 (overlap), or < 0 (failed to solve). * * max_work and reasons for solver failures are as in solve_may_share_memory. */
| 846 | * max_work and reasons for solver failures are as in solve_may_share_memory. |
| 847 | */ |
| 848 | NPY_VISIBILITY_HIDDEN mem_overlap_t |
| 849 | solve_may_have_internal_overlap(PyArrayObject *a, Py_ssize_t max_work) |
| 850 | { |
| 851 | diophantine_term_t terms[NPY_MAXDIMS+1]; |
| 852 | npy_int64 x[NPY_MAXDIMS+1]; |
| 853 | unsigned int i, j, nterms; |
| 854 | |
| 855 | if (PyArray_ISCONTIGUOUS(a)) { |
| 856 | /* Quick case */ |
| 857 | return MEM_OVERLAP_NO; |
| 858 | } |
| 859 | |
| 860 | /* The internal memory overlap problem is looking for two different |
| 861 | solutions to |
| 862 | |
| 863 | sum(a*x) = b, 0 <= x[i] <= ub[i] |
| 864 | |
| 865 | for any b. Equivalently, |
| 866 | |
| 867 | sum(a*x0) - sum(a*x1) = 0 |
| 868 | |
| 869 | Mapping the coefficients on the left by x0'[i] = x0[i] if a[i] > 0 |
| 870 | else ub[i]-x0[i] and opposite for x1, we have |
| 871 | |
| 872 | sum(abs(a)*(x0' + x1')) = sum(abs(a)*ub) |
| 873 | |
| 874 | Now, x0!=x1 if for some i we have x0'[i] + x1'[i] != ub[i]. |
| 875 | We can now change variables to z[i] = x0'[i] + x1'[i] so the problem |
| 876 | becomes |
| 877 | |
| 878 | sum(abs(a)*z) = sum(abs(a)*ub), 0 <= z[i] <= 2*ub[i], z != ub |
| 879 | |
| 880 | This can be solved with solve_diophantine. |
| 881 | */ |
| 882 | |
| 883 | nterms = 0; |
| 884 | if (strides_to_terms(a, terms, &nterms, 0)) { |
| 885 | return MEM_OVERLAP_OVERFLOW; |
| 886 | } |
| 887 | if (PyArray_ITEMSIZE(a) > 1) { |
| 888 | terms[nterms].a = 1; |
| 889 | terms[nterms].ub = PyArray_ITEMSIZE(a) - 1; |
| 890 | ++nterms; |
| 891 | } |
| 892 | |
| 893 | /* Get rid of zero coefficients and empty terms */ |
| 894 | i = 0; |
| 895 | for (j = 0; j < nterms; ++j) { |
| 896 | if (terms[j].ub == 0) { |
| 897 | continue; |
| 898 | } |
| 899 | else if (terms[j].ub < 0) { |
| 900 | return MEM_OVERLAP_NO; |
| 901 | } |
| 902 | else if (terms[j].a == 0) { |
| 903 | return MEM_OVERLAP_YES; |
| 904 | } |
| 905 | if (i != j) { |
no test coverage detected