Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 17.12.24 18:44
Оценка:
Подскажите алгоритм оптимального чтения LSB num бит.
Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
Например: first = 2, num = 5, читаем 00111 = 7.
Первое что приходит:
int v = 0;
for (int i = first; i < num + first; i++)
  v = (v << 1) + (value & (1 << i)) ? 1 : 0;

Меня смущает цикл for и оператор if.
Спасибо.
Re: Алгоритм чтения LSB-bit
От: wl. Россия  
Дата: 17.12.24 19:35
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Подскажите алгоритм оптимального чтения LSB num бит.

V>Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
V>Например: first = 2, num = 5, читаем 00111 = 7.
V>Первое что приходит:
V>int v = 0;
V>for (int i = first; i < num + first; i++)
V>  v = (v << 1) + (value & (1 << i)) ? 1 : 0;

V>Меня смущает цикл for и оператор if.
V>Спасибо.

а чем такой вариант не устраивает?
в каком-то эмуляторе, скорее всего PPSSPP, который эмулирует MIPS, видел шаблоны, которые автоматом конвертируют LSB в MSB, а там уж обычные сдвиги и маски можно применить.
Не предлагаю копаться в таком гигантском коде, чтобы найти эти шаблоны, просто это направление, в котором можно поискать. Не факт даже, что шаблонами быстрее будет
Re: Алгоритм чтения LSB-bit
От: Videoman Россия https://hts.tv/
Дата: 17.12.24 19:42
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Подскажите алгоритм оптимального чтения LSB num бит.

V>Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
V>Например: first = 2, num = 5, читаем 00111 = 7.

Не понятно, для чего, какие ограничения. Нужно просто без циклов? Так пойдет?
#include <cstdint>

int main() 
{
    uint32_t value = 0xf0;
    const uint32_t first = 2;
    const uint32_t num = 5;

    // reverse bits
    value = ((value >> 1) & 0x55555555) | ((value & 0x55555555) << 1);
    value = ((value >> 2) & 0x33333333) | ((value & 0x33333333) << 2);
    value = ((value >> 4) & 0x0F0F0F0F) | ((value & 0x0F0F0F0F) << 4);
    value = ((value >> 8) & 0x00FF00FF) | ((value & 0x00FF00FF) << 8);
    value = ( value >> 16             ) | ( value               << 16);

    // get bit field
    value = (value << first) >> (32 - num);

    return value;
}
Re[2]: Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 18.12.24 06:52
Оценка:
Здравствуйте, wl., Вы писали:
wl.>а чем такой вариант не устраивает?
Конечная цель — чтение кодов Хаффмана.
Хотелось найти максимально производительный код!
Re: Алгоритм чтения LSB-bit
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 18.12.24 07:59
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Подскажите алгоритм оптимального чтения LSB num бит.

V>Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
V>Например: first = 2, num = 5, читаем 00111 = 7.

Компилятор какой? И платформа?

У ARM, например, есть команда rbit, которая разворачивает все биты в слове.
Ну а её аналог с логарифмической сложностью уже есть в соседнем комментарии.
А извлечь начиная с нужной позиции — сдвиги и маскирование — тривиально (и в случае того же ARM делается одной командой ubfx; для x86 надо или shr и and, или shl и shr).

Но непонятно, зачем вообще такой разворот нужен. Уточните на более высоком уровне.
The God is real, unless declared integer.
Re[2]: Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 18.12.24 10:28
Оценка:
Здравствуйте, netch80, Вы писали:
Конечная цель — чтение кодов Хаффмана.
Хотелось найти максимально производительный код!
gcc, win32
Re: Алгоритм чтения LSB-bit
От: Zhendos  
Дата: 18.12.24 10:38
Оценка: +1
Здравствуйте, Vladimir, Вы писали:

V>Подскажите алгоритм оптимального чтения LSB num бит.

V>Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
V>Например: first = 2, num = 5, читаем 00111 = 7.
V>Меня смущает цикл for и оператор if.

Не очень понял смысл цикла, если нужно со 2 по 5 бит, то просто
сдвигаем биты к началу и накладываем маску, что-то типа:

(value >> (first + 1)) & ((1 << (num- 1)) - 1)


V>Первое что приходит:
V>int v = 0;
V>for (int i = first; i < num + first; i++)
V>  v = (v << 1) + (value & (1 << i)) ? 1 : 0;


Кстати в коде ошибка из-за приоритета операторов,
нужно в скобки обернуть выражение "(value & (1 << i)) ? 1 : 0",
чтобы все правильно считалось.

