一种编译器前端乘幂运算的方法技术领域
一种编译器前端乘幂运算的方法主要涉及计算机算法领域。
背景技术
乘幂运算是最基本的数学表达式之一,几乎所有高级语言都直接支持。同时,在实际应用尤其是高性能科学计算和密码算法中使用乘幂运算频率较高。因此,对编译器如何实现乘幂运算提出了较高的优化要求。目前,编译器对乘幂的支持与优化理论研究已经比较成熟,本发明主要是根据这些优化方法提出一个具体的实现算法,为研究编译器前端优化处理乘幂运算提供一个参考。这个算法是Window算法和静态最优加法链表算法的结合,最后给出算法效率分析。
发明内容
通过国家专利检索没有发现关于此系统方面的申请资料。
此方法主要是功能是将前端的乘幂操作转换为等价乘积,该文的算法结合Window算法和静态加法链算法,既能处理任意大小的幂值,又能得到比Window算法更短的加法链。
在实现中,定义的最优静态加法链表的大小为256,Win-dow大小为3:
#definePOWI_TABLE_SIZE256
#definePOWI_WINDOW_SIZE3
静态最优加法链表的定义如下所示:
staticconstunsignedcharpowi_table[POWI_TABLE_SIZE]=
{0,1,1,2,2,3,3,4,/*0-7*/
4,6,5,6,6,10,7,9,/*8-15*/
8,16,9,16,10,12,11,13,/*16-23*/
12,17,13,18,14,24,15,26,/*24-31*/
16,17,17,19,18,33,19,26,/*32-39*/
20,25,21,40,22,27,23,44,/*40-47*/
24,32,25,34,26,29,27,44,/*48-55*/
28,31,29,34,30,60,31,36,/*56-63*/
32,64,33,34,34,46,35,37,/*64-71*/
36,65,37,50,38,48,39,69,/*72-79*/
40,49,41,43,42,51,43,58,/*80-87*/
44,64,45,47,46,59,47,76,/*88-95*/
48,65,49,66,50,67,51,66,/*96-103*/
52,70,53,74,54,104,55,74,/*104-111*/
56,64,57,69,58,78,59,68,/*112-119*/
60,61,61,80,62,75,63,68,/*120-127*/
64,65,65,128,66,129,67,90,/*128-135*/
68,73,69,131,70,94,71,88,/*136-143*/
72,128,73,98,74,132,75,121,/*144-151*/
76,102,77,124,78,132,79,106,/*152-159*/
80,97,81,160,82,99,83,134,/*160-167*/
84,86,85,95,86,160,87,100,/*168-175*/
88,113,89,98,90,107,91,122,/*176-183*/
92,111,93,102,94,126,95,150,/*184-191*/
96,128,97,130,98,133,99,195,/*192-199*/
100,128,101,123,102,164,103,138,/*200-207*/
104,145,105,146,106,109,107,149,/*208-215*/
108,200,109,146,110,170,111,157,/*216-223*/
112,128,113,130,114,182,115,132,/*224-231*/
116,200,117,132,118,158,119,206,/*232-239*/
120,240,121,162,122,147,123,152,/*240-247*/
124,166,125,214,126,138,127,153,/*248-255*/
};
比如求n(n<256)的加法链,powi_tabie[n]和n-powi_tabie[n]即为加法链中的两个元素,以此类推直到有一个元素为1。给出了n!100的最优加法链表,其余的可以在GCC网站中得到。另一个重要的数据结构是:
treevartmp[POWI_TABLE_SIZE];
这个数组用来放置加法链对应的幂值,是存放临时结果的。其中tree[7]是操作数在编译器中间层的表示,称为树节点。其初值除vartmp[1]外都为零,vartmp[1]等于x1对应的树节点。笔者在实现这个算法的时候,没有根据经典的加法链算法,首先求出加法链,然后根据加法链填充中间幂值。而是采用了递规函数来实现,十分简洁,算法的主要部分是递规函数:gfc_expand_powi
算法6:gfc_expand_powi
输入:n,vartmp
输出:vartmp[1]**n
window"(1<<POWI_WINDOW_SIZE)-1;
可以看出,这种算法可以处理任意大小的n值。当n>255时,沿着左边两条分支得出op1和op2。其中的一个操作数为window位,可直接查表得出最优加法链;另一个采用加倍规则,以指数速度递减到小于256,然后查表得出加法链。同时,只要指数小于256,中间结果都保存下来。从最右边的分支可以看到,如果指数小于256,首先检查vartmp中有没有已经算出的结果,如果有就直接使用,避免了再去求加法链。因此,算法的效率很高。
在编译器的具体实现中,还要考虑另外一种情况,即当底数x为整数,指数n为负常整数时,乘幂的结果只有三种情况:-1,0,1。
如果n为负奇数,则x为1,结果为1;x为-1,结果为-1;其余结果为0。即可将乘幂操作转换为如下代码:
p=(x==1?1:x==-1?-1:0);
如果n为负偶数,则x为1或-1,结果为1;其余结果为0。
即可将乘幂操作转换为如下代码:
p=(x==-1llx==1?1:0);
算法的效率主要体现在将乘幂运算转换后乘法运算的次数,在加法链算法中也就是加法链的长度。
对于二进制算法,不管采不采用加法链算法,其乘法次数与幂指数的二进制表示有关,从算法中可以看出其乘法次数为:
ign」+u(n)
其中u(n)表示n的二进制表示中1的个数。
Window算法,其加法链长度为:
L-!-g-g!
!!1-g""+L
!+g
1-g
+2!-1
L为指数n的二进制长度:ign+1,g为n的概率,!为Window的位数。该文没有对算法6的效率进行形式化的证明,但因为它采用了Window算法和静态最优加法链算法,其效率要优于单纯的Window算法。在实际应用中,通过测试某物理模拟题,单机性能提高约3%。