मैट्रिसेस: दो सूचकांक, एक पता

मैट्रिसेस: दो सूचकांक, एक पता

एक मैट्रिक्स संख्याओं का एक ग्रिड है जो पंक्तियों और स्तंभों में व्यवस्थित होता है। एक पंक्ति ग्रिड की एक क्षैतिज रेखा है, जिसे बाएँ से दाएँ पढ़ा जाता है। एक स्तंभ ग्रिड की एक ऊर्ध्वाधर रेखा है, जिसे ऊपर से नीचे पढ़ा जाता है। मेमोरी में पंक्तियों या स्तंभों की कोई अवधारणा नहीं होती। यह बाइट्स की एक लंबी रेखा है, उसी प्रकार का वेक्टर जो पिछले पाठ में शामिल किया गया था। एक मैट्रिक्स को संग्रहीत करने के लिए, उसकी पंक्तियों और स्तंभों को उस एकल रेखा में एक के बाद एक रखा जाना चाहिए। सामान्य विकल्प row-major क्रम है: पहली पंक्ति की हर संख्या संग्रहीत करें, फिर दूसरी पंक्ति की हर संख्या, और तब तक जारी रखें जब तक हर पंक्ति रखी न जाए।

दो सूचकांक, एक पता

एक मैट्रिक्स में किसी तत्व की स्थिति दो इंडेक्स द्वारा दी जाती है: पंक्ति इंडेक्स, जो बताता है कि यह किस पंक्ति से संबंधित है, और स्तंभ इंडेक्स, जो बताता है कि यह किस स्तंभ से संबंधित है। दोनों की गिनती 0 से शुरू होती है, उसी तरह जैसे वेक्टर पाठ में इंडेक्स काम करते थे। मेमोरी संख्याओं का एक एकल सपाट अनुक्रम रखती है, इसलिए दोनों इंडेक्स को पहले एक फ्लैटन्ड इंडेक्स में संयोजित करना होता है: पंक्ति इंडेक्स को मैट्रिक्स में स्तंभों की संख्या से गुणा करें, फिर स्तंभ इंडेक्स जोड़ें। वहाँ से फ्लैटन्ड इंडेक्स उसी तरह एक बाइट पता बन जाता है जैसे वेक्टर का इंडेक्स बनता है: address = base + index * 4।

एक पंक्ति और स्तंभ को एक पते में समतल करना
mul t4, t1, t3 # t4 = पंक्ति इंडेक्स * स्तंभों की संख्या
add t4, t4, t2 # t4 = वह + स्तंभ सूचकांक (समतल किया गया सूचकांक)
slli t4, t4, 2 # t4 = बाइट ऑफ़सेट = इंडेक्स * 4
add t5, t0, t4 # t5 = इस पंक्ति और स्तंभ पर तत्व का पता
lw t5, 0(t5) # t5 = उस पते पर मान

पंक्ति इंडेक्स को स्तंभों की संख्या से गुणा करता है। वेक्टर पाठ में गुणा को शिफ्ट से किया जा सकता था क्योंकि 4 दो की घात है, लेकिन मैट्रिक्स में स्तंभों की संख्या आमतौर पर ऐसी नहीं होती, इसलिए यहाँ के बजाय का उपयोग किया जाता है। स्तंभ इंडेक्स जोड़ा जाता है, और परिणाम को एक और से 4 से स्केल किया जाता है (4 दो की घात है, इसलिए इस भाग के लिए शिफ्ट अभी भी काम करता है)। इससे दिए गए पंक्ति और स्तंभ पर तत्व का बाइट ऑफ़सेट प्राप्त होता है।

पंक्ति-प्रमुख अनुक्रमण
सूची=0× 3 +0=0
1
0x10010000
2
0x10010004
3
0x10010008
4
0x1001000c
5
0x10010010
6
0x10010014
7
0x10010018
8
0x1001001c
9
0x10010020
01
0x10010000
12
0x10010004
23
0x10010008
34
0x1001000c
45
0x10010010
56
0x10010014
67
0x10010018
78
0x1001001c
89
0x10010020

पंक्ति 0, स्तंभ 0 सूचकांक 0 से मेल खाता है।

