views:

58

answers:

4

As the title of this question tells I want to know the best way to mix blocks of bits within an integer (especially 64bit unsigned)

for example I have 8bit integer, where it's bits are 0000 1111 mix 4bits by 4 bits = 0101 0101

example 2: 0010 0110
0 1 1 0 right *0.0.1.0 left* = 00011100 mix 4bits by 4 bits = 0001 1100 Simple is, . places filled with bits of right block

What I am doing rightnow:

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;
}

where setbit is a macro that sets or clears the bit on certain position. What exactly I need is mix each 32bits with next 32bits mix each 16bits with next 16bits mix each 16bits with after next 16bits mix each 8bits with next 8bits etc... I hope I can do rest if one example of such bit operations is available. I have looked on google a lot, but ended up with tutorials which do not demonstrate such scenario.

Stay well.

A: 

What I would do is have a 16-element table that holds the result of expanding each nibble for the multiplex operation. Then just left-shift 1 as needed and bitwise-or the results together.

Ignacio Vazquez-Abrams
Dear Ignacio, I am teacher of statistics, we are fidning ways to shuffle different data, and I know very little about bit operations.**Question is HOW ?**
Jason z
How *what*? How does one write the table? How does one determine the contents of the table? How does one do a bitwise-or in Language X?
Ignacio Vazquez-Abrams
Thanks for the smart answer, unfortunately that doesn't help.int array[ 16 ] = {................. WHAT HERE ..................}v = v | array; ?????This is WHAT I have no idea.
Jason z
{0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55}
Ignacio Vazquez-Abrams
You could let me know this 'why', what this means, unfortunately there are many good answering people on stackoverflow who love answering very diplomatically and let questioning party keep looking for what they want for their whole life. We will post question on some paid site and get it done for our research. You must keep in mind I 61 years old am not computer programmer, we are researchers and we needed little help from programmers that we couldn't find in our area and ended up here. Once again, thank you for your precious time.
Jason z
@Jason: Please note that information about your age, experience, background and field of expertise was not provided in the original question. That makes it kind of hard to take into consideration, when answering.
unwind
Because those are the values you get when you separate out the bits of the nibble.
Ignacio Vazquez-Abrams
I will spend some time reading the bit tweeding hacks :)Actually it's not time for me to learn new things but get nuts and bolts ready so that we can continue our research.Thanks again for being patient with such questions.
Jason z
+2  A: 

See Bit twiddling hacks at the Interleave bits section for a few solutions.

DarkDust
A: 

Found solution from bit tweeding hacks - although it was not good spending a lot time on this small operation. I am sure there must be many good ways doing this, but I needed solution that can keep me concentrated on my research, am sure it is worst way.

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;
}

stay well.

Jason z
A: 
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;
}
Jason z