我试图找到一个符合以下公式的函数:
f(0,0) = ( 0, 1)
f(0,1) = ( 2, 3)
f(0,2) = ( 4, 5)
f(0,3) = ( 6, 7)
f(0,4) = ( 8, 9)
f(0,5) = (10,11)
f(0,6) = (12,13)
f(0,7) = (14,15)
f(1,0) = ( 1, 2)
f(1,1) = ( 1, 3)
f(1,2) = ( 5, 6)
f(1,3) = ( 5, 7)
f(1,4) = ( 9,10)
f(1,5) = ( 9,11)
f(1,6) = (13,14)
f(1,7) = (13,15)
f(2,0) = ( 3, 4)
f(2,1) = ( 3, 5)
f(2,2) = ( 3, 6)
f(2,3) = ( 3, 7)
f(2,4) = (11,12)
f(2,5) = (11,13)
f(2,6) = (11,14)
f(2,7) = (11,15)
我最终得到了以下内容:
pair f(int a, int b){
int k = (b >> a << (a+1)) + (1<<a);
pair p = {k - 1, k + (b%(1<<a))};
return p;
};
但是存在一个问题:模数运算符没有在我所瞄准的架构上实现,因此使代码变慢。有没有不使用它的解决方案?
有一个片段可以快速测试公式:
#include <stdio.h>
typedef struct pair_ { int x; int y; } pair;
pair f(int a, int b){
int k = (b >> a << (a+1)) + (1<<a);
pair p = {k - 1, k + (b%(1<<a))};
return p;
};
int main(){
pair correct[4][16] = {{{0,1},{2,3},{4,5},{6,7},{8,9},{10,11},{12,13},{14,15},{16,17},{18,19},{20,21},{22,23},{24,25},{26,27},{28,29},{30,31}},{{1,2},{1,3},{5,6},{5,7},{9,10},{9,11},{13,14},{13,15},{17,18},{17,19},{21,22},{21,23},{25,26},{25,27},{29,30},{29,31}},{{3,4},{3,5},{3,6},{3,7},{11,12},{11,13},{11,14},{11,15},{19,20},{19,21},{19,22},{19,23},{27,28},{27,29},{27,30},{27,31}},{{7,8},{7,9},{7,10},{7,11},{7,12},{7,13},{7,14},{7,15},{23,24},{23,25},{23,26},{23,27},{23,28},{23,29},{23,30},{23,31}}};
for (int i=0; i<3; ++i)
for (int j=0; j<8; ++j)
printf("f(%.2d,%.2d) = (%.2d,%.2d) | Correct: %d %d\n",
i,
j,
f(i,j).x,
f(i,j).y,
f(i,j).x == correct[i][j].x,
f(i,j).y == correct[i][j].y);
return 0;
};
答案 0 :(得分:3)
但是存在一个问题:模数运算符没有在我所瞄准的架构上实现,因此使代码变慢。有没有不使用它的解决方案?
如果这是唯一的模运算符
b % (1<<a)
可以替换为
b & ((1<<a)-1)
pair f(int a, int b){
int k = (b >> a << (a+1)) + (1<<a);
pair p = { k - 1, k + (b & ((1<<a) - 1)) };
return p;
};
答案 1 :(得分:2)
如果你所说的模数是。
b % (1u << a)
然后你处于良好的状态,因为它始终是2的幂。这个表达式相当于:
b & ~(~0u << a)
转变应该非常快。如果您使用的是没有桶形移位器的处理器,使用查找表可能会更快:
b & mask[a]
将mask
定义为
static unsigned mask[] = {
~(~0u),
~(~0u << 1),
~(~0u << 2),
~(~0u << 3),
~(~0u << 4),
... skipping some entries
~(~0u << 30),
~(~0u << 31),
};