* count number of nonzero bytes in 48 byte block * w must be aligned to 8 bytes * * even though it uses 64 bit types its faster than the bytewise sum on 32 bit * but a 32 bit type version would make it even faster on these platforms */
| 2358 | * but a 32 bit type version would make it even faster on these platforms |
| 2359 | */ |
| 2360 | static inline npy_intp |
| 2361 | count_nonzero_bytes_384(const npy_uint64 * w) |
| 2362 | { |
| 2363 | const npy_uint64 w1 = w[0]; |
| 2364 | const npy_uint64 w2 = w[1]; |
| 2365 | const npy_uint64 w3 = w[2]; |
| 2366 | const npy_uint64 w4 = w[3]; |
| 2367 | const npy_uint64 w5 = w[4]; |
| 2368 | const npy_uint64 w6 = w[5]; |
| 2369 | npy_intp r; |
| 2370 | |
| 2371 | /* |
| 2372 | * last part of sideways add popcount, first three bisections can be |
| 2373 | * skipped as we are dealing with bytes. |
| 2374 | * multiplication equivalent to (x + (x>>8) + (x>>16) + (x>>24)) & 0xFF |
| 2375 | * multiplication overflow well defined for unsigned types. |
| 2376 | * w1 + w2 guaranteed to not overflow as we only have 0 and 1 data. |
| 2377 | */ |
| 2378 | r = ((w1 + w2 + w3 + w4 + w5 + w6) * 0x0101010101010101ULL) >> 56ULL; |
| 2379 | |
| 2380 | /* |
| 2381 | * bytes not exclusively 0 or 1, sum them individually. |
| 2382 | * should only happen if one does weird stuff with views or external |
| 2383 | * buffers. |
| 2384 | * Doing this after the optimistic computation allows saving registers and |
| 2385 | * better pipelining |
| 2386 | */ |
| 2387 | if (NPY_UNLIKELY( |
| 2388 | ((w1 | w2 | w3 | w4 | w5 | w6) & 0xFEFEFEFEFEFEFEFEULL) != 0)) { |
| 2389 | /* reload from pointer to avoid a unnecessary stack spill with gcc */ |
| 2390 | const char * c = (const char *)w; |
| 2391 | npy_uintp i, count = 0; |
| 2392 | for (i = 0; i < 48; i++) { |
| 2393 | count += (c[i] != 0); |
| 2394 | } |
| 2395 | return count; |
| 2396 | } |
| 2397 | |
| 2398 | return r; |
| 2399 | } |
| 2400 | |
| 2401 | #if NPY_SIMD |
| 2402 | /* Count the zero bytes between `*d` and `end`, updating `*d` to point to where to keep counting from. */ |