web-dev-qa-db-ja.com

gccに128ビット整数はありますか?

2つの64ビット数の乗算結果を保存するため、128ビット整数が必要です。 gcc 4.4以降にはそのようなものがありますか?

34
MetallicPriest

128ビット整数型は64ビットターゲットでのみ使用可能であるため、最新のGCCバージョンを既に検出している場合でも可用性を確認する必要があります。理論的には、gcccouldは、1つを保持するのに4x 32ビットのレジスタを必要とするマシンでTImode整数をサポートしますが、そうするケースはないと思います。


GCC 4.6以降には、組み込み型として定義された__int128/unsigned __int128があります。使用
#ifdef __SIZEOF_INT128__それを検出します。

GCC 4.1以降では、__int128_tおよび__uint128_t<stdint.h>で定義します。最近のコンパイラでは、これはおそらく__int128の観点から定義されています。 (#include <stdint.h>の代わりに__int128_t名を使用する場合は、__int128が必要です。)

私は Godboltコンパイラエクスプローラーで をテストしました。最初のバージョンのコンパイラーは、これらの3つのこと(x86-64)のそれぞれをサポートします。 Godboltはgcc4.1、ICC13、およびclang3.0にのみ戻るため、実際の最初のサポートがさらに早い可能性があることを示すために<= 4.1を使用しました。

         legacy               recommended(?)    |  One way of detecting support
        __uint128_t   |  [unsigned]  __int128   |  #ifdef __SIZEOF_INT128__
gcc        <=  4.1    |       4.6               |     4.6
clang      <=  3.0    |       3.1               |     3.3
ICC        <=  13     |     <= 13               |     16.  (Godbolt doesn't have 14 or 15)

ARM、または-m32を使用したx86のような32ビットアーキテクチャ用にコンパイルする場合、これらのコンパイラの最新バージョンでも128ビット整数型はサポートされません。したがってneedは、使用せずにコードが機能する可能性がある場合に、使用前にサポートを検出します。

それを検出するために私が知っている唯一の直接CPPマクロは__SIZEOF_INT128__ですが、残念ながらいくつかの古いコンパイラバージョンはそれを定義せずにサポートしています。 (そして、__uint128_t用のマクロはありません。gcc4.6スタイルのunsigned __int128のみです)。 __ uint128_tが定義されているかどうかを知る方法

一部の人々は、RHEL(RedHat Enterprise Linux)上のgcc4.4などの古いコンパイラバージョン、または同様の無愛想な古いシステムをまだ使用しています。そのような古いgccバージョンが気になる場合は、おそらく__uint128_tに固執したいでしょう。そしておそらく、いくつかの64ビットISAではsizeof(int_fast32_t)に関して64ビットを検出します。これは何らかの理由で8です。ただし、x32やILP32 AArch64などのILP32 ISAではないため、__SIZEOF_INT128__が定義されていない場合は、単にsizeof(void*)を確認してください。

Gccが__int128を定義していない64ビットISAもあれば、gccdoes__int128を定義している32ビットISAもありますが、私は何も知りません。

ここでの別の答えに対するコメントが指摘するように、GCC内部は整数TIモードです。 (テトラ整数= intの4x幅、vs。DImode = double width vs. SImode = plain int。)As GCCマニュアルは指摘__int128は128ビット整数モード(TImode)をサポートするターゲットでサポートされます。

typedef unsigned uint128_t __attribute__ ((mode (TI)));

ランダムな事実:ICC19 -E -dMの定義:

#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128

テスト機能は次のとおりです。

#include <stdint.h>

#define uint128_t __uint128_t
//#define uint128_t unsigned __int128

uint128_t mul64(uint64_t a, uint64_t b) {
    return (uint128_t)a * b;
}

それをサポートするコンパイラはすべて、効率的にコンパイルし、

    mov       rax, rdi
    mul       rsi
    ret                          # return in RDX:RAX
13
Peter Cordes

ああ、大きな整数はCの得意ではありません。

GCCには、バージョン4.somethingから始まるunsigned __int128/__int128型があります(ここではわかりません)。ただし、その前に__int128_t defがあったことを思い出すようです。

これらは64ビットターゲットでのみ使用可能です。

(編集者注:この回答は、gccがuint128_tおよびint128_tを定義したと主張するために使用されました。Godboltコンパイラエクスプローラーでテストしたバージョンは、__を先頭に付けずに、gcc4.1から8.2、またはclangまたはICCを定義していません)

31
slezica

GNU MP Bignum Library などの、任意または大きな精度値を処理するライブラリを使用できます。

13
Reed Copsey