С AVX-512 вы можете сэкономить одну мкоп. Вместо 2x vandpd
+ vcmppd
вы можете использовать vpternlogq
+ vpcmpuq
. Обратите внимание, что в приведенном ниже решении предполагается, что числа не являются NaN
.
Числа с плавающей запятой IEEE-754 обладают тем свойством nice, что они закодированы таким образом, что if x[62:0]
integer_less_than y[62:0]
, затем как с плавающей точкой: abs(x)<abs(y)
.
Таким образом, вместо установки обоих битов знака на 0
, мы можем скопировать бит знака x
в бит знака y
и сравните результат как целое число без знака. В (непроверенном) коде ниже для отрицательного x
оба xi[63]
и yi_sgnx[63]
равны 1
, а для положительного x
оба xi[63]
и yi_sgnx[63]
равны 0
. Таким образом, сравнение беззнаковых целых чисел фактически сравнивает xi[62:0]
с yi[62:0]
, что как раз то, что нам нужно для сравнения abs(x)<abs(y)
.
Инструкция vpternlog
подходит для копирования знакового бита, см. здесь или здесь . Не уверен, что константы z
и 0xCA
выбраны правильно.
__mmask8 cmplt_via_ternlog(__m512d x, __m512d y){
__m512i xi = _mm512_castpd_si512(x);
__m512i yi = _mm512_castpd_si512(x);
__m512i z = _mm512_set1_epi64(0x7FFFFFFFFFFFFFFFull);
__m512i yi_sgnx = _mm512_ternarylogic_epi64(z, yi, xi, 0xCA);
return _mm512_cmp_epu64_mask(xi, yi_sgnx, 1); /* _CMPINT_LT */
}