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