जीएपी , 368 बाइट्स
गणितज्ञों के लिए, यह बहुपद अंगूठी F_2 [x] में गुणा है, x = 2 पर Z के रूप में बहुपद के रूप में मूल्यांकन करके बहुपदों की पहचान प्राकृतिक संख्याओं के साथ।
ज़रूर, चलो ऐसा करते हैं! (यह केवल शिथिल रूप से गढ़ा गया है, यह बिंदु एफ 2 [x] में जाने के लिए और एक जीत प्रविष्टि होने पर किसी भी प्रयास से अधिक गणना करने के लिए अधिक था)
यहाँ कोड है
f:=function(i,j)R:=PolynomialRing(GF(2));x:=IndeterminatesOfPolynomialRing(R);x:=x[1];a:=function(i)local n,r;r:=0*x;while not i=0 do n:=0;while 2^n<=i do n:=n+1;od;n:=n-1;r:=r+x^n;i:=i-2^n;od;return r;end;b:=function(r)local c,i,n;i:=0;n:=0;for c in CoefficientsOfUnivariatePolynomial(r) do if c=Z(2)^0 then n:=n+2^i;fi;i:=i+1;od;return n;end;return b(a(i)*a(j));end;
यहाँ स्पष्टीकरण के साथ अपुष्ट कोड है:
xor_multiplication:=function(i,j)
R:=PolynomialRing(GF(2));
x:=IndeterminatesOfPolynomialRing(R);
x:=x[1];
to_ring:=function(i)
local n,r;
r:=0*x;
while not i=0 do
n:=0;
while 2^n<=i do
n:=n+1;
od;
n:=n-1;
r:=r+x^n;
i:=i-2^n;
od;
return r;
end;
to_ints:=function(r)
local c,i,n;
i:=0;n:=0;
for c in CoefficientsOfUnivariatePolynomial(r) do
if c=Z(2)^0 then
n:=n+2^i;
fi;
i:=i+1;
od;
return n;
end;
return to_ints( to_ring(i)*to_ring(j));
end;
ठीक है, इसलिए सबसे पहले, हम क्षेत्र एफ 2 के ऊपर एकतरफा बहुपद अंगूठी बनाते हैं और इसे कॉल करते हैं R
। ध्यान दें कि GAP में GF(2)
F 2 है।
R:=PolynomialRing(GF(2));
इसके बाद, हम GAP वैरिएबल x
को रिंग के अनिश्चित में असाइन करने जा रहे हैं R
। अब, जब भी मैं x
GAP में कहता हूं , तो सिस्टम को पता चल जाएगा कि मैं रिंग के अनिश्चित होने के बारे में बात कर रहा हूं R
।
x:=IndeterminatesOfPolynomialRing(R);
x:=x[1];
अगला, हमारे दो कार्य हैं, जो एक दूसरे के उल्टे नक्शे हैं। ये नक्शे दोनों पर हैं, लेकिन वे संरचना को संरक्षित नहीं कर रहे हैं, इसलिए मैं उन्हें GAP में लागू करने का बेहतर तरीका नहीं समझ सका। लगभग निश्चित रूप से एक बेहतर तरीका है, यदि आप इसे जानते हैं, तो कृपया टिप्पणी करें!
पहला नक्शा, to_ring
एक पूर्णांक लेता है और इसे अपने संबंधित रिंग तत्व में मैप करता है। यह द्विआधारी एल्गोरिथ्म है, जहां हर एक रूपांतरण का उपयोग करके इस करता है 1
कि द्विआधारी में दिखाई देता है एक ने ले ली है x^n
, जहां n
उचित शक्ति है कि 2 यदि संख्या वास्तव में द्विआधारी था ले जाएगा है।
to_ring:=function(i)
local n,r;
r:=0*x; # initiate r to the zero element of R
while not i=0 do # this is a modified binary algorithm
n:=0;
while 2^n<=i do
n:=n+1;
od;
n:=n-1;
r:=r+x^n;
i:=i-2^n;
od;
return r;
end;
अगला फ़ंक्शन इसे उलट देता है। to_ints
एक रिंग एलिमेंट लेता है और इसे अपने संबंधित पूर्णांक पर मैप करता है। मैं बहुपद के गुणांक और प्रत्येक गैर-गुणांक गुणांक की एक सूची प्राप्त करके ऐसा करता हूं, परिणाम 2 ^ n तक बढ़ जाता है, उसी तरह जैसे कि हम बाइनरी को दशमलव में बदल देंगे।
to_ints:=function(r)
local c,i,n;
i:=0;n:=0;
for c in CoefficientsOfUnivariatePolynomial(r) do
if c=Z(2)^0 then
# ^-- Right here you'll notice that the Z(2) is basically '1' in GF(2). So Z(2)^0 ~ 1 and Z(2)*0 ~ 0
# effectively, this line checks for nonzero coefficients
n:=n+2^i;
fi;
i:=i+1;
od;
return n;
end;
अंतिम चरण के लिए, हम इन कार्यों को कहते हैं। हम दो पूर्णांक इनपुट लेते हैं, उन्हें रिंग में तत्वों में परिवर्तित करते हैं R
, फिर इन तत्वों को एक साथ गुणा करते हैं, और उत्पाद को पूर्णांक में वापस भेजते हैं।
return to_ints( to_ring(i)*to_ring(j));
PCLMULQDQ
CLMUL एक्सटेंशन से 6-बाइट x86 निर्देश है। दुर्भाग्य से मैं पहले (संबंधितPEXT/PDEP
) के x86 निर्देश के अपने ज्ञान के लिए नीच हो गया , इसलिए मैं इसे केवल एक टिप्पणी के रूप में यहाँ छोड़ने जा रहा हूं।