代码如下:
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;
}
此代码在GF(2)上实现矩阵和向量的乘法。返回结果的代码为64x64矩阵M和1x64向量x的乘积。
我想知道这段代码是什么线性代数运算(在GF(2)上):
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;
}
答案 0 :(得分:1)
我想知道这段代码是什么线性代数运算(在GF(2)上):
当然,您的意思是GF(2) 64 ,即GF(2)上64维矢量的字段。
首先考虑循环结构:
for( i = 1; i <= 64; i++ ){ for( j = i; j <= 64; j++ ){
正在查看每对不同的索引(索引本身不一定彼此不同)。那应该提供第一个线索。然后我们看到
if( ((x >> (64-i)) & 1) && ((x >> (64-j)) & 1) )
,它正在测试向量x
是否同时设置了位i
和位j
。如果是这样,则通过向量和(==逐个元素“或”)将一行矩阵A
添加到累积变量a
中。通过在每个内循环迭代中递增b
,我们确保每次迭代都为A
的不同行提供服务。而且这还告诉我们A
必须具有64 * 65/2 = 160行(这很重要)。
通常,这根本不是线性运算。 GF(2)上向量场上的操作o
为线性的准则归结为以下表达式:对所有向量对x
和y
都成立:
o(x + y) = o(x) + o(y)
现在,为方便起见,让我们考虑字段GF(2) 2 而不是GF(2) 64 ;只需添加零即可将结果从前者扩展到后者。令x
为位向量(1,0)(例如,由整数2表示)。令y
为位向量(0,1)(由整数1表示)。并将A
设为此矩阵:
1 0
0 1
1 0
您的操作的结果如下:
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
很显然,不是o(x) + o(y) = o(x + y)
,x
和特征y
的{{1}},所以对此{{1} }。
有些矩阵A
的对应运算是线性的,但是它们表示的线性运算将取决于A
。例如,可以用这种方式表示各种各样的矩阵矢量乘法。对我来说还不清楚是否可以用这种形式表示除矩阵矢量乘法之外的其他线性运算,但我倾向于不这样认为。