【问题标题】:I can't understand this Horner's rule implementation in extended fields GF(p^n)我无法理解这个霍纳在扩展字段 GF(p^n) 中的规则实现
【发布时间】:2016-03-02 16:52:44
【问题描述】:

我正在尝试从this (old) implementation on github 了解 Shamir 的秘密共享方案的实施,并且我正在努力解决扩展字段 GF(p^n) 中的霍纳规则:

void horner(int n, mpz_t y, const mpz_t x, const mpz_t coeff[])
{
  int i;
  mpz_set(y, x);
  for(i = n - 1; i; i--) {
    field_add(y, y, coeff[i]);
    field_mult(y, y, x);
  }
  field_add(y, y, coeff[0]);
}

为什么add 先出现然后mult?算法是什么?为什么不这样:

  mpz_set(y,coeff[n-1]);
  for(i = n - 2; i!=-1; i--) {
    field_mult(y, y, x);
    field_add(y,y,coeff[i]);
  }

【问题讨论】:

标签: c algorithm math gmp


【解决方案1】:

用普通的加法和乘法符号翻译这个horner函数,我们得到:

y = x;                     // mpz_set(y, x);
for(i = n - 1; i; i--) {
    y = y + coeff[i];      // field_add(y, y, coeff[i]);
    y = y * x              // field_mult(y, y, x);
}
y = y + coeff[0]           // field_add(y, y, coeff[0]);

因此计算如下:

您可以看到它不计算任何多项式,但它是霍纳算法的一个变体,用于计算 monic polynomial

现在你的建议是:

y = coeff[n-1];               // mpz_set(y,coeff[n-1]);
for(i = n - 2; i!=-1; i--) {
    y = y * x;                // field_mult(y, y, x);
    y = y + coeff[i];         // field_add(y,y,coeff[i]);
}

因此,您计算以下内容:

您可以看到缺少最高阶项。

如果你想让所有的操作都在循环体内,你可以。 毕竟,分解一系列交替指令的方式只有两种不同:

operation    value of y                                    loop iteration
                                                 add-mult loop      mult-add loop
                x                               initialization         n-1
add       x + coeff[n-1]                             n-1               n-1
mult     (x + coeff[n-1]) * x                        n-1               n-2
add      (x + coeff[n-1]) * x + coeff[n-2]           n-2               n-2
mult    ((x + coeff[n-1]) * x + coeff[n-2]) * x      n-2               n-3
          ...etc...

但您需要将y 显式初始化为值1(即隐式coeff[n]),以便您可以先乘以x 并获得正确的最高阶项。

y = 1;                        // mpz_set(y,1);
for(i = n - 1; i!=-1; i--) {  // NOTICE n - 1 NOT n - 2
    y = y * x;                // field_mult(y, y, x);
    y = y + coeff[i];         // field_add(y,y,coeff[i]);
}

你可以算出你现在又执行了一次乘法运算,它是乘法1 * x。在有限域上,这通常使用对数表和反对数表完成,因此您最好避免这种无用的乘法,尤其是在您要大量计算多项式时。

TL;DR:这种编写霍纳算法的方式将最后一个加法和第一个乘法放在循环体之外。因为最高阶系数是1,所以这个乘法就被完全删除了。

澄清一下:最高阶的术语被保留,但随后是 x^n 而不是 1 * x^n。您可以为完全相同的结果节省一次乘法。

【讨论】:

  • “因为最高阶系数是 1,所以这个乘法被完全删除了。”为什么在上面的公式中我们需要'x^n',如果它被删除了?和系数 1 一样,它被删除了吗?是什么我无法理解... n=3: y=((1x+C[2])x+C[1])x+C[0]=x^3+C[2]x^2+ C[1]x+C[0]。 'x^3' 发生了什么?谢谢。
  • 是的,理解:mpz_set_ui(y,1) 而不是 mpz_set(y,x) 我的意思是:polynomial is expressed as:f(x) = a0 + a1x + a2x2 + ... + akxk =总和 a[k]x^k。 x^n 从何而来? n=3: y=((x+C[2])x+C[1])x+C[0]=**x^3**+C[2]x^2+C[1]x +C[0]。 x=2: **8**+4C[2]+2C[1]+C[0] 不一样 4C[2]+2C[1]+C[0]。
  • 您的表达式在一般情况下有效。在这个特定的实现中,您正在查看一个函数,该函数始终返回 a[n] = 1 的多项式。
  • 对不起,我还是不明白为什么在这个实现中没有系数c[n]的x^n,即x^n + sum c[i]x^i, 0..n-1总和 c[i]x^i 0..n.
  • 如果你看一下函数,没有什么原因,它就是函数的作用。为什么会这样写?因为程序员需要Monic Polynomials。他为什么需要那个?好吧,您将不得不问他或查看算法的其余部分。但是现在,您知道该函数究竟做了什么。
猜你喜欢
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
  • 1970-01-01
相关资源
最近更新 更多