2013-04-02 7 views
5

में संकलन समय पर एक पूर्णांक का आकार प्राप्त करें क्या यह संभव है, और यदि हां, साइटन में पूर्णांक डेटा प्रकारों के बिट्स में आकार निर्धारित करने के लिए कैसे?साइथन

मैं इस तरह कुछ करने के लिए, पूर्णांकों प्राप्त करने के लिए कोशिश कर रहा हूँ आकार:

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: कैसे लिखते हैं?)।
  • साइथन के दस्तावेज में कहा गया है कि केवल DEF द्वारा परिभाषित चीजें और संकलक IF एस में चेक किया जा सकता है, इस प्रकार मुझे संदेह है कि मैं stdint.h का उपयोग कर पाऊंगा।

यह इस तरह लगता है 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 

इस तरह से कि इस IF Cython द्वारा "संसाधित नहीं है" में है, लेकिन यह के माध्यम से और अंतिम सी फाइल में पारित हो जाता है वहाँ बराबर है कोड?

+0

मुझे एक ही समस्या थी। क्या आपके पास कोई भाग्य है? – PierreBdR

+0

@PierreBdR दुर्भाग्य से नहीं। मैं हमेशा 32 बिट डेटा प्रकार का उपयोग कर बस गया, भले ही यह 64 बिट मशीनों में उप-शीर्ष है। यदि आप एक उत्तर चाहते हैं तो आप इस प्रश्न के लिए एक बक्षीस जोड़ने पर विचार कर सकते हैं (अगर आपको लगता है कि इसे बेहतर किया जा सकता है तो इसे संपादित करने में संकोच न करें)। – Bakuriu

उत्तर

0

आकार और शिफ्ट मानों को परिभाषित करने के लिए प्रीप्रोसेसर का उपयोग करने के बजाय मैं आपके vector_length फ़ंक्शन को थोड़ा बदल दूंगा ताकि यह सीधे sizeof का उपयोग कर सके। साइथन sizeof ऑपरेटर का सही ढंग से अनुवाद करेगा और संकलक संकलन-समय पर प्रकार के वास्तविक आकार को प्रतिस्थापित करेगा। सही वेक्टर आकार प्राप्त करने के लिए sizeof और CHAR_BIT का उपयोग करने के बारे में अधिक जानकारी के लिए glibc दस्तावेज़ से इस अनुभाग को देखें: https://www.gnu.org/software/libc/manual/html_node/Width-of-Type.html

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-बिट या इससे अधिक होगा।