-1

Here is the code:

long long mul(long long x)
{
    uint64_t M[64] = INIT;
    uint64_t result = 0;

    for ( int i = 0; i < 64; i++ )
    {
        uint64_t a = x & M[i];
        uint64_t b = 0;
        while ( a ){
            b ^= a & 1;;
            a >>= 1;
        }
        result |= b << (63 - i);
    }
    return result;
}

This code implements multiplication of the matrix and vector on GF(2). The code that returns result as the product of 64x64 matrix M and 1x64 vector x.

I want to know what linear algebraic operation( on GF(2) ) this code is:

long long unknown(long long x)
{
    uint64_t A[] = INIT;
    uint64_t a = 0, b = 0;

    for( i = 1; i <= 64; i++ ){
        for( j = i; j <= 64; j++ ){
            if( ((x >> (64-i)) & 1) && ((x >> (64-j)) & 1) )
                a ^= A[b];
            b++;
        }
    }
    return a;
}
SeHwa
  • 1
  • 1
  • What is `INIT`? – Peter Jul 30 '18 at 13:56
  • It's just some initial value. The matrix to be multiplied with the vector x. But I don't know that A is a matrix. A is not a square matrix. – SeHwa Jul 30 '18 at 14:03
  • 1
    You want to be using `unsigned` data types here. Your shift operations have implementation-defined behavior in the event that the vector or any of the matrix elements have their sign bit set. – John Bollinger Jul 30 '18 at 14:06
  • 1
    I would furthermore suggest explicit-width integer types (*i.e.* `uint64_t`) inasmuch as you seem to rely on that width. `unsigned long long` will not have fewer than 64 bits, but it may have more, and that could get you into trouble or even just extract a needless performance penalty. – John Bollinger Jul 30 '18 at 14:09
  • I know but I omitted it. sorry. – SeHwa Jul 30 '18 at 14:10
  • It looks like the second fragment computes the sum of selected rows of A, which needs to have 64*64 rows. – n. m. could be an AI Jul 30 '18 at 14:32

1 Answers1

1

I want to know what linear algebraic operation( on GF(2) ) this code is:

Of course you mean GF(2)64, the field of 64-dimensional vectors over GF(2).

Consider first the loop structure:

    for( i = 1; i <= 64; i++ ){
        for( j = i; j <= 64; j++ ){

That's looking at every distinct pair of indices (the indices themselves not necessarily distinct from each other). That should provide a first clue. We then see

            if( ((x >> (64-i)) & 1) && ((x >> (64-j)) & 1) )

, which is testing whether vector x has both bit i and bit j set. If it does, then we add a row of matrix A into accumulation variable a, by vector sum (== element-wise exclusive or). By incrementing b on every inner-loop iteration, we ensure that each iteration services a different row of A. And that also tells us that A must have 64 * 65 / 2 = 160 rows (that matter).

In general, this is not a linear operation at all. The criterion for an operation o on a vector field over GF(2) to be linear boils down to this expression holding for all pairs of vectors x and y:

    o(x + y) = o(x) + o(y)

Now, for notational convenience, let's consider the field GF(2)2 instead of GF(2)64; the result can be extended from the former to the latter simply by adding zeroes. Let x be the bit vector (1, 0) (represented, for example, by the integer 2). Let y be the bit vector (0, 1) (represented by the integer 1). And let A be this matrix:

1 0
0 1
1 0

Your operation has the following among its results:

operand   result   as integer   comment
 x        (1, 0)      2         Only the first row is accumulated
 y        (1, 0)      2         Only the third row is accumulated
 x + y    (0, 1)      1         All rows are accumulated

Clearly, it is not the case that o(x) + o(y) = o(x + y) for this x, y, and characteristic A, so the operation is not linear for this A.

There are matrices A for which the corresponding operation is linear, but what linear operation they represent will depend on A. For example, it is possible to represent a wide variety of matrix-vector multiplications this way. It's not clear to me whether linear operations other than matrix-vector multiplications can be represented in this form, but I'm inclined to think not.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157