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;
ここに説明のないコードがあります:
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;
さて、最初に、フィールドF 2上で単変量多項式環を作成し、それを呼び出しますR
。GAPではGF(2)
F 2であることに注意してください。
R:=PolynomialRing(GF(2));
次に、x
リングの不確定要素にGAP変数を割り当てますR
。さて、x
GAPで言うたびに、システムは、リングの不確定性について話していることを認識しR
ます。
x:=IndeterminatesOfPolynomialRing(R);
x:=x[1];
次に、2つの関数があります。これらは相互の逆マップです。これらのマップは両方とも上にありますが、構造を維持するものではないため、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進数を10進数に変換するのと同じ方法で、結果を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;
最後のステップでは、これらの関数を呼び出します。2つの整数入力を取り、それらをリング内の要素に変換しR
、これらの要素を乗算して、その積を整数に送り返します。
return to_ints( to_ring(i)*to_ring(j));
PCLMULQDQ
、CLMUL拡張からの6バイトx86命令です。残念ながら、以前(xに関連するPEXT/PDEP
)x86命令セットの知識に落胆したため、ここにコメントとして残しておきます。