2010-06-23 11 views
5

मैं डी में एक वेक्टर struct है कि इस तरह काम करता है बनाना चाहते हैं:फास्ट वेक्टर स्ट्रक्चर जो डी में [i] और .xyz-operation को अनुमति देता है?

vec u, v; 
vec w = [2,6,8]; 
v.x = 9; // Sets x 
v[1] = w.y; // Sets y 
u = v; // Should copy data 

बाद में मैं भी u = v * u आदि जैसे सामान जोड़ना चाहते हैं लेकिन इसके बाद के संस्करण अब के लिए क्या करेंगे।
यह कितनी दूर मैं आ गए है:

struct vec3f 
{ 
    float[3] data; 
    alias data this; 
    @property 
    { 
     float x(float f) { return data[0] = f; } 
     float y(float f) { return data[1] = f; } 
     float z(float f) { return data[2] = f; } 
     float x() { return data[0]; } 
     float y() { return data[1]; } 
     float z() { return data[2]; } 
    } 
    void opAssign(float[3] v) 
    { 
     data[0] = v[0]; 
     data[1] = v[1]; 
     data[2] = v[2]; 
    } 
} 

अब इस काफी यह काम है कि मैं चाहता था बनाता है, लेकिन मैं अगर यह है "सही" के बारे में बहुत अनिश्चित लग रहा है। क्या opAssign() शायद कुछ मूल्य लौटाए?

मैं यह भी सोच रहा हूं कि यह वास्तव में जितना तेज़ हो सकता है? क्या मैंने alias data[0] x; आदि जोड़ने की कोशिश की है लेकिन यह काम नहीं करता है। कोई विचार? या यह "यह कैसे किया जाता है" है? शायद कंपाइलर प्रोटीरी फ़ंक्शंस को कम या ज्यादा उपनामों को समझने के लिए पर्याप्त स्मार्ट है?

उत्तर

5

कुल मिलाकर, यह बहुत उचित दिखता है। असाइनमेंट चेनिंग के उद्देश्य के लिए, opAssign तर्कसंगत रूप से v को वापस करना चाहिए। हालांकि, अभ्यास में इसे अक्सर अनदेखा किया जाता है और एक प्रदर्शन हिट (मुझे नहीं पता) हो सकता है। डी 1 के विपरीत, आप डी 2 में कार्यों से स्थैतिक सरणी वापस कर सकते हैं।

प्रदर्शन के रूप में, इस बारे में सोचने का सबसे अच्छा तरीका असेंबली स्तर पर है। मानना ​​है कि इनलाइनिंग सक्षम है, x() लगभग निश्चित रूप से रेखांकित किया जाएगा। स्टेटिक सरणी सीधे इंजेक्शन की एक अतिरिक्त परत के बिना संरचना में संग्रहीत हैं। निर्देश return data[0]; संकलक की शुरुआत से ऑफ़सेट से पढ़ने के लिए संकलक उत्पन्न करने के लिए संकलक का कारण बन जाएगा। यह ऑफसेट संकलन समय पर जाना जाएगा। इसलिए, x() पर कॉल करने की संभावना सबसे अधिक वही असेंबली निर्देश उत्पन्न करेगी जैसे कि x वास्तव में एक सार्वजनिक सदस्य चर थे।

एक अन्य संभावना है, हालांकि, एक गुमनाम संघ और struct उपयोग करने के लिए होगा:,

struct vec3f 
{ 
    union { 
     float[3] vec; 

     struct { 
      float x; 
      float y; 
      float z; 
     } 
    } 

    alias vec this; // For assignment of a float[3]. 

} 

नोट कि हालांकि alias this अभी काफी गाड़ी है, और आप शायद अभी तक इसका इस्तेमाल नहीं करना चाहिए जब तक आप ' कुछ बग रिपोर्ट दर्ज करने के लिए तैयार हैं।

2

आप मनमाने ढंग से गहराई के लिए opDispatch का उपयोग कर सकते हैं। मैं आकार और प्रकार पर अपने वेक्टर संरचना को टेम्पलेट करने की भी सिफारिश करता हूं। तुलना के लिए मेरा संस्करण यहां दिया गया है: tools.vector (डी 1, इसलिए स्विजलिंग थोड़ा और बोझिल है)।

+1

+1, मेरे पास opDispatch के साथ swizzling के लिए एक ही विचार था। मैं अभी भी डी के शुरुआती चरणों में हूं, इसलिए मेरा समाधान शायद उतना अच्छा नहीं है जितना हो सकता है। संकलन-समय की चीज़ें जो आप कर सकते हैं वह दिमागी दबदबा है, यद्यपि! – shambulator

2

आप opAssign में एक शॉट में पूरी सरणी कॉपी करने के लिए एक सरणी आपरेशन का उपयोग कर सकते हैं:

data[] = v[]; 
1
@property 
    { 
     float x(float f) { return data[0] = f; } 
     float y(float f) { return data[1] = f; } 
     float z(float f) { return data[2] = f; } 
     float x() { return data[0]; } 
     float y() { return data[1]; } 
     float z() { return data[2]; } 
    } 

क्यों गुण?

मैं इन पंक्तियों को छोड़ने और एक्स, वाई और जेड सार्वजनिक क्षेत्रों को बनाने का सुझाव दूंगा। यह गैर-इनलाइन मोड में प्रदर्शन में भी सुधार करेगा। आप किसी भी डेटा [3] सरणी के लिए संघ का उपयोग कर सकते हैं।