Вот, пожалуйста.
inline bool isLessThan( __m128i a, __m128i b )
{
/* Compare 8-bit lanes for ( a < b ), store the bits in the low 16 bits of the
scalar value: */
const int less = _mm_movemask_epi8( _mm_cmplt_epi8( a, b ) );
/* Compare 8-bit lanes for ( a > b ), store the bits in the low 16 bits of the
scalar value: */
const int greater = _mm_movemask_epi8( _mm_cmpgt_epi8( a, b ) );
/* It's counter-intuitive, but this scalar comparison does the right thing.
Essentially, integer comparison searches for the most significant bit that
differs... */
return less > greater;
}
Порядок меньше идеального, поскольку coz pcmpgtb
обрабатывает эти байты как целые числа со знаком, но вы сказали, что это не важно для вашего варианта использования.
Обновление: вот немного более медленная версия с uint128_t
порядком сортировки.
// True if a < b, for unsigned 128 bit integers
inline bool cmplt_u128( __m128i a, __m128i b )
{
// Flip the sign bits in both arguments.
// Transforms 0 into -128 = minimum for signed bytes,
// 0xFF into +127 = maximum for signed bytes
const __m128i signBits = _mm_set1_epi8( (char)0x80 );
a = _mm_xor_si128( a, signBits );
b = _mm_xor_si128( b, signBits );
// Now the signed byte comparisons will give the correct order
const int less = _mm_movemask_epi8( _mm_cmplt_epi8( a, b ) );
const int greater = _mm_movemask_epi8( _mm_cmpgt_epi8( a, b ) );
return less > greater;
}
Мы строим сравнения без знака из числа со знаком, сдвигая диапазон входных данных без знака к знаку (переключив старший бит = вычесть 128).