बाईं ओर का ग्रिड दिखाता है कि कागज़ पर मैट्रिक्स कैसे खींचा जाता है। दाईं ओर की एकल पंक्ति दिखाती है कि वही संख्याएँ मेमोरी में कैसे रखी जाती हैं। हाइलाइट ग्रिड में पढ़ने के क्रम में चलता है: पंक्ति 0 बाएँ से दाएँ, फिर पंक्ति 1, फिर पंक्ति 2। उसी क्षण वही तत्व नीचे की फ्लैटन्ड पंक्ति में प्रकाशित होता है, क्योंकि पंक्ति इंडेक्स को स्तंभों की संख्या से गुणा करके स्तंभ इंडेक्स जोड़ने पर उस तत्व का पता मिलता है, जो दोनों ओर दिखाए गए हेक्स मान से मेल खाता है। RISC-V केवल दाईं ओर की फ्लैटन्ड रेखा के साथ काम करता है। ग्रिड एक आकार है जो आपके प्रोग्राम का .data लेआउट और उसका आपका अपना पठन उस एकल रेखा पर थोपता है, ऊपर दिखाए गए , , और अंकगणित का उपयोग करके। एक बार जब ग्रिड और फ्लैटन्ड पंक्ति को एक ही चीज़ के रूप में दो बार दिखाया गया समझ लिया जाए, तो वही पैटर्न डेटा के किसी भी ग्रिड को कवर करता है: किसी छवि की पिक्सेल पंक्तियाँ, एक गेम बोर्ड, या एक स्प्रेडशीट। प्रत्येक एक सरणी है, जिस तक एक अतिरिक्त गुणा से पहुँचा जाता है।

मैट्रिक्स का योग

3 बाय 3 मैट्रिक्स के प्रत्येक अवयव को जोड़ें
.data
m: .word 1, 2, 3, 4, 5, 6, 7, 8, 9 # 3x3 मैट्रिक्स, पंक्ति दर पंक्ति संग्रहीत
.text
la t0, m # आधार पता
li t1, 3 # पंक्तियों की संख्या
li t2, 3 # स्तंभों की संख्या
li t3, 0 # मौजूदा पंक्ति इंडेक्स, 0 से शुरू
li s0, 0 # चालू योग
row_loop:
beq t3, t1, row_done
li t4, 0 # मौजूदा स्तंभ इंडेक्स, 0 से शुरू
col_loop:
beq t4, t2, col_done
mul t5, t3, t2 # पंक्ति इंडेक्स * स्तंभों की संख्या
add t5, t5, t4 # + स्तंभ इंडेक्स = चपटा हुआ इंडेक्स
slli t5, t5, 2 # बाइट ऑफ़सेट = इंडेक्स * 4
add t6, t0, t5 # इस पंक्ति और स्तंभ पर तत्व का पता
lw t6, 0(t6) # उस पते पर मान
add s0, s0, t6 # योग += तत्व
addi t4, t4, 1 # अगले स्तंभ पर आगे बढ़ता है
j col_loop
col_done:
addi t3, t3, 1 # अगली पंक्ति पर आगे बढ़ता है
j row_loop
row_done:
mv a0, s0 # कुल योग प्रिंट करता है: 1+2+...+9 = 45
li a7, 1
ecall
li a7, 10
ecall

दो नेस्टेड लूप मैट्रिक्स को इंडेक्स करते हैं। बाहरी लूप एक पंक्ति चुनता है और आंतरिक लूप उस पंक्ति के भीतर एक स्तंभ चुनता है। पंक्ति इंडेक्स को स्तंभों की संख्या से गुणा करता है। स्तंभ इंडेक्स जोड़ने और 4 से स्केल करने पर उस तत्व का पता मिलता है। उस पते पर संग्रहीत मान लोड किया जाता है और चालू योग में जोड़ा जाता है। जब आंतरिक लूप एक पंक्ति पूरी कर लेता है, तो बाहरी लूप अगली पंक्ति पर चला जाता है, जब तक सभी 3 पंक्तियाँ संसाधित न हो जाएँ।

ℹ
रो-मेजर क्रम पहली पंक्ति की सभी संख्याएँ संग्रहीत करता है, फिर दूसरी पंक्ति की सभी संख्याएँ, और इसी पैटर्न में जारी रहता है। यह एक नियम के बजाय एक परंपरा है। अन्य भाषाएँ, जिनमें Fortran भी शामिल है, कॉलम-मेजर क्रम का उपयोग करती हैं: पहले कॉलम की सभी संख्याएँ, फिर दूसरे कॉलम की सभी संख्याएँ, और इसी तरह। डेटा लिखने वाले और डेटा पढ़ने वाले को इस बात पर सहमत होना चाहिए कि कौन सा लेआउट उपयोग किया गया था। RISC-V जिस भी पते की आप गणना करते हैं, उसी पर पढ़ता और लिखता है।