Все-это тихий (не сигнализирующий, иначе нормальный) NaN, который вы хотите. Самый простой способ получить единицу - с помощью SSE2 pcmpeqd xmm0,xmm0
установить для каждого бита в регистре значение 1
, то есть целое число дополнения 2 -1
. ( Эффективно установить все биты в регистре ЦП на 1 / Каковы наилучшие последовательности команд для генерации векторных констант на лету? )
Это на самом деле -NaN
- бит знака установлен. Рассмотрите целочисленное смещение вправо (psrld xmm0,1
) или делите на ноль / ноль (xorps xmm0,xmm0
/ divpd xmm0,xmm0
), если это нежелательно.
Математические функции, которые хотят возвращать NaN, часто также хотят чтобы убедиться, что бит недопустимого для FP фиксированного исключения установлен в MXCSR (или фактически вызовет исключение, если ваш вызывающий абонент разоблачил это исключение). Чтобы сделать , что , вы можете умножить или добавить NaN к себе. например,
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
или mulss
для одинарной точности float
. mulpd
/ mulps
также будет уместным.
Битовый шаблон для умножения или добавления NaN с NaN определенно все еще является NaN, и все равно должен быть такой же полезной нагрузкой, так что все равно единицами.
Наличие возвращаемого значения в результате mulsd
или addsd
(или divsd
) также имеет то преимущество, что если вызывающий использует этот регистр повторно в al oop, он не будет иметь задержка обхода домена. (В семействе Sandybridge это длится вечно. Например, каждый addsd xmm1, xmm0
будет иметь дополнительный цикл задержки от ввода xmm1 к выводу xmm1, если xmm0 пришел от pcmpeqd
, даже если это было длинным go и целочисленным SIMD Уоп уже удалился.)
Вы можете даже сделать это без ответвлений, если вы используете cmpsd
или cmppd
: вы можете orps
эту маску 0 / -1 в результате для сделать это NaN или без изменений. Если какой-то другой расчет (или уже будет) установит флаг FP-invalid или если вас это не волнует, все готово.
Остерегайтесь удлинения критического пути с помощью дополнительного cmp / или; если вы ожидаете, что это очень редко, вы все равно можете сравнить и перейти, например, с movmskpd
/ test eax,eax
/ jnz
на результат cmppd, чтобы посмотреть, был ли установлен какой-либо бит =>, один из элементов SIMD не прошел некоторую проверку.