NUMPY_API * Counts the number of non-zero elements in the array. * * Returns -1 on error. */
| 2644 | * Returns -1 on error. |
| 2645 | */ |
| 2646 | NPY_NO_EXPORT npy_intp |
| 2647 | PyArray_CountNonzero(PyArrayObject *self) |
| 2648 | { |
| 2649 | PyArray_NonzeroFunc *nonzero; |
| 2650 | char *data; |
| 2651 | npy_intp stride, count; |
| 2652 | npy_intp nonzero_count = 0; |
| 2653 | int needs_api = 0; |
| 2654 | PyArray_Descr *dtype; |
| 2655 | |
| 2656 | NpyIter *iter; |
| 2657 | NpyIter_IterNextFunc *iternext; |
| 2658 | char **dataptr; |
| 2659 | npy_intp *strideptr, *innersizeptr; |
| 2660 | NPY_BEGIN_THREADS_DEF; |
| 2661 | |
| 2662 | dtype = PyArray_DESCR(self); |
| 2663 | /* Special low-overhead version specific to the boolean/int types */ |
| 2664 | if (PyArray_ISALIGNED(self) && ( |
| 2665 | PyDataType_ISBOOL(dtype) || PyDataType_ISINTEGER(dtype))) { |
| 2666 | return count_nonzero_int( |
| 2667 | PyArray_NDIM(self), PyArray_BYTES(self), PyArray_DIMS(self), |
| 2668 | PyArray_STRIDES(self), dtype->elsize |
| 2669 | ); |
| 2670 | } |
| 2671 | |
| 2672 | nonzero = PyArray_DESCR(self)->f->nonzero; |
| 2673 | /* If it's a trivial one-dimensional loop, don't use an iterator */ |
| 2674 | if (PyArray_TRIVIALLY_ITERABLE(self)) { |
| 2675 | needs_api = PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI); |
| 2676 | PyArray_PREPARE_TRIVIAL_ITERATION(self, count, data, stride); |
| 2677 | |
| 2678 | if (needs_api){ |
| 2679 | while (count--) { |
| 2680 | if (nonzero(data, self)) { |
| 2681 | ++nonzero_count; |
| 2682 | } |
| 2683 | if (PyErr_Occurred()) { |
| 2684 | return -1; |
| 2685 | } |
| 2686 | data += stride; |
| 2687 | } |
| 2688 | } |
| 2689 | else { |
| 2690 | NPY_BEGIN_THREADS_THRESHOLDED(count); |
| 2691 | while (count--) { |
| 2692 | if (nonzero(data, self)) { |
| 2693 | ++nonzero_count; |
| 2694 | } |
| 2695 | data += stride; |
| 2696 | } |
| 2697 | NPY_END_THREADS; |
| 2698 | } |
| 2699 | |
| 2700 | return nonzero_count; |
| 2701 | } |
| 2702 | |
| 2703 | /* |
no test coverage detected