간격 , 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;
좋아, 첫째로, 우리는 필드 F를 통해 단 변수 다항식 링 만들고 2 및 호출 R
. 참고 GF(2)
F 인 2 GAP있다.
R:=PolynomialRing(GF(2));
다음으로 GAP 변수 x
를 ring의 결정에 할당합니다 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
링 요소를 가져와 해당 정수에 매핑합니다. 나는 다항식의 계수 목록을 가져 와서 0이 아닌 각 계수에 대해 결과를 2 ^ n 씩 증가시킵니다. 이진수를 10 진수로 변환하는 것과 같습니다.
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 명령어 세트에 대한 지식으로 다운 투표를 받았 으므로 여기에 의견으로 남겨 두겠습니다.