C中x64的128位算术运算

时间:2011-03-13 10:53:50

标签: c integer 64-bit biginteger 128-bit

在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位整数运算。)

3 个答案:

答案 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.Multiprecisioncalccrypto/uint128_t中的(u)int128_t。为此,像GMP这样的任意精度算术库都太昂贵了。一个示例:Optimization story: Switching from GMP to gcc's __int128 reduced run time by 95%

答案 2 :(得分:1)

您可能需要检查GNU多精度算术库:

http://gmplib.org/