bullitufa
@bullitufa
электронщик программист (микроконтроллеры и PC)

Как реализовать функцию копирования бит со смещениями в src и/или dst и не кратным 8 количестве бит?

Всем доброго!

Необходимо (оптимально) скопировать count бит из uint8_t буфера со смещением стартового бита в другой буфер и тоже со смещением стартового буфера.
Какой более оптимальный способ стоит использовать?
**
 * @param dst Pointer to destination buffer
 * @param src Pointer to sources buffer
 * @param dst_start Beginning bit number. Value of range 0..7
 * @param src_start Read start bit number. Value of range 0..7 - Смещение с которого начинать писать.
 * @param count Number of bits to copy. Value of range 1..255
 * @return Number of bits to copied
 */
int memcpy_bit(uint8_t *dst, uint8_t dst_start, uint8_t *src, uint8_t src_start, uint8_t count)


UPD4
Необходимо начиная с "src_start" бита первого элемента буфера "src", скопировать (заменить содержимое!)
"count" бит в буфер "dst" начиная с "dst_start" бита.
Байты:          3-ий       2-ой       1-ый       0-ой
src[4] = { 0101_1111, 0101_1111, 0101_1111, 0101_1111 }
dst[4] = { 1100_1111, 0010_0000, 0010_0000, 1010_1010 }
src_start = 3
dst_start = 5
count = 25 // Для примера: 4*8 - dst_start - 2(оставляем значение старших бит dst)
memcpy_bit(uint8_t *dst, uint8_t dst_start, uint8_t *src, uint8_t src_start, uint8_t count);
После выполнения функции:
1. младшие 5 бит 0-вого байта dst остались прежними
2. 2 старших бита 3-его байта dst остались прежними
                                              ! 5-ый бит
src     xx xx11 1101  0111 1101  0111 1101  011x xx     // сдвинул src так, чтобы src_start был над dst_start. x - игнорируемые биты
dst[4] = { 1100_1111, 0010_0000, 0010_0000, 0110_1010 } // исходное значение
dst[4] = { 1111_1101, 0111 1101  0111 1101, 0110_1010 } // результат

Так как порядок инициализация слева направо, а выше указал в порядке справа налево, вот исходники для тестов:
uint8_t src[4]     = { 0b01011111, 0b01011111, 0b01011111, 0b01011111 };
uint8_t dst[4]     = { 0b10101010, 0b00100000, 0b00100000, 0b11001111 };
uint8_t dst_res[4] = { 0b01101010, 0b01111101, 0b01111101, 0b11111101 };
  • Вопрос задан
  • 174 просмотра
Пригласить эксперта
Ответы на вопрос 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Самое эффективное - использовать какой-нибудь SSE (гуглите shift bits sse. Лучше всего, мне кажется, подойдет _mm_slli_epi64). Но там очень много кода и случаев будет. Придется отдельно разбирать случаи сдвига влево и вправо, отдельно вычленять биты, которые SSE операция при сдвиге бы потеряла и записывать куда надо.

Следующий по эффективности вариант - это читать в int64_t, и там сдвигать биты. Придется сначала из переменной доставать старшые/младшие 1-7 бит и писать их отдельно, потом сдвигать биты и записывать куда надо. Используйте memcopy для чтения/записи 64-ех бит. Еще можно ускорить, если отдельно обработать первые несколько байт до 64-битного выравнивания, и потом придется еще обрабоать отдельно лишние 0-7 байтов в конце, если их количество не делится на 8.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы