2013-04-02 10 views
5

可能なのですか?はいの場合、Cythonの整数データ型のサイズを決定する方法はありますか?Cythonでコンパイル時に整数のサイズを取得する

cdef WORD_BITS = 0 
IF sizeof(unsigned long long) == 8: 
    WORD_BITS = 64 
    DEF VECTOR_LENGTH_SHIFT_AMOUNT = 6 
ELSE: 
    WORD_BITS = 32 
    DEF VECTOR_LENGTH_SHIFT_AMOUNT = 5 

ctypedef unsigned long long word_t 

cdef int vector_length(size_t bit_size): 

    cdef size_t size = bit_size >> VECTOR_LENGTH_SHIFT_AMOUNT 
    if size << VECTOR_LENGTH_SHIFT_AMOUNT < bit_size: 
     size += 1 
    return size 

cdef class BitVector(object): 

    cdef size_t length 
    cdef size_t array_size 
    cdef word_t *array 

    def __cinit__(self, size_t size): 
     self.length = size 
     self.array_size = vector_length(size) 
     self.array = <word_t *>calloc(self.array_size, sizeof(word_t)) 

    def __dealloc__(self): 
     free(self.array) 

は、私は、配列の要素と要素自体の単一ビットの両方を処理する必要があるので、私が持っている:私は、整数を得るために、このような何かをしようとしている

は、サイズ(適切なマスク/シフトを計算するために)いくつのビットが含まれているかを知ることができます。上記のようなコードをコンパイルすると、次のような結果が得られます。

$python setup.py build_ext --inplace 
Compiling bitvector.pyx because it changed. 
Cythonizing bitvector.pyx 

Error compiling Cython file: 
------------------------------------------------------------ 
... 
cimport cython 


# check whether we are running on a 64 or 32 bit architecture. 
cdef WORD_BITS = 0 
IF sizeof(unsigned long long) == 8: 
^
------------------------------------------------------------ 

bitvector.pyx:7:3: Invalid compile-time expression 

Traceback (most recent call last): 
    File "setup.py", line 6, in <module> 
    ext_modules=cythonize('bitvector.pyx') 
    File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 673, in cythonize 
    cythonize_one(*args[1:]) 
    File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 737, in cythonize_one 
    raise CompileError(None, pyx_file) 
Cython.Compiler.Errors.CompileError: bitvector.pyx 

有効な代替方法はありますか?

私は整数型を定義する必要がありstdint.hヘッダがあることを知っているが、私は以来、それを使用する方法を考えることはできません。

  • 私はタイプがあるかどうかを確認する方法がわからないが定義されていません(例えば、IF uint64_t is not defined:はどのようにcythonで記述しますか?)。
  • DEFとコンパイラで定義されたものだけがIFでチェックできることが記載されているので、とにかく私はを使用できるとは思っていません。

それは私が今

Cからマシンコードへのコンパイル時に私が作りたいのチェックのみを行うことができるので、これはCythonでは実現不可能であるように思える、とないcythonからC.

へwonder:この種のチェックがCのソースコードに追加されるようにcython拡張を書くことは可能でしょうか?同等であり、この IFはCythonで「処理されない」ように

cdef WORD_BITS = 0 
IF sizeof(unsigned long long) == 8: 
    WORD_BITS = 64 
    DEF VECTOR_LENGTH_SHIFT_AMOUNT = 6 
ELSE: 
    WORD_BITS = 32 
    DEF VECTOR_LENGTH_SHIFT_AMOUNT = 5 

ctypedef unsigned long long word_t 

を、それが通過して、最終的なCファイルに渡されます。私は意味

は、私が何とか書くことができますコード?

+0

私はまったく同じ問題を抱えていました。あなたは運がありましたか? – PierreBdR

+0

@PierreBdR残念ながら、 64ビットマシンでは最適ではないにもかかわらず、常に32ビットのデータ型を使用して解決しました。回答を希望する場合は、この質問に奨励金を追加することを検討してください(改善したいと思う場合は、自由に編集してください)。 – Bakuriu

答えて

0

プリプロセッサーを使用してサイズとシフト値を定義する代わりに、vector_length関数をわずかに変更してsizeofを直接使用できるようにしました。 Cythonはsizeof演算子を正しく変換し、コンパイラはタイプの実際のサイズをコンパイル時のに置き換えます。 sizeofCHAR_BITを使用して、正しいベクトルサイズ:https://www.gnu.org/software/libc/manual/html_node/Width-of-Type.htmlを取得する方法の詳細については、glibcのドキュメントのこのセクションを参照してください。

from libc.stdlib cimport calloc, free 
from libc.limits cimport CHAR_BIT 

ctypedef unsigned long long word_t 

cdef size_t vector_length(size_t bit_size): 
    cdef size_t bits_per_word = CHAR_BIT*sizeof(word_t) 
    return (bit_size + bits_per_word - 1)/bits_per_word 

cdef class BitVector(object): 
    cdef size_t length 
    cdef size_t array_size 
    cdef word_t *array 

    def __cinit__(self, size_t size): 
     self.length = size 
     self.array_size = vector_length(size) 
     self.array = <word_t *>calloc(self.array_size, sizeof(word_t)) 

    def __dealloc__(self): 
     free(self.array) 

unsigned long longは、少なくとも64ビット(https://en.wikipedia.org/wiki/C_data_types)であることがまた注目に値します。あなたのコードは、または 64または32ビットのいずれかであると仮定しているようですが、標準準拠のコンパイラでは64ビット以上になります。

関連する問題