LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
mul_fft.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../include/lammp/impl/inlines.h"
17#include "../../../include/lammp/impl/mparam.h"
18#include "../../../include/lammp/impl/tmp_alloc.h"
19#include "../../../include/lammp/lmmpn.h"
20
21
22// ((mp_size_t)3 << (2 * (n) - 5)) + 1 是预计算的阈值,n是对应的k值
23#define _FFT_TABLE_ENTRY(n) {((mp_size_t)3 << (2 * (n) - 5)) + 1, (n)}
24#define _FFT_TABLE_ENTRY4(n) \
25 _FFT_TABLE_ENTRY(n), _FFT_TABLE_ENTRY((n) + 1), _FFT_TABLE_ENTRY((n) + 2), _FFT_TABLE_ENTRY((n) + 3)
26
27// best_k_(next_size_(n)) = best_k_(n)
28// table[i+1][0]-1 必须是 2^(table[i][1]-LOG2_LIMB_BITS) 的整数倍
29// LOG2_LIMB_BITS:每个 limb 的比特数的2对数,为 log2(64) = 6
30static const mp_size_t lmmp_fft_table_[][2] = {
31 {0, 6},
32 {1597, 7},
33 {1655, 6},
34 {1917, 7},
35 {3447, 8},
36 {3565, 7},
37 {3831, 8},
38 {7661, 9},
39 {8145, 8},
40 {8685, 9},
41 {14289, 10},
42 {16289, 9},
43 {20433, 10},
44 {24481, 9},
45 {26577, 10},
46 {28593, 11},
47 {32545, 10},
48 {57249, 11},
49 {65313, 10},
50 {73633, 11},
51 {98081, 12},
52 {130625, 11},
53 {196385, 12},
54 {261697, 11},
55 {294689, 12},
56 {392769, 13},
57 {523265, 12},
58 {654913, 11},
59 {917281, 13},
60 {1047553, 11},
61 {1600001, 12},
62 {1834561, 14},
63 {2095105, 12},
68 {(mp_size_t)-1, 127}};
69
70typedef struct {
71 mp_ptr temp_coef; // 用于数据交换的临时系数数组
72 mp_size_t lenw; // 系数的机器字(limb)长度
73 mp_ssize_t maxdepth; // 内存栈的最大深度(已分配的层数)
74 mp_ssize_t tempdepth; // 内存栈的当前深度(正在使用的层数)
75 void* mem[16]; // 存储16层内存块的指针
76 mp_size_t memsize[16]; // 存储每层内存块的大小(以字节为单位)
78
79/**
80 * @brief 查找对于 m>=n 的模 B^m+1 FFT运算的最优k值
81 * @param n - 输入的机器字长度
82 * @return 最优的k值
83 */
85 mp_size_t k = 0;
86 while (n >= lmmp_fft_table_[k + 1][0]) ++k;
87 return lmmp_fft_table_[k][1];
88}
89
90/**
91 * @brief 计算FFT运算所需的最小规整化长度(向上取整到2^k的倍数)
92 * @param n - 原始长度
93 * @return 规整后的长度(为2^k的倍数)
94 */
99 n = (((n - 1) >> k) + 1) << k;
100 return n;
101}
102
103/**
104 * @brief FFT内存栈的分配/释放接口
105 * @param ms - 内存栈结构体栈帧
106 * @param size - 分配大小(字节),size=0表示释放当前层内存
107 * @return 分配成功:返回mp_ptr*;释放:返回0
108 */
110 if (size) {
111 if (++ms->tempdepth > ms->maxdepth) {
112 ms->mem[++ms->maxdepth] = lmmp_alloc(size);
113 ms->memsize[ms->maxdepth] = size;
114 }
115 lmmp_debug_assert(ms->memsize[ms->tempdepth] == size);
116 return ms->mem[ms->tempdepth];
117 } else {
118 if (--ms->tempdepth < 0) {
119 for (mp_size_t i = 0; i <= (mp_size_t)(ms->maxdepth); ++i) lmmp_free(ms->mem[i]);
120 ms->maxdepth = -1;
121 }
122 return 0;
123 }
124}
125
126/**
127 * @brief [dst,lenw+1] = [(bit*)numa+bitoffset, bits]
128 * @param dst - 输出系数数组(长度lenw+1)
129 * @param numa - 输入大数指针
130 * @param bitoffset - 起始比特偏移量(>=0)
131 * @param bits - 提取的比特数(0 < bits <= LIMB_BITS*lenw)
132 * @param lenw - 输出系数的机器字长度
133 * @warning bitoffset>=0, 0<bits<=LIMB_BITS*lenw, sep(dst,numa)
134 */
136 // shr = 机器字内的比特偏移(0~LIMB_BITS-1)
137 // offset = 起始机器字的索引
139
140 mp_size_t lena = (bitoffset + bits - 1) / LIMB_BITS - offset + 1, endp = (bits - 1) / LIMB_BITS;
141
142 if (shr)
144 else
146
147 dst[endp] &= LIMB_MAX >> (-bits & (LIMB_BITS - 1));
148
149 lmmp_zero(dst + endp + 1, lenw - endp);
150}
151
152/**
153 * @brief 对模 2^n+1 的系数执行左移操作
154 * @param ms - 内存栈结构体指针
155 * @param coef - 输入输出系数数组指针(指针的指针,用于交换内存)
156 * @param shl - 左移的比特数(0<shl<2*n)
157 * @warning n = ms->lenw * LIMB_BITS
158 * *coef 已伪归一化(mod 2^n+1)
159 * ms->temp_coef 至少有 lenw+1 个机器字
160 */
162 mp_size_t l = ms->lenw; // 系数的机器字长度
163 mp_size_t w = shl / LIMB_BITS; // 左移的机器字数量
164 shl &= LIMB_BITS - 1; // 剩余的比特偏移(0~LIMB_BITS-1)
165 mp_ptr src = *coef; // 源系数数组
166 mp_ptr dst = ms->temp_coef; // 目标临时数组
167 mp_limb_t cc, rd; // 进位变量(cc=carry, rd=read)
168
169 if (w >= l) {
170 w -= l;
171 if (shl) {
172 lmmp_shl_(dst, src + l - w, w + 1, shl);
173 rd = dst[w];
174 cc = lmmp_shlnot_(dst + w, src, l - w, shl);
175 } else {
176 if (w)
177 lmmp_copy(dst, src + l - w, w);
178 rd = src[l];
179 lmmp_not_(dst + w, src, l - w);
180 cc = 0;
181 }
182 dst[l] = 0;
183 ++cc;
184 lmmp_inc_1(dst, cc);
185
186 if (++rd == 0)
187 lmmp_inc(dst + w + 1);
188 else
189 lmmp_inc_1(dst + w, rd);
190 } else {
191 if (shl) {
192 lmmp_shlnot_(dst, src + l - w, w + 1, shl);
193 rd = ~dst[w];
194 cc = lmmp_shl_(dst + w, src, l - w, shl);
195 } else {
196 if (w)
197 lmmp_not_(dst, src + l - w, w);
198 rd = src[l];
199
200 lmmp_copy(dst + w, src, l - w);
201 cc = 0;
202 }
203 dst[l] = 2;
204 lmmp_inc_1(dst, 3);
205 lmmp_dec_1(dst, cc);
206
207 if (++rd == 0)
208 lmmp_dec(dst + w + 1);
209 else
210 lmmp_dec_1(dst + w, rd);
211
212 cc = dst[l];
213 dst[l] = dst[0] < cc;
214 lmmp_dec_1(dst, cc - dst[l]);
215 }
216
217 ms->temp_coef = src;
218 *coef = dst;
219}
220
221/**
222 * @brief 对模 2^n+1 的系数执行右移操作
223 * 右移shr位 = 左移(2n - shr)位(mod 2^n+1的循环特性)
224 * @param ms - 内存栈结构体指针
225 * @param coef - 输入输出系数数组指针
226 * @param shr - 右移的比特数(0 < shr < 2*n)
227 */
231
232/**
233 * @brief FFT蝶形运算(Butterfly Operation)
234 * (a,b) = (a + b, (a-b) << w ) mod 2^n+1
235 * a=[coef[0],ms->lenw+1], b=[coef[wing],ms->lenw+1], n=ms->lenw * LIMB_BITS
236 * @param ms - 内存栈结构体指针
237 * @param coef - 系数数组指针数组(coef[0]=a, coef[wing]=b)
238 * @param wing - b的索引
239 * @param w - 左移的比特数(0<=w<n)
240 * @warning n = ms->lenw * LIMB_BITS
241 * a,b 均已伪归一化(mod 2^n+1)
242 * ms->temp_coef 有至少 lenw + 1 个字长
243 */
245 mp_ptr numa = coef[0]; // 系数a
246 mp_ptr numb = coef[wing]; // 系数b
247 mp_ptr numc = ms->temp_coef; // 临时数组(存储a-b<<w)
248 mp_size_t shl = w & (LIMB_BITS - 1); // 比特级左移量
249 w /= LIMB_BITS; // 机器字级左移量
250 mp_size_t l = ms->lenw; // 系数长度(机器字)
251
252 mp_slimb_t acyo = 0, scyo = 0, ch;
253 mp_limb_t shlcyo = 0, chp = 0, chn = 0;
254
255 for (mp_size_t off = 0; off < l - w; off += PART_SIZE) {
259 if (shl)
261 }
262
263 ch = shlcyo + (-scyo << shl);
264 if (ch > 0)
265 chp = ch;
266 else
267 chn = -ch;
268
269 scyo = 0;
270 shlcyo = 0;
271
272 for (mp_size_t off = l - w; off < l; off += PART_SIZE) {
274 scyo = lmmp_sub_nc_(numc + off - (l - w), numb + off, numa + off, cursize, scyo);
276 if (shl)
277 shlcyo = lmmp_shl_c_(numc + off - (l - w), numc + off - (l - w), cursize, shl, shlcyo);
278 }
279
280 numc[w] += shlcyo; // 左移进位加到numc[w]
281 scyo = -scyo + numb[l] - numa[l]; // 调整借位(包含最高位)
282 acyo += numa[l] + numb[l]; // 调整进位(包含最高位)
283
284 numa[l] = numa[0] < (mp_limb_t)(acyo);
286
287 numc[l] = 1;
288 ++chn;
289 if (scyo > 0)
290 lmmp_inc_1(numc + w, scyo << shl);
291 else if (scyo < 0) {
292 if (scyo == -2 && shl == LIMB_BITS - 1)
293 lmmp_dec(numc + w + 1);
294 else
295 lmmp_dec_1(numc + w, -scyo << shl);
296 }
297 chp += numc[l];
298
299 if (chn >= chp) {
300 numc[l] = 0;
302 } else {
303 chp -= chn;
304 numc[l] = numc[0] < chp;
305 lmmp_dec_1(numc, chp - numc[l]);
306 }
307
308 coef[wing] = numc;
309 ms->temp_coef = numb;
310}
311
312/**
313 * @brief FFT蝶形运算(Butterfly Operation)
314 * (a,b) = (a+(b>>w), a-(b>>w)) mod 2^n+1
315 * a=[coef[0],ms->lenw+1], b=[coef[wing],ms->lenw+1], n=ms->lenw * LIMB_BITS
316 * @param ms - 内存栈结构体指针
317 * @param coef - 系数数组指针数组(coef[0]=a, coef[wing]=b)
318 * @param wing - b的索引
319 * @param w - 左移的比特数(0<=w<n)
320 * @warning n = ms->lenw * LIMB_BITS
321 * a,b 均已伪归一化(mod 2^n+1)
322 * ms->temp_coef 有至少 lenw + 1 个字长
323 */
325 mp_ptr numa = coef[0];
326 mp_ptr numb = coef[wing];
327 mp_ptr numc = ms->temp_coef;
328 mp_size_t shr = w & (LIMB_BITS - 1);
329 w /= LIMB_BITS;
330 mp_size_t l = ms->lenw;
331
332 mp_slimb_t bcyo = 0, acyo = 0, ah;
333 mp_limb_t shrcyo = shr ? numb[0] << (LIMB_BITS - shr) : 0;
334
335 for (mp_size_t off = l - w; off < l; off += PART_SIZE) {
337 if (shr)
338 lmmp_shr_c_(numb + off - (l - w), numb + off - (l - w), cursize, shr,
339 numb[off - (l - w) + cursize] << (LIMB_BITS - shr));
340 bcyo = lmmp_add_nc_(numc + off, numa + off, numb + off - (l - w), cursize, bcyo);
341 acyo = lmmp_sub_nc_(numa + off, numa + off, numb + off - (l - w), cursize, acyo);
342 }
343
344 for (mp_size_t off = 0; off < l - w; off += PART_SIZE) {
346 if (shr)
347 lmmp_shr_c_(numb + w + off, numb + w + off, cursize, shr, numb[off + w + cursize] << (LIMB_BITS - shr));
350 }
351
352 acyo += numb[l] >> shr;
353 bcyo = -bcyo - (numb[l] >> shr);
354
355 acyo -= numa[l - w - 1] < shrcyo;
356 numa[l - w - 1] -= shrcyo;
357 numc[l - w - 1] += shrcyo;
358 bcyo += numc[l - w - 1] < shrcyo;
359
360 ah = numa[l];
361
362 numa[l] += 1;
363 if (w == 0)
364 numa[l] += acyo;
365 else {
366 if (acyo < 0)
367 lmmp_dec(numa + l - w);
368 else
369 lmmp_inc_1(numa + l - w, acyo);
370 }
371 acyo = numa[l] - 1;
372 if (acyo < 0) {
373 numa[l] = 0;
374 lmmp_inc(numa);
375 } else {
376 numa[l] = numa[0] < (mp_limb_t)acyo;
378 }
379
380 numc[l] = ah + 2;
381 if (w == 0)
382 numc[l] += bcyo;
383 else {
384 if (bcyo > 0)
385 lmmp_inc(numc + l - w);
386 else
387 lmmp_dec_1(numc + l - w, -bcyo);
388 }
389 bcyo = numc[l] - 2;
390 if (bcyo <= 0) {
391 numc[l] = 0;
393 } else {
394 numc[l] = numc[0] < (mp_limb_t)bcyo;
396 }
397
398 coef[wing] = numc;
399 ms->temp_coef = numb;
400}
401
402/**
403 * @brief FFT递归函数
404 * @param ms - 内存栈结构体指针
405 * @param coef - 系数数组指针数组
406 * @param dis - 索引步长
407 * @param k - FFT层数(递归深度)
408 * @param w - 每次蝶形运算的移位基数
409 * @param w0 - 初始移位偏移
410 */
412 if (k == 1)
414 else {
415 k -= 2;
416 mp_size_t Kq = dis << k;
417 for (mp_size_t i = 0; i < Kq; i += dis) {
418 lmmp_fft_bfy_(ms, coef + i, 2 * Kq, i * w + w0);
419 lmmp_fft_bfy_(ms, coef + i + Kq, 2 * Kq, (i + Kq) * w + w0);
420 lmmp_fft_bfy_(ms, coef + i, Kq, 2 * (i * w + w0));
421 lmmp_fft_bfy_(ms, coef + i + Kq * 2, Kq, 2 * (i * w + w0));
422 }
423 if (k > 0) {
424 lmmp_fft_b1_(ms, coef, dis, k, 4 * w, 4 * w0);
425 lmmp_fft_b1_(ms, coef + Kq, dis, k, 4 * w, 4 * w0);
426 lmmp_fft_b1_(ms, coef + Kq * 2, dis, k, 4 * w, 4 * w0);
427 lmmp_fft_b1_(ms, coef + Kq * 3, dis, k, 4 * w, 4 * w0);
428 }
429 }
430}
431
433 if (k == 1)
434 lmmp_fft_bfy_(ms, coef, 1, 0);
435 else {
436 k -= 2;
437 mp_size_t Kq = ((mp_size_t)1) << k;
438 for (mp_size_t i = 0; i < Kq; ++i) {
439 lmmp_fft_bfy_(ms, coef + i, Kq * 2, i * w);
440 lmmp_fft_bfy_(ms, coef + i + Kq, Kq * 2, (i + Kq) * w);
441 lmmp_fft_bfy_(ms, coef + i, Kq, 2 * i * w);
442 lmmp_fft_bfy_(ms, coef + i + 2 * Kq, Kq, 2 * i * w);
443 }
444 if (k > 0) {
445 lmmp_fft_4_(ms, coef, k, w * 4);
446 lmmp_fft_4_(ms, coef + Kq, k, w * 4);
447 lmmp_fft_4_(ms, coef + 2 * Kq, k, w * 4);
448 lmmp_fft_4_(ms, coef + 3 * Kq, k, w * 4);
449 }
450 }
451}
452
454 mp_size_t k1 = k >> 1;
455 k -= k1;
456 mp_size_t Kp = ((mp_size_t)1) << k;
457 mp_size_t Kq = ((mp_size_t)1) << k1;
458
459 for (mp_size_t i = 0; i < Kp; ++i) lmmp_fft_b1_(ms, coef + i, Kp, k1, w, i * w);
460
461 for (mp_size_t i = 0; i < Kq; ++i) lmmp_fft_4_(ms, coef + Kp * i, k, w * Kq);
462}
463
465 if (k == 1)
467 else {
468 k -= 2;
469 mp_size_t Kq = dis << k;
470 if (k > 0) {
471 lmmp_ifft_b1_(ms, coef, dis, k, 4 * w, 4 * w0);
472 lmmp_ifft_b1_(ms, coef + Kq, dis, k, 4 * w, 4 * w0);
473 lmmp_ifft_b1_(ms, coef + Kq * 2, dis, k, 4 * w, 4 * w0);
474 lmmp_ifft_b1_(ms, coef + Kq * 3, dis, k, 4 * w, 4 * w0);
475 }
476 for (mp_size_t i = 0; i < Kq; i += dis) {
477 lmmp_ifft_bfy_(ms, coef + i, Kq, 2 * (i * w + w0));
478 lmmp_ifft_bfy_(ms, coef + i + Kq * 2, Kq, 2 * (i * w + w0));
479 lmmp_ifft_bfy_(ms, coef + i, 2 * Kq, i * w + w0);
480 lmmp_ifft_bfy_(ms, coef + i + Kq, 2 * Kq, (i + Kq) * w + w0);
481 }
482 }
483}
484
486 if (k == 1)
487 lmmp_ifft_bfy_(ms, coef, 1, 0);
488 else {
489 k -= 2;
490 mp_size_t Kq = ((mp_size_t)1) << k;
491 if (k > 0) {
492 lmmp_ifft_4_(ms, coef, k, w * 4);
493 lmmp_ifft_4_(ms, coef + Kq, k, w * 4);
494 lmmp_ifft_4_(ms, coef + 2 * Kq, k, w * 4);
495 lmmp_ifft_4_(ms, coef + 3 * Kq, k, w * 4);
496 }
497 for (mp_size_t i = 0; i < Kq; ++i) {
498 lmmp_ifft_bfy_(ms, coef + i, Kq, 2 * i * w);
499 lmmp_ifft_bfy_(ms, coef + i + 2 * Kq, Kq, 2 * i * w);
500 lmmp_ifft_bfy_(ms, coef + i, Kq * 2, i * w);
501 lmmp_ifft_bfy_(ms, coef + i + Kq, Kq * 2, (i + Kq) * w);
502 }
503 }
504}
505
507 mp_size_t k1 = k >> 1;
508 k -= k1;
509 mp_size_t Kp = ((mp_size_t)1) << k;
510 mp_size_t Kq = ((mp_size_t)1) << k1;
511
512 for (mp_size_t i = 0; i < Kq; ++i) lmmp_ifft_4_(ms, coef + Kp * i, k, w * Kq);
513
514 for (mp_size_t i = 0; i < Kp; ++i) lmmp_ifft_b1_(ms, coef + i, Kp, k1, w, i * w);
515}
516
517/**
518 * @brief 费马变换 模 B^n+1 乘法的结果合并
519 * @param ms - 内存栈结构体指针
520 * @param dst - 输出结果数组
521 * @param pfca - FFT系数数组指针数组
522 * @param K - FFT块数(2^k)
523 * @param k - FFT层数
524 * @param n - 系数总比特数
525 * @param M - 每个块的比特数
526 * @param rn - 结果长度(机器字)
527 */
530 mp_ptr dst,
531 mp_ptr* pfca,
532 mp_size_t K,
533 mp_size_t k,
534 mp_size_t n,
535 mp_size_t M,
537) {
538 mp_size_t rhead = 0, nlen = ms->lenw + 1;
539 mp_slimb_t borrow = 0, maxc = 0;
540
541 for (mp_size_t i = 0; i < K; ++i) {
542 lmmp_fft_shr_coef_(ms, pfca + i, (i * n >> k) + k);
543 mp_ptr nums = pfca[i];
544
545 if (nums[nlen - 1]) {
546 lmmp_dec(nums);
547 --nums[nlen - 1];
548 }
549 if (nums[nlen - 1] == 0 && nums[nlen - 2] >> (LIMB_BITS - 1)) {
550 lmmp_dec(nums);
551 --nums[nlen - 1];
552 }
553
554 if (borrow) {
555 mp_size_t brshift = borrow - 1 + n - M;
558 --nums[nlen - 1];
560 ++nums[nlen - 1];
561 }
562 borrow = -nums[nlen - 1];
563 nums[nlen - 1] = 0;
564
565 mp_size_t roffset = i * M;
566 mp_size_t shl = roffset & (LIMB_BITS - 1);
568
569 if (shl)
571
572 if (i == 0) {
574 rhead = nlen;
575 } else if (roffset + nlen <= rn) {
577 rhead = roffset + nlen;
578 } else {
580 maxc -= lmmp_sub_(dst, dst, rn, nums + rn - roffset, nlen + roffset - rn);
581 rhead = rn;
582 }
583 }
584
585 if (borrow) {
586 mp_size_t cyshift = borrow - 1 + n - M;
590 }
591
592 if (maxc > 0) {
593 dst[rn] = dst[0] < (mp_limb_t)maxc;
594 lmmp_dec_1(dst, maxc - dst[rn]);
595 } else {
596 dst[rn] = 0;
598 }
599}
600
601/**
602 * @brief 费马变换乘法递归函数(核心乘法逻辑)
603 * @param ms - 内存栈结构体指针
604 * @param pc1 - 第一个数的FFT系数数组指针数组
605 * @param pc2 - 第二个数的FFT系数数组指针数组
606 * @param K0 - FFT块数
607 * @warning K0>0
608 * 所有系数均已伪归一化(mod B^lenw+1)
609 * nsqr=1表示乘法,nsqr=0表示平方
610 */
612 int nsqr = pc1 != pc2;
613 mp_ptr push_temp_coef = ms->temp_coef;
614 mp_size_t rn = ms->lenw;
615
618 for (mp_size_t i = 0; i < K0; ++i) {
619 if (nsqr)
620 lmmp_mul_n_(temp_mul, pc1[i], pc2[i], rn + 1);
621 else
622 lmmp_sqr_(temp_mul, pc1[i], rn + 1);
623
624 // 模 B^rn+1 归一化:temp_mul - temp_mul[rn ...]
626 pc1[i][rn] = 0;
627 lmmp_inc_1(pc1[i], maxc);
628 }
630 } else {
631 mp_size_t N = rn * LIMB_BITS; // 总比特数
633 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
634 lmmp_debug_assert(!(N & (K - 1)));
635 mp_size_t M = N >> k; // 每个块的比特数(N/K)
636 mp_size_t n = 2 * M + k + 2; // 扩展系数长度(保证归一化)
637
638 // 规整n:必须是LIMB_BITS和K的整数倍
639 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
640 n = (((n - 1) >> k) + 1) << k;
641
642 ms->lenw = n / LIMB_BITS;
643 mp_size_t nlen = ms->lenw + 1;
644
645 ms->temp_coef = (mp_ptr)lmmp_fft_memstack_(ms, (((nlen + 1) << (k + nsqr)) + nlen) * LIMB_BYTES);
646 mp_ptr *pfca = (mp_ptr*)(ms->temp_coef + nlen), *pfcb = pfca;
647 for (mp_size_t i = 0; i < K; ++i) pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
648 if (nsqr) {
649 pfcb += (nlen + 1) << k;
650 for (mp_size_t i = 0; i < K; ++i) pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
651 }
652
653 for (mp_size_t j = 0; j < K0; ++j) {
654 mp_ptr numa = pc1[j];
655 mp_ptr numb = pc2[j];
656
657 for (mp_size_t i = 0; i < K; ++i) {
658 lmmp_fft_extract_coef_(pfca[i], numa, M * i, M + (i == K - 1), ms->lenw);
659 if (i > 0)
660 lmmp_fft_shl_coef_(ms, pfca + i, i * n >> k);
661 }
662 lmmp_fft_(ms, pfca, k, n >> (k - 1));
663
664 if (nsqr) {
665 for (mp_size_t i = 0; i < K; ++i) {
666 lmmp_fft_extract_coef_(pfcb[i], numb, M * i, M + (i == K - 1), ms->lenw);
667 if (i > 0)
668 lmmp_fft_shl_coef_(ms, pfcb + i, i * n >> k);
669 }
670 lmmp_fft_(ms, pfcb, k, n >> (k - 1));
671 }
672
673 // dot product
675
676 lmmp_ifft_(ms, pfca, k, n >> (k - 1));
677
679 }
681 }
682
683 ms->temp_coef = push_temp_coef;
684 ms->lenw = rn;
685}
686
688 int nsqr = numa != numb || na != nb; // 判断是否为平方运算
689 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
691 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
692 lmmp_debug_assert(!(N & (K - 1)));
693 mp_size_t M = N >> k; // 每个块的比特数
694 mp_size_t n = 2 * M + k + 2; // 扩展系数长度
695
696 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
697 n = (((n - 1) >> k) + 1) << k;
698
699 // 初始化内存栈
701 msr.maxdepth = -1;
702 msr.tempdepth = -1;
703 msr.lenw = n / LIMB_BITS;
704 mp_size_t nlen = msr.lenw + 1;
705
706 msr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&msr, (((nlen + 1) << (k + nsqr)) + nlen) * LIMB_BYTES);
707
708 mp_ptr *pfca = (mp_ptr*)(msr.temp_coef + nlen), *pfcb = pfca;
710
711 for (mp_size_t i = 0; i < K; ++i) {
713 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
714 if (narest > 0) {
715 coeflen = M + (i == K - 1);
717 narest -= coeflen;
719 if (i > 0)
720 lmmp_fft_shl_coef_(&msr, pfca + i, i * n >> k);
721 } else {
722 lmmp_zero(pfca[i], nlen);
723 }
724 }
725 lmmp_fft_(&msr, pfca, k, n >> (k - 1));
726
727 if (nsqr) {
728 pfcb += (nlen + 1) << k;
729 for (mp_size_t i = 0; i < K; ++i) {
731 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
732 if (nbrest > 0) {
733 coeflen = M + (i == K - 1);
735 nbrest -= coeflen;
737 if (i > 0)
738 lmmp_fft_shl_coef_(&msr, pfcb + i, i * n >> k);
739 } else {
740 lmmp_zero(pfcb[i], nlen);
741 }
742 }
743 lmmp_fft_(&msr, pfcb, k, n >> (k - 1));
744 }
745
747
748 lmmp_ifft_(&msr, pfca, k, n >> (k - 1));
749
751
752 // 处理模 B^rn+1 的溢出
753 if (dst[rn] && !lmmp_zero_q_(dst, rn)) {
754 dst[rn] = 0;
755 lmmp_dec(dst);
756 }
757
759}
760
762 int nsqr = numa != numb || na != nb; // 判断是否为平方运算
763 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
764 mp_size_t k = lmmp_fft_best_k_(rn); // 最优FFT层数
765 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
766 // 断言:N必须是K的整数倍
767 lmmp_debug_assert(!(N & (K - 1)));
768 mp_size_t M = N >> k; // 每个块的比特数
769 mp_size_t n = 2 * M + k; // 扩展系数长度(梅森数比费马数少2)
770
771 // 规整n:必须是LIMB_BITS和K/2的整数倍
772 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
773 n = (((n - 1) >> (k - 1)) + 1) << (k - 1);
774
775 // 初始化内存栈
777 msr.maxdepth = -1;
778 msr.tempdepth = -1;
779 msr.lenw = n / LIMB_BITS;
780 mp_size_t nlen = msr.lenw + 1;
781
782 msr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&msr, (((nlen + 1) << (k + nsqr)) + nlen) * LIMB_BYTES);
783
784 mp_ptr *pfca = (mp_ptr*)(msr.temp_coef + nlen), *pfcb = pfca;
786
787 for (mp_size_t i = 0; i < K; ++i) {
789 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
790 if (narest > 0) {
792 narest -= coeflen;
794 } else {
795 lmmp_zero(pfca[i], nlen);
796 }
797 }
798 lmmp_fft_(&msr, pfca, k, n >> (k - 1));
799
800 if (nsqr) {
801 pfcb += (nlen + 1) << k;
802 for (mp_size_t i = 0; i < K; ++i) {
804 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
805 if (nbrest > 0) {
807 nbrest -= coeflen;
809 } else {
810 lmmp_zero(pfcb[i], nlen);
811 }
812 }
813 lmmp_fft_(&msr, pfcb, k, n >> (k - 1));
814 }
815
817
818 lmmp_ifft_(&msr, pfca, k, n >> (k - 1));
819
820 mp_size_t rhead = 0, maxc = 0;
821 for (mp_size_t i = 0; i < K; ++i) {
823 mp_ptr nums = pfca[i];
824
825 if (nums[nlen - 1]) {
826 lmmp_dec(nums);
827 lmmp_debug_assert(nums[nlen - 1] == 1);
828 nums[nlen - 1] = 0;
829 }
830
831 mp_size_t roffset = i * M;
832 mp_size_t shl = roffset & (LIMB_BITS - 1);
834
835 if (shl)
837
838 if (i == 0) {
840 rhead = nlen;
841 } else if (roffset + nlen <= rn) {
843 rhead = roffset + nlen;
844 } else {
846 maxc += lmmp_add_(dst, dst, rn, nums + rn - roffset, nlen + roffset - rn);
847 rhead = rn;
848 }
849 }
850
851 if (!lmmp_add_1_(dst, dst, rn, 1 + maxc))
852 lmmp_dec(dst);
853
855}
856
857typedef struct {
862 int fermat_flag; // 是否分配了费马内存
863 int mersenne_flag; // 是否分配了梅森内存
864} fft_cache;
865
867 if (GH->fermat_flag)
868 lmmp_fft_memstack_(&GH->msr_fermat, 0);
869 if (GH->mersenne_flag)
870 lmmp_fft_memstack_(&GH->msr_mersenne, 0);
871}
872
873/*
874FIXME: 可以将固定的临时memstack移动到缓存中,而非每次都进行重新分配,另一个优化点可以是,将重复计算的一些值也移入到
875 缓存中,只需要初始化一次即可。建议分成初始化函数和循环计算函数。
876*/
877
879 mp_ptr dst,
886) {
887 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
889 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
890 lmmp_debug_assert(!(N & (K - 1)));
891 mp_size_t M = N >> k; // 每个块的比特数
892 mp_size_t n = 2 * M + k + 2; // 扩展系数长度
893
894 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
895 n = (((n - 1) >> k) + 1) << k;
896
899 amsr.maxdepth = -1;
900 amsr.tempdepth = -1;
901 amsr.lenw = n / LIMB_BITS;
902 mp_size_t nlen = amsr.lenw + 1;
903 mp_size_t a_size = (((nlen + 1) << (k)) + nlen) * LIMB_BYTES;
904 mp_size_t b_size = (((nlen + 1) << (k)) + nlen) * LIMB_BYTES;
905 amsr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&amsr, a_size);
906
907 mp_ptr* pfca = (mp_ptr*)(amsr.temp_coef + nlen);
908 mp_ptr* pfcb = NULL;
909
910 if (GH->fermat_flag) {
911 bmsr = &GH->msr_fermat;
912 bmsr->lenw = n / LIMB_BITS;
913 pfcb = (mp_ptr*)(GH->temp_coef_fermat + nlen);
914 } else {
915 bmsr = &GH->msr_fermat;
916 bmsr->maxdepth = -1;
917 bmsr->tempdepth = -1;
918 bmsr->lenw = n / LIMB_BITS;
919 bmsr->temp_coef = (mp_ptr)lmmp_fft_memstack_(bmsr, b_size);
920 GH->temp_coef_fermat = bmsr->temp_coef;
921 pfcb = (mp_ptr*)(bmsr->temp_coef + nlen);
922 }
923
925 for (mp_size_t i = 0; i < K; ++i) {
927 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
928 if (narest > 0) {
929 coeflen = M + (i == K - 1);
931 narest -= coeflen;
933 if (i > 0)
934 lmmp_fft_shl_coef_(&amsr, pfca + i, i * n >> k);
935 } else {
936 lmmp_zero(pfca[i], nlen);
937 }
938 }
939 lmmp_fft_(&amsr, pfca, k, n >> (k - 1));
940
941 if (!GH->fermat_flag) {
942 GH->fermat_flag = 1;
943 for (mp_size_t i = 0; i < K; ++i) {
945 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
946 if (nbrest > 0) {
947 coeflen = M + (i == K - 1);
949 nbrest -= coeflen;
951 if (i > 0)
952 lmmp_fft_shl_coef_(bmsr, pfcb + i, i * n >> k);
953 } else {
954 lmmp_zero(pfcb[i], nlen);
955 }
956 }
957 lmmp_fft_(bmsr, pfcb, k, n >> (k - 1));
958 }
959
961
962 lmmp_ifft_(&amsr, pfca, k, n >> (k - 1));
963
965
966 if (dst[rn] && !lmmp_zero_q_(dst, rn)) {
967 dst[rn] = 0;
968 lmmp_dec(dst);
969 }
970
972}
973
975 mp_ptr dst,
982) {
983 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
984 mp_size_t k = lmmp_fft_best_k_(rn); // 最优FFT层数
985 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
986 // 断言:N必须是K的整数倍
987 lmmp_debug_assert(!(N & (K - 1)));
988 mp_size_t M = N >> k; // 每个块的比特数
989 mp_size_t n = 2 * M + k; // 扩展系数长度(梅森数比费马数少2)
990
991 // 规整n:必须是LIMB_BITS和K/2的整数倍
992 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
993 n = (((n - 1) >> (k - 1)) + 1) << (k - 1);
994
995 // 初始化内存栈
998 amsr.maxdepth = -1;
999 amsr.tempdepth = -1;
1000 amsr.lenw = n / LIMB_BITS;
1001 mp_size_t nlen = amsr.lenw + 1;
1002 mp_size_t a_size = (((nlen + 1) << (k)) + nlen) * LIMB_BYTES;
1003 mp_size_t b_size = (((nlen + 1) << (k)) + nlen) * LIMB_BYTES;
1004 amsr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&amsr, a_size);
1005
1006 mp_ptr* pfca = (mp_ptr*)(amsr.temp_coef + nlen);
1007 mp_ptr* pfcb = NULL;
1008
1009 if (GH->mersenne_flag) {
1010 bmsr = &GH->msr_mersenne;
1011 bmsr->lenw = n / LIMB_BITS;
1012 pfcb = (mp_ptr*)(GH->temp_coef_mersenne + nlen);
1013 } else {
1014 bmsr = &GH->msr_mersenne;
1015 bmsr->maxdepth = -1;
1016 bmsr->tempdepth = -1;
1017 bmsr->lenw = n / LIMB_BITS;
1018 bmsr->temp_coef = (mp_ptr)lmmp_fft_memstack_(bmsr, b_size);
1019 GH->temp_coef_mersenne = bmsr->temp_coef;
1020 pfcb = (mp_ptr*)(bmsr->temp_coef + nlen);
1021 }
1022
1024
1025 for (mp_size_t i = 0; i < K; ++i) {
1027 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
1028 if (narest > 0) {
1030 narest -= coeflen;
1032 } else {
1033 lmmp_zero(pfca[i], nlen);
1034 }
1035 }
1036 lmmp_fft_(&amsr, pfca, k, n >> (k - 1));
1037
1038 if (!GH->mersenne_flag) {
1039 GH->mersenne_flag = 1;
1040 for (mp_size_t i = 0; i < K; ++i) {
1042 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
1043 if (nbrest > 0) {
1045 nbrest -= coeflen;
1047 } else {
1048 lmmp_zero(pfcb[i], nlen);
1049 }
1050 }
1051 lmmp_fft_(bmsr, pfcb, k, n >> (k - 1));
1052 }
1053
1055
1056 lmmp_ifft_(&amsr, pfca, k, n >> (k - 1));
1057
1058 mp_size_t rhead = 0, maxc = 0;
1059 for (mp_size_t i = 0; i < K; ++i) {
1061 mp_ptr nums = pfca[i];
1062
1063 if (nums[nlen - 1]) {
1064 lmmp_dec(nums);
1065 lmmp_debug_assert(nums[nlen - 1] == 1);
1066 nums[nlen - 1] = 0;
1067 }
1068
1069 mp_size_t roffset = i * M;
1070 mp_size_t shl = roffset & (LIMB_BITS - 1);
1071 roffset /= LIMB_BITS;
1072
1073 if (shl)
1075
1076 if (i == 0) {
1078 rhead = nlen;
1079 } else if (roffset + nlen <= rn) {
1081 rhead = roffset + nlen;
1082 } else {
1084 maxc += lmmp_add_(dst, dst, rn, nums + rn - roffset, nlen + roffset - rn);
1085 rhead = rn;
1086 }
1087 }
1088
1089 if (!lmmp_add_1_(dst, dst, rn, 1 + maxc))
1090 lmmp_dec(dst);
1091
1093}
1094
1096 lmmp_param_assert(na > 0 && nb > 0);
1098 mp_size_t hn = lmmp_fft_next_size_((na + nb + 1) >> 1);
1099 lmmp_assert(na + nb > hn);
1101
1103 mp_size_t nam = na;
1104 if (na > hn) {
1105 /*
1106 Z = B^hb - 1
1107 amodm = a mod Z
1108 */
1109 if (lmmp_add_(dst, numa, hn, numa + hn, na - hn))
1110 lmmp_inc(dst);
1111 amodm = dst;
1112 nam = hn;
1113 }
1115
1117 mp_size_t nap = na;
1118 if (na > hn) {
1119 /*
1120 Z = B^hp - 1
1121 amodp = a mod Z
1122 */
1123 tp[hn] = 0;
1124 if (lmmp_sub_(tp, numa, hn, numa + hn, na - hn))
1125 lmmp_inc(tp);
1126 amodp = tp;
1127 nap = hn + 1;
1128 }
1130
1132 cy <<= LIMB_BITS - 1;
1133 dst[hn - 1] += cy;
1134 if (dst[hn - 1] < cy)
1135 lmmp_inc(dst);
1136
1137 if (na + nb == 2 * hn) {
1138 cy = tp[hn] + lmmp_sub_n_(dst + hn, dst, tp, hn);
1139 // cy==1 means [tp,hn+1]!=0, then [dst,hn]!=0
1140 // cy==2 is impossible since [tp,hn+1] is normalized.
1141 // so the following dec won't overflow.
1142 lmmp_dec_1(dst, cy);
1143 } else {
1144 cy = lmmp_sub_n_(dst + hn, dst, tp, na + nb - hn);
1145 cy = tp[hn] + lmmp_sub_nc_(tp + na + nb - hn, dst + na + nb - hn, tp + na + nb - hn, 2 * hn - (na + nb), cy);
1146 cy = lmmp_sub_1_(dst, dst, na + nb, cy);
1147 }
1148 lmmp_free(tp);
1149}
1150
1152 mp_ptr dst,
1153 mp_size_t hn,
1155 mp_size_t na,
1157 mp_size_t nb,
1158 fft_cache* GH
1159) {
1160 lmmp_param_assert(na > 0 && nb > 0);
1162 lmmp_assert(na + nb > hn);
1164
1166 mp_size_t nam = na;
1167 if (na > hn) {
1168 /*
1169 Z = B^hb - 1
1170 amodm = a mod Z
1171 */
1172 if (lmmp_add_(dst, numa, hn, numa + hn, na - hn))
1173 lmmp_inc(dst);
1174 amodm = dst;
1175 nam = hn;
1176 }
1178
1180 mp_size_t nap = na;
1181 if (na > hn) {
1182 /*
1183 Z = B^hp - 1
1184 amodp = a mod Z
1185 */
1186 tp[hn] = 0;
1187 if (lmmp_sub_(tp, numa, hn, numa + hn, na - hn))
1188 lmmp_inc(tp);
1189 amodp = tp;
1190 nap = hn + 1;
1191 }
1193
1195 cy <<= LIMB_BITS - 1;
1196 dst[hn - 1] += cy;
1197 if (dst[hn - 1] < cy)
1198 lmmp_inc(dst);
1199
1200 if (na + nb == 2 * hn) {
1201 cy = tp[hn] + lmmp_sub_n_(dst + hn, dst, tp, hn);
1202 // cy==1 means [tp,hn+1]!=0, then [dst,hn]!=0
1203 // cy==2 is impossible since [tp,hn+1] is normalized.
1204 // so the following dec won't overflow.
1205 lmmp_dec_1(dst, cy);
1206 } else {
1207 cy = lmmp_sub_n_(dst + hn, dst, tp, na + nb - hn);
1208 cy = tp[hn] + lmmp_sub_nc_(tp + na + nb - hn, dst + na + nb - hn, tp + na + nb - hn, 2 * hn - (na + nb), cy);
1209 cy = lmmp_sub_1_(dst, dst, na + nb, cy);
1210 }
1211 lmmp_free(tp);
1212}
1213
1217 mp_size_t na,
1220) {
1221 lmmp_param_assert(na >= 3 * nb);
1223 mp_size_t sna = 3 * nb;
1224 mp_size_t hn = lmmp_fft_next_size_((sna + nb + 1) >> 1);
1225 sna = (hn << 1) - 1 - nb;
1226 fft_cache GH = {.mersenne_flag = 0, .fermat_flag = 0};
1228 dst += sna;
1229 numa += sna;
1230 na -= sna;
1231 lmmp_copy(ws, dst, nb);
1232 while (na >= sna) {
1234 if (lmmp_add_n_(dst, dst, ws, nb))
1235 lmmp_inc(dst + nb);
1236 dst += sna;
1237 numa += sna;
1238 na -= sna;
1239 lmmp_copy(ws, dst, nb);
1240 }
1242 // remaining na < sna
1243 if (na >= nb)
1244 lmmp_mul_(dst, numa, na, numb, nb);
1245 else if (na > 0)
1246 lmmp_mul_(dst, numb, nb, numa, na);
1247 else // na == 0
1248 lmmp_zero(dst, nb);
1249 if (lmmp_add_n_(dst, dst, ws, nb))
1250 lmmp_inc(dst + nb);
1251 lmmp_free(ws);
1252}
#define k
#define l
#define lmmp_mul_n_
Definition inlines.h:167
#define lmmp_sqr_
Definition inlines.h:166
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#define lmmp_zero(dst, n)
Definition lmmp.h:369
uint64_t mp_size_t
Definition lmmp.h:77
int64_t mp_slimb_t
Definition lmmp.h:78
#define lmmp_debug_assert(x)
Definition lmmp.h:390
void * lmmp_alloc(size_t size)
内存分配函数(调用lmmp_heap_alloc_fn)
Definition memory.c:164
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
#define LIMB_MAX
Definition lmmp.h:89
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
Definition memory.c:202
int64_t mp_ssize_t
Definition lmmp.h:79
uint64_t mp_limb_t
Definition lmmp.h:76
#define lmmp_assert(x)
Definition lmmp.h:373
#define LMMP_MIN(l, o)
Definition lmmp.h:351
#define LIMB_BITS
Definition lmmp.h:86
#define LOG2_LIMB_BITS
Definition lmmp.h:88
#define lmmp_param_assert(x)
Definition lmmp.h:401
mp_limb_t lmmp_shlnot_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
左移后按位取反操作 [dst,na] = ~([numa,na] << shl),dst的低shl位填充1
static mp_limb_t lmmp_add_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数加法静态内联函数 [dst,na]=[numa,na]+[numb,nb]
Definition lmmpn.h:1050
mp_limb_t lmmp_shr1add_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带进位加法后右移1位 [dst,n] = ([numa,n] + [numb,n] + c) >> 1
Definition shr.c:89
mp_limb_t lmmp_shr_c_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr, mp_limb_t c)
带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位
Definition shr.c:40
#define lmmp_dec(p)
大数减1宏(预期无借位)
Definition lmmpn.h:965
static mp_limb_t lmmp_add_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数加单精度数静态内联函数 [dst,na]=[numa,na]+x
Definition lmmpn.h:1103
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
mp_limb_t lmmp_shr_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr)
大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
Definition shr.c:19
void lmmp_mul_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
不等长大数乘法操作 [dst,na+nb] = [numa,na] * [numb,nb]
mp_limb_t lmmp_shl_c_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl, mp_limb_t c)
带进位的大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充c的低shl位
Definition shl.c:42
mp_limb_t lmmp_add_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c
Definition add_n.c:19
mp_limb_t lmmp_shl_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
Definition shl.c:19
static mp_limb_t lmmp_sub_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]
Definition lmmpn.h:1064
#define lmmp_dec_1(p, dec)
大数减指定值宏(预期无借位)
Definition lmmpn.h:977
static mp_limb_t lmmp_sub_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
Definition lmmpn.h:1114
void lmmp_not_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)
mp_limb_t lmmp_sub_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
Definition sub_n.c:80
#define lmmp_inc_1(p, inc)
大数加指定值宏(预期无进位)
Definition lmmpn.h:950
mp_limb_t lmmp_sub_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
Definition sub_n.c:19
mp_limb_t lmmp_add_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
Definition add_n.c:81
static int lmmp_zero_q_(mp_srcptr p, mp_size_t n)
大数判零函数(内联)
Definition lmmpn.h:1019
#define MUL_FFT_MODF_THRESHOLD
Definition mparam.h:65
#define PART_SIZE
Definition mparam.h:89
#define LIMB_BYTES
Definition mparam.h:85
static void lmmp_fft_shr_coef_(fft_memstack *ms, mp_ptr *coef, mp_size_t shr)
对模 2^n+1 的系数执行右移操作 右移shr位 = 左移(2n - shr)位(mod 2^n+1的循环特性)
Definition mul_fft.c:228
void lmmp_mul_mersenne_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
Definition mul_fft.c:761
mp_ptr temp_coef
Definition mul_fft.c:71
mp_ssize_t maxdepth
Definition mul_fft.c:73
static void lmmp_mul_fermat_recurse_(fft_memstack *ms, mp_ptr *pc1, mp_ptr *pc2, mp_size_t K0)
费马变换乘法递归函数(核心乘法逻辑)
Definition mul_fft.c:611
static void lmmp_mul_mersenne_single_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, fft_cache *GH)
Definition mul_fft.c:974
static void lmmp_ifft_bfy_(fft_memstack *ms, mp_ptr *coef, mp_size_t wing, mp_size_t w)
FFT蝶形运算(Butterfly Operation) (a,b) = (a+(b>>w), a-(b>>w)) mod 2^n+1 a=[coef[0],ms->lenw+1],...
Definition mul_fft.c:324
static void lmmp_fft_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:453
#define _FFT_TABLE_ENTRY4(n)
Definition mul_fft.c:24
void lmmp_mul_fft_unbalance_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na, mp_srcptr restrict numb, mp_size_t nb)
Definition mul_fft.c:1214
static void * lmmp_fft_memstack_(fft_memstack *ms, mp_size_t size)
FFT内存栈的分配/释放接口
Definition mul_fft.c:109
static void lmmp_fft_shl_coef_(fft_memstack *ms, mp_ptr *coef, mp_size_t shl)
对模 2^n+1 的系数执行左移操作
Definition mul_fft.c:161
mp_ptr temp_coef_mersenne
Definition mul_fft.c:861
static void lmmp_mul_fft_cache_(mp_ptr dst, mp_size_t hn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, fft_cache *GH)
Definition mul_fft.c:1151
static void lmmp_mul_fermat_recombine_(fft_memstack *ms, mp_ptr dst, mp_ptr *pfca, mp_size_t K, mp_size_t k, mp_size_t n, mp_size_t M, mp_size_t rn)
费马变换 模 B^n+1 乘法的结果合并
Definition mul_fft.c:528
static void lmmp_ifft_b1_(fft_memstack *ms, mp_ptr *coef, mp_size_t dis, mp_size_t k, mp_size_t w, mp_size_t w0)
Definition mul_fft.c:464
void lmmp_mul_fermat_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1
Definition mul_fft.c:687
static void lmmp_mul_fft_cache_free_(fft_cache *GH)
Definition mul_fft.c:866
static void lmmp_ifft_4_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:485
static void lmmp_fft_bfy_(fft_memstack *ms, mp_ptr *coef, mp_size_t wing, mp_size_t w)
FFT蝶形运算(Butterfly Operation) (a,b) = (a + b, (a-b) << w ) mod 2^n+1 a=[coef[0],ms->lenw+1],...
Definition mul_fft.c:244
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算FFT运算所需的最小规整化长度(向上取整到2^k的倍数)
Definition mul_fft.c:95
static mp_size_t lmmp_fft_best_k_(mp_size_t n)
查找对于 m>=n 的模 B^m+1 FFT运算的最优k值
Definition mul_fft.c:84
static void lmmp_ifft_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:506
static void lmmp_fft_extract_coef_(mp_ptr dst, mp_srcptr numa, mp_size_t bitoffset, mp_size_t bits, mp_size_t lenw)
[dst,lenw+1] = [(bit*)numa+bitoffset, bits]
Definition mul_fft.c:135
mp_ssize_t tempdepth
Definition mul_fft.c:74
static const mp_size_t lmmp_fft_table_[][2]
Definition mul_fft.c:30
int fermat_flag
Definition mul_fft.c:862
int mersenne_flag
Definition mul_fft.c:863
fft_memstack msr_mersenne
Definition mul_fft.c:859
fft_memstack msr_fermat
Definition mul_fft.c:858
void lmmp_mul_fft_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
FFT乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
Definition mul_fft.c:1095
mp_size_t lenw
Definition mul_fft.c:72
static void lmmp_fft_b1_(fft_memstack *ms, mp_ptr *coef, mp_size_t dis, mp_size_t k, mp_size_t w, mp_size_t w0)
FFT递归函数
Definition mul_fft.c:411
static void lmmp_fft_4_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:432
mp_ptr temp_coef_fermat
Definition mul_fft.c:860
static void lmmp_mul_fermat_single_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, fft_cache *GH)
Definition mul_fft.c:878
#define numb
#define tp
#define n
#define w0
#define ALLOC_TYPE(n, type)
Definition tmp_alloc.h:173