Program Tip

C ++에 128 비트 정수가 있습니까?

programtip 2020. 12. 11. 19:18
반응형

C ++에 128 비트 정수가 있습니까?


128 비트 길이의 UUID 를 변수 에 저장해야 합니다. C ++에 128 비트 데이터 유형이 있습니까? 산술 연산이 필요하지 않고 값을 매우 빠르게 저장하고 읽고 싶을뿐입니다.

C ++ 11의 새로운 기능도 괜찮습니다.


GCC 및 Clang 지원 __int128


Checkout Boost의 구현 :

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t v = 1;

이것은 특히 산술 연산을해야하는 경우 문자열과 배열보다 낫습니다.


GCC는를 제공하지만 __int128128 비트를 저장할 수있을만큼 넓은 정수 모드를 가진 대상 (프로세서)에 대해서만 지원됩니다. 주어진 시스템에서를 sizeof () intmax_tuintmax_t최대 값을 결정하는, 컴파일러 및 플랫폼 지원.


귀하의 질문은 두 부분으로 구성됩니다.

1. 128-bin정수. @PatrikBeck boost::multiprecision제안한 것처럼 정말 큰 정수에 좋은 방법입니다.

2. 저장 UUID/ GUID/ CLSID또는 당신이 부르는 무엇이든 가변적 입니다. 이 경우 boost::multiprecision좋은 생각이 아닙니다. 그 목적을 위해 설계된 GUID 구조필요합니다 . 크로스 플랫폼 태그가 추가되면 해당 구조를 코드에 복사하여 다음과 같이 만들 수 있습니다.

struct GUID
{
    uint32_t Data1;
    uint16_t Data2;
    uint16_t Data3;
    uint8_t Data4[8];
};

이 형식은 내부적 인 이유로 Microsoft에서 정의한 것으로 다음과 같이 단순화 할 수도 있습니다.

struct GUID
{
    uint8_t Data[16];
};

여러 가지를 다룰 수있는 객체보다는 단순한 구조로 더 나은 성능을 얻을 수 있습니다. 어쨌든 GUIDS로 수학을 할 필요가 없으므로 멋진 개체가 필요하지 않습니다.


Microsoft 호출 규칙에서는 RAX : EAX 쌍에서 2 개의 32 비트 값만 반환 할 수 있으므로 Visual-C ++에는 128 비트 정수가 없습니다. 결과와 함께 두 개의 정수를 곱하면 두 단어로 된 정수가되기 때문에는 계속 두통을 일으 킵니다. 대부분의로드 앤 스토어 머신은 두 개의 CPU 워드 크기 정수로 작업을 지원하지만 4로 작업하려면 소프트웨어 해킹이 필요하므로 32 비트 CPU는 128 비트 정수를 처리 할 수 ​​없으며 8 비트 및 16 비트 CPU는 64를 처리 할 수 ​​없습니다. 비용이 많이 드는 소프트웨어 해킹이없는 비트 정수. 두 개의 64 비트 정수를 곱하면 128 비트 정수를 얻게되므로 GCC 버전 4.6은 128 비트 정수를 지원하므로 64 비트 CPU는 128 비트와 정기적으로 작동합니다. 이것은 반환 레지스터에서 하나의 64 비트 단어를 반환하고 참조를 사용하여 다른 하나를 전달하는 추악한 해킹을해야하기 때문에 이식 가능한 코드 작성에 문제가 있습니다. 예를 들어 다음을 사용하여 부동 소수점 숫자를 빠르게 인쇄하려면Grisu 는 다음과 같이 128 비트 부호없는 곱셈을 사용합니다.

#include <cstdint>
#if defined(_MSC_VER) && defined(_M_AMD64)
#define USING_VISUAL_CPP_X64 1
#include <intrin.h>
#include <intrin0.h>
#pragma intrinsic(_umul128)
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define USING_GCC 1
#if defined(__x86_64__)
#define COMPILER_SUPPORTS_128_BIT_INTEGERS 1
#endif
#endif

#if USING_VISUAL_CPP_X64
    UI8 h;
    UI8 l = _umul128(f, rhs_f, &h);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#elif USING_GCC
    UIH p = static_cast<UIH>(f) * static_cast<UIH>(rhs_f);
    UI8 h = p >> 64;
    UI8 l = static_cast<UI8>(p);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#else
    const UI8 M32 = 0xFFFFFFFF;
    const UI8 a = f >> 32;
    const UI8 b = f & M32;
    const UI8 c = rhs_f >> 32;
    const UI8 d = rhs_f & M32;
    const UI8 ac = a * c;
    const UI8 bc = b * c;
    const UI8 ad = a * d;
    const UI8 bd = b * d;
    UI8 tmp = (bd >> 32) + (ad & M32) + (bc & M32);
    tmp += 1U << 31;  /// mult_round
    return TBinary(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs_e + 64);
#endif
  }

TBigInteger 템플릿을 사용하고 부호있는 128 비트 정수인 경우 TBigInt <128, true> 또는 부호없는 128 비트 정수인 경우 TBigInt <128, false>와 같은 템플릿 배열의 비트 범위를 설정합니다. 늦게 답장하는 데 도움이 되었기를 바라며 다른 사람이 이미이 방법을 찾았습니다.


나는 사용하는 것이 좋습니다 std::bitset<128>(당신은 항상 같은 것을 할 수 있습니다 using UUID = std::bitset<128>;). 다른 답변에서 제안한 사용자 지정 구조체와 유사한 메모리 레이아웃을 가질 수 있지만 자체 비교 연산자, 해시 등을 정의 할 필요는 없습니다.

참고 URL : https://stackoverflow.com/questions/18439520/is-there-a-128-bit-integer-in-c

반응형