diff --git a/src/geometry.hpp b/src/geometry.hpp index 9aeb82a0..66d82562 100644 --- a/src/geometry.hpp +++ b/src/geometry.hpp @@ -54,6 +54,15 @@ forceinline u64 closest(u64 occupied) { return x & occupied; } +forceinline m8x64 ray_fill(m8x64 x) { +#if LPS_AVX512 + u64 y = (x.raw + 0x7E7E7E7E7E7E7E7E) & 0x8080808080808080; + return m8x64{(y - (y >> 7)) << 1}; +#else + return std::bit_cast(std::bit_cast(x).nonzeros()); +#endif +} + forceinline m8x64 attackers_from_rays(u8x64 ray_places) { constexpr u8 K = 1 << 0; constexpr u8 WP = 1 << 1; diff --git a/src/position.cpp b/src/position.cpp index b80d8731..738cc2ae 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -573,16 +573,9 @@ std::tuple Position::calc_pin_mask() const { // Pinners are second-closest pieces that are enemy sliders of the correct type. m8x64 pinner = maybe_pinner1 & maybe_pinner2; -// Does this ray have a pinner? -#if LPS_AVX512 - const m8x16 has_attacker_vecmask = u8x16{_mm_set1_epi64x(pinner.raw)}.nonzeros(); - const m8x64 pinned = m8x64{static_cast( - _mm_cvtsi128_si64(has_attacker_vecmask.mask(u8x16{_mm_set1_epi64x(maybe_pinned.raw)}).raw))}; -#else - m8x64 no_pinner_mask = std::bit_cast(std::bit_cast(pinner).to_vector().zeros()); - m8x64 pinned = maybe_pinned.andnot(no_pinner_mask); -#endif - + // Does this ray have a pinner? + const m8x64 has_pinner = geometry::ray_fill(pinner); + const m8x64 pinned = maybe_pinned & has_pinner; u8x64 nonmasked_pinned_ids = geometry::lane_broadcast(pinned.mask(ray_places & u8x64::splat(0xF)));