我目前用于计算legendre符号的代码是
inline int legendre(int pa, int pm){
register unsigned int a = pa;
register unsigned int m = pm;
int t = 1;
int tmp=0;
while (a>1) {
tmp=__builtin_ctz(a);//a=x*2^tmp, where x is odd
a>>=tmp;
if(tmp&1 &&((m&7)==3 || (m&7)==5))//if it is an odd power and m=3,5 mod 8
t=-t;//invert result
if((a&3)==3 && (m&3)==3)//if m=3 mod 4 and a=3 mod 4
t=-t;//invert result
m %= a;
tmp=a;
a=m;
m=tmp;//exchange variables
}
if (m == 1) return t;
return 0;
}
这里可以进行任何优化吗?
答案 0 :(得分:1)
根据您已经编写的内容,看起来只能进行相当微不足道的优化。
// Get rid of the inline, it's pointless for functions this large.
// Some compilers might remove the inline for big functions.
int legendre(int pa, int pm){
// Rather than creating variables here, you COULD make global
// variables and assign them here. That would get rid of some
// time taken creating these local variables.
register unsigned int a = pa;
register unsigned int m = pm;
int t = 1;
int tmp=0;
while (a>1) {
tmp=__builtin_ctz(a);//a=x*2^tmp, where x is odd
a>>=tmp;
// This just throws both if-statements into one.
if((tmp&1 &&((m&7)==3 || (m&7)==5))
|| ((a&3)==3 && (m&3)==3)) t = -t;
m %= a;
tmp=a;
a=m;
m=tmp;//exchange variables
}
if (m == 1) return t;
return 0;
}
除此之外,这段代码看起来很好。我认为你不必担心它。
答案 1 :(得分:0)
我能看到的唯一可能是优化的是标志翻转:
t = (t ^ -1) + 1
或
t = ~t + 1; // I don't prefer this one
有趣的是 - 它在某些平台上可能会变慢,尤其是虚拟机,因此您需要手动检查。
修改强>:
好的,发现我忽略了一件好事,你创建了一个临时变量来交换它们,你可以使用XOR,因为它们都是整数:
m = m^a;
a = a^m;
m = m^a;
这样,vars将交换它们的值而不需要temp var