在x86上实现bignums时,显然数字大小的最有效选择是32位。但是,您需要算术最多两倍的数字大小(即32 + 32 = 33,32 * 32 = 64,64 / 32 = 32)。幸运的是,x86不仅提供了这个功能,而且还可以从便携式C(uint64_t)访问它。
类似地,在x64上,最好使用64位数字。这将需要128位算术(即64 + 64 = 65,64 * 64 = 128,128 / 64 = 64)。幸运的是,x64提供了这个功能。不幸的是,它无法通过便携式C进行访问,但显然有人可以进入组装。
所以我的问题是它是否可以从非便携式C访问.X64上的任何C编译器都提供对此的访问,如果是,那么语法是什么?
(注意,我不是在谈论128位向量,它们被严格地视为32或64位字的集合,它们之间没有进位传播,但是关于实际的128位整数运算。)
答案 0 :(得分:12)
gcc将__uint128_t
和__int128_t
作为扩展名。
答案 1 :(得分:3)
GCC 4.1引入了__int128_t
和__uint128_t
内置类型的初始128位整数支持,但自GCC 4.6起__int128
/ unsigned __int128
以来正式发布了128位类型< / p>
Clang也支持这些类型,尽管我从什么时候开始不知道。 Godbolt(3.0.0)上的第一个版本确实支持__int128_t
ICC自13.0.0版以来获得了相同的支持:128-bit integers supporting +, -, *, /, and % in the Intel C Compiler?
另请参见
如果您使用的是MSVC,则不直接支持128位类型,但是有许多内在函数可以帮助您执行128位操作:
64 * 64 = 128:_mul128()
,_umul128()
,__mulh()
,__umulh()
128/64 = 64:_div128()
,_udiv128()
64 + 64 = 65:通过将总和的下半部分与任何操作数进行比较,可以很容易地获得加法中的进位:
struct uint128 {
uint64_t H, L;
};
inline uint128 add(uint128 a, uint128 b)
{
uint128 c;
c.L = a.L + b.L; // add low parts
c.H = a.H + b.H + (c.L < a.L); // add high parts and carry
return c;
}
同一事物可用于128位减法
还有一些内在的偏移,尽管实现这些琐碎琐碎的事情:__shiftleft128()
,__shiftright128()
如果您使用的是不受支持的编译器,则只需使用许多可用库中的某些固定宽度类型,这会更快。例如ttmath:UInt<4>
(具有四个32位分支的128位int类型),或Boost.Multiprecision和calccrypto/uint128_t中的(u)int128_t
。为此,像GMP这样的任意精度算术库都太昂贵了。一个示例:Optimization story: Switching from GMP to gcc's __int128
reduced run time by 95%
答案 2 :(得分:1)
您可能需要检查GNU多精度算术库: