| ... | ... | @@ -9,45 +9,26 @@ const std = @import("std"); |
| 9 | 9 | // SWAR-Masks and factors can be defined as 2-adic fractions |
| 10 | 10 | // TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, |
| 11 | 11 | // subsubsection "Working with the rightmost bits" and "Sideways addition". |
| 12 | | fn popcountXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 { |
| 12 | |
| 13 | fn popcountXi2_generic(comptime ST: type) fn (a: ST) callconv(.C) i32 { |
| 13 | 14 | return struct { |
| 14 | | fn f(a: T) callconv(.C) i32 { |
| 15 | fn f(a: ST) callconv(.C) i32 { |
| 15 | 16 | @setRuntimeSafety(builtin.is_test); |
| 16 | | |
| 17 | | var x = switch (@bitSizeOf(T)) { |
| 18 | | 32 => @bitCast(u32, a), |
| 19 | | 64 => @bitCast(u64, a), |
| 20 | | 128 => @bitCast(u128, a), |
| 21 | | else => unreachable, |
| 22 | | }; |
| 23 | | const k1 = switch (@bitSizeOf(T)) { // -1/3 |
| 24 | | 32 => @as(u32, 0x55555555), |
| 25 | | 64 => @as(u64, 0x55555555_55555555), |
| 26 | | 128 => @as(u128, 0x55555555_55555555_55555555_55555555), |
| 27 | | else => unreachable, |
| 28 | | }; |
| 29 | | const k2 = switch (@bitSizeOf(T)) { // -1/5 |
| 30 | | 32 => @as(u32, 0x33333333), |
| 31 | | 64 => @as(u64, 0x33333333_33333333), |
| 32 | | 128 => @as(u128, 0x33333333_33333333_33333333_33333333), |
| 33 | | else => unreachable, |
| 34 | | }; |
| 35 | | const k4 = switch (@bitSizeOf(T)) { // -1/17 |
| 36 | | 32 => @as(u32, 0x0f0f0f0f), |
| 37 | | 64 => @as(u64, 0x0f0f0f0f_0f0f0f0f), |
| 38 | | 128 => @as(u128, 0x0f0f0f0f_0f0f0f0f_0f0f0f0f_0f0f0f0f), |
| 39 | | else => unreachable, |
| 40 | | }; |
| 41 | | const kf = switch (@bitSizeOf(T)) { // -1/255 |
| 42 | | 32 => @as(u32, 0x01010101), |
| 43 | | 64 => @as(u64, 0x01010101_01010101), |
| 44 | | 128 => @as(u128, 0x01010101_01010101_01010101_01010101), |
| 17 | const UT = switch (ST) { |
| 18 | i32 => u32, |
| 19 | i64 => u64, |
| 20 | i128 => u128, |
| 45 | 21 | else => unreachable, |
| 46 | 22 | }; |
| 47 | | x = x - ((x >> 1) & k1); // aggregate duos |
| 48 | | x = (x & k2) + ((x >> 2) & k2); // aggregate nibbles |
| 49 | | x = (x + (x >> 4)) & k4; // aggregate bytes |
| 50 | | x = (x *% kf) >> @bitSizeOf(T) - 8; // 8 most significant bits of x + (x<<8) + (x<<16) + .. |
| 23 | var x = @bitCast(UT, a); |
| 24 | x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos |
| 25 | x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles |
| 26 | + (x & (~@as(UT, 0) / 5)); |
| 27 | x += x >> 4; |
| 28 | x &= ~@as(UT, 0) / 17; // 0x0F...0F, aggregate bytes |
| 29 | // 8 most significant bits of x + (x<<8) + (x<<16) + .. |
| 30 | x *%= ~@as(UT, 0) / 255; // 0x01...01 |
| 31 | x >>= (@bitSizeOf(ST) - 8); |
| 51 | 32 | return @intCast(i32, x); |
| 52 | 33 | } |
| 53 | 34 | }.f; |