LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
numth.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_NUMTH_H
17#define LAMMP_NUMTH_H
18
19#include <stdbool.h>
20
21#include "lmmp.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif // __cplusplus
26
27typedef uint8_t uchar;
28typedef int8_t schar;
31typedef uint32_t uint;
32typedef uint64_t ulong;
33typedef int32_t sint;
34typedef int64_t slong;
35typedef uint8_t* ucharp;
36typedef int8_t* scharp;
39typedef uint32_t* uintp;
40typedef int32_t* sintp;
41typedef uint64_t* ulongp;
42typedef int64_t* slongp;
43
44
45/**
46 * @brief 计算 a 在2^32下的逆元
47 * @param a 待求逆元
48 * @warning a%2==1
49 * @return 逆元
50 */
52
53/**
54 * @brief 计算 a 在2^64下的逆元
55 * @param a 待求逆元
56 * @warning a%2==1
57 * @return 逆元
58 */
60
61/**
62 * @brief 计算 [numa,2] 在 B^2 下的逆元
63 * @param numa 待求逆元指针(长度为 2 个limb)
64 * @param dst 结果指针(长度为 2 个limb)
65 * @warning numa!=NULL, dst!=NULL, numa[0]%2==1, eqsep(dst,numa)
66 */
68
69/**
70 * @brief 计算 [numa,3] 在 B^3 下的逆元
71 * @param numa 待求逆元指针(长度为 3 个limb)
72 * @param dst 结果指针(长度为 3 个limb)
73 * @warning numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)
74 */
76
77/**
78 * @brief 计算 [numa,4] 在 B^4 下的逆元
79 * @param numa 待求逆元指针(长度为 4 个limb)
80 * @param dst 结果指针(长度为 4 个limb)
81 * @warning numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)
82 */
84
85/**
86 * @brief 计算 [numa,n] 在 B^n 下的逆元
87 * @param numa 待求逆元指针(长度为 n 个limb)
88 * @param dst 结果指针(长度为 n 个limb)
89 * @param n 结果的 limb 长度
90 * @param tp 临时工作区指针(长度为 5*(n+1)/2 个limb)
91 * @warning numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa,tp)
92 */
94
95/**
96 * @brief 计算 a 在 B^n 下的逆元
97 * @param dst 结果指针(长度为 n 个limb)
98 * @param a 待求逆元
99 * @param n 结果的 limb 长度
100 * @warning a%2==1, n>1, dst!=NULL
101 */
103
104/**
105 * @brief 计算 [numa,2] 在 B^n 下的逆元
106 * @param dst 结果指针(长度为 n 个limb)
107 * @param numa 待求逆元指针(长度为 2 个limb)
108 * @param n 结果的 limb 长度
109 * @warning numa[0]%2==1, n>2, dst!=NULL, numa!=NULL, sep(dst,numa)
110 */
112
113/**
114 * @brief 计算 [numa,na] 在 B^n 下的逆元
115 * @param dst 结果指针(长度为 n 个limb)
116 * @param numa 待求逆元指针(长度为 na 个limb)
117 * @param na 待求逆元的 limb 长度
118 * @param n 结果的 limb 长度
119 * @param tp 临时工作区指针(长度为 (9*na+5)/2 个limb)
120 * @warning numa[0]%2==1, n>na, dst!=NULL, numa!=NULL, tp!=NULL, sep(dst,numa,tp)
121 */
123
124/**
125 * @brief 计算 [numa,na] 在 B^n 下的逆元
126 * @param dst 结果指针(长度为 n 个limb)
127 * @param numa 待求逆元指针(长度为 na 个limb)
128 * @param na 待求逆元的 limb 长度
129 * @param n 结果的 limb 长度
130 * @warning n>=na>0, numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)
131 */
133
134/**
135 * @brief 精确除法([dst,nn]=[np,nn]/d,且余数必须为0)
136 * @param dst 结果指针(长度为 nn 个limb)
137 * @param np 被除数指针(长度为 nn 个limb)
138 * @param nn 被除数的 limb 长度
139 * @param d 除数
140 * @param dinv 除数的逆元(d*dinv==1 mod 2^64)
141 * @warning d%2==1, d*dinv==1 mod 2^64, nn>0, dst!=NULL, np!=NULL, eqsep(dst,np)
142 */
144
145/**
146 * @brief 精确除法([dst,nn]=[np,nn]/[dp,2],且余数必须为0)
147 * @param dst 结果指针(长度为 nn-1 个limb)
148 * @param np 被除数指针(长度为 nn 个limb)
149 * @param nn 被除数的 limb 长度
150 * @param dp 除数指针(长度为 2 个limb)
151 * @param dinv 除数的逆元指针(长度为 2 个limb)
152 * @warning dp[0]%2==1, dp*dinv==1 mod 2^128, nn>1, dst!=NULL, np!=NULL, eqsep(dst,np), sep(dp,dinv,[dst|np])
153 */
155
156/**
157 * @brief 精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0)
158 * @param dst 结果指针(长度为 nn-dn+1 个limb)
159 * @param np 被除数指针(长度为 nn 个limb),将会被修改为全零
160 * @param nn 被除数的 limb 长度
161 * @param dp 除数指针(长度为 dn 个limb)
162 * @param dn 结除数的 limb 长度
163 * @param dinv 除数[dp,dn]关于B^dn的逆元,若为NULL,则自动计算
164 * @warning dp[0]%2==1, nn>=dn>0, dst!=NULL, np!=NULL, dp!=NULL, eqsep(dst,np), sep(dp,dinv,[dst|np])
165 * @note 若dst==np,只会覆写 [dst,nn-dn+1] 区域
166 */
168
169/**
170 * @brief 精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0),朴素算法
171 * @param dst 结果指针(长度为 nn-dn+1 个limb)
172 * @param np 被除数指针(长度为 nn 个limb),将会被覆写为全零
173 * @param nn 被除数的 limb 长度
174 * @param dp 除数指针(长度为 dn 个limb)
175 * @param dn 结除数的 limb 长度
176 * @param dinv 除数低位dp[0]关于B的逆元
177 * @warning dp[0]%2==1, d[0]*dinv==1 mod 2^64, nn>=dn>0, dst!=NULL, np!=NULL, dp!=NULL, eqsep(dst,np), sep(dp,[dst|np])
178 * @note 若dst==np,将会覆写 [dst,nn] 区域,其中 [dst,nn-dn+1] 为商,[dst+nn-dn+1,dn-1] 将会被覆写为0
179 */
181
182/**
183 * @brief 精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0),分治算法
184 * @param dst 结果指针(长度为 nn-dn+1 个limb)
185 * @param np 被除数指针(长度为 nn 个limb)
186 * @param nn 被除数的 limb 长度
187 * @param dp 除数指针(长度为 dn 个limb)
188 * @param dn 结除数的 limb 长度
189 * @warning dp[0]%2==1, nn>=dn>0, dn>=nn-dn+1, dst!=NULL, np!=NULL, dp!=NULL, sep(dst,np,dp)
190 */
192
193/**
194 * @brief 精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0)
195 * @param dst 结果指针(长度为 nn-dn+1 个limb)
196 * @param np 被除数指针(长度为 nn 个limb)
197 * @param nn 被除数的 limb 长度
198 * @param dp 除数指针(长度为 dn 个limb)
199 * @param dn 结除数的 limb 长度
200 * @warning dp[0]%2==1, nn>=dn>0, dst!=NULL, np!=NULL, dp!=NULL, eqsep(dst,np), sep([dst|np],dp)
201 */
203
204/**
205 * @brief 计算两个无符号整数的最大公约数
206 * @param u 第一个无符号整数
207 * @param v 第二个无符号整数
208 * @return 最大公约数
209 * @warning u!=0, v!=0
210 */
212
213/**
214 * @brief 计算两个无符号整数的最大公约数
215 * @param up 第一个无符号整数指针
216 * @param un 第一个无符号整数的 limb 长度
217 * @param v 第二个无符号整数
218 * @warning v!=0, up!=NULL, un>0
219 * @return 最大公约数
220 */
222
223/**
224 * @brief 计算两个无符号整数的最大公约数
225 * @param up 第一个无符号整数指针,长度为 2
226 * @param vp 第二个无符号整数指针,长度为 2
227 * @param dst 结果指针(长度为 2,两个 limb 都会进行写入,即使最高位可能为0)
228 * @warning up!=NULL, vp!=NULL, [up,2]!=0, [vp,2]!=0, dst!=NULL, eqsep(dst,[up|vp])
229 * @note 我们不要求 up 和 vp 的高位不为 0,但要求两个数均不可以高低位全为 0
230 * @return dst 的实际 limb 长度
231 */
233
234/**
235 * @brief 计算两个无符号整数的最大公约数
236 * @param up 第一个无符号整数指针
237 * @param un 第一个无符号整数的 limb 长度
238 * @param vp 第二个无符号整数指针,长度为 2
239 * @param dst 结果指针(长度至少为 2,两个 limb 都会进行写入,即使最高位可能为0)
240 * @warning up!=NULL, un>2, vp!=NULL, vp[1]!=0, dst!=NULL, eqsep(dst,[up|vp])
241 * @return dst 的实际 limb 长度
242 */
244
245/**
246 * @brief 计算两个无符号整数的最大公约数(不建议使用此算法,更高版本可能被彻底弃用)
247 * @param dst 结果指针(长度至少为 min(un,vn))
248 * @param up 第一个无符号整数指针
249 * @param un 第一个无符号整数的 limb 长度
250 * @param vp 第二个无符号整数指针
251 * @param vn 第二个无符号整数的 limb 长度
252 * @warning up!=NULL, un>0, vp!=NULL, vn>0, eqsep(dst,[up|vp]), dst!=NULL
253 * @note 朴素的辗转相除法,与Lehmer算法具有相似的渐进时间复杂度,但Lehmer算法绝大多数场合更加优秀
254 * @return dst 的实际 limb 长度
255 */
257
258/**
259 * @brief 计算两个无符号整数的最大公约数(Lehmer算法)
260 * @param dst 结果指针(长度至少为 min(un,vn))
261 * @param up 第一个无符号整数指针
262 * @param un 第一个无符号整数的 limb 长度
263 * @param vp 第二个无符号整数指针
264 * @param vn 第二个无符号整数的 limb 长度
265 * @warning up!=NULL, un>0, vp!=NULL, vn>0, eqsep(dst,[up|vp]), dst!=NULL
266 * @return dst 的实际 limb 长度
267 */
269
270/**
271 * @brief 计算两个无符号整数的乘积,对mod取模,商放入 q 中
272 * @param a 第一个无符号整数
273 * @param b 第二个无符号整数
274 * @param q 商的结果指针
275 * @param mod 取模数
276 * @warning a < mod, b < mod, q!=NULL
277 * @return 余数
278 */
280
281/**
282 * @brief 计算 base^exp 对 mod 取模
283 * @param base 底数
284 * @param exp 指数
285 * @param mod 模数
286 * @warning base < mod, mod > 1
287 * @return base^exp 对 mod 取模的结果
288 */
290
291/**
292 * @brief 计算 base^exp 对 mod 取模
293 * @param base 底数
294 * @param exp 指数
295 * @param mod 模数
296 * @warning base < mod, mod > 1
297 * @return base^exp 对 mod 取模的结果
298 */
300
301/**
302 * @brief 大于n的下一个素数
303 * @param n 起始点(不含)
304 * @warning 如果 n 大于等于ulong可表示最大的质数,则返回ulong_max
305 * @return 大于n的下一个素数
306 */
308
309/**
310 * @brief 小于等于n的上一个素数
311 * @param n 起始点(含)
312 * @warning 如果 n 小于2,则返回 0
313 * @return 小于等于n的上一个素数,如果n恰好为素数,则返回 n
314 */
316
317/**
318 * @brief 判断素数
319 * @param n 待判断的数
320 * @return 若 n 为素数,返回 true,否则返回 false
321 */
323
324/**
325 * @brief 判断素数
326 * @param n 待判断的数
327 * @note 如果 n 的实际值小于2^32,此函数不会调用 lmmp_is_prime_uint_,
328 * 如果你可以保证 n 的实际值小于2^32,使用 lmmp_is_prime_uint_ 将会更快
329 * @return 若 n 为素数,返回 true,否则返回 false
330 */
332
333/**
334 * @brief 判断素数(无试除法)
335 * @param n 待判断的数(建议为极有可能为素数的数)
336 * @note 不进行试除法过滤,适用于判断已被小素数试除法过滤的数或强伪素数
337 * @warning n>=2
338 * @return 若 n 为素数,返回 true,否则返回 false
339 */
341
342/**
343 * @brief 计算幂次方需要的limb缓冲区长度 [base,n] ^ exp
344 * @param base 底数指针
345 * @param n 底数 limb 长度
346 * @param exp 指数
347 * @warning n>0, base[n-1]!=0, [base,n]>1
348 * @return 返回值为 [base,n]^exp 需要的 limb 缓冲区长度(比实际长度多)
349 */
351
352/**
353 * @brief 计算幂次方需要的limb缓冲区长度 base ^ exp
354 * @param base 底数
355 * @param exp 指数
356 * @warning exp>0, base>=1
357 * @return 返回值为 base^exp 需要的 limb 缓冲区长度(比实际长度多)
358 */
360
361/**
362 * @brief 计算奇数次幂算法 [dst,rn] = [base,n] ^ exp
363 * @param dst 结果指针
364 * @param rn 结果指针的 limb 缓冲区长度
365 * @param base 底数指针
366 * @param n 底数指针的 limb 长度
367 * @param exp 指数
368 * @warning n>0, base[n-1]!=0, sep(dst,base), [base,n]>1, exp>=3, exp%2==1
369 * @return 返回 dst 的实际 limb 长度
370 */
372
373/**
374 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
375 * @param dst 结果指针
376 * @param rn 结果指针的 limb 长度
377 * @param base 底数(4位无符号整数)
378 * @param exp 指数
379 * @warning 1<=base<=0xf, exp>0
380 * @return 返回 dst 的实际 limb 长度
381 */
383
384/**
385 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
386 * @param dst 结果指针
387 * @param rn 结果指针的 limb 长度
388 * @param base 底数(8位无符号整数)
389 * @param exp 指数
390 * @warning 0<base<=0xff, exp>0
391 * @return 返回 dst 的实际 limb 长度
392 */
394
395/**
396 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
397 * @param dst 结果指针
398 * @param rn 结果指针的 limb 长度
399 * @param base 底数(16位无符号整数)
400 * @param exp 指数
401 * @warning 0<base<=0xffff, exp>0
402 * @return 返回 dst 的实际 limb 长度
403 */
405
406/**
407 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
408 * @param dst 结果指针
409 * @param rn 结果指针的 limb 长度
410 * @param base 底数(32位无符号整数)
411 * @param exp 指数
412 * @warning 0<base<=2^32-1, exp>0
413 * @return 返回 dst 的实际 limb 长度
414 */
416
417/**
418 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
419 * @param dst 结果指针
420 * @param rn 结果指针的 limb 长度
421 * @param base 底数(64位无符号整数)
422 * @param exp 指数
423 * @warning 2^32<=base<=2^64-1, exp>0
424 * @return 返回 dst 的实际 limb 长度
425 */
427
428/**
429 * @brief 计算幂次方 [dst,rn] = [base,1] ^ exp
430 * @param dst 结果指针
431 * @param base 底数
432 * @param exp 指数
433 * @warning base>=1, exp>0
434 * @return 返回 dst 的实际 limb 长度
435 */
437
438/**
439 * @brief 计算幂次方2比特窗口快速幂算法 [dst,rn] = [base,n] ^ exp
440 * @param dst 结果指针
441 * @param rn 结果指针的 limb 长度
442 * @param base 底数指针
443 * @param n 底数指针的 limb 长度
444 * @param exp 指数
445 * @warning n>0, base[n-1]!=0, sep(dst,base), exp>0
446 * @return 返回 dst 的实际 limb 长度
447 */
449
450/**
451 * @brief 计算大整数幂 [dst,rn] = [base,n] ^ exp
452 * @param dst 结果指针
453 * @param rn 结果指针的 limb 长度
454 * @param base 底数指针
455 * @param n 底数指针的 limb 长度
456 * @param exp 指数
457 * @warning n>0, base[n-1]!=0, sep(dst,base), exp>0
458 * @return 返回 dst 的实际 limb 长度
459 */
461
462/**
463 * @brief 计算 nPr 排列数的 limb 缓冲区长度
464 * @param n 排列数的总数
465 * @param r 排列数的选择数
466 * @param bits 被修改为 nPr 的2的因子数
467 * @warning r<=n, bits!=NULL
468 * @return nPr 排列数的 limb 缓冲区长度(比实际长度多)
469 */
471
472/**
473 * @brief 计算 nPr 排列数的奇数部分
474 * @param dst 结果指针
475 * @param rn 结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
476 * @param n 排列数的总数
477 * @param r 排列数的选择数
478 * @warning 0xffff>=n>=r, dst!=NULL, rn>0
479 * @return 返回 dst 的实际 limb 长度
480 */
482
483/**
484 * @brief 计算 nPr 排列数的奇数部分
485 * @param dst 结果指针
486 * @param rn 结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
487 * @param n 排列数的总数
488 * @param r 排列数的选择数
489 * @warning 0xffffffff>=n>=r, dst!=NULL, rn>0
490 * @return 返回 dst 的实际 limb 长度
491 */
493
494/**
495 * @brief 计算 nPr 排列数的奇数部分
496 * @param dst 结果指针
497 * @param rn 结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
498 * @param n 排列数的总数
499 * @param r 排列数的选择数
500 * @warning n>=r, dst!=NULL, rn>0
501 * @return 返回 dst 的实际 limb 长度
502 */
504
505/**
506 * @brief 计算 nPr 排列数 ( nPr = n! / (n-r)! )
507 * @param dst 结果指针
508 * @param bits nPr 的2的因子数
509 * @param rn 结果指针的 limb 长度
510 * @param n 排列数的总数
511 * @param r 排列数的选择数
512 * @warning n>=r, dst!=NULL, rn>0
513 * @return 返回 dst 的实际 limb 长度
514 */
516
517/**
518 * @brief 计算 n! 阶乘的 limb 缓冲区长度
519 * @param n 阶乘的阶数
520 * @param bits 被修改为 n! 的2的因子数
521 * @warning bits!=NULL
522 * @return n! 阶乘的 limb 缓冲区长度(比实际长度多)
523 */
525
526/**
527 * @brief 计算 n! 阶乘的奇数部分
528 * @param dst 结果指针
529 * @param rn 结果指针的 limb 长度(factorial_size_ 函数的返回值 - bits/LIMB_BITS)
530 * @param n 阶乘的阶数
531 * @warning n>0xffff, dst!=NULL, rn>0
532 * @return 返回 dst 的实际 limb 长度
533 */
535
536/**
537 * @brief 计算 n! 阶乘
538 * @param dst 结果指针
539 * @param bits n! 的2的因子数
540 * @param rn 结果指针的 limb 长度
541 * @param n 阶乘的阶数
542 * @warning dst!=NULL, rn>0
543 * @return 返回 dst 的实际 limb 长度
544 */
546
547/**
548 * @brief 计算 n!! 双阶乘的 limb 缓冲区长度
549 * @param n 双阶乘的阶数
550 * @param bits 被修改为 n!! 的2的因子数
551 * @warning bits!=NULL
552 * @return n!! 双阶乘的 limb 缓冲区长度
553 */
555
556/**
557 * @brief 计算 n!! 双阶乘
558 * @param dst 结果指针
559 * @param bits n!! 的2的因子数
560 * @param rn 结果指针的 limb 长度
561 * @param n 双阶乘的阶数
562 * @warning dst!=NULL, rn>0
563 * @note 0的双阶乘为1,n为偶数时,n!!=2*4*...*n,n为奇数时,n!!=1*3*...*n
564 * @return 返回 dst 的实际 limb 长度
565 */
567
568/**
569 * @brief 计算hyper阶乘的 limb 缓冲区长度
570 * @param n hyper阶乘的阶数
571 * @param bits 被修改为 hyper阶乘的2的因子数
572 * @warning bits!=NULL
573 * @return hyper阶乘的 limb 缓冲区长度
574 */
576
577/**
578 * @brief 计算hyper阶乘(k^k累乘至n)
579 * @param dst 结果指针
580 * @param bits hyper阶乘的2的因子数
581 * @param rn 结果指针的 limb 长度
582 * @param n hyper阶乘的阶数
583 * @warning dst!=NULL, rn>0
584 * @return dst 的实际 limb 长度
585 */
587
588/**
589 * @brief 计算super阶乘的 limb 缓冲区长度
590 * @param n super阶乘的阶数
591 * @param bits 被修改为 super阶乘的2的因子数
592 * @warning bits!=NULL
593 * @return super阶乘的 limb 缓冲区长度
594 */
596
597/**
598 * @brief 计算super阶乘(k!累乘至n)
599 * @param dst 结果指针
600 * @param bits super阶乘的2的因子数
601 * @param rn 结果指针的 limb 长度
602 * @param n super阶乘的阶数
603 * @warning dst!=NULL, rn>0
604 * @return dst 的实际 limb 长度
605 */
607
608/**
609 * @brief 计算质数阶乘的 limb 缓冲区长度
610 * @param n 质数阶乘的阶数
611 * @return 质数阶乘的 limb 缓冲区长度
612 */
614
615/**
616* @brief 计算质数阶乘(不超过n的质数累乘)
617* @param dst 结果指针
618* @param rn 结果指针的 limb 长度
619* @param n 质数阶乘的阶数
620* @warning dst!=NULL, rn>0
621* @return dst 的实际 limb 长度
622*/
624
625/**
626 * @brief 计算 nCr 组合数的 limb 缓冲区长度
627 * @param n 组合数的总数
628 * @param r 组合数的选择数
629 * @param bits 被修改为 nCr 的2的因子数
630 * @warning r<=n/2, bits!=NULL
631 * @return nCr 组合数的 limb 缓冲区长度(比实际长度多 1-2 个 limb)
632 */
634
635/**
636 * @brief 计算 nCr 组合数的奇数部分
637 * @param dst 结果指针
638 * @param rn 结果指针的 limb 长度
639 * @param n 组合数的总数
640 * @param r 组合数的选择数
641 * @return 返回 dst 的实际 limb 长度
642 * @warning r<=n/2, n<=0xffff, dst!=NULL, rn>0
643 */
645
646/**
647 * @brief 计算 nCr 组合数的奇数部分
648 * @param dst 结果指针
649 * @param rn 结果指针的 limb 长度
650 * @param n 组合数的总数
651 * @param r 组合数的选择数
652 * @return 返回 dst 的实际 limb 长度
653 * @warning r<=n/2, 0xffff<n, dst!=NULL, rn>0
654 */
656
657/**
658 * @brief 计算 nCr 组合数 ( nCr = n! / (r!(n-r)!) )
659 * @param dst 结果指针
660 * @param bits nCr 的2的因子数
661 * @param rn 结果指针的 limb 长度
662 * @param n 组合数的总数
663 * @param r 组合数的选择数
664 * @return 返回 dst 的实际 limb 长度
665 * @warning r<=n/2, n<=0xffffffff, dst!=NULL, rn>0
666 */
668
669/**
670 * @brief 计算多项式系数的 limb 缓冲区长度
671 * @param r 需要计算的系数的数组
672 * @param m 系数的个数
673 * @param n 输出变量,将会被修改为 r[i] 的总和,即r1+r2+...+rm
674 * @return 多项式系数的 limb 缓冲区长度(比实际长度多 1-2 个 limb)
675 * @note 多项式系数为 ( r1+r2+...+rm )! / ( r1! * r2! * ... * rm!)
676 * @warning 我们使用 ulong* n 来同时计算 r[i] 的总和,因为 n 可能超过 0xffffffff。
677 * 我们预计算 n,这不仅可以作为后续多项式系数函数的参数传入。
678 * 同时也请调用者注意判断 n 是否超过了 0xffffffff
679 * 这是 lmmp_multinomial_ 函数的限制。
680 */
682
683/**
684 * @brief 计算多项式系数
685 * @param dst 结果指针
686 * @param rn 结果指针的 limb 长度
687 * @param n r[i] 的总和
688 * @param r 需要计算的系数的数组
689 * @param m 系数的个数
690 * @warning m>1, n>0
691 * @note 多项式系数为 ( r1+r2+...+rm )! / ( r1! * r2! * ... * rm!)
692 * @return 返回 dst 的实际 limb 长度
693 */
695
696/**
697 * @brief 计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度
698 * @param x 首项
699 * @param n 等差数列共n+1项
700 * @param m 公差
701 * @warning x>0, m>1, n>0, x+n*m<=0xffffffff
702 * @return 等差数列乘积的 limb 缓冲区长度(比实际长度多 1-2 个 limb)
703 */
705
706/**
707 * @brief 计算等差数列乘积 x(x+m)...(x+n*m)
708 * @param dst 结果指针
709 * @param rn 结果指针的 limb 长度
710 * @param x 首项
711 * @param n 等差数列共n+1项
712 * @param m 公差(大于1)
713 * @warning x>0, m>1, n>0, dst!=NULL, rn>0, x+n*m<=0xffffffff
714 * @return 结果的实际的 limb 缓冲区长度
715 */
717
718/**
719 * @brief 试除法
720 * @param num 被除数
721 * @param nn 被除数的 limb 长度
722 * @param N 试除法尝试的质数最大值
723 * @param rn 结果指针的 limb 长度
724 * @warning num!=NULL, nn>0, N>2, rn!=NULL
725 * @note 试除法尝试从 2-N 中所有质数进行试除,如果能整除则会插入到返回结果数组中,没有整除的则会返回 NULL。
726 * 结果指针请使用 lmmp_free() 函数进行释放。
727 * @return 结果指针,返回不超过N,且能整除[np,nn]的素数(从小到大排列),若没有能够整除的素数,则返回NULL
728 */
730
731/**
732 * @brief 除去[np,nn]中的[dp,dn]的因子
733 * @param np 被除数指针,将会被修改为除去因子后的数
734 * @param nn 被除数指针的 limb 长度,将会被修改除去因子后的长度
735 * @param dp 除数指针
736 * @param dn 除数指针的 limb 长度
737 * @warning np!=NULL, nn>0, dp!=NULL, dn>0
738 * @note 如果[np,nn]能被[dp,dn]整除,则[np,nn]将被修改为除去因子后的数,nn将被修改为除去因子后的长度。
739 * 如果不能被整除,则[np,nn]保持不变,并返回0。
740 * @return [np,nn]中被[dp,dn]除去的因子的个数,如果不能被整除,则返回0
741 */
743
744/**
745 * @brief 计算算术平方根 floor(sqrt(a))
746 * @param a 被开方数
747 * @return floor(sqrt(a))
748 */
750
751/**
752 * @brief 计算算数立方根 floor(cbrt(n))
753 * @param n 被开方数
754 * @return floor(cbrt(n))
755 * @warning n>0
756 * @note 使用Chebyshev估计,当n较大时,此算法更占优势
757 */
759
760/**
761 * @brief 计算算数立方根 floor(cbrt(n))
762 * @param n 被开方数
763 * @return floor(cbrt(n))
764 * @note 会依据n的大小,选择合适的算法
765 */
767
768/**
769 * @brief 计算算数立方根 floor(cbrt(a0+a1*B+a2*B^2))
770 * @param a0 低位 limb
771 * @param a1 中位 limb
772 * @param a2 高位 limb
773 * @warning a1>0
774 * @note a2可以为0,但a1需要大于0,即这个数至少应有65个bit
775 * @return floor(cbrt(a0+a1*B+a2*B^2))
776 */
778
779/**
780 * @brief 计算算数立方根 floor(cbrt([numa,na]))
781 * @param dst 结果指针(长度为 2 个limb)
782 * @param numa 被开方数指针
783 * @param na 被开方数的 limb 长度
784 * @warning dst!=NULL, numa!=NULL, 3<na<=6, numa[na-1]!=0, eqsep(dst,numa)
785 */
787
788/**
789 * @brief 计算近似立方根 floor(cbrt(a0+a1*B+a2*B^2))-[0|1]
790 * @param a0 低位 limb
791 * @param a1 中位 limb
792 * @param a2 高位 limb
793 * @warning a1>0
794 * @note a2可以为0,但a1需要大于0,即这个数至少应有65个bit
795 * @return floor(cbrt(a0+a1*B+a2*B^2))-[0|1]
796 */
798
799/**
800 * @brief 计算近似立方根 floor(cbrt([numa,na]))-[0|1]
801 * @param dst 结果指针(长度为 2 个limb)
802 * @param numa 被开方数指针
803 * @param na 被开方数的 limb 长度
804 * @warning dst!=NULL, numa!=NULL, 3<na<=6, numa[na-1]!=0, eqsep(dst,numa)
805 */
807
808/**
809 * @brief 计算 floor(n^(1/root))
810 * @param n 被开方数
811 * @param root 开方次数
812 * @return floor(n^(1/root))
813 * @note root=0时,返回0
814 */
816
817
818#ifdef __cplusplus
819}
820#endif // __cplusplus
821
822#endif // LAMMP_NUMTH_H
mp_limb_t * mp_ptr
Definition lmmp.h:80
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
uint64_t mp_limb_t
Definition lmmp.h:76
#define LAMMP_API
Definition lmmp.h:61
#define a0
#define a1
#define a2
#define tp
#define n
mp_size_t lmmp_odd_nCr_uint_(mp_ptr dst, mp_size_t rn, uint n, uint r)
计算 nCr 组合数的奇数部分
mp_limb_t lmmp_cbrt_3_(mp_limb_t a0, mp_limb_t a1, mp_limb_t a2)
计算算数立方根 floor(cbrt(a0+a1*B+a2*B^2))
Definition cbrt.c:74
mp_size_t lmmp_multinomial_size_(const uintp r, uint m, ulong *n)
计算多项式系数的 limb 缓冲区长度
ulong lmmp_prev_prime_ulong_(ulong n)
小于等于n的上一个素数
mp_size_t lmmp_odd_factorial_uint_(mp_ptr dst, mp_size_t rn, uint n)
计算 n! 阶乘的奇数部分
mp_size_t lmmp_remove_(mp_ptr np, mp_size_t *nn, mp_srcptr dp, mp_size_t dn)
除去[np,nn]中的[dp,dn]的因子
mp_size_t lmmp_gcd_basecase_(mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
计算两个无符号整数的最大公约数(不建议使用此算法,更高版本可能被彻底弃用)
mp_size_t lmmp_gcd_lehmer_(mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
计算两个无符号整数的最大公约数(Lehmer算法)
Definition gcd_lehmer.c:242
int16_t * sshortp
Definition numth.h:38
mp_size_t lmmp_u4_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
mp_size_t lmmp_pow_1_size_(mp_limb_t base, ulong exp)
计算幂次方需要的limb缓冲区长度 base ^ exp
Definition pow.c:25
uint8_t uchar
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition numth.h:27
void lmmp_divexact_(mp_ptr dst, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0)
mp_size_t lmmp_odd_nPr_ushort_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
ulong lmmp_cbrt_chebyshev_(ulong n)
计算算数立方根 floor(cbrt(n))
Definition cbrt_1.c:40
mp_size_t lmmp_pow_win2_(mp_ptr dst, mp_size_t rn, mp_srcptr base, mp_size_t n, ulong exp)
计算幂次方2比特窗口快速幂算法 [dst,rn] = [base,n] ^ exp
mp_size_t lmmp_gcd_2_(mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp)
计算两个无符号整数的最大公约数
Definition gcd_2.c:162
ulong lmmp_binvert_ulong_(ulong a)
计算 a 在2^64下的逆元
Definition binvert_1.c:42
mp_size_t lmmp_arith_seqprod_size_(uint x, uint n, uint m)
计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度
void lmmp_binvert_n_dc_(mp_ptr dst, mp_srcptr numa, mp_size_t n, mp_ptr tp)
计算 [numa,n] 在 B^n 下的逆元
mp_size_t lmmp_u32_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
uint16_t * ushortp
Definition numth.h:37
mp_size_t lmmp_pow_1_(mp_ptr dst, mp_size_t rn, mp_limb_t base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
uint64_t * ulongp
Definition numth.h:41
void lmmp_cbrtapprox_6_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
计算近似立方根 floor(cbrt([numa,na]))-[0|1]
Definition cbrt.c:106
uint32_t uint
Definition numth.h:31
ulong lmmp_cbrt_ulong_(ulong n)
计算算数立方根 floor(cbrt(n))
Definition cbrt_1.c:133
bool lmmp_is_prime_uint_(uint n)
判断素数
mp_size_t lmmp_superfac_size_(ushort n, mp_bitcnt_t *bits)
计算super阶乘的 limb 缓冲区长度
bool lmmp_is_prime_notrial_(ulong n)
判断素数(无试除法)
mp_size_t lmmp_2factorial_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
计算 n!! 双阶乘
uint lmmp_binvert_uint_(uint a)
计算 a 在2^32下的逆元
Definition binvert_1.c:30
mp_size_t lmmp_pow_basecase_(mp_ptr dst, mp_size_t rn, mp_srcptr base, mp_size_t n, ulong exp)
计算奇数次幂算法 [dst,rn] = [base,n] ^ exp
ulong lmmp_mulmod_ulong_(ulong a, ulong b, ulong mod, ulongp q)
计算两个无符号整数的乘积,对mod取模,商放入 q 中
uint8_t * ucharp
Definition numth.h:35
int8_t * scharp
Definition numth.h:36
mp_limb_t lmmp_gcd_1_(mp_srcptr up, mp_size_t un, mp_limb_t vlimb)
计算两个无符号整数的最大公约数
Definition gcd_1.c:44
uint32_t * uintp
Definition numth.h:39
mp_size_t lmmp_factorial_size_(uint n, mp_bitcnt_t *bits)
计算 n! 阶乘的 limb 缓冲区长度
int64_t slong
Definition numth.h:34
void lmmp_divexact_basecase_(mp_ptr dst, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)
精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0),朴素算法
mp_size_t lmmp_u64_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
mp_size_t lmmp_u8_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
void lmmp_binvert_2_(mp_ptr dst, mp_srcptr numa)
计算 [numa,2] 在 B^2 下的逆元
Definition binvert_1.c:56
mp_size_t lmmp_primefac_size_(uint n)
计算质数阶乘的 limb 缓冲区长度
int16_t sshort
Definition numth.h:30
mp_size_t lmmp_hyperfac_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, ushort n)
计算hyper阶乘(k^k累乘至n)
mp_size_t lmmp_u16_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
void lmmp_binvert_3_(mp_ptr dst, mp_srcptr numa)
计算 [numa,3] 在 B^3 下的逆元
ulong lmmp_sqrt_ulong_(ulong a)
计算算术平方根 floor(sqrt(a))
Definition nthroot.c:21
void lmmp_divexact_1_(mp_ptr dst, mp_srcptr np, mp_size_t nn, mp_limb_t d, mp_limb_t dinv)
精确除法([dst,nn]=[np,nn]/d,且余数必须为0)
Definition divexact.c:24
uint lmmp_powmod_uint_(uint base, ulong exp, uint mod)
计算 base^exp 对 mod 取模
mp_size_t lmmp_2factorial_size_(uint n, mp_bitcnt_t *bits)
计算 n!! 双阶乘的 limb 缓冲区长度
int8_t schar
Definition numth.h:28
void lmmp_binvert_unbalanced_1_(mp_ptr dst, mp_limb_t a, mp_size_t n)
计算 a 在 B^n 下的逆元
mp_size_t lmmp_factorial_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
计算 n! 阶乘
ulong lmmp_powmod_ulong_(ulong base, ulong exp, ulong mod)
计算 base^exp 对 mod 取模
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算两个无符号整数的最大公约数
Definition gcd_1.c:24
mp_size_t lmmp_hyperfac_size_(ushort n, mp_bitcnt_t *bits)
计算hyper阶乘的 limb 缓冲区长度
mp_size_t lmmp_nCr_size_(uint n, uint r, mp_bitcnt_t *bits)
计算 nCr 组合数的 limb 缓冲区长度
void lmmp_binvert_4_(mp_ptr dst, mp_srcptr numa)
计算 [numa,4] 在 B^4 下的逆元
void lmmp_divexact_unbalanced_(mp_ptr dst, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn, mp_ptr dinv)
精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0)
mp_size_t lmmp_nCr_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, uint n, uint r)
计算 nCr 组合数 ( nCr = n! / (r!(n-r)!) )
uint16_t ushort
Definition numth.h:29
mp_size_t lmmp_nPr_size_(ulong n, ulong r, mp_bitcnt_t *bits)
计算 nPr 排列数的 limb 缓冲区长度
mp_size_t lmmp_primefac_(mp_ptr dst, mp_size_t rn, uint n)
计算质数阶乘(不超过n的质数累乘)
mp_size_t lmmp_pow_(mp_ptr dst, mp_size_t rn, mp_srcptr base, mp_size_t n, ulong exp)
计算大整数幂 [dst,rn] = [base,n] ^ exp
void lmmp_divexact_2_(mp_ptr dst, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_srcptr dinv)
精确除法([dst,nn]=[np,nn]/[dp,2],且余数必须为0)
void lmmp_cbrt_6_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
计算算数立方根 floor(cbrt([numa,na]))
Definition cbrt.c:152
int64_t * slongp
Definition numth.h:42
bool lmmp_is_prime_ulong_(ulong n)
判断素数
ulong lmmp_nthroot_ulong_(ulong n, ulong root)
计算 floor(n^(1/root))
Definition nthroot.c:55
mp_size_t lmmp_multinomial_(mp_ptr dst, mp_size_t rn, uint n, const uintp r, uint m)
计算多项式系数
uint64_t ulong
Definition numth.h:32
void lmmp_binvert_unbalanced_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t n, mp_ptr tp)
计算 [numa,na] 在 B^n 下的逆元
mp_limb_t lmmp_cbrtapprox_3_(mp_limb_t a0, mp_limb_t a1, mp_limb_t a2)
计算近似立方根 floor(cbrt(a0+a1*B+a2*B^2))-[0|1]
Definition cbrt.c:32
int32_t sint
Definition numth.h:33
mp_size_t lmmp_superfac_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, ushort n)
计算super阶乘(k!累乘至n)
ushortp lmmp_trialdiv_(mp_srcptr np, mp_size_t nn, ushort N, ushort *rn)
试除法
mp_size_t lmmp_arith_seqprod_(mp_ptr dst, mp_size_t rn, uint x, uint n, uint m)
计算等差数列乘积 x(x+m)...(x+n*m)
int32_t * sintp
Definition numth.h:40
mp_size_t lmmp_pow_size_(mp_srcptr base, mp_size_t n, ulong exp)
计算幂次方需要的limb缓冲区长度 [base,n] ^ exp
Definition pow.c:81
mp_size_t lmmp_odd_nPr_ulong_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
mp_size_t lmmp_odd_nCr_ushort_(mp_ptr dst, mp_size_t rn, uint n, uint r)
计算 nCr 组合数的奇数部分
ulong lmmp_next_prime_ulong_(ulong n)
大于n的下一个素数
mp_size_t lmmp_nPr_(mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数 ( nPr = n! / (n-r)! )
mp_size_t lmmp_gcd_22_(mp_ptr dst, mp_srcptr up, mp_srcptr vp)
计算两个无符号整数的最大公约数
Definition gcd_2.c:27
mp_size_t lmmp_odd_nPr_uint_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
void lmmp_binvert_unbalanced_2_(mp_ptr dst, mp_srcptr numa, mp_size_t n)
计算 [numa,2] 在 B^n 下的逆元
void lmmp_binvert_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t n)
计算 [numa,na] 在 B^n 下的逆元
void lmmp_divexact_divide_(mp_ptr dst, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
精确除法([dst,nn]=[np,nn]/[dp,dn],且余数必须为0),分治算法