2011-01-29 18 views
8

में एकल-आवृत्ति सरणी के बारे में कुछ प्रश्न मैं जीएनयू मल्टी-प्रेसिजन (जीएमपी) लाइब्रेरी कोड का उपयोग करके मनमानी-लंबाई पूर्णांक का उपयोग करके कुछ कोड को देख रहा था। एक एमपी पूर्णांक के लिए प्रकार g12.h शीर्षलेख फ़ाइल में परिभाषित mpz_t है।टाइपपीफ

लेकिन, मेरे पास इस लाइब्रेरी-परिभाषित mpz_t प्रकार की निम्न-स्तरीय परिभाषा के बारे में कुछ प्रश्न हैं।

/* THIS IS FROM THE GNU MP LIBRARY gmp.h HEADER FILE */ 
typedef struct 
{ 
    /* SOME OTHER STUFF HERE */ 
} __mpz_struct; 

typedef __mpz_struct mpz_t[1]; 

पहला सवाल: __mpz_struct साथ [1] सहयोगी करता है हैडर कोड में? दूसरे शब्दों में, typedef एक mpz_t को एक घटना के साथ __mpz_struct सरणी के रूप में परिभाषित करना है?

दूसरा प्रश्न: सरणी क्यों? (और क्यों केवल एक घटना?) क्या यह उन struct hacks में से एक है जिसके बारे में मैंने सुना है?

तीसरा सवाल (शायद परोक्ष रूप से दूसरे प्रश्न से संबंधित): mpz_init_set(mpz_t, unsigned long int) समारोह के लिए जीएमपी प्रलेखन, इसका इस्तेमाल करने के पारित-दर-मूल्य के रूप में ही हालांकि एक ग्रहण करेंगे है कि इस समारोह के भीतर अपनी सामग्री को संशोधित किया जाएगा कहते हैं फ़ंक्शन कहा जाता है (और इस प्रकार पास-बाय-रेफरेंस की आवश्यकता होगी) वाक्यविन्यास। मेरे कोड को देखें:

/* FROM MY CODE */ 
mpz_t fact_val;    /* declaration */ 
mpz_init_set_ui(fact_val, 1); /* Initialize fact_val */ 

करता एकल घटना सरणी सक्षम पारित-दर-संदर्भ स्वचालित रूप से (सी में सरणी/सूचक अर्थ विज्ञान के टूटने की वजह से)? मैं स्वतंत्र रूप से स्वीकार करता हूं कि मैं इसका अधिक विश्लेषण कर रहा हूं, लेकिन मुझे निश्चित रूप से इस पर कोई चर्चा पसंद आएगी। धन्यवाद!

उत्तर

3

* पहला प्रश्न: क्या [1] __mpz_struct के साथ संबद्ध है? दूसरे शब्दों में, टाइप किया गया है कि एक mpz_t प्रकार को __mpz_struct सरणी के रूप में परिभाषित करना एक घटना है? *

हां।

दूसरा प्रश्न: सरणी क्यों? (और क्यों केवल एक घटना?) क्या यह उन संरचनाओं में से एक है जिन्हें मैंने सुना है?

मुझे मारता है। पता नहीं, लेकिन एक संभावना यह है कि लेखक एक ऑब्जेक्ट बनाना चाहता था जो संदर्भ द्वारा स्वचालित रूप से पारित किया गया था, या, "हां", संभवतः संरचना हैक। यदि आपको कभी भी संरचना के अंतिम सदस्य के रूप में mpz_t ऑब्जेक्ट दिखाई देता है, तो "लगभग निश्चित रूप से" यह संरचना हैक है। एक आवंटन

