NPY_SIMD * Counts the number of non-zero values in a raw array. * The one loop process is shown below(take SSE2 with 128bits vector for example): * |------------16 lanes---------| *[vsum8] 255 255 255 ... 255 255 255 255 count_zero_bytes_u8: counting 255*16 elements * !! * |------------8 lanes---------| *[vsum16] 65535 65535 65535 ... 65535
| 2454 | * (2*16-1)*16 |
| 2455 | */ |
| 2456 | static inline NPY_GCC_OPT_3 npy_intp |
| 2457 | count_nonzero_u8(const char *data, npy_intp bstride, npy_uintp len) |
| 2458 | { |
| 2459 | npy_intp count = 0; |
| 2460 | if (bstride == 1) { |
| 2461 | #if NPY_SIMD |
| 2462 | npy_uintp len_m = len & -npyv_nlanes_u8; |
| 2463 | npy_uintp zcount = 0; |
| 2464 | for (const char *end = data + len_m; data < end;) { |
| 2465 | npyv_u16x2 vsum16 = count_zero_bytes_u16((const npy_uint8**)&data, (const npy_uint8*)end, NPY_MAX_UINT16); |
| 2466 | npyv_u32x2 sum_32_0 = npyv_expand_u32_u16(vsum16.val[0]); |
| 2467 | npyv_u32x2 sum_32_1 = npyv_expand_u32_u16(vsum16.val[1]); |
| 2468 | zcount += npyv_sum_u32(npyv_add_u32( |
| 2469 | npyv_add_u32(sum_32_0.val[0], sum_32_0.val[1]), |
| 2470 | npyv_add_u32(sum_32_1.val[0], sum_32_1.val[1]) |
| 2471 | )); |
| 2472 | } |
| 2473 | len -= len_m; |
| 2474 | count = len_m - zcount; |
| 2475 | #else |
| 2476 | if (!NPY_ALIGNMENT_REQUIRED || npy_is_aligned(data, sizeof(npy_uint64))) { |
| 2477 | int step = 6 * sizeof(npy_uint64); |
| 2478 | int left_bytes = len % step; |
| 2479 | for (const char *end = data + len; data < end - left_bytes; data += step) { |
| 2480 | count += count_nonzero_bytes_384((const npy_uint64 *)data); |
| 2481 | } |
| 2482 | len = left_bytes; |
| 2483 | } |
| 2484 | #endif // NPY_SIMD |
| 2485 | } |
| 2486 | for (; len > 0; --len, data += bstride) { |
| 2487 | count += (*data != 0); |
| 2488 | } |
| 2489 | return count; |
| 2490 | } |
| 2491 | |
| 2492 | static inline NPY_GCC_OPT_3 npy_intp |
| 2493 | count_nonzero_u16(const char *data, npy_intp bstride, npy_uintp len) |
nothing calls this directly
no test coverage detected