Эмуляция переменного сдвига разряда с помощью только постоянные сдвиги?

Сообщение об ошибке: ERROR Cannot prepare tests due to an error.

выдается, когда TestCafe не может передать ваш тестовый код. Это означает, что в тестовом коде есть синтаксическая ошибка.

Ваш код должен выглядеть следующим образом:

fixture ('Init Tests')
    .page('http://devexpress.github.io/testcafe/example/');

test('Check Initial pg', async (t) => { 
    await t.expect(Selector('title').innerText).eql('XXXXXXX'); 
});
12
задан Peter Cordes 26 January 2019 в 05:29
поделиться

7 ответов

Итак ...

Я решил попробовать и это, поскольку Майк Эктон заявил, что это будет быстрее, чем использование микрокодированного сдвига CELL / PS3 на своем сайте CellPerformance, где он предлагает избегать косвенного сдвига . Однако во всех моих тестах использование микрокодированной версии было не только быстрее, чем полная универсальная замена непрямого сдвига без ветвлений, но и требовалось меньше памяти для кода (1 инструкция).

Единственная причина, по которой я сделал это как шаблоны должны были получить правильный вывод как для знаковых (обычно арифметических), так и для беззнаковых (логических) сдвигов.

template <typename T> FORCEINLINE T VariableShiftLeft(T nVal, int nShift)
{   // 31-bit shift capability (Rolls over at 32-bits)
    const int bMask1=-(1&nShift);
    const int bMask2=-(1&(nShift>>1));
    const int bMask3=-(1&(nShift>>2));
    const int bMask4=-(1&(nShift>>3));
    const int bMask5=-(1&(nShift>>4));
    nVal=(nVal&bMask1) + nVal;   //nVal=((nVal<<1)&bMask1) | (nVal&(~bMask1));
    nVal=((nVal<<(1<<1))&bMask2) | (nVal&(~bMask2));
    nVal=((nVal<<(1<<2))&bMask3) | (nVal&(~bMask3));
    nVal=((nVal<<(1<<3))&bMask4) | (nVal&(~bMask4));
    nVal=((nVal<<(1<<4))&bMask5) | (nVal&(~bMask5));
    return(nVal);
}
template <typename T> FORCEINLINE T VariableShiftRight(T nVal, int nShift)
{   // 31-bit shift capability (Rolls over at 32-bits)
    const int bMask1=-(1&nShift);
    const int bMask2=-(1&(nShift>>1));
    const int bMask3=-(1&(nShift>>2));
    const int bMask4=-(1&(nShift>>3));
    const int bMask5=-(1&(nShift>>4));
    nVal=((nVal>>1)&bMask1) | (nVal&(~bMask1));
    nVal=((nVal>>(1<<1))&bMask2) | (nVal&(~bMask2));
    nVal=((nVal>>(1<<2))&bMask3) | (nVal&(~bMask3));
    nVal=((nVal>>(1<<3))&bMask4) | (nVal&(~bMask4));
    nVal=((nVal>>(1<<4))&bMask5) | (nVal&(~bMask5));
    return(nVal);
}

РЕДАКТИРОВАТЬ: Примечание по isel () Я видел ваш код isel () на вашем веб-сайте .

// if a >= 0, return x, else y
int isel( int a, int x, int y )
{
    int mask = a >> 31; // arithmetic shift right, splat out the sign bit
    // mask is 0xFFFFFFFF if (a < 0) and 0x00 otherwise.
    return x + ((y - x) & mask);
};

FWIW, если вы переписываете свой isel () для выполнения маски и дополнения маски, это будет быстрее на вашей цели PowerPC, поскольку компилятор умный достаточно для генерации кода операции 'andc'. Это то же количество кодов операций, но в кодах операций меньше зависимости между результатом и регистром ввода. Две операции маски также могут выполняться параллельно на суперскалярном процессоре. Это может быть на 2-3 цикла быстрее, если все выровнено правильно. Вам просто нужно изменить возврат к этому для версий PowerPC:

return (x & (~mask)) + (y & mask);
8
ответ дан 2 December 2019 в 19:56
поделиться

Как насчет этого:

if (y & 16) x <<= 16;
if (y & 8) x <<= 8;
if (y & 4) x <<= 4;
if (y & 2) x <<= 2;
if (y & 1) x <<= 1;

вероятно, займет больше времени все же для выполнения, но легче чередоваться, если у Вас будет другой код для движения между.

5
ответ дан 2 December 2019 в 19:56
поделиться

Давайте предположим, что Ваш макс. сдвиг равняется 31. Таким образом, объем сдвига является 5-разрядным числом. Поскольку смещение кумулятивно, мы можем повредить это в пять постоянных сдвигов. Очевидная версия использует ветвление, но Вы исключили это.

Позвольте N быть числом между 1 и 5. Вы хотите сместиться x на 2 Н, если бит, значение которого составляет 2 Н, установлен в y, иначе сохраните x в целости. Здесь один способ сделать это:

#define SHIFT(N) x = isel(((y >> N) & 1) - 1, x << (1 << N), x);

Макрос присваивается к x также x << 2ᴺ или xВ зависимости от того, установлен ли Энный бит в y или нет.

И затем драйвер:

SHIFT(1); SHIFT(2); SHIFT(3); SHIFT(4); SHIFT(5)

Обратите внимание, что N является макро-переменной и становится постоянным.

Не знайте хотя, если это будет на самом деле быстрее, чем переменный сдвиг. Если бы это было бы, каждый задается вопросом, почему микрокод не выполнил бы это вместо этого...

4
ответ дан 2 December 2019 в 19:56
поделиться

Эти повреждения моя голова. Я теперь отбросил полдюжину идей. Все они используют понятие, что, добавляя вещь к себе сдвиги уехали 1, выполнение того же к сдвигам результата уехало 4 и так далее. Если Вы сохраняете все частичные результаты для сдвига оставленными 0, 1, 2, 4, 8, и 16, то путем тестирования битов от 0 до 4 из переменной сдвига можно получить начальный сдвиг. Теперь сделайте это снова, однажды для каждого 1 бита в переменной сдвига. Откровенно говоря, Вы могли бы также отослать свой процессор для кофе.

Одно место я искал бы реальную справку, является Восхищением Хакера Hank Warren (который является единственной полезной частью этого ответа).

1
ответ дан 2 December 2019 в 19:56
поделиться

Как насчет этого:

int[] multiplicands = { 1, 2, 4, 8, 16, 32, ... etc ...};

int ShiftByVar( int x, int y )
{
    //return x << y;
    return x * multiplicands[y];
}
0
ответ дан 2 December 2019 в 19:56
поделиться

Существует некоторый хороший материал здесь относительно черной магии побитовой обработки: Усовершенствованная побитовая обработка fu (блог Christer Ericson)

Не знайте, непосредственно применим ли какой-либо из него, но если существует путь, вероятно, существуют некоторые подсказки к тому пути там где-нибудь.

0
ответ дан 2 December 2019 в 19:56
поделиться

Вот что-то, что банально невозможно прокрутить:

int result= value;

int shift_accumulator= value;

for (int i= 0; i<5; ++i)
{
    result += shift_accumulator & (-(k & 1)); // replace with isel if appropriate
    shift_accumulator += shift_accumulator;
    k >>= 1;
}
-1
ответ дан 2 December 2019 в 19:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: