смешать N бит со следующими N битами (например, каждые 4 бита) 00001111 -> 01010101 - PullRequest
1 голос
/ 27 августа 2010

Как видно из названия этого вопроса, я хочу знать, как лучше всего смешивать блоки битов в целое число (особенно в 64-битных беззнаковых)

например у меня есть 8-битное целое, где это биты 0000 1111 микс 4 бит на 4 биты = 0101 0101

пример 2: 0010 0110
0 1 1 0 вправо 0.0.1.0 осталось = 00011100 смешать 4 бита на 4 бита = 0001 1100 Простое,. места, заполненные битами правого блока

Что я делаю правильно сейчас:

uint64_t mix32(uint64_t v) {
    uint64_t ret=0;
    int x=0;
    for(int i=0; i<32; i++) {
        setbit(ret, x, getbit(v, i));
        x++;
        setbit(ret, x, getbit(v, i+32));
        x++;
    }

    return ret;
}

где setbit - это макрос, который устанавливает или очищает бит в определенной позиции. Что именно мне нужно смешивать каждые 32 бита со следующими 32 бита смешайте каждые 16 бит со следующими 16 битами смешивать каждые 16 бит с последующими 16 битами смешайте каждые 8 ​​бит со следующими 8 битами так далее... Я надеюсь, что смогу сделать отдых, если доступен один пример таких битовых операций. Я много смотрел в Google, но в итоге получил учебники, которые не демонстрируют такой сценарий.

Будь здоров.

Ответы [ 4 ]

3 голосов
/ 27 августа 2010

См. Бит с твилами в разделе Чередование битов для нескольких решений.

0 голосов
/ 29 августа 2010
unsigned __int64 mix32(unsigned __int64 v, bool right_even=true) {
    unsigned __int64 z = 0; 

    if(right_even)
        v = swap32(v);

    unsigned __int32 x = (v&0xffffffffUL);
    unsigned __int32 y = (v&0xffffffffUL)>>32;

    for (int i = 0; i < sizeof(x) * 8; i++) 
       z |= (x & 1ULL << i) << i | (y & 1ULL << i) << (i + 1);

    return z;
}
0 голосов
/ 27 августа 2010

Нашел решение от хитов с твидами, хотя тратить много времени на эту маленькую операцию было не очень хорошо. Я уверен, что должно быть много хороших способов сделать это, но мне нужно решение, которое поможет мне сосредоточиться на своих исследованиях, уверен, это худший способ.

uint64_t mix32(uint64_t v, bool right_even=true) {
    unsigned uint32_t x;   // Interleave bits of x and y, so that all of the
    unsigned uint32_t y;   // bits of x are in the even positions and y in the odd;
    unsigned uint64_t z = 0; // z gets the resulting Morton Number.

    if(right_even)
        v = swap32(v); //swap 32bit blocks

    char *n = (char*)malloc(sizeof(v));
    memcpy(n, &v, sizeof(v));
    memcpy(&y, n, sizeof(y));
    memcpy(&x, n+sizeof(x), sizeof(x));

    for (int i = 0; i < sizeof(x) * 8; i++) // unroll for more speed...
       z |= (x & 1ULL << i) << i | (y & 1ULL << i) << (i + 1);

    return z;
}

оставайся здоровым.

0 голосов
/ 27 августа 2010

То, что я хотел бы сделать, - это иметь 16-элементную таблицу, в которой содержится результат расширения каждого куска для операции мультиплексирования. Затем просто сдвиньте влево 1 по необходимости и поразрядно - или результаты вместе.

...