47
\$\begingroup\$

You goal is to implement the operation of XOR (carryless) multiplication, defined below, in as few bytes as possible.

If we think of bitwise XOR (^) as binary addition without carrying

   101   5
^ 1001   9
  ----  
  1100  12
  
  5^9=12

we can perform XOR multiplication @ by doing binary long-multiplication but doing the adding step without carrying as bitwise XOR ^.

     1110  14
   @ 1101  13
    -----
     1110
       0
   1110
^ 1110 
  ------
  1000110  70
  
  14@13=70

(For mathematicians, this is multiplication in the polynomial ring \$F_2[x]\$, identifying polynomials with natural numbers by evaluating at \$x=2\$ as a polynomial over \$\mathbb Z\$.)

XOR multiplication commutes a@b=b@a, associates (a@b)@c=a@(b@c), and distributes over bitwise XOR a@(b^c)=(a@b)^(a@c). In fact, it is the unique such operation that matches multiplication a@b=a*b whenever a and b are powers of 2 like 1,2,4,8....

Requirements

Take two non-negative integers as input and output or print their XOR-product. This should be as numbers or their decimal string representations, not their binary expansions. Fewest bytes wins.

Don't worry about integer overflows.

Here are some test cases formatted as a b a@b.

0 1 0
1 2 2
9 0 0
6 1 6
3 3 5
2 5 10
7 9 63
13 11 127
5 17 85
14 13 70
19 1 19
63 63 1365
\$\endgroup\$
5
  • 17
    \$\begingroup\$ This is better known as "carry-less multiplication", which you might want to add the the question title, and with high probability the smallest entry is the 6-byte x86 instruction PCLMULQDQ from the CLMUL extension. Unfortunately I got downvoted for my knowledge of the x86 instruction set before (Related to PEXT/PDEP), so I'm going to just leave this as a comment here. \$\endgroup\$ Commented May 16, 2015 at 16:14
  • \$\begingroup\$ @IwillnotexistIdonotexist Thanks for the note, it's nice to have a name to Google. \$\endgroup\$
    – xnor
    Commented May 16, 2015 at 21:04
  • \$\begingroup\$ If that above is not "xor" you have to call in a different way as xorc or xornc ... It is not xor \$\endgroup\$
    – user58988
    Commented Dec 4, 2016 at 9:33
  • 2
    \$\begingroup\$ @RosLuP It's not xor, it's xor multiplication. \$\endgroup\$
    – xnor
    Commented Dec 4, 2016 at 9:39
  • \$\begingroup\$ @boboquack Actually, I believe nimber multiplication is different. For instance, it has 2*2==3. Both of these distribute over nim addition, but the one in this challenge matches multiplication on powers of 2, whereas the nimber on matches only on 2^(2^n). \$\endgroup\$
    – xnor
    Commented Dec 4, 2016 at 23:39

36 Answers 36

1
2
1
\$\begingroup\$

Itr, 9 bytes

BàBC*µRxB

online interpreter

Explanation

            ; implicit input
BàB         ; convert input to bit lists
   C*µRx    ; polynomial multiplication in F2[X]
        B   ; convert bit-list to number
            ; implicit output
\$\endgroup\$
1
\$\begingroup\$

Nekomata, 5 bytes

ᵃƂ×Öƃ

Attempt This Online!

ᵃƂ×Öƃ
ᵃƂ      Convert both inputs to binary digits
  ×     Convolve
   Ö    Modulo 2
    ƃ   Convert back to decimal
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 6 bytes

bƒÞƈ∷B

Try it Online! Port of UnrelatedString's Jelly answer, go upvote that!

b      # Binary digits
 ƒÞƈ   # convolve
    ∷  # Take modulo 2
     B # Convert back from binary
\$\endgroup\$
0
\$\begingroup\$

golflua 68

x,y=I.r("*n","*n")r=0~@i=0,31r=B.x(r,x*B.ls(B.rs(y,i)%2,i+1))$w(r/2)

Does basically the same bitshifting as Ypnypn's Java answer, but seems to require the divide by 2 at the end to work correctly. Takes in values as stdin, examples below

> 14 13 
70
> 19 1 
19
> 5 17 
85
\$\endgroup\$
0
\$\begingroup\$

Ceylon, 90 bytes

alias I=>Integer;I x(I a,I b)=>[for(i in 0:64)if(b.get(i))a*2^i].fold(0)((y,z)=>y.xor(z));

This is just the algorithm as described: multiply a by 2^i wherever the ith bit is set in b, and add them all together using xor. Iterates over 0:64 because Integers are 64-bit in Ceylon when running on JVM (lower when running as Javascript, but then b.get(i) just returns false).

Formatted:

alias I => Integer;

I x(I a, I b) =>
      [
        for (i in 0:64)
            if (b.get(i))
                a * 2^i
      ].fold(0)((y, z) => y.xor(z));

The alias safes here just a single byte.

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 42 bytes

Port of the Java answer. Go upvote that!

x=>y=>(g=i=>i&&g(--i)^x*((y>>i)%2)<<i)(32)

Try it online!

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.