GAP , 368 ไบต์
สำหรับนักคณิตศาสตร์นี่คือการคูณในพหุนามแหวน F_2 [x] การระบุพหุนามกับจำนวนธรรมชาติโดยการประเมินที่ x = 2 เป็นพหุนามมากกว่า Z
แน่นอนเรามาทำเช่นนั้น! (นี่เป็นเพียงการตีกอล์ฟอย่างหลวม ๆ ประเด็นก็คือย้ายเข้าสู่ F 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;
นี่คือรหัส ungolfed พร้อมคำอธิบาย:
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;
เอาล่ะออกก่อนดังนั้นเราจะสร้างชื่อแหวน univariate กว่าสนาม F 2R
และเรียกมันว่า โปรดทราบว่าGF(2)
เป็น F 2ใน GAP
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
686 x86 จากส่วนขยาย CLMUL น่าเสียดายที่ฉันลงคะแนนสำหรับความรู้เกี่ยวกับชุดคำสั่ง x86 ก่อนหน้านี้ (ที่เกี่ยวข้องกับPEXT/PDEP
) ดังนั้นฉันจะทิ้งความคิดเห็นไว้ที่นี่