Stub помогает нам запустить тест. Как? Он дает значения, которые помогают запустить тест. Эти значения сами по себе не являются реальными, и мы создали эти значения только для запуска теста. Например, мы создаем HashMap, чтобы дать нам значения, похожие на значения в таблице базы данных. Поэтому вместо прямого взаимодействия с базой данных мы взаимодействуем с Hashmap.
Mock - это поддельный объект, который запускает тест. где мы положим assert.
Что вам по сути нужно сделать, это установить все байты (входных данных), которые вы хотите заменить, на ноль. Затем установите все остальные байты подстановки в ноль и ИЛИ результаты. У вас уже есть маска для этого из _mm_cmpeq_epi8
. В целом, это можно сделать так:
__m128i mask = _mm_cmpeq_epi8(inp, val);
return _mm_or_si128(_mm_and_si128(mask, sub), _mm_andnot_si128(mask, inp));
Поскольку последняя комбинация и / и не / или очень распространена, SSE4.1 ввел команду, которая (по существу) объединяет их в одну:
__m128i mask = _mm_cmpeq_epi8(inp, val);
return _mm_blendv_epi8(inp, sub, mask);
На самом деле, clang5.0 и более поздние версии достаточно умны, чтобы заменить первый вариант вторым при компиляции с оптимизацией: https://godbolt.org/z/P-tcik
Примечание: если значение подстановки действительно 0x01
, вы можете использовать тот факт, что маска (результат сравнения) равна 0x00
или 0xff
(то есть -0x01
). ), т. е. вы можете обнулить значения, которые хотите заменить, и затем вычесть маску:
__m128i val = _mm_set1_epi8(0x06);
__m128i mask = _mm_cmpeq_epi8(inp, val);
return _mm_sub_epi8(_mm_andnot_si128(mask, inp), mask);
Это может сохранить либо загрузку вектора 0x01
из памяти, либо потерю для него регистра. И в зависимости от вашей архитектуры он может иметь немного лучшую пропускную способность.