malloc(sizeof(struct whatever) + sizeof(mpz_t) * some_number)` 

एक मृत देनदार होगा।

क्या एकल-घटना सरणी पास-दर-संदर्भ स्वचालित रूप से सक्षम करती है ...?

आह, आपने इसे भी समझ लिया। "हां", एक संभावित कारण अधिक जटिल संदर्भों के खर्च पर पास-दर-संदर्भ को सरल बनाना है।

मुझे लगता है कि एक और संभावना यह है कि डेटा मॉडल या एल्गोरिदम में कुछ बदल गया, और लेखक हर संदर्भ को ढूंढना और इसे किसी भी तरह से बदलना चाहता था। इस तरह के प्रकार में बदलाव कार्यक्रम को उसी आधार प्रकार से छोड़ देगा लेकिन हर अनवरोधित संदर्भ में त्रुटि-आउट होगा।

+0

दिलचस्प बात यह है कि __mpz_struct में अंतिम तत्व वास्तव में एक सूचक (एक mp_limb_t पर है, जिसे स्वयं एक हस्ताक्षरित लंबे लंबे int के रूप में टाइप किया गया है [क्या मुंह वाला है!])। मैंने संक्षिप्तता के हित में सामग्री को समाप्त कर दिया। – pr1268

4

यह सी 2 पर वर्णित अर्थ में एक संरचना हैक प्रतीत नहीं होता है। ऐसा लगता है कि वे पॉइंटर अर्थशास्त्र के लिए mpz_t चाहते हैं (संभवतः, वे चाहते हैं कि लोग इसे अपारदर्शी सूचक की तरह उपयोग करें)। निम्नलिखित के टुकड़े के बीच वाक्यात्मक अंतर पर विचार करें:

struct __mpz_struct data[1]; 

(&data[0])->access = 1; 
gmp_func(data, ...); 

और

mpz_t data; 

data->access = 1; 
gmp_func(data, ...); 

संकेत में सी सरणियों क्षय, यह भी mpz_t प्रकार के लिए संदर्भ द्वारा स्वचालित पारित करने के लिए अनुमति देता है क्योंकि।

यह आपको malloc या free की आवश्यकता के बिना पॉइंटर-प्रकार के प्रकार का उपयोग करने की अनुमति देता है।

2

इसका कारण mpn के कार्यान्वयन से आता है। विशेष रूप से, यदि आप गणितीय रूप से इच्छुक हैं तो आपको पता चलेगा कि एन प्राकृतिक संख्याओं का सेट है (1,2,3,4 ...) जबकि ज़ेड पूर्णांक का सेट है (..., - 2, -1,0 , 1,2, ...)।

जेड के लिए एक बिग्नम लाइब्रेरी लागू करना एन के लिए ऐसा करने के बराबर है और साइन ऑपरेशन के लिए कुछ विशेष नियमों को ध्यान में रखते हुए, यानी यह ट्रैक रखते हुए कि आपको कोई अतिरिक्त या घटाव करने की आवश्यकता है और नतीजा क्या है।

typedef unsigned int  mp_limb_t; 
typedef mp_limb_t *  mp_ptr; 

और अब के एक समारोह के हस्ताक्षर पर काम पर ध्यान दें::

__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); 

अब, कैसे एक bignum पुस्तकालय कार्यान्वित किया जाता है के लिए के रूप में ... यहाँ एक लाइन आप एक सुराग देने के लिए है

असल में, यह नीचे आता है कि एक "अंग" एक पूर्णांक फ़ील्ड है जो किसी संख्या के बिट्स का प्रतिनिधित्व करता है और पूरी संख्या को एक विशाल सरणी के रूप में दर्शाया जाता है। चालाक हिस्सा यह है कि जीएमपी यह सब एक बहुत ही कुशल, अच्छी तरह से अनुकूलित तरीके से करता है।

वैसे भी, चर्चा पर वापस जाएं। असल में, सी में चारों ओर सरणी पास करने का एकमात्र तरीका है, जैसा कि आप जानते हैं, उन सरणी को पॉइंटर्स पास करने के लिए जो प्रभावी रूप से संदर्भ द्वारा पारित करने में सक्षम बनाता है। अब, क्या चल रहा है इसका ट्रैक रखने के लिए, दो प्रकार परिभाषित किए गए हैं, mp_ptr जो mp_limb_t की एक सरणी है जो आपके नंबर को स्टोर करने के लिए पर्याप्त है, और mp_srcptr जो कि इसका एक कॉन्स संस्करण है, ताकि आप गलती से बिट्स को बदल नहीं सकें आप जो काम कर रहे हैं उस पर स्रोत बिग्नम का।

func(ptr output, src in1, src in2) 

आदि इस प्रकार, मुझे लगता है mpz_* कार्यों इस कन्वेंशन का पालन करें बस एक समान होना चाहिए और ऐसा इसलिए है क्योंकि है कि कैसे लेखकों में सोच रहे हैं: मूल विचार है कि कार्यों के सबसे इस पैटर्न का पालन है।

लघु संस्करण: आपको एक बिग्नम lib को कैसे कार्यान्वित करना है, यह आवश्यक है।

+1

ठीक है, मैं इस कार्यान्वयन की तकनीक के बजाय भाषा/वाक्यविन्यास विनिर्देशों के बारे में अधिक उत्सुक था, लेकिन मुझे अभी भी आपका जवाब पसंद है। +1। धन्यवाद! अनुलेख मैंने जीएनयू बीसी कमांड-लाइन मनमानी-परिशुद्धता कैलक्यूलेटर के लिए स्रोत कोड को भी देखा है, यह देखते हुए कि वे बड़ी संख्या में प्रोग्रामेटिक तरीके से कैसे करते हैं, इसलिए यह मेरे लिए बहुत विदेशी नहीं है। – pr1268

+0

@ pr1268 मैंने मिपर (एक जीएमपी कांटा) पर कुछ संक्षिप्त प्रयोगात्मक सामान किया जो मैंने कभी नहीं किया, यही कारण है कि मुझे इसके बारे में कुछ पता है, सिर्फ सोचा कि मैं इसे अतिरिक्त जानकारी के लिए साझा करता हूं। –

संबंधित मुद्दे