Плюс вполне возможно UB из-за работы с потенциально отрицательными
числами, лучше конечно использовать "unsigned int" в битовой арифметике.
Отредактировано 18.12.2024 10:40 Zhendos . Предыдущая версия .
Re[3]: Алгоритм чтения LSB-bit
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.12.24 13:40
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Конечная цель — чтение кодов Хаффмана.

V>Хотелось найти максимально производительный код!
V>gcc, win32

Коды Хаффмана вычислительно тяжелы. Точно ли именно чтение их является узким местом в плане производительности?
Re[4]: Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 18.12.24 14:48
Оценка:
Здравствуйте, Pzz, Вы писали:
Pzz>Коды Хаффмана вычислительно тяжелы. Точно ли именно чтение их является узким местом в плане производительности?
В данный момент реализую декомпрессию статического Deflate. Коды Хаффмина вычисляются на основании таблицы кодов. Основная нагрузка прочитать 7-ми, 8-ми, 9-ти битовый код из потока. Коды Хаффмана пишутся справа налево.
Re: Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 18.12.24 14:56
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Подскажите алгоритм оптимального чтения LSB num бит.

V>Есть число 11110000 = F0. Необходимо прочитать справа налево num bit, начиная с first.
V>Например: first = 2, num = 5, читаем 00111 = 7.
V>Первое что приходит:
V>int v = 0;
V>for (int i = first; i < num + first; i++)
V>  v = (v << 1) + (value & (1 << i)) ? 1 : 0;

V>Меня смущает цикл for и оператор if.
V>Спасибо.
Пришла идея: Записать обратный порядок бит, затем читать как обычно.
v = F0;
a = (((v >> 0) & 1) << 7) |
    (((v >> 1) & 1) << 6) |
    (((v >> 2) & 1) << 5) |
    (((v >> 3) & 1) << 4) |
    (((v >> 4) & 1) << 3) |
    (((v >> 5) & 1) << 2) |
    (((v >> 6) & 1) << 1) |
    (((v >> 7) & 1) << 0);
result = (a >> 8-(2+5)) & 1F;
Re[2]: Алгоритм чтения LSB-bit
От: kov_serg Россия  
Дата: 19.12.24 10:35
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Пришла идея: Записать обратный порядок бит, затем читать как обычно.[ccode]

Вы изобретаете свой "горный" велосипед или хотите сделать учебную реализацию уже сущестующего алгоритма упаковки?
Re[3]: Алгоритм чтения LSB-bit
От: Vladimir Россия  
Дата: 19.12.24 11:49
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Vladimir, Вы писали:


V>>Пришла идея: Записать обратный порядок бит, затем читать как обычно.[ccode]

_>Вы изобретаете свой "горный" велосипед или хотите сделать учебную реализацию уже сущестующего алгоритма упаковки?
Новое прочтение RFC1951 (Deflate).
Re[2]: Алгоритм чтения LSB-bit
От: sergii.p  
Дата: 19.12.24 11:59
Оценка:
Здравствуйте, Vladimir, Вы писали:

V>Пришла идея: Записать обратный порядок бит, затем читать как обычно.


https://graphics.stanford.edu/~seander/bithacks.html#SwappingBitsXOR

unsigned int reverse_bits(unsigned int v)
{
    return (v * 0x0202020202ULL & 0x010884422010ULL) % 1023;
}
Re[3]: Алгоритм чтения LSB-bit
От: pva  
Дата: 22.12.24 15:58
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>
SP>unsigned int reverse_bits(unsigned int v)
SP>{
SP>    return (v * 0x0202020202ULL & 0x010884422010ULL) % 1023;
SP>}
SP>

Странно, почему не "& 0x3ff", а % 1023. И почему ограничение в диаппазоне 10 бит.

Как альтернатива — можно использовать предпросчитанную таблицу для реверса. Тогда все сведется к return (inversion[value] >> num) & ((1 << size) — 1);
newbie
Re[4]: Алгоритм чтения LSB-bit
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 22.12.24 18:41
Оценка:
Здравствуйте, pva, Вы писали:

SP>>
SP>>unsigned int reverse_bits(unsigned int v)
SP>>{
SP>>    return (v * 0x0202020202ULL & 0x010884422010ULL) % 1023;
SP>>}
SP>>

pva>Странно, почему не "& 0x3ff", а % 1023.

Эквивалентом "&0x3ff" было бы "%1024", а не "%1023". Внимательнее plz

pva> И почему ограничение в диаппазоне 10 бит.


Для более длинного нужны и константы длиннее. А этот фокус работает только со специально рассчитанными константами. В Hackersʼ Delight описана ещё пачка подобных.

pva>Как альтернатива — можно использовать предпросчитанную таблицу для реверса. Тогда все сведется к return (inversion[value] >> num) & ((1 << size) — 1);


Дорого.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.