首页 > 解决方案 > Is there a 256-bit integer type?

问题描述

OS: Linux (Debian 10)

CC: GCC 8.3

CPU: i7-5775C

There is a unsigned __int128/__int128 in GCC, but is there any way to have a uint256_t/int256_t in GCC?

I have read of a __m256i which seems to be from Intel. Is there any header that I can include to get it?

Is it as usable as a hypothetic unsigned __int256? I mean if you can assign from/to it, compare them, bitwise operations, etc.

What is its signed equivalent (if any)?


EDIT 1:

I achieved this:

#include <immintrin.h>
typedef __m256i uint256_t;

and compiled. If I can do some operations with it, I'll update it here.


EDIT 2:

Issues found:

uint256_t   m;
int         l = 5;

m = ~((uint256_t)1 << l);

ouput:

error: can’t convert a value of type ‘int’ to vector type ‘__vector(4) long long int’ which has different size
  m = ~((uint256_t)1 << l);

标签: cgccx86-64bigintextended-precision

解决方案


Clang 具有支持除法以外的操作的_ExtInt扩展整数,但 SIMD 对此没有用,因为元素之间有进位1。其他主流 x86-64 编译器甚至没有。您需要一个库或其他东西来定义自定义类型并使用 clang 将使用的相同 add-with-carry 指令。(或纯 C 2中效率较低的仿真)。

__m256i是 AVX2 SIMD 4x uint64_t(或更窄的元素大小,如 8x uint32_t)。 它不是 256 位标量整数类型,您不能将其用于标量操作,__m256i var = 1甚至无法编译. 没有 x86 SIMD支持大于 64 位的整数,并且 Intel 内部类型喜欢__m128i并且__m256i纯粹用于 SIMD。

GCC 的__int128/unsigned __int128通常使用标量add/adc和/或标量mul/ imul,因为 AVX2 通常对扩展精度没有帮助。(仅适用于元素边界无关的按位 AND/OR/XOR。)


脚注 1:对于 BigInteger 类型实际上有一些使用 SIMD 的范围,但只能使用专门的格式。更重要的是,您必须手动选择何时重新规范化(传播进位),因此您的计算必须围绕它进行设计;它不是直接替代品。请参阅 Mysticial 关于长整数例程可以从 SSE 中受益的答案吗?

脚注2:不幸的是,C不提供加法/减法的进位,因此用C编写甚至不方便。/在 sum = a+b没有carry = sum<a进位的情况下进行执行,但是用C编写全加器要困难得多。编译器通常会制作垃圾 asm,而不仅仅是在可用的机器上使用本机 add-with-carry 指令。用于非常大整数的扩展精度库,如GMP,通常用 asm 编写。


推荐阅读