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