/* Returns 1 if the arrays have overlapping data, 0 otherwise */ NPY_NO_EXPORT int arrays_overlap(PyArrayObject *arr1, PyArrayObject *arr2) { npy_uintp start1 = 0, start2 = 0, end1 = 0, end2 = 0; get_array_memory_extents(arr1, &start1, &end1); get_array_memory_extents(arr2, &start2, &end2); return (start1 < end2) && (start2 < end1); }
/** * Determine whether two arrays share some memory. * * Returns: 0 (no shared memory), 1 (shared memory), or < 0 (failed to solve). * * Note that failures to solve can occur due to integer overflows, or effort * required solving the problem exceeding max_work. The general problem is * NP-hard and worst case runtime is exponential in the number of dimensions. * max_work controls the amount of work done, either exact (max_work == -1), only * a simple memory extent check (max_work == 0), or set an upper bound * max_work > 0 for the number of solution candidates considered. */ NPY_VISIBILITY_HIDDEN mem_overlap_t solve_may_share_memory(PyArrayObject *a, PyArrayObject *b, Py_ssize_t max_work) { npy_int64 rhs; diophantine_term_t terms[2*NPY_MAXDIMS+2]; npy_uintp start1 = 0, start2 = 0, end1 = 0, end2 = 0, size1 = 0, size2 = 0; npy_int64 x[2*NPY_MAXDIMS+2]; unsigned int nterms; get_array_memory_extents(a, &start1, &end1, &size1); get_array_memory_extents(b, &start2, &end2, &size2); if (!(start1 < end2 && start2 < end1 && start1 < end1 && start2 < end2)) { /* Memory extents don't overlap */ return MEM_OVERLAP_NO; } if (max_work == 0) { /* Too much work required, give up */ return MEM_OVERLAP_TOO_HARD; } /* Convert problem to Diophantine equation form with positive coefficients. The bounds computed by offset_bounds_from_strides correspond to all-positive strides. start1 + sum(abs(stride1)*x1) == start2 + sum(abs(stride2)*x2) == end1 - 1 - sum(abs(stride1)*x1') == end2 - 1 - sum(abs(stride2)*x2') <=> sum(abs(stride1)*x1) + sum(abs(stride2)*x2') == end2 - 1 - start1 OR sum(abs(stride1)*x1') + sum(abs(stride2)*x2) == end1 - 1 - start2 We pick the problem with the smaller RHS (they are non-negative due to the extent check above.) */ rhs = MIN(end2 - 1 - start1, end1 - 1 - start2); if (rhs != (npy_uintp)rhs) { /* Integer overflow */ return MEM_OVERLAP_OVERFLOW; } nterms = 0; if (strides_to_terms(a, terms, &nterms, 1)) { return MEM_OVERLAP_OVERFLOW; } if (strides_to_terms(b, terms, &nterms, 1)) { return MEM_OVERLAP_OVERFLOW; } if (PyArray_ITEMSIZE(a) > 1) { terms[nterms].a = 1; terms[nterms].ub = PyArray_ITEMSIZE(a) - 1; ++nterms; } if (PyArray_ITEMSIZE(b) > 1) { terms[nterms].a = 1; terms[nterms].ub = PyArray_ITEMSIZE(b) - 1; ++nterms; } /* Simplify, if possible */ if (diophantine_simplify(&nterms, terms, rhs)) { /* Integer overflow */ return MEM_OVERLAP_OVERFLOW; } /* Solve */ return solve_diophantine(nterms, terms, rhs, max_work, 0, x); }