redis6.0.5之dict阅读笔记7-dict之奇妙函数rev

redis6.0.5之dict阅读笔记7-dict之奇妙函数rev
基本的函数我们已经看过,接下来我们把剩余的函数拿出来看看,发现剩下的函数相当奇妙
******************************************************************
/* Function to reverse bits. Algorithm from:
 * http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */
对比特位取反
这个算法的思想是每次先将区域分成平均高低两部分,然后对调每个区域的高低部分,直到区域中的元素为1个为止
static unsigned long rev(unsigned long v) {
    unsigned long s = CHAR_BIT * sizeof(v); // bit size; must be power of 2
    unsigned long mask = ~0UL; //全部为1
    while ((s >>= 1) > 0) { //每一次,将所在区域一分为二
        mask ^= (mask << s); //将所在区域的掩码值分成两半
        v = ((v >> s) & mask) | ((v << s) & ~mask);
        ((v >> s) & mask) 是将高区部分调整到低区
        ((v << s) & ~mask) 是将低区部分调整到高区
        再将两部分合起来就是整体,直到区域中的元素为1为止,无需交换即停止
    }
    return v; //得到我们取反的内容
}
举例说明如下:
初始值如下:
unsigned long v = 155ul+65536ul+65536ul*65536+65536ul*65536*65536+65536ul*65536ul*65536ul*65536ul+65536ul*65536*65536ul*65536*65536ul;
init: 
00000000000000010000000000000001   00000000000000010000000010011011
         高区                                       低区
第一步平均分成高低2个区域(64/2 = 32),每个32个元素,并且将高低两个区域进行交换,得到如下结果
Step1:
0000000000000001  0000000010011011          0000000000000001  0000000000000001
 低高区             低低区                     高高区           高低区  (这一行是为下步做准备的,看的更加清楚)
           低区                                         高区
第二步,将两个区域再分成高低平均两部分,在各自区域内进行高低区域交换,得到如下结果
Step2:
00000000  10011011  00000000  00000001          00000000  00000001  00000000  00000001
低低高区  低低低区  低高高区  低高低区          高低高区  高低低区  高高高区  高高低区  (这一行是为下步做准备的,看的更加清楚)
       低低区              低高区                      高低区              高高区
                低区                                         高区
第三步,继续将4个区域各自分成高低平均两部分,在各级区域内进行高地区域交换,得到如下结果                     
Step3:
10011011    00000000       00000001    00000000             00000001    00000000      00000001    00000000
低低低区    低低高区       低高低区    低高高区             高低低区    高低高区      高高低区    高高高区
       低低区                    低高区                             高低区                   高高区
                     低区                                                        高区
第三步,继续将8个区域各自分成高低平均两部分,在各自区域内进行高低区域交换(H代表高,L代表低) ,得到如下结果  
Step4:
1011   1001    0000  0000       0001  0000    0000  0000             0001  0000    0000  0000      0001  0000    0000  0000
LLLH   LLLL    LLHH  LLHL       LHLH  LHLL    LHHH  LHHL             HLLH  HLLL    HLHH  HLHL      HHLH  HHLL    HHHH  HHHL
    低低低区    低低高区         低高低区      低高高区               高低低区      高低高区        高高低区      高高高区
       低低区                    低高区                                        高低区                      高高区
                     低区                                                        高区
第三步,继续将16个区域各自分成高低平均两部分,在各自区域内进行高低区域交换(H代表高,L代表低) ,得到如下结果 
Step5:
11      10     01     10      00     00      00     00       01     00     00    00         00    00     00    00            
LLLLH  LLLLL   LLLHH  LLLHL   LLHLH  LLHLL   LLHHH  LLHHL    LHLLH  LHLLL  LHLHH LHLHL   LHHLH LHHLL  LHHHH LHHHL 
LLLL             LLLH             LLHL           LLHH             LHLL         LHLH           LHHL        LHHH            
    低低低区                          低低高区                             低高低区                低高高区               
       低低区                                                                       低高区                                        
                                                        低区                                                        
------------------------------------------------------------------------------------------------------------------------
01      00     00     00      00     00      00     00       01     00     00    00      00    00     00    00
HLLLH   HLLLL  HLLHH  HLLHL   HLHLH  HLHLL   HLHHH  HLHHL    HHLLH  HHLLL  HHLHH HHLHL   HHHLH HHHLL  HHHHH HHHHL
    HLLL          HLLH             HLHL            HLHH           HHLL          HHLH          HHHL         HHHH
        高低低区                          高低高区                     高高低区                      高高高区
                        高低区                                                      高高区
第三步,继续将32个区域各自分成高低平均两部分,在各自区域内进行高低区域交换(H代表高,L代表低) ,得到最终结果,每个区域为一个元素                                                    高区
Step6:
1      1       0       1       1    00100000000100000000000000010000000000000001000000000000000
LLLLLL LLLLLH  LLLLHL  LLLLHH 依次类推

******************************************************************
测试代码如下:
unsigned long v = 155ul+65536ul+65536ul*65536+65536ul*65536*65536+65536ul*65536ul*65536ul*65536ul+65536ul*65536*65536ul*65536*65536ul;
printbits(v);
v = rev(v);
printbits(v);
v = rev(v);
printbits(v);
//打印结果如下
0000000000000001000000000000000100000000000000010000000010011011
init:0000000000000001000000000000000100000000000000010000000010011011
Step1:0000000000000001000000001001101100000000000000010000000000000001
Step2:0000000010011011000000000000000100000000000000010000000000000001
Step3:1001101100000000000000010000000000000001000000000000000100000000
Step4:1011100100000000000100000000000000010000000000000001000000000000
Step5:1110011000000000010000000000000001000000000000000100000000000000
Step6:1101100100000000100000000000000010000000000000001000000000000000
1101100100000000100000000000000010000000000000001000000000000000
init:1101100100000000100000000000000010000000000000001000000000000000
Step1:1000000000000000100000000000000011011001000000001000000000000000
Step2:1000000000000000100000000000000010000000000000001101100100000000
Step3:0000000010000000000000001000000000000000100000000000000011011001
Step4:0000000000001000000000000000100000000000000010000000000010011101
Step5:0000000000000010000000000000001000000000000000100000000001100111
Step6:0000000000000001000000000000000100000000000000010000000010011011
0000000000000001000000000000000100000000000000010000000010011011

//调用的函数如下
static void printbits(unsigned long v) {
    unsigned long bit = 1ul<<63;
    while(bit) {
        printf("%s", (v&bit) ? "1" : "0");
        bit >>= 1;
    }
    printf("\n");
}

static unsigned long rev(unsigned long v) {
    unsigned long s = CHAR_BIT * sizeof(v); // bit size; must be power of 2
    unsigned long mask = ~0UL;
    int step = 0;
    printf("init:");
    printbits(v);

    while ((s >>= 1) > 0) {
        mask ^= (mask << s);
        v = ((v >> s) & mask) | ((v << s) & ~mask);
        step++;
        printf("Step%d:",step);
        printbits(v);
    }
    return v;
}

******************************************************************

 

posted on 2020-08-20 19:38  子虚乌有  阅读(266)  评论(0)    收藏  举报