11

私の 64 ビット コンピュータでは、long longタイプは 64 ビットです。

print(sizeof(long long))
# prints 8

128 ビット整数を使用する必要があり、幸運にもGCC はこれらをサポートしています。Cython 内でこれらを使用するにはどうすればよいですか?

以下は動作しません。foo.pyxだけを含むコンパイル

cdef __int128_t x = 0

収量

$ cython foo.pyx 

Error compiling Cython file:
------------------------------------------------------------
...

cdef __int128_t x = 0
    ^
------------------------------------------------------------

foo.pyx:2:5: '__int128_t' is not a type identifier
4

3 に答える 3

10

編集: これはもはや回避策ではありません。これが正しい方法です。@IanHの回答も参照してください。

さて、あなたが抱えている問題は、cythonあなたのタイプを認識しないということですgcc。だから私たちはだまそうとすることができcythonます。

ファイルhelloworld.pyx:

cdef extern from "header_int128.h":
    # this is WRONG, as this would be a int64. it is here
    # just to let cython pass the first step, which is generating
    # the .c file.
    ctypedef unsigned long long int128

print "hello world"

cpdef int foo():
    cdef int128 foo = 4
    return 32

ファイルheader_int128.h:

typedef __int128_t int128;

ファイルsetup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize("helloworld.pyx"))

今、私のマシンで を実行するpython setup.py build_ext --inplaceと、最初のステップがパスし、ファイルhelloworld.cが生成され、gccコンパイルもパスします。

ファイルを開くと、変数が実際に として宣言されているhelloworld.cことを確認できます。fooint128

この回避策の使用には十分注意してください。int128特に、たとえば anを aに割り当てた場合、cython は C コードでキャストを必要とint64しないことがあります。これは、プロセスのその段階で実際にはそれらを区別しないためです。

于 2014-12-20T19:24:35.263 に答える
5

ここに 2 セントを投入します。

まず、外部 typedef を使用するという他の回答で提案されている解決策は、単なる回避策ではありません。これは、Cython ドキュメントがこのようなことを行うべきだと言っている方法です。関連セクションを参照してください。引用: 「ヘッダー ファイルが、数値型のプラットフォーム依存のフレーバーを参照するなどの typedef 名を使用wordする場合、対応する ctypedef ステートメントが必要になりますが、型を正確に一致させる必要はありません。適切な一般的なものを使用するだけです。種類 (int、float など)。たとえばctypedef int word、a の実際のサイズが何であれword(ヘッダー ファイルで正しく定義されている場合)、Python 型との間の変換があれば、この新しい型にも使用されます。 "

また、すでに途中で別の場所にインクルードした型の typedef を含むヘッダー ファイルを実際に作成する必要はありません。これをするだけ

cdef extern from *:
    ctypedef int int128 "__int128_t"

または、Cython でも C と同じ名前を使用したい場合は、

cdef extern from *:
    ctypedef int __int128_t

これが機能していることを示すテストを次に示します。128 ビット演算が機能し、a > 1a が 64 ビット整数として表現できる場合、最初の関数は同じ数値を再度出力します。そうでない場合、整数オーバーフローにより 0 が出力されます。2 番目の関数は、64 ビット演算が使用された場合に何が起こるかを示しています。

Cython ファイル

# cython: cdivision = True

cdef extern from *:
    ctypedef int int128 "__int128_t"

def myfunc(long long a):
    cdef int128 i = a
    # set c to be the largest positive integer possible for a signed 64 bit integer
    cdef long long c = 0x7fffffffffffffff
    i *= c
    cdef long long b = i / c
    print b

def myfunc_bad(long long a):
    cdef long long i = a
    # set c to be the largest positive integer possible for a signed 64 bit integer
    cdef long long c = 0x7fffffffffffffff
    i *= c
    cdef long long b = i / c
    print b

Python では、両方の関数がインポートされた後、myfunc(12321)は正しい値をmyfunc_bad(12321)出力し、 は 0 を出力します。

于 2014-12-22T19:15:41.483 に答える
3

これは、@Giulio Ghirardo によって提案されたハックの使用例です。

ファイルcbitset.pxには次が含まれます。

typedef unsigned __int128 bitset;

ファイルbitset.pyxには次が含まれます。

from libc.stdlib cimport malloc
from libc.stdio cimport printf

cdef extern from "cbitset.h":
    ctypedef unsigned long long bitset

cdef char* bitset_tostring(bitset n):
    cdef char* bitstring = <char*>malloc(8 * sizeof(bitset) * sizeof(char) + 1)
    cdef int i = 0
    while n:
        if (n & <bitset>1):
            bitstring[i] = '1'
        else:
            bitstring[i] = '0'

        n >>= <bitset>1
        i += 1
    bitstring[i] = '\0'
    return bitstring

cdef void print_bitset(bitset n):
    printf("%s\n", bitset_tostring(n))

ファイルmain.pyxには次が含まれます。

from bitset cimport print_bitset

cdef extern from "cbitset.h":
    ctypedef unsigned long long bitset

# x contains a number consisting of more than 64 1's
cdef bitset x = (<bitset>1 << 70) - 1

print_bitset(x)
# 1111111111111111111111111111111111111111111111111111111111111111111111

ファイルsetup.pyには次が含まれます。

from distutils.core import setup
from Cython.Build import cythonize

setup(
    name="My app that used 128 bit ints",
    ext_modules=cythonize('main.pyx')
)

コマンドを使用してこれをコンパイルします

python3 setup.py build_ext --inplace

コマンドを使用して実行します

python3 -c 'import main'
于 2014-12-21T20:08:57.667 に答える