C 中 x64 的 128 位算术
在 x86 上实现 bignum 时,显然数字大小最有效的选择是 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 编译器是否提供对此的访问,如果是,语法是什么?
(请注意,我不是在谈论严格视为 32 或 64 位字的集合且它们之间没有进位传播的 128 位向量,而是在谈论实际的 128 位整数运算。)
When implementing bignums on x86, obviously the most efficient choice for digit size is 32 bits. However, you need arithmetic up to twice the digit size (i.e. 32+32=33, 32*32=64, 64/32=32). Fortunately, not only does x86 provide this, but it's also accessible from portable C (uint64_t
).
Similarly, on x64 it would be desirable to use 64-bit digits. This would require 128 bit arithmetic (i.e. 64+64=65, 64*64=128, 128/64=64). Fortunately, x64 provides this. Unfortunately, it's not accessible from portable C, though obviously one could dip into assembly.
So my question is whether it's accessible from non-portable C. Do any C compilers on x64 provide access to this, and if so, what's the syntax?
(Note that I'm not talking about 128-bit vectors that are strictly treated as collections of 32 or 64-bit words with no carry propagation between them, but about actual 128-bit integer operations.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
GCC 4.1 通过
__int128_t
和__uint128_t
内置类型引入了初始 128 位整数支持,但 128 位类型自 GCC 4.6 为__int128
/unsigned __int128
Clang 也支持这些类型,尽管我不知道从什么时候开始。 但 Godbolt (3.0.0) 上的第一个版本确实支持
__int128_t
尽管ICC 获得了支持, 自版本 13.0.0 以来支持相同:128 位整数在英特尔 C 编译器中支持 +、-、*、/ 和 %?
另请参阅
如果您使用的是 MSVC,则不直接支持 128 位类型,但有许多内在函数可以帮助您执行 128 位类型操作:
64*64→128:<代码>_mul128(),
_umul128()
,__mulh()
,__umulh()
128/64→64:
_div128()
,_udiv128()
64+64→65:通过将和的低位部分与任意操作数进行比较,可以轻松获得加法中的进位:
64-64→65:我们可以使用与加法中相同的减法方法< /p>
还有一些用于移位的内在函数,尽管实现这些是微不足道的:
__shiftleft128()
,__shiftright128()
如果您使用的是不受支持的编译器,则只需使用一些固定宽度类型从许多可用的库中,这会快得多。例如
ttmath:UInt<4>
(128 位 int 类型,四个 32 位肢体),或 Boost.Multi precision 和 calccrypto/uint128_t。像 GMP 这样的任意精度算术库对此来说成本太高。一个例子:优化故事:从 GMP 切换到 gcc 的__int128
减少了运行时间95%GCC 4.1 introduced initial 128-bit integer support with the
__int128_t
and__uint128_t
built-in types but 128-bit type was officially released since GCC 4.6 as__int128
/unsigned __int128
Clang also supports those types although I don't know since when. The first version on Godbolt (3.0.0) does support
__int128_t
thoughICC gained the same support since version 13.0.0: 128-bit integers supporting +, -, *, /, and % in the Intel C Compiler?
See also
If you're on MSVC then there's no direct support for a 128-bit type but there are many intrinsics helping you do 128-bit operations:
64*64→128:
_mul128()
,_umul128()
,__mulh()
,__umulh()
128/64→64:
_div128()
,_udiv128()
64+64→65: The carry in an addition can be easily obtained by comparing the low part of the sum with any of the operands:
64-64→65: We can use the same method for subtraction as in addition
There are also intrinsics for shifting although implementing these is trivial:
__shiftleft128()
,__shiftright128()
If you're on an unsupported compiler then just use some fixed-width types from many available libraries, that would be much faster. For example
ttmath:UInt<4>
(a 128-bit int type with four 32-bit limbs), or(u)int128_t
in Boost.Multiprecision and calccrypto/uint128_t. An arbitrary-precision arithmetic library like GMP is just too costly for this. One example: Optimization story: Switching from GMP to gcc's__int128
reduced run time by 95%您可能需要检查 GNU 多精度算术库:
http://gmplib.org/
You may want to check the GNU Multiple Precision Arithmetic Library:
http://gmplib.org/