diff --git a/inc/zoo/swar/SWAR.h b/inc/zoo/swar/SWAR.h index db371a9a..c79f33fe 100644 --- a/inc/zoo/swar/SWAR.h +++ b/inc/zoo/swar/SWAR.h @@ -340,10 +340,6 @@ struct BooleanSWAR: SWAR { friend constexpr auto equals(SWAR, SWAR) noexcept; - template - friend constexpr BooleanSWAR - constantIsGreaterEqual(SWAR) noexcept; - template friend constexpr BooleanSWAR constantIsGreaterEqual_MSB_off(SWAR) noexcept; @@ -374,36 +370,31 @@ convertToBooleanSWAR(SWAR arg) noexcept { return SWAR{SWAR::MostSignificantBit} & arg; } +template +constexpr T median(T x, U y, V z) { + return (x | y) & (y | z) & (x | z); +} + +template +constexpr BooleanSWAR +greaterEqual(SWAR left, SWAR right) noexcept { + // Adapted from TAOCP V4 P152 + // h is msbselector, x is right, l is lower/left. Sets MSB to 1 in lanes + // in test variable t for when xi < yi for lane i . Invert for greaterEqual. + // t = h & ~ + // z = (x|h) - (y&~h) + using S = swar::SWAR; + const auto h = S::MostSignificantBit, x = left.value(), y = right.value(); // x=left, y= right is x < y + const auto z = (x|h) - (y&~h); + // bitwise ternary median! + const auto t = h & ~median(x, ~y, z); + return ~BooleanSWAR{static_cast(t)}; // ~(x= y +} + template constexpr BooleanSWAR constantIsGreaterEqual(SWAR subtrahend) noexcept { - static_assert(1 < NBits, "Degenerated SWAR"); - constexpr auto MSB_Position = NBits - 1; - constexpr auto MSB = T(1) << MSB_Position; - constexpr auto MSB_Mask = - SWAR{meta::BitmaskMaker::value}; - constexpr auto Minuend = - SWAR{meta::BitmaskMaker::value}; - constexpr auto N_MSB = MSB & N; - - auto subtrahendWithMSB_on = MSB_Mask & subtrahend; - auto subtrahendWithMSB_off = ~subtrahendWithMSB_on; - auto subtrahendMSBs_turnedOff = subtrahend ^ subtrahendWithMSB_on; - if constexpr(N_MSB) { - auto leastSignificantComparison = Minuend - subtrahendMSBs_turnedOff; - auto merged = - subtrahendMSBs_turnedOff | // the minuend MSBs are on - leastSignificantComparison; - return MSB_Mask & merged; - } else { - auto minuendWithMSBs_turnedOn = Minuend | MSB_Mask; - auto leastSignificantComparison = - minuendWithMSBs_turnedOn - subtrahendMSBs_turnedOff; - auto merged = - subtrahendWithMSB_off & // the minuend MSBs are off - leastSignificantComparison; - return MSB_Mask & merged; - } + return greaterEqual(SWAR{N}, subtrahend); } template @@ -428,27 +419,6 @@ constantIsGreaterEqual_MSB_off(SWAR subtrahend) noexcept { } } -template -constexpr T median(T x, U y, V z) { - return (x | y) & (y | z) & (x | z); -} - -template -constexpr BooleanSWAR -greaterEqual(SWAR left, SWAR right) noexcept { - // Adapted from TAOCP V4 P152 - // h is msbselector, x is right, l is lower/left. Sets MSB to 1 in lanes - // in test variable t for when xi < yi for lane i . Invert for greaterEqual. - // t = h & ~ - // z = (x|h) - (y&~h) - using S = swar::SWAR; - const auto h = S::MostSignificantBit, x = left.value(), y = right.value(); // x=left, y= right is x < y - const auto z = (x|h) - (y&~h); - // bitwise ternary median! - const auto t = h & ~median(x, ~y, z); - return ~BooleanSWAR{static_cast(t)}; // ~(x= y -} - // In the condition where only MSBs will be on, we can fast lookup with 1 multiply the index of the most signficant byte that is on. // This appears to be a mapping from the (say) 256 unique values of a 64 bit int where only MSBs of each 8 bits can be on, but I don't fully understand it. // Adapted from TAOCP Vol 4A Page 153 Eq 94. @@ -473,7 +443,7 @@ greaterEqual_MSB_off(SWAR left, SWAR right) noexcept { template constexpr auto booleans(SWAR arg) noexcept { - return ~constantIsGreaterEqual<0>(arg); + return ~greaterEqual(SWAR{0}, arg); } template