/*罗伯特·穆纳福(Robert Munafo)为c++编写的int128.c-128-bit整数算法(并通过proj/…/MCS.per复制到rhtf/…/int128.c.txt)许可证这个程序是自由软件:你可以重新发布它和/或修改它根据由自由软件基金会,许可证版本3,或(由您选择)任何更高版本。分发此程序是为了希望它会有用,但无任何保证;甚至没有适销性或特定用途的适用性。请参阅GNU通用公共许可证获取更多详细信息。您应该已经收到GNU通用公共许可证的副本与此程序一起使用。如果没有,请参阅.此源代码的许可证(GPL版本3)位于:mrob.com/pub/ries/GPL-3.txt文件说明书要将128位整数添加到现有程序中,请执行以下操作:将-DI128_COMPAT_PLUS_EQUAL传递给编译器(除非旧编译器)将程序重命名为“foo.cxx”,重新编译,处理错误消息包括/整型128.c将变量声明为s128修订历史记录20040416修复div1中的错误:当余数为0时,它的答案太低20070812 Add+=等运算符20070818将降级添加到long-long,以及在RHS上使用s64、u64或s32的许多运算符20070820大规模更快的乘法算法20070822从双精度加法转换20070825修复运算符中的错误-(const s128_o&,s32)20090619修复div1中的错误:当商为2的幂和余数是0(显然是不同的情况bug I修复于20040416)20091122修复mult1中的错误:乘法时符号处理欺骗失败-1 * 0. 现在,它又回到了简单的“将其视为未签名”方法。20130410添加GPL许可证标头20170215添加#define开关I128_COMPAT_PLUS_EQUAL以避免错误“‘s128_o::s128_o’命名构造函数,而不是类型”20191019避免比较有符号和无符号,以修复错误使用与C语言不兼容的编译器时出现的规范6.3.1.8。(使用时,这些错误导致错误结果operator+或operator+=,右侧为s32或s64)20191022 s128_str现在正确处理最小值-(2^127)20201029在赋值运算符(+=、/=等)中添加“return lhs;”*/#如果ndef _ int128c_#定义_ int128_c_/*编译行应提供-I/Users/munafo/shared/proj/include或同等产品*/#包括“rpmtypes.h”#包括“int128.h”#包括#包括//赋值和赋值转换运算符s128_o::s128_o(整数x){此->低=x;如果(x<0){此->高=-1;}其他{此->高=0;}}s128_o::s128_o(s64 x){这个->低=x;如果(x<0){此->高=-1;}其他{此->高=0;}}s128_o::s128_o(双x){u64吨、米、小时、升;如果(x<-1.7014118346046e38){//溢出负值this->high=HIGHBIT;此->低=0;}否则,如果(x<-9.2233720368547e18){//取54位尾数并移位到位t=*((u64*)&x);m=(t&BITS51_0)|BIT_52;t=(t&BITS62_0)>>52;//如果x是1.5*2^1,t将是1024//如果x是1.5*2^52,t将是1024+51=1075t=t-1075;如果(t>64){l=0;h=m<<(t-64);}其他{l=m<<t;h=m>>(64-t);}这个->低=~l;这个->高=~h;}否则,如果(x<9.2233720368547e18){//它适合u64此->低=((u64)x);这个->高=((x<0)-1 : 0);}否则,如果(x<1.7014118346046e38){//取54位尾数并移位到位t=*((u64*)&x);m=(t&BITS51_0)|BIT_52;t=(t&BITS62_0)>>52;//如果x是1.5*2^1,t将是1024//如果x是1.5*2^52,t将是1024+51=1075t=吨-1075;如果(t>64){此->低=0;这个->高=m<<(t-64);}其他{这个->低=m<<t;这个->高=m>>(64-t);}}其他{//溢出正此->高=BITS62_0;此->低=所有;}}//中缀添加s128o运算符+(常数s128o&lhs,常数s128O&rhs){s128 _ res;res.high=lhs.high+rhs.high;res.low=lhs.low+rhs.low;if(res.low<rhs.low){(res.高)++;}返回res;}/*20191019一些未实现C规范6.3.1.8的编译器二元运算符中不同类型的整数;下列变更*/s128o运算符+(常数s128o和lhs,s64 rhs){s128 _ res;如果(rhs<0){res.high=左侧高位-1;res.low=lhs.low+rhs;如果(res.low<lhs.low){//20191019是“(res.lowlhs.低){//借(res.高)--;}返回res;}s128o运算符-(常数s128o和lhs,s32 rhs){s128 _ res;s128_ob;b.low=相对湿度;b.high=(相对湿度<0)-1 : 0;res.high=lhs.high-b.high;res.low=lhs.low-b.low;如果(res.low>lhs.low){(res.high)--;}返回res;}//一元减号(负号)s128_o运算符-(常数s128_o&x){s128 _ res;res.high=~(x.high);res.low=~(x.low);res.low+=1;if(res.low==0){res.高+=1;}返回res;}//支持乘法、除法和模运算的例程s128 s128_小时(s128_o x){第128号公路;//打印f(“%.16llX%016llX>>”,x.high,x.low);rv.low=(x.low>>1)|(x.high<<63);rv.high=x.high>>1;//打印(“%.16llX%016llX\n”,rv.high,rv.low);返回rv;}s128 s128_shl(s128_o x){第128号公路;rv.high=(x.high<<1)|(x.low>>63);rv.low=x.low<<1;返回rv;}//乘法//旧:28.7新:6.3/*启用这两个定义以进行错误检查*/#定义MULT1_OLD 0#定义MULT1_NEW 1静态整数m1err=0;s128_o多t1(s128_o-xi,s128_oyi){#如果MULT1_OLDs128_o x、y、rv1;整数秒;#结尾#如果MULT1_NEW第128号修正案2;u64 acc,ac2,携带,o1,o2;u64 a、b、c、d、e、f、g、h、ah、bh、ch、dh、bg、cg、dg、cf、df、de;#结尾#如果MULT1_OLDs=1;x=xi;y=yi;如果(x<((s128o)0)){s=-s;x=-x;}如果(y<((s128o)0)){s=-s;y=-y;}rv1=0;而(y!=((s128o)0)){if(y.low&1){rv1=rv1+x;}x=s128_shl(x);y=s128_shr(y);}如果(s<0){rv1=-rv1;}#结尾#如果MULT1_NEW/*x a b c d(x a b b c d)是的,如果是---------------啊bh ch dhbg、cg、dgcf df(立方英尺-立方英尺)判定元件---------------------------氧气---o1--*/d=xi.低&LO_WORD;c=(xi.low&HI_WORD)>>32LL;b=xi.高&LO_WORD;a=(xi.高&HI_WORD)>>32LL;h=yi.low&LO_WORD;g=(yi.low&HI_WORD)>>32LL;f=yi.high和LO_WORD;e=(yi.high&HI_WORD)>>32LL;acc=d*h;o1=符合&LO_WORD;acc>>=32LL;进位=0;ac2=acc+c*h;if(ac2<acc){进位++;}acc=ac2+d*g;if(acc<ac2){进位++;}rv2.low=o1|(acc<<32LL);ac2=(acc>>32LL)|(进位<<32LL);进位=0;acc=ac2+b*h;if(acc<ac2){进位++;}ac2=acc+c*g;if(ac2<acc){进位++;}acc=ac2+d*f;if(acc<ac2){进位++;}o2=符合&LO_WORD;ac2=(acc>>32LL)|(进位<<32LL);acc=ac2+a*h;ac2=acc+b*g;acc=ac2+c*f;ac2=acc+d*e;rv2.high=(ac2<<32LL)|o2;#如果MULT1_OLDif((rv1.high!=rv2.high)(rv1.low!=rv2.low)){printf(“m1 err1%16llX%016llX*%16llX%016llX\n”,xi.高,xi.低,yi.高,yi.低);printf(“abcd%8llX%08llX%0.8llX%008llX\n”,a,b,c,d);printf(“efgh%8llX%08llX%08llX%08llX\n”,e,f,g,h);打印(“->%16llX%016llX\n”,rv2.high,rv2.low);m1err++;如果(m1err>10){出口(-1);}}#结尾#结尾#如果MULT1_NEW返回rv2;#其他返回rv1;#结尾}s128_运算符*(常数s128_o和lhs,常数s128_和rhs){第128号公路;rv=mult1(lhs,rhs);返回rv;}s128_o运算符*(常量s128_o&lhs,u64 rhs){s128_o t;第128号公路;t=rhs;rv=多t1(lhs,t);返回rv;}s128_o运算符*(常数s128_o&lhs,s64 rhs){第128页;第128号公路;t=rhs;rv=多t1(lhs,t);返回rv;}s128_o运算符*(常量s128_o&lhs,long int rhs){第128页;第128号公路;t=((s64)rhs);rv=多t1(lhs,t);返回rv;}s128_o运算符*(常数s128_o&lhs,s32 rhs){第128页;第128号公路;t=rhs;rv=多t1(lhs,t);返回rv;}//部门s128_o div1(s128_ox,s128_d,s128_*r){整数秒;s128_o d1、p2、rv;//printf(“除以%.16llX%016llX/%.16llX%0161llX\n”,x.high,x.low,d.high,d.low);/*检查是否被零除*/如果((d.low==0)&&(d.how==O)){rv.low=x.low/d.low;/*这将导致运行时错误*/}s=1;如果(x<((s128o)0)){//请注意,MININT将保持不变,如下所示。s=-s;x=-x;}如果(d<((s128o)0)){s=-s;d=-d;}如果(d==((s128o)1)){/*这包括溢出情况MININT/-1*/rv=x;x=0;}否则,如果(x<((s128o)d)){/*x<d,所以商是0,x是余数*/rv=0;}其他{rv=0;/*计算2乘以d的最大幂,即<=x*/p2=1;d1=d;x=x-d1;而(x>=d1){x=x-d1;d1=d1+d1;p2=p2+p2;}x=x+d1;而(p2!=((s128o)0)){//打印(“x%.16llX%016llX d1%.16llX%0161llX\n”,x.high,x.low,d1.high,d1.low);如果(x>=d1){x=x-d1;rv=rv+p2;//printf(“`..%.16llX%016llX\n”,rv.high,rv.low);}p2=s128小时(p2);d1=s128_shr(d1);}/*x中剩下的是余数*/}/*输入登录结果*/如果(s<0){rv=-rv;}/*如果他们要求归还剩余部分*/如果(r){*r=x;}返回rv;}s128_o运算符/(常数s128_o&x,常数s128_ o&d){第128号公路;rv=div1(x,d,0);返回rv;}s128_o运算符/(常量s128_o&x,u64 d){第128页;第128号公路;t.高=0;t.low=d;rv=div1(x,t,0);返回rv;}//比较运算符int运算符<(const s128_o&lhs,const s1280_o&rhs){if(lhs.high<rhs.high)返回1;if(相对高度<相对高度)返回0;//高分量相等if(lhs.low<rhs.low)返回1;返回0;}int运算符<(常数s128_o&lhs,s32-rhs){s128或;r=相对湿度;if(左侧高<右侧高)返回1;if(r.high<lhs.high)返回0;//高分量相等if(左侧低<右侧低)返回1;返回0;}int运算符<=(const s128_o&lhs,const s1280_o&rhs){if((lhs.high==rhs.high)&&(lhs.low==rhs.low))返回1;if(lhs.high<rhs.high)返回1;if(相对高度<相对高度)返回0;//高分量相等如果(lhs.low<rhs.low)返回1;返回0;}int运算符<=(常数s128_o&lhs,s32-rhs){第128页;t=rhs;if((lhs.high=t.high)&&(lhs.low=t.low))返回1;if(lhs.high<t.high)返回1;if(t.high<lhs.high)返回0;//高分量相等if(lhs.low<t.low)返回1;返回0;}int运算符==(const s128_o&lhs,const s1280_o&rhs){if(lhs.high!=rhs.high)返回0;if(lhs.low!=rhs.low)返回0;返回1;}int运算符==(常量s128_o&lhs,s32 rhs){s128_o t;t=rhs;返回((lhs.high=t.high)&&(lhs.low=t.low));}int运算符!=(常数s128_o和lhs,常数s128_和rhs){if(lhs.high!=rhs.high)返回1;if(lhs.low!=rhs.low)返回1;返回0;}int运算符!=(常数s128_o和lhs,s32 rhs){第128页;t=rhs;返回((lhs.high!=t.high)| |(lhs.low!=t.low));}int运算符>(常量s128_o和lhs,常量s128_和rhs){if(左侧高>右侧高)返回1;if(相对高度>相对高度)返回0;//高分量相等if(lhs.low>rhs.low)返回1;返回0;}int运算符>(常数s128_o&lhs,s32-rhs){第128页;t=rhs;if(lhs.high>t.high)返回1;if(t.high>lhs.high)返回0;//高分量相等if(lhs.low>t.low)返回1;返回0;}int运算符>=(const s128_o&lhs,const s1280_o&rhs){if((lhs.high==rhs.high)&&(lhs.low==rhs.low))返回1;if(左侧高>右侧高)返回1;if(相对高度>相对高度)返回0;//高分量相等if(lhs.low>rhs.low)返回1;返回0;}//输出转换u64 s128_u64(s128 x){返回(x.low);}u32 s128 _u32(s128 x){u32 rv;rv=x.low;收益率(rv);}无效s128_str(s128 x,字符*s){int d,nd,进行中,fl1;s128吨,第10页;fl1=0;如果(x<((s128o)0)){*s=“-”;s++;x=-x;}如果(x<((s128o)0)){/*它仍然是负数!这意味着我们正在处理“MIN_INT”值,它是-(2^127)。这使得我们的算法无法正常工作,因此我们将其更改为1-2^127,再次取反以获得(2^127)-1,并设置一个标志告诉自己在最后一个数字上加1(从7到8)*/x=x+1;x=-x;fl1=1;}如果(x==((s128o)0)){*s=“0”;s++;*s=0;/*正在终止null*/回报;}//计算x中的位数p10=1;nd=0;going=1;while((p10<=x)&&(going)){p10=p10+p10;如果(p10<((s128o)0)){going=0;}t=p10;p10=p10+p10;如果(p10<((s128o)0)){going=0;}p10=p10+p10;如果(p10<((s128o)0)){going=0;}p10=p10+t;如果(p10<((s128o)0)){going=0;}nd++;}//提取每个数字而(nd>0){整数i;nd--;p10=1;对于(i=0;i=第10页){x=x-p10;d++;}如果(fl1&&(nd==0)){d++;}*s=('0'+d);s++;}*s=0;/*正在终止null*/}#结尾/*int128.c结束*/