256 位版本
__uint128_t a[2], b[2], c[2]; // c = a + b
c[0] = a[0] + b[0]; // add low part
c[1] = a[1] + b[1] + (c[0] < a[0]); // add high part and carry
编辑: 192 位版本。这样您就可以消除像@harold 所说的那样的 128 位比较:
struct uint192_t {
__uint128_t H;
uint64_t L;
} a, b, c; // c = a + b
c.L = a.L + b.L;
c.H = a.H + b.H + (c.L < a.L);
或者,您可以使用整数溢出内置函数或检查算术内置函数
bool carry = __builtin_uaddl_overflow(a.L, b.L, &c.L);
c.H = a.H + b.H + carry;
在 Godbolt 上演示
如果你在一个循环中做了很多添加,你应该考虑使用 SIMD 和/或与多线程并行运行它们。对于 SIMD,您可能需要更改类型的布局,以便一次添加所有低部分和所有高部分。一旦可能的解决方案是此处建议的数组结构数组,实用的 BigNum AVX/SSE 可能吗?
SSE2: llhhllhhllhhllhh
AVX2: llllhhhhllllhhhh
AVX512: llllllllhhhhhhhh
使用 AVX-512,您可以一次添加 8 个 64 位值。因此,您可以在 3 条指令中添加 8 个 192 位值,再加上一些用于进位。有关更多信息,请阅读是否可以使用 SSE 和 SSE2 生成 128 位宽的整数?
使用 AVX-2 或 AVX-512,您可能还具有非常快的水平加法,因此即使您没有并行加法链,也值得一试 256 位。但是对于 192 位加法,那么 3 个 add/adc 指令会快得多
还有许多具有固定宽度整数类型的库。例如Boost.Multiprecision
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
uint256_t myUnsignedInt256 = 1;
其他一些库:
也可以看看