LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
lmmpn.h
浏览该文件的文档.
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/*
17 本库的实现部分灵感来源于或改编自
18
19 GNU-MP (https://gmplib.org/),
20 FLINT (https://www.flintlib.org/),
21
22 符号说明:
23
24 B 基数,固定为 2^64
25
26 [p,n,b] 表示指针p指向的、以b为基数的n位数
27 p[i-1] 代表其第i位最低有效位 (0<i<=n)
28 如果省略b,则默认基数为B。通常情况下,
29 用此符号表示函数参数时,一般暗指高位不存在0,
30 而用此符号表示函数返回值时,表示将会写入的区间,
31 即使可能写入为0。
32
33 sep 指针指向的内存区域完全分离
34
35 eqsep 完全相同的内存区域或者完全分离
36
37 备注:我们都假定地址是向上增长的,dst <= num+1
38 的内存布局可以这样表示
39 dst ──┐
40 num ──┐ |00000000|00000000|
41 |********|********|
42
43 MSB(x) x的最高有效位,比如最高有效位为1,MSB(x)=1
44 代表 x >= B / 2
45
46 [x|y] x或y,用于表示参数或返回值的取值范围
47*/
48
49#ifndef LAMMP_LMMPN_H
50#define LAMMP_LMMPN_H
51
52#include <stdbool.h>
53#include "lmmp.h"
54
55#define INLINE_ static inline
56
57#ifdef __cplusplus
58extern "C" {
59#endif
60
61/**
62 * @brief 运行时判断端序
63 * @return true 表示小端序,false 表示大端序
64 */
65INLINE_ bool lmmp_endian(void) {
66 int num = 1;
67 return (*(char*)&num) == 0;
68}
69
70/**
71 * @brief 计算满足 2^k > x 的最小自然数k
72 * @param x 输入的64位无符号整数
73 * @return 满足条件的最小自然数k
74 */
76
77/**
78 * @brief 计算一个64位无符号整数中1的个数
79 * @param x 输入的64位无符号整数
80 * @return 1的个数
81 */
83
84/**
85 * @brief 计算一个单精度数(limb)中前导零的个数
86 * @param x 输入的64位无符号整数
87 * @return 前导零的位数(范围:0~64)
88 */
90
91/**
92 * @brief 计算一个单精度数(limb)中末尾零的个数
93 * @param x 输入的64位无符号整数
94 * @return 末尾零的位数(范围:0~64)
95 */
97
98/**
99 * @brief 计算两个64位无符号整数相乘的高位结果 (a*b)/B
100 * @param a 第一个64位无符号整数
101 * @param b 第二个64位无符号整数
102 * @return 乘积的高64位结果
103 */
105
106/**
107 * @brief 计算两个64位无符号整数相乘的128位结果 (a*b)
108 * @param dst 输出结果缓冲区,存储乘积结果,长度为 2
109 * @param a 第一个64位无符号整数
110 * @param b 第二个64位无符号整数
111 * @warning dst 必须指向一个长度为 2 的数组
112 * @return 无返回值
113 */
115
116/**
117 * @brief 带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c
118 * @param dst 结果输出指针
119 * @param numa 第一个加数指针
120 * @param numb 第二个加数指针
121 * @param n limb长度
122 * @param c 初始进位值 [0|1]
123 * @warning c=[0|1], n>0, eqsep(dst,[numa|numb])
124 * @return 运算后的最终进位值 [0|1]
125 */
127
128/**
129 * @brief 无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
130 * @param dst 结果输出指针
131 * @param numa 第一个加数指针
132 * @param numb 第二个加数指针
133 * @param n limb长度
134 * @warning n>0, eqsep(dst,[numa|numb])
135 * @return 运算后的最终进位值 [0|1]
136 */
138
139/**
140 * @brief 带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
141 * @param dst 结果输出指针
142 * @param numa 被减数指针
143 * @param numb 减数指针
144 * @param n limb长度
145 * @param c 初始借位值 [0|1]
146 * @warning c=[0|1], n>0, eqsep(dst,[numa|numb])
147 * @return 运算后的最终借位值 [0|1]
148 */
150
151/**
152 * @brief 无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
153 * @param dst 结果输出指针
154 * @param numa 被减数指针
155 * @param numb 减数指针
156 * @param n limb长度
157 * @warning n>0, eqsep(dst,[numa|numb])
158 * @return 运算后的最终借位值 [0|1]
159 */
161
162/**
163 * @brief 同时执行n位加法和减法 ([dsta,n],[dstb,n]) = ([numa,n]+[numb,n],[numa,n]-[numb,n])
164 * @param dsta 加法结果输出指针
165 * @param dstb 减法结果输出指针
166 * @param numa 第一个操作数指针(被加数/被减数)
167 * @param numb 第二个操作数指针(加数/减数)
168 * @param n limb长度
169 * @warning n>0, eqsep(dsta,[numa|numb]), eqsep(dstb,[numa|numb])
170 * @return 组合返回值 cb = 2*c + b (c为加法进位, b为减法借位)
171 * 返回值范围: 0(无进位无借位),1(无进位有借位),2(有进位无借位),3(有进位有借位)
172 */
174
175/**
176 * @brief 加法后右移1位 [dst,n] = ([numa,n] + [numb,n]) >> 1
177 * @param dst 结果输出指针
178 * @param numa 第一个加数指针
179 * @param numb 第二个加数指针
180 * @param n limb长度
181 * @warning n>0, eqsep(dst,[numa|numb])
182 * @return 右移操作产生的进位值 [0|1]
183 */
185
186/**
187 * @brief 带进位加法后右移1位 [dst,n] = ([numa,n] + [numb,n] + c) >> 1
188 * @param dst 结果输出指针
189 * @param numa 第一个加数指针
190 * @param numb 第二个加数指针
191 * @param n limb长度
192 * @param c 初始进位值 [0|1]
193 * @warning n>0, c=[0|1], eqsep(dst,[numa|numb])
194 * @return 右移操作产生的进位值 [0|1]
195 */
197
198/**
199 * @brief 减法后右移1位 [dst,n] = ([numa,n] - [numb,n]) >> 1
200 * @param dst 结果输出指针
201 * @param numa 被减数指针
202 * @param numb 减数指针
203 * @param n 操作数的位数(limb数量)
204 * @warning n>0, eqsep(dst,[numa|numb])
205 * @return 右移操作产生的进位值 (0或1)
206 */
208
209/**
210 * @brief 带借位减法后右移1位 [dst,n] = ([numa,n] - [numb,n] - c) >> 1
211 * @param dst 结果输出指针
212 * @param numa 被减数指针
213 * @param numb 减数指针
214 * @param n limb长度
215 * @param c 初始借位值 [0|1]
216 * @warning n>0, c=[0|1], eqsep(dst,[numa|numb])
217 * @return 右移操作产生的进位值 [0|1]
218 */
220
221/**
222 * @brief 大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
223 * @param dst 结果输出指针
224 * @param numa 源操作数指针
225 * @param na limb长度
226 * @param shr 右移的位数 (0~63)
227 * @warning na>0, 0<=shr<64, eqsep(dst,numa)
228 * 允许dst指针地址小于numa(即支持原地长移位操作)
229 * @return 其最高shr个比特位填充[numa,na]被移出的shr个最低位,其余比特位为0
230 */
232
233/**
234 * @brief 带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位
235 * @param dst 结果输出指针
236 * @param numa 源操作数指针
237 * @param na limb长度
238 * @param shr 右移的位数 (0~63)
239 * @param c 进位值(其低(64-shr)位必须为0)
240 * @warning na>0, 0<=shr<64, eqsep(dst,numa)
241 * c的低(64-shr)位必须为0
242 * 允许dst指针地址小于numa(即支持原地长移位操作)
243 * @return 其最高shr个比特位填充[numa,na]被移出的shr个最低位,其余比特位为0
244 */
246
247/**
248 * @brief 大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
249 * @param dst 结果输出指针
250 * @param numa 源操作数指针
251 * @param na limb长度
252 * @param shl 左移的位数 (0~63)
253 * @warning na>0, 0<=shl<64, eqsep(dst,numa)
254 * 允许dst指针地址大于numa(即支持原地长移位操作)
255 * @return 其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0
256 */
258
259/**
260 * @brief 带进位的大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充c的低shl位
261 * @param dst 结果输出指针
262 * @param numa 源操作数指针
263 * @param na limb长度
264 * @param shl 左移的位数 (0~63)
265 * @param c 进位值(其高(64-shl)位必须为0)
266 * @warning na>0, 0<=shl<64, eqsep(dst,numa)
267 * c的高(64-shl)位必须为0
268 * 允许dst指针地址大于numa(即支持原地长移位操作)
269 * @return 其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0
270 */
272
273/**
274 * @brief 大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)
275 * @param dst 结果输出指针
276 * @param numa 源操作数指针
277 * @param na limb长度
278 * @warning na>0, eqsep(dst,numa)
279 */
281
282/**
283 * @brief 左移后按位取反操作 [dst,na] = ~([numa,na] << shl),dst的低shl位填充1
284 * @param dst 结果输出指针
285 * @param numa 源操作数指针
286 * @param na limb长度
287 * @param shl 左移的位数 (0~63)
288 * @warning na>0, 0<=shl<64, eqsep(dst,numa)
289 * @return 其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0
290 */
292
293/**
294 * @brief 加法结合左移1位操作 [dst,n] = [numa,n] + ([numb,n] << 1)
295 * @param dst 结果输出指针
296 * @param numa 被加数指针
297 * @param numb 加数指针(先左移1位)
298 * @param n limb长度
299 * @warning n>0, eqsep(dst,[numa|numb])
300 * @return 运算后的进位值 [0|1|2]
301 */
303
304/**
305 * @brief 减法结合左移1位操作 [dst,n] = [numa,n] - ([numb,n] << 1)
306 * @param dst 结果输出指针
307 * @param numa 被减数指针
308 * @param numb 减数指针(先左移1位)
309 * @param n limb长度
310 * @warning n>0, eqsep(dst,[numa|numb])
311 * @return 运算后的借位值 [0|1|2]
312 */
314
315/**
316 * @brief 大数乘以单limb并累加操作 [numa,n] += [numb,n] * b
317 * @param numa 被加数指针(结果也存储在此)
318 * @param numb 乘数指针
319 * @param n limb长度
320 * @param b 乘数
321 * @warning n>0, eqsep(numa,numb))
322 * @return 运算后的进位limb值
323 */
325
326/**
327 * @brief 大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b
328 * @param numa 被减数指针(结果也存储在此)
329 * @param numb 乘数指针
330 * @param n limb长度
331 * @param b 乘数
332 * @warning n>0, eqsep(numa,numb))
333 * @return 运算后的借位limb值
334 */
336
337/**
338 * @brief 大数乘以单limb操作 [dst,na] = [numa,na] * x
339 * @param dst 结果输出指针
340 * @param numa 被乘数指针
341 * @param na 操作数的位数(limb数量)
342 * @param x 单个limb乘数
343 * @warning na>0, eqsep(dst,numa)
344 * 支持 dst<=numa+1 的内存布局
345 * @return 运算后的进位limb值
346 */
348
349/**
350 * @brief 基础平方运算 [dst,2*na] = [numa,na]^2
351 * @param dst 输出结果缓冲区,长度至少为2*na
352 * @param numa 输入操作数,长度为na
353 * @param na 输入操作数的 limb 长度
354 * @warning 0<na, sep(dst,numa)
355 * @return 无返回值,结果存储在dst中
356 */
358
359/**
360 * @brief Toom-2平方运算 [dst,2*na] = [numa,na]^2
361 * @param dst 输出结果缓冲区,长度至少为 2*na
362 * @param numa 输入操作数,长度为na
363 * @param na 输入操作数的 limb 长度
364 * @warning ??<na, sep(dst,numa)
365 * @return 无返回值,结果存储在dst中
366 */
368
369/**
370 * @brief Toom-3平方运算 [dst,2*na] = [numa,na]^2
371 * @param dst 输出结果缓冲区,长度至少为2*na
372 * @param numa 输入操作数,长度为na
373 * @param na 输入操作数的单精度数(limb)长度
374 * @warning ??<na, sep(dst,numa)
375 * @return 无返回值,结果存储在dst中
376 */
378
379/**
380 * @brief Toom-4平方运算 [dst,2*na] = [numa,na]^2
381 * @param dst 输出结果缓冲区,长度至少为2*na
382 * @param numa 输入操作数,长度为na
383 * @param na 输入操作数的单精度数(limb)长度
384 * @warning ??<na, sep(dst,numa)
385 * @return 无返回值,结果存储在dst中
386 */
388
389/**
390 * @brief 基础乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
391 * @param dst 输出结果缓冲区,长度至少为 na+nb
392 * @param numa 第一个输入操作数,长度为 na
393 * @param na 第一个操作数的 limb 长度
394 * @param numb 第二个输入操作数,长度为 nb
395 * @param nb 第二个操作数的 limb 长度
396 * @warning 0<nb<=na, sep(dst,[numa|numb])
397 * @return 无返回值,结果存储在dst中
398 */
400
401/**
402 * @brief Toom-22乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
403 * @param dst 输出结果缓冲区,长度至少为 na+nb
404 * @param numa 第一个输入操作数,长度为 na
405 * @param na 第一个操作数的 limb 长度
406 * @param numb 第二个输入操作数,长度为 nb
407 * @param nb 第二个操作数的 limb 长度
408 * @warning 4/5<=nb/na<=1, nb>=5, sep(dst,[numa|numb])
409 * @return 无返回值,结果存储在dst中
410 */
412
413/**
414 * @brief Toom-32乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
415 * @param dst 输出结果缓冲区,长度至少为 na+nb
416 * @param numa 第一个输入操作数,长度为 na
417 * @param na 第一个操作数的 limb 长度
418 * @param numb 第二个输入操作数,长度为 nb
419 * @param nb 第二个操作数的 limb 长度
420 * @warning 5/9<=nb/na<=4/5, nb>=12, sep(dst,[numa|numb])
421 * @return 无返回值,结果存储在dst中
422 */
424
425/**
426 * @brief Toom-33乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
427 * @param dst 输出结果缓冲区,长度至少为 na+nb
428 * @param numa 第一个输入操作数,长度为 na
429 * @param na 第一个操作数的 limb 长度
430 * @param numb 第二个输入操作数,长度为 nb
431 * @param nb 第二个操作数的 limb 长度
432 * @warning 4/5<=nb/na<=1, nb>=26, sep(dst,[numa|numb])
433 * @return 无返回值,结果存储在dst中
434 */
436
437/**
438 * @brief Toom-42乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
439 * @param dst 输出结果缓冲区,长度至少为 na+nb
440 * @param numa 第一个输入操作数,长度为 na
441 * @param na 第一个操作数的 limb 长度
442 * @param numb 第二个输入操作数,长度为 nb
443 * @param nb 第二个操作数的 limb 长度
444 * @warning 1/3<=nb/na<=5/9, nb>=20, sep(dst,[numa|numb])
445 * @return 无返回值,结果存储在dst中
446 */
448
449/**
450 * @brief Toom-42不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
451 * @param dst 输出结果缓冲区,长度至少为 na+nb
452 * @param numa 第一个输入操作数,长度为 na
453 * @param na 第一个操作数的 limb 长度
454 * @param numb 第二个输入操作数,长度为 nb
455 * @param nb 第二个操作数的 limb 长度
456 * @warning na>=3*nb, nb>=20, sep(dst,[numa|numb])
457 * @return 无返回值,结果存储在dst中
458 */
460
461/**
462 * @brief Toom-43乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
463 * @param dst 输出结果缓冲区,长度至少为 na+nb
464 * @param numa 第一个输入操作数,长度为 na
465 * @param na 第一个操作数的 limb 长度
466 * @param numb 第二个输入操作数,长度为 nb
467 * @param nb 第二个操作数的 limb 长度
468 * @warning 3/5<=nb/na<=4/5, nb>=??, sep(dst,[numa|numb])
469 * @return 无返回值,结果存储在dst中
470 */
472
473/**
474 * @brief Toom-44乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
475 * @param dst 输出结果缓冲区,长度至少为 na+nb
476 * @param numa 第一个输入操作数,长度为 na
477 * @param na 第一个操作数的 limb 长度
478 * @param numb 第二个输入操作数,长度为 nb
479 * @param nb 第二个操作数的 limb 长度
480 * @warning 4/5<=nb/na<=1, nb>=??, sep(dst,[numa|numb])
481 * @return 无返回值,结果存储在dst中
482 */
484
485/**
486 * @brief Toom-52乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
487 * @param dst 输出结果缓冲区,长度至少为 na+nb
488 * @param numa 第一个输入操作数,长度为 na
489 * @param na 第一个操作数的 limb 长度
490 * @param numb 第二个输入操作数,长度为 nb
491 * @param nb 第二个操作数的 limb 长度
492 * @warning 1/3<=nb/na<=9/20, nb>=??, sep(dst,[numa|numb])
493 * @return 无返回值,结果存储在dst中
494 */
496
497/**
498 * @brief Toom-53乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
499 * @param dst 输出结果缓冲区,长度至少为 na+nb
500 * @param numa 第一个输入操作数,长度为 na
501 * @param na 第一个操作数的 limb 长度
502 * @param numb 第二个输入操作数,长度为 nb
503 * @param nb 第二个操作数的 limb 长度
504 * @warning 9/20<=nb/na<=3/5, nb>=??, sep(dst,[numa|numb])
505 * @return 无返回值,结果存储在dst中
506 */
508
509/**
510 * @brief Toom-62乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
511 * @param dst 输出结果缓冲区,长度至少为 na+nb
512 * @param numa 第一个输入操作数,长度为 na
513 * @param na 第一个操作数的 limb 长度
514 * @param numb 第二个输入操作数,长度为 nb
515 * @param nb 第二个操作数的 limb 长度
516 * @warning 1/5<=nb/na<=1/3, nb>=??, sep(dst,[numa|numb])
517 * @return 无返回值,结果存储在dst中
518 */
520
521/**
522 * @brief Toom-62不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
523 * @param dst 输出结果缓冲区,长度至少为 na+nb
524 * @param numa 第一个输入操作数,长度为 na
525 * @param na 第一个操作数的 limb 长度
526 * @param numb 第二个输入操作数,长度为 nb
527 * @param nb 第二个操作数的 limb 长度
528 * @warning na>=5*nb, nb>=??, sep(dst,[numa|numb])
529 * @return 无返回值,结果存储在dst中
530 */
532
533/**
534 * @brief 计算满足 >=n 的最小费马/梅森乘法可行尺寸
535 * @param n 输入的目标尺寸
536 * @return 满足条件的SSA乘法最小尺寸
537 */
539
540/**
541 * @brief 费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1
542 * @param dst 输出结果缓冲区,长度至少为 rn+1
543 * @param rn 模运算的阶数参数,rn = lmmp_fft_next_size_((na + nb + 1) >> 1)
544 * @param numa 第一个输入操作数,长度为 na
545 * @param na 第一个操作数的 limb 长度
546 * @param numb 第二个输入操作数,长度为 nb
547 * @param nb 第二个操作数的 limb 长度
548 * @warning eqsep(dst,[numa|numb]), 0<=[numa,na]<2*B^rn, 0<=[numb,nb]<2*B^rn, rn = lmmp_fft_next_size_((na+nb+1)>>1)
549 * @return 无返回值,结果存储在dst中
550 */
552
553/**
554 * @brief 梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
555 * @param dst 输出结果缓冲区,长度至少为 rn
556 * @param rn 模运算的阶数参数,rn = lmmp_fft_next_size_((na + nb + 1) >> 1)
557 * @param numa 第一个输入操作数,长度为 na
558 * @param na 第一个操作数的 limb 长度
559 * @param numb 第二个输入操作数,长度为 nb
560 * @param nb 第二个操作数的 limb 长度
561 * @warning eqsep(dst,[numa|numb]), 0<=[numa,na]<B^rn, 0<=[numb,nb]<B^rn, rn = lmmp_fft_next_size_((na+nb+1)>>1)
562 * @return 无返回值,结果存储在dst中,
563 */
565
566/**
567 * @brief FFT乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
568 * @param dst 输出结果缓冲区,长度至少为 na+nb
569 * @param numa 第一个输入操作数,长度为 na
570 * @param na 第一个操作数的 limb 长度
571 * @param numb 第二个输入操作数,长度为 nb
572 * @param nb 第二个操作数的 limb 长度
573 * @warning ???<=nb<=na, sep(dst,[numa|numb])
574 * @return 无返回值,结果存储在dst中
575 */
577
578/**
579 * @brief FFT不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
580 * @param dst 输出结果缓冲区,长度至少为 na+nb
581 * @param hn FFT模域参数
582 * @param numa 第一个输入操作数,长度为 na
583 * @param na 第一个操作数的 limb 长度
584 * @param numb 第二个输入操作数,长度为 nb
585 * @param nb 第二个操作数的 limb 长度
586 * @warning ???<=nb<=na, na>=3*nb, sep(dst,[numa|numb])
587 * @return 无返回值,结果存储在dst中
588 */
590
591/**
592 * @brief 大数平方操作 [dst,2*na] = [numa,na]^2
593 * @warning na>0, sep(dst,numa)
594 * @param dst 平方结果输出指针(需要2*na的limb长度)
595 * @param numa 源操作数指针
596 * @param na limb长度
597 */
599
600/**
601 * @brief 等长大数乘法操作 [dst,2*n] = [numa,n] * [numb,n]
602 * @warning n>0, sep(dst,[numa|numb])
603 * @param dst 乘积结果输出指针(需要 2*n 的 limb 长度)
604 * @param numa 第一个乘数指针
605 * @param numb 第二个乘数指针
606 * @param n limb长度
607 */
609
610/**
611 * @brief 不等长大数乘法操作 [dst,na+nb] = [numa,na] * [numb,nb]
612 * @warning 0<nb<=na, sep(dst,[numa|numb])
613 * @param dst 乘积结果输出指针(需要 na+nb 的 limb 长度)
614 * @param numa 第一个乘数指针(较长的操作数)
615 * @param na 第一个操作数的 limb 长度
616 * @param numb 第二个乘数指针(较短的操作数)
617 * @param nb 第二个操作数的 limb 长度
618 */
620
621/**
622 * @brief 低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
623 * @param dst 输出结果缓冲区,长度至少为 n
624 * @param numa 第一个输入操作数,长度为 n
625 * @param numb 第二个输入操作数,长度为 n
626 * @param n limb长度
627 * @warning n>0, sep(dst,[numa|numb])
628 * 特殊情况:当 n >= MULLO_DC_THRESHOLD 时,eqsep(dst,[numa|numb])是允许的
629 * @return 无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n
630 */
632
633/**
634 * @brief 低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
635 * @param dst 输出结果缓冲区,长度至少为 n
636 * @param numa 第一个输入操作数,长度为 n
637 * @param numb 第二个输入操作数,长度为 n
638 * @param tp 临时缓冲区,长度至少为 2*n
639 * @param n limb长度
640 * @warning n>0, sep(dst,[numa|numb],tp)
641 * @return 无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n
642 */
644
645/**
646 * @brief 低位平方 [dst,n] = [numa,n]^2 mod B^n
647 * @param dst 输出结果缓冲区,长度至少为 n
648 * @param numa 第一个输入操作数,长度为 n
649 * @param tp 临时缓冲区,长度至少为 2*n
650 * @param n limb长度
651 * @warning n>0, sep(dst,numa,tp)
652 * @return 无返回值,结果存储在dst中,[dst,n]=[numa,n]^2 mod B^n
653 */
655
656/**
657 * @brief 低位FFT乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
658 * @param dst 输出结果缓冲区,长度至少为 n
659 * @param numa 第一个输入操作数,长度为 n
660 * @param numb 第二个输入操作数,长度为 n
661 * @param scratch 临时缓冲区,长度至少为 2*n
662 * @param n 缓冲区 limb 长度
663 * @warning ???<n, sep(scratch,[numa|numb]), eqsep(dst,scratch)
664 * @return 无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n
665 */
667
668/**
669 * @brief 1阶逆元计算 (inv1)
670 * @param x 输入的64位无符号整数,最高位为1(MSB(x)=1)
671 * @return 计算结果:(B^2-1)/x - B
672 * @warning MSB(x)=1, 即x>=2^63
673 */
675
676/**
677 * @brief 2-1阶逆元计算 (inv21)
678 * @param xh 输入数的高64位部分
679 * @param xl 输入数的低64位部分
680 * @return 计算结果:(B^3-1)/(xh*B+xl) - B
681 * @warning MSB(xh)=1, 即xh>=2^63
682 */
684
685/**
686 * @brief 近似逆元计算
687 * @param dst 输出结果缓冲区,长度为na
688 * @param numa 输入操作数,长度为na
689 * @param na 输入操作数的 limb 长度
690 * @warning na>0, MSB(numa)=1, sep(dst,numa)
691 * @return 无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na] - B^na
692 */
694
695/**
696 * @brief 近似逆元计算(牛顿迭代法)
697 * @param dst 输出结果缓冲区,长度为na
698 * @param numa 输入操作数,长度为na
699 * @param na 输入操作数的 limb 长度
700 * @warning na>4, MSB(numa)=1, sep(dst,numa)
701 * @return 无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na]-B^na+[0|-1]
702 */
704
705/**
706 * @brief 近似逆元计算 (invappr)
707 * @param dst 输出结果缓冲区,长度为na
708 * @param numa 输入操作数,长度为na
709 * @param na 输入操作数的 limb 长度
710 * @warning na>0, MSB(numa)=1, sep(dst,numa)
711 * @return 无返回值,结果存储在dst中,[dst,na] = (B^(2*na)-1)/[numa,na] - B^na + [0|-1]
712 */
714
715/**
716 * @brief 3/2位除法运算 [numa,2]=[numa,3] mod [numb,2]
717 * @param numa 输入被除数(长度3),运算后存储余数(长度2)
718 * @param numb 输入除数(长度2)
719 * @param inv21 除数的2-1阶逆元(提前计算好的inv21([numb,2]))
720 * @return 商值(单精度数)
721 * @warning [numa,3]<[numb,2]*B, MSB(numb)=1, inv21=inv21([numb,2]), eqsep(numa,numb)
722 */
724
725/**
726 * @brief 单精度数除法
727 * @param dstq 输出商的缓冲区(可为NULL,此时仅计算余数)
728 * @param numa 输入被除数,长度为na
729 * @param na 被除数的 limb 长度
730 * @param x 除数(单个 limb )
731 * @return 除法余数(单个 limb )
732 * @warning na>0, x!=0, eqsep(dstq,numa), dstq>=numa-1 是可以接受的
733 * @note if (dstq!=NULL) [dstq,na] = [numa,na] div x
734 */
736
737/**
738 * @brief 单精度数取余
739 * @param numa 输入被除数,长度为na
740 * @param na 被除数的 limb 长度
741 * @param x 除数(单个 limb )
742 * @return 除法余数(单个 limb )
743 * @warning na>0, x!=0, eqsep(dstq,numa), dstq>=numa-1 是可以接受的
744 */
746
747/**
748 * @brief 双精度数除法 (除数为2个limb)
749 * @param dstq 输出商的缓冲区,长度至少为na-1
750 * @param numa 输入被除数(长度na)
751 * @param na 被除数的 limb 长度
752 * @param numb 输入除数(长度2)[numb,2]=[numa,na] mod [numb,2]
753 * @warning na>=2, numb[1]!=0, eqsep(dstq,numa), dstq>=numa 是可以接受的
754 * @note if (dstq!=NULL) [dstq,na-1]=[numa,na] div [numb,2]
755 */
757
758/**
759 * @brief 双精度数取余 (除数为2个limb)
760 * @param numa 输入被除数(长度na)
761 * @param na 被除数的 limb 长度
762 * @param numb 输入除数(长度2)[numb,2]=[numa,na] mod [numb,2]
763 * @warning na>=2, numb[1]!=0, eqsep(dstq,numa), dstq>=numa 是可以接受的
764 */
766
767/**
768 * @brief 基础除法运算
769 * @param dstq 输出商的缓冲区,长度至少为na-nb
770 * @param numa 输入被除数(长度na),运算后存储余数(长度nb)
771 * @param na 被除数的单精度数(limb)长度
772 * @param numb 输入除数,长度为nb
773 * @param nb 除数的单精度数(limb)长度
774 * @param inv21 除数的2-1阶逆元(inv21([numb+nb-2,2]))
775 * @return 商的最高位(qh)
776 * @warning na>=nb>=3, MSB(numb)=1, inv21=inv21([numb+nb-2,2]), sep(dstq,numa,numb)
777 * @note qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,na-nb]=[numa,na] mod [numb,nb], return qh
778 */
781
782/**
783 * @brief 分治除法运算
784 * @param dstq 输出商的缓冲区,长度至少为na-nb
785 * @param numa 输入被除数(长度na),运算后存储余数(长度nb)
786 * @param na 被除数的单精度数(limb)长度
787 * @param numb 输入除数,长度为nb
788 * @param nb 除数的单精度数(limb)长度
789 * @param inv21 除数的2-1阶逆元(inv21([numb+nb-2,2]))
790 * @return 商的最高位(qh)
791 * @warning na>=2*nb, nb>=6, MSB(numb)=1, inv21=inv21([numb+nb-2,2]), sep(dstq,numa,numb)
792 * @note qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,na-nb]=[numa,na] mod [numb,nb], return qh
793 */
796
797/**
798 * @brief 计算预计算逆元的尺寸
799 * @param nq 商的 limb 长度
800 * @param nb 除数的 limb 长度
801 * @return 计算需要预计算逆元尺寸ni(ni<=nb)
802 * @note 用于已归一化除法([nq+nb]/[nb]=[nq])的逆元 ni 尺寸
803 */
805 mp_size_t ni, b;
806 if (nq > nb) {
807 b = (nq - 1) / nb + 1; // ceil(nq/nb), number of blocks
808 ni = (nq - 1) / b + 1; // ceil(nq/b)
809 } else if (3 * nq > nb) {
810 ni = (nq - 1) / 2 + 1; // b=2
811 } else {
812 ni = (nq - 1) / 1 + 1; // b=1
813 }
814 return ni;
815}
816
817/**
818 * @brief 除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
819 * @param dst 输出预计算逆元的缓冲区,长度为ni
820 * @param numa 输入操作数,长度为na
821 * @param na 输入操作数的 limb 长度
822 * @param ni 预计算逆元的目标尺寸
823 * @warning na>=ni>0, MSB(numa)=1, eqsep(dst,numa)
824 * @note if (ni=na) [dst,na] = (B^(2*na)-1) / [numa,na] - B^na
825 */
827
828/**
829 * @brief 大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]
830 * @param dst 逆元结果输出指针
831 * @param numa 源操作数指针
832 * @param na 操作数的 limb 长度
833 * @param nf 精度因子
834 * @warning na>0, numa[na-1]!=0, eqsep(dst,numa)
835 */
837
838/**
839 * @brief 精确逆元计算 [dstq,na+ni+2] = B^(2*(na+ni)) / ([numa,na] * B^ni)
840 * @param dstq 输出商的缓冲区,长度至少为na+ni+2
841 * @param numa 输入被除数(长度na)
842 * @param na 被除数的 limb 长度
843 * @param ni 精度因子
844 * @warning na>0, sep(dstq,numa), dstq!=NULL, numa[na-1]!=0
845 * @note 也就是计算 B^(2*na+ni) div ([numa,na]
846 */
848
849/**
850 * @brief 乘法逆元除法
851 * @param dstq 输出商的缓冲区,长度至少为na-nb
852 * @param numa 输入被除数(长度na),运算后存储余数(长度nb)
853 * @param na 被除数的 limb 长度
854 * @param numb 输入除数,长度为nb
855 * @param nb 除数的 limb 长度
856 * @param invappr 预计算的近似逆元,长度为ni
857 * @param ni 预计算逆元的 limb 长度
858 * @return 商的最高位(qh)
859 * @warning na>=nb>=ni>0, MSB(numb)=1, [invappr,ni]=inv_prediv([numb,nb]), sep(dstq,numa,numb,invappr))
860 * @note qh:[dstq,na-1]=[numa,na] div x, [numa,1]=[numa,na] mod x, return qh
861 */
864
865/**
866 * @brief 单精度数除法(除数为1个limb)
867 * @param dstq 输出商的缓冲区,长度至少为na-1
868 * @param numa 输入被除数(长度na),运算后存储余数(长度1)
869 * @param na 被除数的 limb 长度
870 * @param x 除数(单个 limb )
871 * @return 商的最高位(qh)
872 * @warning na>1, MSB(x)=1, sep(dstq,numa)
873 * @note qh:[dstq,na-1]=[numa,na] div x, [numa,1]=[numa,na] mod x, return qh
874 */
876
877/**
878 * @brief 双精度数除法(除数为2个limb)
879 * @param dstq 输出商的缓冲区,长度至少为na-2
880 * @param numa 输入被除数(长度na),运算后存储余数(长度2)
881 * @param na 被除数的 limb 长度
882 * @param numb 输入除数,长度为2
883 * @return 商的最高位(qh)
884 * @warning na>2, MSB(numb)=1, sep(dstq,numa,numb)
885 * @note qh:[dstq,na-2]=[numa,na] div [numb,2], [numa,2]=[numa,na] mod [numb,2], return qh
886 */
888
889/**
890 * @brief 除法运算
891 * @param dstq 输出商的缓冲区,长度至少为na-nb
892 * @param numa 输入被除数(长度na),运算后存储余数(长度nb)
893 * @param na 被除数的 limb 长度
894 * @param numb 输入除数,长度为nb
895 * @param nb 除数的 limb 长度
896 * @return 商的最高位(qh)
897 * @warning na>=nb>0, MSB(numb)=1, sep(dstq,numa,numb)
898 * @note qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,nb]=[numa,na] mod [numb,nb], return qh
899 */
901
902/**
903 * @brief 大数除法和取模操作
904 * @note 如果dstq不为NULL: [dstq,na-nb+1] = [numa,na] / [numb,nb] (商)
905 * 如果dstr不为NULL: [dstr,nb] = [numa,na] mod [numb,nb] (余数)
906 * @warning 0<nb<=na, numb[nb-1]!=0, sep(dstq,[numa|numb]), eqsep(dstr,[numa|numb]))
907 * 特殊情况: nb==1时, dstq>=numa-1 是允许的
908 * nb==2时, dstq>=numa 是允许的
909 * @param dstq 商结果输出指针(NULL表示不计算商)
910 * @param dstr 余数结果输出指针(NULL表示不计算余数)
911 * @param numa 被除数指针
912 * @param na 被除数的 limb 长度
913 * @param numb 除数指针
914 * @param nb 除数的 limb 长度
915 */
917
918/**
919 * @brief 大数平方根和取余操作
920 * @note 如果dstr不为NULL: [dsts,nf+na/2+1], [dstr,nf+na/2+1] = sqrtrem([numa,na]*B^(2*nf))
921 * 也即 [numa,na] × B^(2×nf) = [dsts,nf+na/2+1]^2 + [dstr,nf+na/2+1]
922 * 且 0 <= [dstr,nf+na/2+1] < 2 * [dsts,nf+na/2+1] + 1
923 * 如果dstr为NULL: [dsts,nf+na/2+1] = [round|floor](sqrt([numa,na]*B^(2*nf)))
924 * @warning na>0, numa[na-1]!=0, eqsep(dsts,numa), eqsep(dstr,numa)
925 * @param dsts 平方根结果输出指针
926 * @param dstr 余数结果输出指针(NULL表示不计算余数)
927 * @param numa 源操作数指针
928 * @param na 操作数的 limb 长度
929 * @param nf 精度因子
930 */
932
933/**
934 * @brief 大数加1宏(预期无进位)
935 * @param p 指向大数起始位置的指针
936 * @note 从最低位开始加1,直到遇到非零值(预期无进位溢出)
937 */
938#define lmmp_inc(p) \
939 do { \
940 mp_ptr _p_ = (p); \
941 while (++(*(_p_++)) == 0); \
942 } while (0)
943
944/**
945 * @brief 大数加指定值宏(预期无进位)
946 * @param p 指向大数起始位置的指针
947 * @param inc 要加的单精度数值
948 * @note 先加最低位,若产生进位则逐位加1,直到无进位(预期无溢出)
949 */
950#define lmmp_inc_1(p, inc) \
951 do { \
952 mp_ptr _p_ = (p); \
953 mp_limb_t _inc_ = (inc), _x_; \
954 _x_ = *_p_ + _inc_; \
955 *_p_ = _x_; \
956 if (_x_ < _inc_) \
957 while (++(*(++_p_)) == 0); \
958 } while (0)
959
960/**
961 * @brief 大数减1宏(预期无借位)
962 * @param p 指向大数起始位置的指针
963 * @note 从最低位开始减1,直到遇到非零值(预期无借位溢出)
964 */
965#define lmmp_dec(p) \
966 do { \
967 mp_ptr _p_ = (p); \
968 while ((*(_p_++))-- == 0); \
969 } while (0)
970
971/**
972 * @brief 大数减指定值宏(预期无借位)
973 * @param p 指向大数起始位置的指针
974 * @param dec 要减的单精度数值
975 * @note 先减最低位,若产生借位则逐位减1,直到无借位(预期无溢出)
976 */
977#define lmmp_dec_1(p, dec) \
978 do { \
979 mp_ptr _p_ = (p); \
980 mp_limb_t _dec_ = (dec), _x_; \
981 _x_ = *_p_; \
982 *_p_ = _x_ - _dec_; \
983 if (_x_ < _dec_) \
984 while ((*(++_p_))-- == 0); \
985 } while (0)
986
987/**
988 * @brief 大数比较函数(内联)
989 * @param numa 第一个大数,长度为n
990 * @param numb 第二个大数,长度为n
991 * @param n 大数的单精度数(limb)长度
992 * @return 1(numa>numb) / 0(numa==numb) / -1(numa<numb)
993 * @warning n>0, numa!=NULL, numb!=NULL
994 * @note 从最高位开始逐位比较,直到找到不同位
995 */
997 lmmp_param_assert(n > 0);
1000 mp_ssize_t i = n;
1001 mp_limb_t x, y;
1002 while (--i >= 0) {
1003 x = numa[i];
1004 y = numb[i];
1005 if (x != y)
1006 return (x > y ? 1 : -1);
1007 }
1008 return 0;
1009}
1010
1011/**
1012 * @brief 大数判零函数(内联)
1013 * @param p 指向大数起始位置的指针
1014 * @param n 大数的单精度数(limb)长度
1015 * @return 1(全零) / 0(非零)
1016 * @warning n>0
1017 * @note 从最高位开始检查,只要有非零位则返回0
1018 */
1020 do {
1021 if (p[--n] != 0)
1022 return 0;
1023 } while (n != 0);
1024 return 1;
1025}
1026
1027#define LMMP_AORS_(FUNCTION, TEST) \
1028 mp_limb_t _x_; \
1029 if (FUNCTION(dst, numa, numb, nb)) { \
1030 do { \
1031 if (nb >= na) \
1032 return 1; \
1033 _x_ = numa[nb]; \
1034 } while (TEST); \
1035 } \
1036 if (dst != numa && na != nb) \
1037 lmmp_copy(dst + nb, numa + nb, na - nb); \
1038 return 0
1039
1040/**
1041 * @brief 大数加法静态内联函数 [dst,na]=[numa,na]+[numb,nb]
1042 * @param dst 输出结果缓冲区,存储numa + numb
1043 * @param numa 第一个加数,长度为na
1044 * @param na 第一个加数的 limb 长度
1045 * @param numb 第二个加数,长度为nb
1046 * @param nb 第二个加数的 limb 长度
1047 * @return 进位标志(1表示有进位,0表示无进位)
1048 * @warning 0<nb<=na, eqsep(dst,[numa|numb])
1049 */
1053
1054/**
1055 * @brief 大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]
1056 * @param dst 输出结果缓冲区,存储numa - numb
1057 * @param numa 被减数,长度为na
1058 * @param na 被减数的 limb 长度
1059 * @param numb 减数,长度为nb
1060 * @param nb 减数的 limb 长度
1061 * @return 借位标志(1表示有借位,0表示无借位)
1062 * @warning 0<nb<=na, eqsep(dst,[numa|numb])
1063 */
1067
1068#undef LMMP_AORS_
1069
1070// 单精度加减运算通用宏:封装单精度加减的公共逻辑
1071#define LMMP_AORS_1_(OP, CB) \
1072 mp_size_t _i_ = 1; \
1073 mp_limb_t _x_ = numa[0], _r_ = _x_ OP x; \
1074 dst[0] = _r_; \
1075 if (CB(_r_, _x_, x)) { \
1076 do { \
1077 if (_i_ >= na) \
1078 return 1; \
1079 _x_ = numa[_i_]; \
1080 _r_ = _x_ OP 1; \
1081 dst[_i_] = _r_; \
1082 ++_i_; \
1083 } while (CB(_r_, _x_, 1)); \
1084 } \
1085 if (numa != dst && na != _i_) \
1086 lmmp_copy(dst + _i_, numa + _i_, na - _i_); \
1087 return 0
1088
1089// 加法进位判断宏:判断加法是否产生进位
1090#define LMMP_ADDCB_(r, x, y) ((r) < (y))
1091// 减法借位判断宏:判断减法是否产生借位
1092#define LMMP_SUBCB_(r, x, y) ((x) < (y))
1093
1094/**
1095 * @brief 大数加单精度数静态内联函数 [dst,na]=[numa,na]+x
1096 * @param dst 输出结果缓冲区,存储numa + x
1097 * @param numa 被加数,长度为na
1098 * @param na 被加数的 limb 长度
1099 * @param x 加数(单个 limb )
1100 * @return 进位标志(1表示有进位,0表示无进位)
1101 * @warning na>0, eqsep(dst,numa)
1102 */
1104
1105/**
1106 * @brief 大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
1107 * @param dst 输出结果缓冲区,存储numa - x
1108 * @param numa 被减数,长度为na
1109 * @param na 被减数的 limb 长度
1110 * @param x 减数(单个 limb )
1111 * @return 借位标志(1表示有借位,0表示无借位)
1112 * @warning na>0, eqsep(dst,numa)
1113 */
1115
1116/**
1117 * @brief 计算大数转换为字符串,字符串需要的缓冲区长度
1118 * @param numa 输入大数,长度为na
1119 * @param na 大数的 limb 长度
1120 * @param base 目标基数(2~256)
1121 * @return 大数在指定基数下的位数
1122 * @warning na>=0, 2<=base<=256
1123 * @note 将会忽略numa的前导零,
1124 * 1. if (numa!=NULL) 返回的长度可能会多分配一个字符空间
1125 * 2. if (numa==NULL) 返回na个limb长度的数的最大可能字符长度(最坏情况)
1126 */
1128
1129/**
1130 * @brief 计算字符串转大数所需的 limb 缓冲区长度
1131 * @param src 输入字符串指针
1132 * @param len 字符串长度
1133 * @param base 字符串的基数(2~256)
1134 * @return 存储该字符串数值所需的 limb 缓冲区长度
1135 * @warning len>=0, 2<=base<=256
1136 * @note 将会忽略前导零,
1137 * 1. if (src!=NULL) 返回的长度可能会多分配一个 limb 空间
1138 * 2. if (src==NULL) 返回len位base进制数的最大可能 limb 长度(最坏情况)
1139 */
1141
1142/**
1143 * @brief 字符串转大数操作 [src,len,base] to [dst,return value,B]
1144 * @warning len>=0, 2<=base<=256
1145 * @param dst 大数结果输出指针
1146 * @param src 字符串源指针
1147 * @param len 字符串长度
1148 * @param base 字符串的进制基数
1149 * @return 转换后的大数 limb 长度
1150 */
1152
1153/**
1154 * @brief 大数转字符串操作 [numa,na,B] to [dst,return value,base]
1155 * @warning na>=0, 2<=base<=256
1156 * @param dst 字符串结果输出指针
1157 * @param numa 大数源指针
1158 * @param na 大数的 limb 长度
1159 * @param base 目标字符串的进制基数
1160 * @return 转换后的字符串长度
1161 */
1163
1164/**
1165 * @brief 提取高位指定位数,并返回低位bits位数
1166 * @param num 待提取的大数指针
1167 * @param n num的 limb 长度
1168 * @param bits 待提取的位数(1-64)
1169 * @param ext 提取结果输出指针
1170 * @warning n>0, 1<=bits<=64, ext!=NULL
1171 * @note 如果bits大于num的实际位数,则不会保证ext有效位数为bits位;
1172 * 如果bits小于等于num的实际位数,则ext将会有bits位有效位数。
1173 * @return 剩余的低位bits数量
1174 */
1176
1177#ifdef __cplusplus
1178} // extern "C"
1179#endif
1180
1181#undef LMMP_ADDCB_
1182#undef LMMP_SUBCB_
1183#undef LMMP_AORS_1_
1184
1185
1186#undef INLINE_
1187
1188#endif // LAMMP_LMMPN_H
#define c
#define an
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_leading_zeros_
Definition inlines.h:160
#define lmmp_mul_n_
Definition inlines.h:167
#define lmmp_mullh_
Definition inlines.h:164
#define lmmp_sqr_
Definition inlines.h:166
#define lmmp_limb_popcnt_
Definition inlines.h:163
#define lmmp_tailing_zeros_
Definition inlines.h:161
#define lmmp_mulh_
Definition inlines.h:165
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint8_t mp_byte_t
Definition lmmp.h:75
size_t mp_bitcnt_t
Definition lmmp.h:82
uint64_t mp_size_t
Definition lmmp.h:77
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
int64_t mp_ssize_t
Definition lmmp.h:79
uint64_t mp_limb_t
Definition lmmp.h:76
#define LAMMP_API
Definition lmmp.h:61
#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
#define LMMP_SUBCB_(r, x, y)
Definition lmmpn.h:1092
mp_limb_t lmmp_div_3_2_(mp_ptr numa, mp_srcptr numb, mp_limb_t inv21)
3/2位除法运算 [numa,2]=[numa,3] mod [numb,2]
void lmmp_mul_toom22_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-22乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
mp_limb_t lmmp_div_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
除法运算
void lmmp_invappr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算 (invappr)
static mp_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:804
mp_limb_t lmmp_div_1_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
单精度数除法(除数为1个limb)
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:77
void lmmp_mul_toom44_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-44乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
#define LMMP_AORS_(FUNCTION, TEST)
Definition lmmpn.h:1027
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
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
mp_limb_t lmmp_shr1add_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
加法后右移1位 [dst,n] = ([numa,n] + [numb,n]) >> 1
Definition shr.c:62
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
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
void lmmp_mul_toom42_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-42乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
void lmmp_inv_prediv_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t ni)
除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
Definition div_mulinv.c:22
void lmmp_div_2_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数除法 (除数为2个limb)
Definition div.c:234
void lmmp_sqr_basecase_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
基础平方运算 [dst,2*na] = [numa,na]^2
void lmmp_mul_toom42_unbalance_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-42不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
void lmmp_mullo_dc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_ptr tp, mp_size_t n)
低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
mp_limb_t lmmp_subshl1_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
减法结合左移1位操作 [dst,n] = [numa,n] - ([numb,n] << 1)
Definition shl.c:83
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
mp_bitcnt_t lmmp_extract_bits_(mp_srcptr num, mp_size_t n, mp_limb_t *ext, int bits)
提取高位指定位数,并返回低位bits位数
void lmmp_mul_toom43_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-43乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
mp_limb_t lmmp_mod_1_(mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数取余
Definition div.c:31
mp_size_t lmmp_to_str_(mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
大数转字符串操作 [numa,na,B] to [dst,return value,base]
Definition to_str.c:175
void lmmp_mod_2_(mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数取余 (除数为2个limb)
Definition div.c:155
#define LMMP_AORS_1_(OP, CB)
Definition lmmpn.h:1071
void lmmp_mul_basecase_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
基础乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
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_size_t lmmp_from_str_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
字符串转大数操作 [src,len,base] to [dst,return value,B]
Definition from_str.c:154
void lmmp_mul_toom32_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-32乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
mp_size_t lmmp_to_str_len_(mp_srcptr numa, mp_size_t na, int base)
计算大数转换为字符串,字符串需要的缓冲区长度
Definition to_str.c:23
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
#define INLINE_
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition lmmpn.h:55
void lmmp_invappr_newton_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算(牛顿迭代法)
void lmmp_mul_toom52_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-52乘法运算 [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_addshl1_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
加法结合左移1位操作 [dst,n] = [numa,n] + ([numb,n] << 1)
Definition shl.c:66
void lmmp_mul_toom62_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-62乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
void lmmp_sqr_toom2_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
Toom-2平方运算 [dst,2*na] = [numa,na]^2
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
void lmmp_sqr_toom3_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
Toom-3平方运算 [dst,2*na] = [numa,na]^2
void lmmp_mul_fft_unbalance_(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]
mp_limb_t lmmp_shr1sub_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:143
void lmmp_bninv_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_size_t ni)
精确逆元计算 [dstq,na+ni+2] = B^(2*(na+ni)) / ([numa,na] * B^ni)
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算满足 >=n 的最小费马/梅森乘法可行尺寸
Definition mul_fft.c:95
void lmmp_sqrlo_dc_(mp_ptr dst, mp_srcptr numa, mp_ptr tp, mp_size_t n)
低位平方 [dst,n] = [numa,n]^2 mod B^n
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
#define LMMP_ADDCB_(r, x, y)
Definition lmmpn.h:1090
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
void lmmp_sqr_toom4_(mp_ptr pp, mp_srcptr ap, mp_size_t an)
Toom-4平方运算 [dst,2*na] = [numa,na]^2
void lmmp_mul_toom53_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-53乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
void lmmp_mullo_fft_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_ptr scratch)
低位FFT乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
Definition mullo.c:22
mp_limb_t lmmp_addmul_1_(mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
大数乘以单limb并累加操作 [numa,n] += [numb,n] * b
mp_limb_t lmmp_mul_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数乘以单limb操作 [dst,na] = [numa,na] * x
void lmmp_inv_basecase_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算
mp_limb_t lmmp_add_n_sub_n_(mp_ptr dsta, mp_ptr dstb, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
同时执行n位加法和减法 ([dsta,n],[dstb,n]) = ([numa,n]+[numb,n],[numa,n]-[numb,n])
Definition add_n_sub_n.c:20
static bool lmmp_endian(void)
运行时判断端序
Definition lmmpn.h:65
mp_limb_t lmmp_div_mulinv_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_srcptr invappr, mp_size_t ni)
乘法逆元除法
void lmmp_inv_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t nf)
大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]
Definition inv.c:163
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
mp_limb_t lmmp_div_2_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb)
双精度数除法(除数为2个limb)
void lmmp_div_(mp_ptr dstq, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数除法和取模操作
Definition div.c:74
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
void lmmp_not_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)
mp_limb_t lmmp_submul_1_(mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b
void lmmp_sqrt_(mp_ptr dsts, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_size_t nf)
大数平方根和取余操作
Definition sqrt.c:333
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
mp_limb_t lmmp_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:117
mp_limb_t lmmp_shr1sub_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
减法后右移1位 [dst,n] = ([numa,n] - [numb,n]) >> 1
Definition shr.c:116
mp_limb_t lmmp_inv_2_1_(mp_limb_t xh, mp_limb_t xl)
2-1阶逆元计算 (inv21)
Definition inv.c:20
mp_limb_t lmmp_div_basecase_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
基础除法运算
void lmmp_mul_toom62_unbalance_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-62不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
void lmmp_mullo_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
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_div_divide_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
分治除法运算
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
void lmmp_mul_toom33_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
Toom-33乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
mp_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
计算字符串转大数所需的 limb 缓冲区长度
Definition from_str.c:23
#define numb
#define tp
#define n
#define scratch