- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
发表于 2008-4-28 15:05:13
|
显示全部楼层
下面贴出GMP kara乘法 的代码:来自GMP 4.22 中的 mpn\generic\mul_n.c ,GMP 4.22 可从 http://swox.com/gmp/ 下载
顺便说一下,我的代码比他的简单,而且是基于2^30进制的。- /* Multiplies using 3 half-sized mults and so on recursively.
- * p[0..2*n-1] := product of a[0..n-1] and b[0..n-1].
- * No overlap of p[...] with a[...] or b[...].
- * ws is workspace.
- */
-
- void
- mpn_kara_mul_n (mp_ptr p, mp_srcptr a, mp_srcptr b, mp_size_t n, mp_ptr ws)
- {
- mp_limb_t w, w0, w1;
- mp_size_t n2;
- mp_srcptr x, y;
- mp_size_t i;
- int sign;
-
- n2 = n >> 1;
- ASSERT (n2 > 0);
-
- if ((n & 1) != 0)
- {
- /* Odd length. */
- mp_size_t n1, n3, nm1;
-
- n3 = n - n2;
-
- sign = 0;
- w = a[n2];
- if (w != 0)
- w -= mpn_sub_n (p, a, a + n3, n2);
- else
- {
- i = n2;
- do
- {
- --i;
- w0 = a[ i ];
- w1 = a[n3 + i];
- }
- while (w0 == w1 && i != 0);
- if (w0 < w1)
- {
- x = a + n3;
- y = a;
- sign = ~0;
- }
- else
- {
- x = a;
- y = a + n3;
- }
- mpn_sub_n (p, x, y, n2);
- }
- p[n2] = w;
-
- w = b[n2];
- if (w != 0)
- w -= mpn_sub_n (p + n3, b, b + n3, n2);
- else
- {
- i = n2;
- do
- {
- --i;
- w0 = b[ i ];
- w1 = b[n3 + i];
- }
- while (w0 == w1 && i != 0);
- if (w0 < w1)
- {
- x = b + n3;
- y = b;
- sign = ~sign;
- }
- else
- {
- x = b;
- y = b + n3;
- }
- mpn_sub_n (p + n3, x, y, n2);
- }
- p[n] = w;
-
- n1 = n + 1;
- if (n2 < MUL_KARATSUBA_THRESHOLD)
- {
- if (n3 < MUL_KARATSUBA_THRESHOLD)
- {
- mpn_mul_basecase (ws, p, n3, p + n3, n3);
- mpn_mul_basecase (p, a, n3, b, n3);
- }
- else
- {
- mpn_kara_mul_n (ws, p, p + n3, n3, ws + n1);
- mpn_kara_mul_n (p, a, b, n3, ws + n1);
- }
- mpn_mul_basecase (p + n1, a + n3, n2, b + n3, n2);
- }
- else
- {
- mpn_kara_mul_n (ws, p, p + n3, n3, ws + n1);
- mpn_kara_mul_n (p, a, b, n3, ws + n1);
- mpn_kara_mul_n (p + n1, a + n3, b + n3, n2, ws + n1);
- }
-
- if (sign)
- mpn_add_n (ws, p, ws, n1);
- else
- mpn_sub_n (ws, p, ws, n1);
-
- nm1 = n - 1;
- if (mpn_add_n (ws, p + n1, ws, nm1))
- {
- mp_limb_t x = (ws[nm1] + 1) & GMP_NUMB_MASK;
- ws[nm1] = x;
- if (x == 0)
- ws[n] = (ws[n] + 1) & GMP_NUMB_MASK;
- }
- if (mpn_add_n (p + n3, p + n3, ws, n1))
- {
- mpn_incr_u (p + n1 + n3, 1);
- }
- }
- else
- {
- /* Even length. */
- i = n2;
- do
- {
- --i;
- w0 = a[ i ];
- w1 = a[n2 + i];
- }
- while (w0 == w1 && i != 0);
- sign = 0;
- if (w0 < w1)
- {
- x = a + n2;
- y = a;
- sign = ~0;
- }
- else
- {
- x = a;
- y = a + n2;
- }
- mpn_sub_n (p, x, y, n2);
-
- i = n2;
- do
- {
- --i;
- w0 = b[ i ];
- w1 = b[n2 + i];
- }
- while (w0 == w1 && i != 0);
- if (w0 < w1)
- {
- x = b + n2;
- y = b;
- sign = ~sign;
- }
- else
- {
- x = b;
- y = b + n2;
- }
- mpn_sub_n (p + n2, x, y, n2);
-
- /* Pointwise products. */
- if (n2 < MUL_KARATSUBA_THRESHOLD)
- {
- mpn_mul_basecase (ws, p, n2, p + n2, n2);
- mpn_mul_basecase (p, a, n2, b, n2);
- mpn_mul_basecase (p + n, a + n2, n2, b + n2, n2);
- }
- else
- {
- mpn_kara_mul_n (ws, p, p + n2, n2, ws + n);
- mpn_kara_mul_n (p, a, b, n2, ws + n);
- mpn_kara_mul_n (p + n, a + n2, b + n2, n2, ws + n);
- }
-
- /* Interpolate. */
- if (sign)
- w = mpn_add_n (ws, p, ws, n);
- else
- w = -mpn_sub_n (ws, p, ws, n);
- w += mpn_add_n (ws, p + n, ws, n);
- w += mpn_add_n (p + n2, p + n2, ws, n);
- MPN_INCR_U (p + n2 + n, 2 * n - (n2 + n), w);
- }
- }
复制代码 |
|