LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
numth.h 文件参考
#include <stdbool.h>
#include "lmmp.h"
+ numth.h 的引用(Include)关系图:
+ 此图展示该文件直接或间接的被哪些文件引用了:

浏览源代码.

类型定义

typedef int8_t schar
 
typedef int8_tscharp
 
typedef int32_t sint
 
typedef int32_t * sintp
 
typedef int64_t slong
 
typedef int64_t * slongp
 
typedef int16_t sshort
 
typedef int16_tsshortp
 
typedef uint8_t uchar
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 
typedef uint8_t * ucharp
 
typedef uint32_t uint
 
typedef uint32_t * uintp
 
typedef uint64_t ulong
 
typedef uint64_t * ulongp
 
typedef uint16_t ushort
 
typedef uint16_tushortp
 

函数

mp_size_t lmmp_2factorial_ (mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
 计算 n!! 双阶乘
 
mp_size_t lmmp_2factorial_size_ (uint n, mp_bitcnt_t *bits)
 计算 n!! 双阶乘的 limb 缓冲区长度
 
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)
 
mp_size_t lmmp_arith_seqprod_size_ (uint x, uint n, uint m)
 计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度
 
void lmmp_binvert_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t n)
 计算 [numa,na] 在 B^n 下的逆元
 
void lmmp_binvert_2_ (mp_ptr dst, mp_srcptr numa)
 计算 [numa,2] 在 B^2 下的逆元
 
void lmmp_binvert_3_ (mp_ptr dst, mp_srcptr numa)
 计算 [numa,3] 在 B^3 下的逆元
 
void lmmp_binvert_4_ (mp_ptr dst, mp_srcptr numa)
 计算 [numa,4] 在 B^4 下的逆元
 
void lmmp_binvert_n_dc_ (mp_ptr dst, mp_srcptr numa, mp_size_t n, mp_ptr tp)
 计算 [numa,n] 在 B^n 下的逆元
 
uint lmmp_binvert_uint_ (uint a)
 计算 a 在2^32下的逆元
 
ulong lmmp_binvert_ulong_ (ulong a)
 计算 a 在2^64下的逆元
 
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 下的逆元
 
void lmmp_binvert_unbalanced_1_ (mp_ptr dst, mp_limb_t a, mp_size_t n)
 计算 a 在 B^n 下的逆元
 
void lmmp_binvert_unbalanced_2_ (mp_ptr dst, mp_srcptr numa, mp_size_t n)
 计算 [numa,2] 在 B^n 下的逆元
 
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))
 
void lmmp_cbrt_6_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 计算算数立方根 floor(cbrt([numa,na]))
 
ulong lmmp_cbrt_chebyshev_ (ulong n)
 计算算数立方根 floor(cbrt(n))
 
ulong lmmp_cbrt_ulong_ (ulong n)
 计算算数立方根 floor(cbrt(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]
 
void lmmp_cbrtapprox_6_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 计算近似立方根 floor(cbrt([numa,na]))-[0|1]
 
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)
 
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)
 
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_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),朴素算法
 
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),分治算法
 
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_factorial_ (mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
 计算 n! 阶乘
 
mp_size_t lmmp_factorial_size_ (uint n, mp_bitcnt_t *bits)
 计算 n! 阶乘的 limb 缓冲区长度
 
mp_limb_t lmmp_gcd_11_ (mp_limb_t u, mp_limb_t v)
 计算两个无符号整数的最大公约数
 
mp_limb_t lmmp_gcd_1_ (mp_srcptr up, mp_size_t un, mp_limb_t vlimb)
 计算两个无符号整数的最大公约数
 
mp_size_t lmmp_gcd_22_ (mp_ptr dst, mp_srcptr up, mp_srcptr vp)
 计算两个无符号整数的最大公约数
 
mp_size_t lmmp_gcd_2_ (mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp)
 计算两个无符号整数的最大公约数
 
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算法)
 
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_hyperfac_size_ (ushort n, mp_bitcnt_t *bits)
 计算hyper阶乘的 limb 缓冲区长度
 
bool lmmp_is_prime_notrial_ (ulong n)
 判断素数(无试除法)
 
bool lmmp_is_prime_uint_ (uint n)
 判断素数
 
bool lmmp_is_prime_ulong_ (ulong n)
 判断素数
 
ulong lmmp_mulmod_ulong_ (ulong a, ulong b, ulong mod, ulongp q)
 计算两个无符号整数的乘积,对mod取模,商放入 q 中
 
mp_size_t lmmp_multinomial_ (mp_ptr dst, mp_size_t rn, uint n, const uintp r, uint m)
 计算多项式系数
 
mp_size_t lmmp_multinomial_size_ (const uintp r, uint m, ulong *n)
 计算多项式系数的 limb 缓冲区长度
 
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)!) )
 
mp_size_t lmmp_nCr_size_ (uint n, uint r, mp_bitcnt_t *bits)
 计算 nCr 组合数的 limb 缓冲区长度
 
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_nPr_size_ (ulong n, ulong r, mp_bitcnt_t *bits)
 计算 nPr 排列数的 limb 缓冲区长度
 
ulong lmmp_nthroot_ulong_ (ulong n, ulong root)
 计算 floor(n^(1/root))
 
mp_size_t lmmp_odd_factorial_uint_ (mp_ptr dst, mp_size_t rn, uint n)
 计算 n! 阶乘的奇数部分
 
mp_size_t lmmp_odd_nCr_uint_ (mp_ptr dst, mp_size_t rn, uint n, uint r)
 计算 nCr 组合数的奇数部分
 
mp_size_t lmmp_odd_nCr_ushort_ (mp_ptr dst, mp_size_t rn, uint n, uint r)
 计算 nCr 组合数的奇数部分
 
mp_size_t lmmp_odd_nPr_uint_ (mp_ptr dst, mp_size_t rn, ulong n, ulong r)
 计算 nPr 排列数的奇数部分
 
mp_size_t lmmp_odd_nPr_ulong_ (mp_ptr dst, mp_size_t rn, ulong n, ulong r)
 计算 nPr 排列数的奇数部分
 
mp_size_t lmmp_odd_nPr_ushort_ (mp_ptr dst, mp_size_t rn, ulong n, ulong r)
 计算 nPr 排列数的奇数部分
 
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
 
mp_size_t lmmp_pow_1_ (mp_ptr dst, mp_size_t rn, mp_limb_t base, ulong exp)
 计算幂次方 [dst,rn] = [base,1] ^ exp
 
mp_size_t lmmp_pow_1_size_ (mp_limb_t base, ulong exp)
 计算幂次方需要的limb缓冲区长度 base ^ exp
 
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
 
mp_size_t lmmp_pow_size_ (mp_srcptr base, mp_size_t n, ulong exp)
 计算幂次方需要的limb缓冲区长度 [base,n] ^ exp
 
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
 
uint lmmp_powmod_uint_ (uint base, ulong exp, uint mod)
 计算 base^exp 对 mod 取模
 
ulong lmmp_powmod_ulong_ (ulong base, ulong exp, ulong mod)
 计算 base^exp 对 mod 取模
 
ulong lmmp_prev_prime_ulong_ (ulong n)
 小于等于n的上一个素数
 
mp_size_t lmmp_primefac_ (mp_ptr dst, mp_size_t rn, uint n)
 计算质数阶乘(不超过n的质数累乘)
 
mp_size_t lmmp_primefac_size_ (uint n)
 计算质数阶乘的 limb 缓冲区长度
 
mp_size_t lmmp_remove_ (mp_ptr np, mp_size_t *nn, mp_srcptr dp, mp_size_t dn)
 除去[np,nn]中的[dp,dn]的因子
 
ulong lmmp_sqrt_ulong_ (ulong a)
 计算算术平方根 floor(sqrt(a))
 
mp_size_t lmmp_superfac_ (mp_ptr dst, mp_bitcnt_t bits, mp_size_t rn, ushort n)
 计算super阶乘(k!累乘至n)
 
mp_size_t lmmp_superfac_size_ (ushort n, mp_bitcnt_t *bits)
 计算super阶乘的 limb 缓冲区长度
 
ushortp lmmp_trialdiv_ (mp_srcptr np, mp_size_t nn, ushort N, ushort *rn)
 试除法
 
mp_size_t lmmp_u16_pow_1_ (mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
 计算幂次方 [dst,rn] = [base,1] ^ exp
 
mp_size_t lmmp_u32_pow_1_ (mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
 计算幂次方 [dst,rn] = [base,1] ^ exp
 
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_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
 

类型定义说明

◆ schar

在文件 numth.h28 行定义.

◆ scharp

在文件 numth.h36 行定义.

◆ sint

typedef int32_t sint

在文件 numth.h33 行定义.

◆ sintp

typedef int32_t* sintp

在文件 numth.h40 行定义.

◆ slong

typedef int64_t slong

在文件 numth.h34 行定义.

◆ slongp

typedef int64_t* slongp

在文件 numth.h42 行定义.

◆ sshort

在文件 numth.h30 行定义.

◆ sshortp

在文件 numth.h38 行定义.

◆ uchar

typedef uint8_t uchar

Copyright (C) 2026 HJimmyK(Jericho Knox)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 numth.h27 行定义.

◆ ucharp

typedef uint8_t* ucharp

在文件 numth.h35 行定义.

◆ uint

typedef uint32_t uint

在文件 numth.h31 行定义.

◆ uintp

typedef uint32_t* uintp

在文件 numth.h39 行定义.

◆ ulong

typedef uint64_t ulong

在文件 numth.h32 行定义.

◆ ulongp

typedef uint64_t* ulongp

在文件 numth.h41 行定义.

◆ ushort

在文件 numth.h29 行定义.

◆ ushortp

在文件 numth.h37 行定义.

函数说明

◆ lmmp_2factorial_()

mp_size_t lmmp_2factorial_ ( mp_ptr  dst,
mp_bitcnt_t  bits,
mp_size_t  rn,
uint  n 
)

计算 n!! 双阶乘

参数
dst结果指针
bitsn!! 的2的因子数
rn结果指针的 limb 长度
n双阶乘的阶数
警告
dst!=NULL, rn>0
注解
0的双阶乘为1,n为偶数时,n!!=2*4*...*n,n为奇数时,n!!=1*3*...*n
返回
返回 dst 的实际 limb 长度

◆ lmmp_2factorial_size_()

mp_size_t lmmp_2factorial_size_ ( uint  n,
mp_bitcnt_t bits 
)

计算 n!! 双阶乘的 limb 缓冲区长度

参数
n双阶乘的阶数
bits被修改为 n!! 的2的因子数
警告
bits!=NULL
返回
n!! 双阶乘的 limb 缓冲区长度

◆ lmmp_arith_seqprod_()

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)

参数
dst结果指针
rn结果指针的 limb 长度
x首项
n等差数列共n+1项
m公差(大于1)
警告
x>0, m>1, n>0, dst!=NULL, rn>0, x+n*m<=0xffffffff
返回
结果的实际的 limb 缓冲区长度

◆ lmmp_arith_seqprod_size_()

mp_size_t lmmp_arith_seqprod_size_ ( uint  x,
uint  n,
uint  m 
)

计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度

参数
x首项
n等差数列共n+1项
m公差
警告
x>0, m>1, n>0, x+n*m<=0xffffffff
返回
等差数列乘积的 limb 缓冲区长度(比实际长度多 1-2 个 limb)

计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 arith_seqprod.c24 行定义.

24 {
28 // x(x+m)(x+2m)...(x+nm) <= (x+m*n/2)^(n+1)
29 ulong t = (x + ((ulong)m * n + 1) / 2);
31 // 共有n+1个数,每个数的位数最多为uint,一个limb最多可以容纳两个uint乘积
32 mp_size_t rn2 = (n + 1) / 2 + 1;
33 return LMMP_MIN(rn1, rn2);
34}
uint64_t mp_size_t
Definition lmmp.h:77
#define LMMP_MIN(l, o)
Definition lmmp.h:351
#define lmmp_param_assert(x)
Definition lmmp.h:401
#define t
#define n
mp_size_t lmmp_pow_1_size_(mp_limb_t base, ulong exp)
计算幂次方需要的limb缓冲区长度 base ^ exp
Definition pow.c:25
uint64_t ulong
Definition numth.h:32

引用了 LMMP_MIN, lmmp_param_assert, lmmp_pow_1_size_(), n , 以及 t.

+ 函数调用图:

◆ lmmp_binvert_()

void lmmp_binvert_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  n 
)

计算 [numa,na] 在 B^n 下的逆元

参数
dst结果指针(长度为 n 个limb)
numa待求逆元指针(长度为 na 个limb)
na待求逆元的 limb 长度
n结果的 limb 长度
警告
n>=na>0, numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)

◆ lmmp_binvert_2_()

void lmmp_binvert_2_ ( mp_ptr  dst,
mp_srcptr  numa 
)

计算 [numa,2] 在 B^2 下的逆元

参数
numa待求逆元指针(长度为 2 个limb)
dst结果指针(长度为 2 个limb)
警告
numa!=NULL, dst!=NULL, numa[0]%2==1, eqsep(dst,numa)

在文件 binvert_1.c56 行定义.

56 {
57 lmmp_param_assert(numa[0] % 2 == 1);
58 mp_limb_t k, t;
59 mp_limb_t a1 = numa[1];
60 mp_limb_t a0 = numa[0];
63 /*
64 xn * a0 == 1 + k * B
65 yn := xn * (2 - a * xn) mod B^2
66 := xn * (2 - a0 * xn - a1 * xn * B) mod B^2
67 := xn * (2 - 1 - k*B - a1 * xn * B) mod B^2
68 := xn * (1 - k*B - a1 * xn * B) mod B^2
69 := (xn - xn*k * B - a1 * xn^2 * B) mod B^2
70 */
71 _umul64to128_(a0, xn, &t, &k);
72 z = xn * k;
73 z += a1 * xn * xn;
74 dst[0] = xn;
75 dst[1] = -z;
76}
#define k
ulong lmmp_binvert_ulong_(ulong a)
计算 a 在2^64下的逆元
Definition binvert_1.c:42
#define xn
uint64_t mp_limb_t
Definition lmmp.h:76
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:174
#define a0
#define a1

引用了 _umul64to128_(), a0, a1, k, lmmp_binvert_ulong_(), lmmp_param_assert, n, t , 以及 xn.

被这些函数引用 lmmp_binvert_3_(), lmmp_binvert_4_(), lmmp_binvert_n_dc_(), lmmp_binvert_unbalanced_2_() , 以及 lmmp_divexact_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_binvert_3_()

void lmmp_binvert_3_ ( mp_ptr  dst,
mp_srcptr  numa 
)

计算 [numa,3] 在 B^3 下的逆元

参数
numa待求逆元指针(长度为 3 个limb)
dst结果指针(长度为 3 个limb)
警告
numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)

被这些函数引用 lmmp_binvert_n_dc_().

+ 这是这个函数的调用关系图:

◆ lmmp_binvert_4_()

void lmmp_binvert_4_ ( mp_ptr  dst,
mp_srcptr  numa 
)

计算 [numa,4] 在 B^4 下的逆元

参数
numa待求逆元指针(长度为 4 个limb)
dst结果指针(长度为 4 个limb)
警告
numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa)

被这些函数引用 lmmp_binvert_n_dc_().

+ 这是这个函数的调用关系图:

◆ lmmp_binvert_n_dc_()

void lmmp_binvert_n_dc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  n,
mp_ptr  tp 
)

计算 [numa,n] 在 B^n 下的逆元

参数
numa待求逆元指针(长度为 n 个limb)
dst结果指针(长度为 n 个limb)
n结果的 limb 长度
tp临时工作区指针(长度为 5*(n+1)/2 个limb)
警告
numa!=NULL, dst!=NULL, numa[0]%2==1, sep(dst,numa,tp)

被这些函数引用 lmmp_divexact_divide_() , 以及 lmmp_divexact_unbalanced_().

+ 这是这个函数的调用关系图:

◆ lmmp_binvert_uint_()

uint lmmp_binvert_uint_ ( uint  a)

计算 a 在2^32下的逆元

参数
a待求逆元
警告
a%2==1
返回
逆元

在文件 binvert_1.c30 行定义.

30 {
31 lmmp_param_assert(a % 2 == 1);
32 uint r, y;
33
34 r = binv_tab[(a / 2) & 0x7F]; /* 8 bits */
35 y = 1 - a * r;
36 r = r * (1 + y); /* 16 bits */
37 y *= y;
38 r = r * (1 + y); /* 32 bits */
39 return r;
40}
static const uchar binv_tab[128]
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition binvert_1.c:22
uint32_t uint
Definition numth.h:31

引用了 binv_tab, lmmp_param_assert , 以及 n.

◆ lmmp_binvert_ulong_()

ulong lmmp_binvert_ulong_ ( ulong  a)

计算 a 在2^64下的逆元

参数
a待求逆元
警告
a%2==1
返回
逆元

在文件 binvert_1.c42 行定义.

42 {
43 lmmp_param_assert(a % 2 == 1);
44 ulong r, y;
45
46 r = binv_tab[(a / 2) & 0x7F]; /* 8 bits */
47 y = 1 - a * r;
48 r = r * (1 + y); /* 16 bits */
49 y *= y;
50 r = r * (1 + y); /* 32 bits */
51 y *= y;
52 r = r * (1 + y); /* 64 bits */
53 return r;
54}

引用了 binv_tab, lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_binvert_2_(), lmmp_binvert_n_dc_(), lmmp_binvert_unbalanced_1_(), lmmp_divexact_(), lmmp_is_prime_notrial_() , 以及 lmmp_powmod_ulong_().

+ 这是这个函数的调用关系图:

◆ lmmp_binvert_unbalanced_()

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 下的逆元

参数
dst结果指针(长度为 n 个limb)
numa待求逆元指针(长度为 na 个limb)
na待求逆元的 limb 长度
n结果的 limb 长度
tp临时工作区指针(长度为 (9*na+5)/2 个limb)
警告
numa[0]%2==1, n>na, dst!=NULL, numa!=NULL, tp!=NULL, sep(dst,numa,tp)

◆ lmmp_binvert_unbalanced_1_()

void lmmp_binvert_unbalanced_1_ ( mp_ptr  dst,
mp_limb_t  a,
mp_size_t  n 
)

计算 a 在 B^n 下的逆元

参数
dst结果指针(长度为 n 个limb)
a待求逆元
n结果的 limb 长度
警告
a%2==1, n>1, dst!=NULL

被这些函数引用 lmmp_binvert_().

+ 这是这个函数的调用关系图:

◆ lmmp_binvert_unbalanced_2_()

void lmmp_binvert_unbalanced_2_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  n 
)

计算 [numa,2] 在 B^n 下的逆元

参数
dst结果指针(长度为 n 个limb)
numa待求逆元指针(长度为 2 个limb)
n结果的 limb 长度
警告
numa[0]%2==1, n>2, dst!=NULL, numa!=NULL, sep(dst,numa)

被这些函数引用 lmmp_binvert_().

+ 这是这个函数的调用关系图:

◆ lmmp_cbrt_3_()

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))

参数
a0低位 limb
a1中位 limb
a2高位 limb
警告
a1>0
注解
a2可以为0,但a1需要大于0,即这个数至少应有65个bit
返回
floor(cbrt(a0+a1*B+a2*B^2))

在文件 cbrt.c74 行定义.

74 {
76
78 if (r == LIMB_MAX)
79 return LIMB_MAX;
80 mp_limb_t t[3], a[3] = {a0, a1, a2};
81 lmmp_cube_3_(t, r + 1);
82 int cmp = lmmp_cmp_(t, a, 3);
83 // approx的结果至多只会低估1
84 if (cmp <= 0)
85 return r + 1;
86 else
87 return r;
88}
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
static void lmmp_cube_3_(mp_ptr restrict dst, mp_limb_t a)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition cbrt.c:23
#define LIMB_MAX
Definition lmmp.h:89
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
#define a2

引用了 a0, a1, a2, LIMB_MAX, lmmp_cbrtapprox_3_(), lmmp_cmp_(), lmmp_cube_3_(), lmmp_param_assert, n , 以及 t.

+ 函数调用图:

◆ lmmp_cbrt_6_()

void lmmp_cbrt_6_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

计算算数立方根 floor(cbrt([numa,na]))

参数
dst结果指针(长度为 2 个limb)
numa被开方数指针
na被开方数的 limb 长度
警告
dst!=NULL, numa!=NULL, 3<na<=6, numa[na-1]!=0, eqsep(dst,numa)

在文件 cbrt.c152 行定义.

152 {
153 mp_limb_t ret[2];
155
156 if (ret[1] == LIMB_MAX && ret[0] == LIMB_MAX) {
157 dst[0] = LIMB_MAX;
158 dst[1] = LIMB_MAX;
159 } else {
160 mp_limb_t r[2];
161 r[0] = ret[0] + 1;
162 r[1] = ret[1] + (r[0] == 0 ? 1 : 0);
163 mp_limb_t t[10];
164 mp_size_t tn = lmmp_cube_(t, r, 2, t + 6);
165 if (tn < na) {
166 dst[0] = r[0];
167 dst[1] = r[1];
168 } else if (tn > na) {
169 dst[0] = ret[0];
170 dst[1] = ret[1];
171 } else if (tn == na) {
172 int cmp = lmmp_cmp_(t, numa, tn);
173 // approx的结果至多只会低估1
174 if (cmp <= 0) {
175 dst[0] = r[0];
176 dst[1] = r[1];
177 } else {
178 dst[0] = ret[0];
179 dst[1] = ret[1];
180 }
181 }
182 }
183}
static mp_size_t lmmp_cube_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na, mp_ptr restrict tp)
计算 [numa, na] 的立方
Definition cbrt.c:98
void lmmp_cbrtapprox_6_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
计算近似立方根 floor(cbrt([numa,na]))-[0|1]
Definition cbrt.c:106

引用了 LIMB_MAX, lmmp_cbrtapprox_6_(), lmmp_cmp_(), lmmp_cube_(), n , 以及 t.

+ 函数调用图:

◆ lmmp_cbrt_chebyshev_()

ulong lmmp_cbrt_chebyshev_ ( ulong  n)

计算算数立方根 floor(cbrt(n))

参数
n被开方数
返回
floor(cbrt(n))
警告
n>0
注解
使用Chebyshev估计,当n较大时,此算法更占优势

在文件 cbrt_1.c40 行定义.

40 {
42 typedef union {
44 double double_val;
45 } uni;
46
47 int rem, mul;
48 double factor, root, dec, dec2;
50 uni alias;
51
52 /* upper_limit is the max cube root possible for one word */
53
54 const ulong upper_limit = 2642245; /* 2642245 < (2^64)^(1/3) */
55 const ulong expo_mask = 0x7FF0000000000000; /* exponent bits in double */
56 const ulong mantissa_mask = 0x000FFFFFFFFFFFFF; /* mantissa bits in float */
57 const ulong table_mask = 0x000F000000000000; /* first 4 bits of mantissa */
58 const uint mantissa_bits = 52;
59 const ulong bias_hex = 0x3FE0000000000000;
60 const uint bias = 1022;
61 alias.double_val = (double)n;
62
63 expo = alias.uword_val & expo_mask; /* extracting exponent */
65 expo -= bias; /* Subtracting bias */
66
67 /* extracting first 4 bits of mantissa, this will help select correct poly */
68 /* note mantissa of 0.5 is 0x0000000000000 not 0x1000000000000 */
69
70 table_index = alias.uword_val & table_mask;
71 table_index >>= (mantissa_bits - 4);
72
73 /* extracting decimal part, 0.5 <= dec <= 1 */
74 ret = alias.uword_val & mantissa_mask;
75 ret |= bias_hex;
76 alias.uword_val = ret;
77 dec = alias.double_val;
78
79 rem = expo % 3;
80 expo /= 3; /* cube root of 2^expo */
81 factor = factor_table[rem]; /* select factor */
82
83 /* Calculating cube root of dec using chebyshev approximation polynomial */
84 /* Evaluating approx polynomial at (dec) by Estrin's scheme */
85
86 dec2 = dec * dec;
87 root = (coeff[table_index][0] + coeff[table_index][1] * dec);
88 root += (coeff[table_index][2] * dec2);
89
90 mul = (ulong)1 << expo; /* mul = 2^expo */
91 root *= mul; /* dec^(1/3) * 2^(expo/3) */
92 root *= factor; /* root*= (expo%3)^(1/3) */
93 ret = root;
94
95 /* In case ret^3 or (ret+1)^3 will cause overflow */
96
97 if (ret >= upper_limit) {
99 return upper_limit;
100 ret = upper_limit - 1;
101 }
102 while (ret * ret * ret <= n) {
103 (ret) += 1;
104 if (ret == upper_limit)
105 break;
106 }
107 while (ret * ret * ret > n) (ret) -= 1;
108
109 return ret;
110}
static const float coeff[16][3]
Definition cbrt_1.c:23
static const float factor_table[]
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition cbrt_1.c:20

引用了 coeff, factor_table, lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_cbrt_ulong_().

+ 这是这个函数的调用关系图:

◆ lmmp_cbrt_ulong_()

ulong lmmp_cbrt_ulong_ ( ulong  n)

计算算数立方根 floor(cbrt(n))

参数
n被开方数
返回
floor(cbrt(n))
注解
会依据n的大小,选择合适的算法

在文件 cbrt_1.c133 行定义.

133 {
134 double val, x, xcub, num, den;
136
137 if (n < 125)
138 return (n >= 1) + (n >= 8) + (n >= 27) + (n >= 64);
139 if (n < 1331)
140 return 5 + (n >= 216) + (n >= 343) + (n >= 512) + (n >= 729) + (n >= 1000);
141 if (n < 4913)
142 return 11 + (n >= 1728) + (n >= 2197) + (n >= 2744) + (n >= 3375) + (n >= 4096);
143
144 val = (double)n;
145
146 if (n >= 1ULL << 46)
147 return lmmp_cbrt_chebyshev_(n);
148
149 upper_limit = 2642245; /* 2642245 = floor((2^64)^(1/3)) */
150
151 x = lmmp_cbrt_estimate((double)n);
152
153 /* Kahan's iterations to get cube root */
154
155 xcub = x * x * x;
156 num = (xcub - val) * x;
157 den = (xcub + xcub + val);
158 x -= (num / den);
159 ret = x;
160
161 if (ret >= upper_limit) {
163 return upper_limit;
164 ret = upper_limit - 1;
165 }
166 while (ret * ret * ret <= n) {
167 (ret) += 1;
168 if (ret == upper_limit)
169 break;
170 }
171 while (ret * ret * ret > n) (ret) -= 1;
172
173 return ret;
174}
static double lmmp_cbrt_estimate(double a)
Definition cbrt_1.c:112
ulong lmmp_cbrt_chebyshev_(ulong n)
计算算数立方根 floor(cbrt(n))
Definition cbrt_1.c:40

引用了 lmmp_cbrt_chebyshev_(), lmmp_cbrt_estimate() , 以及 n.

被这些函数引用 lmmp_nthroot_ulong_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_cbrtapprox_3_()

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]

参数
a0低位 limb
a1中位 limb
a2高位 limb
警告
a1>0
注解
a2可以为0,但a1需要大于0,即这个数至少应有65个bit
返回
floor(cbrt(a0+a1*B+a2*B^2))-[0|1]

在文件 cbrt.c32 行定义.

32 {
34 mp_limb_t x[2];
35 /* exact high 65 bits */
38 if (a2 == 0) {
41 a1_bits--;
42 if (a1_bits == 0)
43 a_hi = a0;
44 else
45 a_hi = (a1 << (LIMB_BITS - a1_bits)) | (a0 >> a1_bits);
46 } else {
48 bits = LIMB_BITS * 2 + a2_bits;
49 a2_bits--;
50 if (a2_bits == 0)
51 a_hi = a1;
52 else
53 a_hi = (a2 << (LIMB_BITS - a2_bits)) | (a1 >> a2_bits);
54 }
56
57 x[1] = bits - 1;
58 x[0] = log2_fixed_64(a_hi);
59
60 mp_limb_t r = lmmp_div_1_(x, x, 2, 3);
61 if (2 * r >= 3) // round
62 lmmp_inc(x);
63
64 mp_bitcnt_t shift = x[1];
65 x[0] = exp2_fixed_64(x[0]);
66
68 if (shift == 64)
69 return LIMB_MAX;
70 else
71 return (x[0] >> (64 - shift)) | (1ULL << shift);
72}
#define lmmp_limb_bits_
Definition inlines.h:162
size_t mp_bitcnt_t
Definition lmmp.h:82
#define lmmp_debug_assert(x)
Definition lmmp.h:390
#define LIMB_BITS
Definition lmmp.h:86
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:77
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
uint64_t exp2_fixed_64(uint64_t x)
floor(exp2(x/B)*B-B), B=2^64
Definition log2_exp2.c:485
uint64_t log2_fixed_64(uint64_t x)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition log2_exp2.c:458

引用了 a0, a1, a2, exp2_fixed_64(), LIMB_BITS, LIMB_MAX, lmmp_debug_assert, lmmp_div_1_(), lmmp_inc, lmmp_limb_bits_, lmmp_param_assert, log2_fixed_64() , 以及 n.

被这些函数引用 lmmp_cbrt_3_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_cbrtapprox_6_()

void lmmp_cbrtapprox_6_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

计算近似立方根 floor(cbrt([numa,na]))-[0|1]

参数
dst结果指针(长度为 2 个limb)
numa被开方数指针
na被开方数的 limb 长度
警告
dst!=NULL, numa!=NULL, 3<na<=6, numa[na-1]!=0, eqsep(dst,numa)

在文件 cbrt.c106 行定义.

106 {
107 lmmp_param_assert(na > 3 && na <= 6);
109 lmmp_param_assert(numa[na - 1] != 0);
110 /* extract the first 129 bits */
111 int bits = lmmp_limb_bits_(numa[na - 1]);
112 mp_bitcnt_t n = bits - 1;
114 if (bits == 1) {
115 high = numa[na - 2];
116 low = numa[na - 3];
117 } else {
118 bits--;
119 high = (numa[na - 1] << (64 - bits)) | (numa[na - 2] >> bits);
120 low = (numa[na - 2] << (64 - bits)) | (numa[na - 3] >> bits);
121 }
122
123 n += LIMB_BITS * (na - 1);
124 mp_limb_t x[3] = {0, 0, n};
125
127 mp_limb_t r = lmmp_div_1_(x, x, 3, 3);
128 if (2 * r >= 3) // round
129 lmmp_inc(x);
130
131 n = x[2];
132 high = x[1];
133 low = x[0];
134
136
137 lmmp_debug_assert(n >= 64 && n <= 128);
138 if (n == 64) {
139 dst[0] = x[1];
140 dst[1] = 1;
141 } else if (n < 128) {
142 n -= 64;
143 mp_limb_t t = 1ULL << n;
144 dst[1] = (x[1] >> (64 - n)) | t;
145 dst[0] = (x[1] << n) | (x[0] >> (64 - n));
146 } else {
147 dst[1] = LIMB_MAX;
148 dst[0] = LIMB_MAX;
149 }
150}
void exp2_fixed_128(uint64_t *dst, uint64_t high, uint64_t low)
floor(exp2(x/B)*B-B), B=2^128
Definition log2_exp2.c:409
void log2_fixed_128(uint64_t *dst, uint64_t high, uint64_t low)
floor(log2(1+x/B)*B), B=2^128
Definition log2_exp2.c:292

引用了 exp2_fixed_128(), LIMB_BITS, LIMB_MAX, lmmp_debug_assert, lmmp_div_1_(), lmmp_inc, lmmp_limb_bits_, lmmp_param_assert, log2_fixed_128(), n , 以及 t.

被这些函数引用 lmmp_cbrt_6_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_divexact_()

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)

参数
dst结果指针(长度为 nn-dn+1 个limb)
np被除数指针(长度为 nn 个limb)
nn被除数的 limb 长度
dp除数指针(长度为 dn 个limb)
dn结除数的 limb 长度
警告
dp[0]%2==1, nn>=dn>0, dst!=NULL, np!=NULL, dp!=NULL, eqsep(dst,np), sep([dst|np],dp)

被这些函数引用 lmmp_odd_nCr_div_().

+ 这是这个函数的调用关系图:

◆ lmmp_divexact_1_()

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)

参数
dst结果指针(长度为 nn 个limb)
np被除数指针(长度为 nn 个limb)
nn被除数的 limb 长度
d除数
dinv除数的逆元(d*dinv==1 mod 2^64)
警告
d%2==1, d*dinv==1 mod 2^64, nn>0, dst!=NULL, np!=NULL, eqsep(dst,np)

精确除法([dst,nn]=[np,nn]/d,且余数必须为0)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 divexact.c24 行定义.

24 {
25 lmmp_param_assert(d % 2 == 1);
26 lmmp_param_assert(dinv * d == 1);
27 lmmp_param_assert(nn > 0);
28 lmmp_debug_assert(dst != NULL && np != NULL);
29 mp_limb_t c = 0;
30 mp_limb_t l, s, lo, hi, q;
32 for (i = 0; i < nn - 1; i++) {
33 s = np[i];
34 l = s - c;
35 c = l > s;
36 q = l * dinv;
37 dst[i] = q;
38 _umul64to128_(q, d, &lo, &hi);
39 c += hi;
40 }
41 s = np[i];
42 l = s - c;
43 c = l > s;
44 q = l * dinv;
45 dst[i] = q;
46 lmmp_debug_assert(c == 0);
47}
#define l
#define c
#define s
#define lo

引用了 _umul64to128_(), c, l, lmmp_debug_assert, lmmp_param_assert, lo, n , 以及 s.

被这些函数引用 lmmp_divexact_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_divexact_2_()

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)

参数
dst结果指针(长度为 nn-1 个limb)
np被除数指针(长度为 nn 个limb)
nn被除数的 limb 长度
dp除数指针(长度为 2 个limb)
dinv除数的逆元指针(长度为 2 个limb)
警告
dp[0]%2==1, dp*dinv==1 mod 2^128, nn>1, dst!=NULL, np!=NULL, eqsep(dst,np), sep(dp,dinv,[dst|np])

◆ lmmp_divexact_basecase_()

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),朴素算法

参数
dst结果指针(长度为 nn-dn+1 个limb)
np被除数指针(长度为 nn 个limb),将会被覆写为全零
nn被除数的 limb 长度
dp除数指针(长度为 dn 个limb)
dn结除数的 limb 长度
dinv除数低位dp[0]关于B的逆元
警告
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])
注解
若dst==np,将会覆写 [dst,nn] 区域,其中 [dst,nn-dn+1] 为商,[dst+nn-dn+1,dn-1] 将会被覆写为0

◆ lmmp_divexact_divide_()

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),分治算法

参数
dst结果指针(长度为 nn-dn+1 个limb)
np被除数指针(长度为 nn 个limb)
nn被除数的 limb 长度
dp除数指针(长度为 dn 个limb)
dn结除数的 limb 长度
警告
dp[0]%2==1, nn>=dn>0, dn>=nn-dn+1, dst!=NULL, np!=NULL, dp!=NULL, sep(dst,np,dp)

◆ lmmp_divexact_unbalanced_()

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)

参数
dst结果指针(长度为 nn-dn+1 个limb)
np被除数指针(长度为 nn 个limb),将会被修改为全零
nn被除数的 limb 长度
dp除数指针(长度为 dn 个limb)
dn结除数的 limb 长度
dinv除数[dp,dn]关于B^dn的逆元,若为NULL,则自动计算
警告
dp[0]%2==1, nn>=dn>0, dst!=NULL, np!=NULL, dp!=NULL, eqsep(dst,np), sep(dp,dinv,[dst|np])
注解
若dst==np,只会覆写 [dst,nn-dn+1] 区域

◆ lmmp_factorial_()

mp_size_t lmmp_factorial_ ( mp_ptr  dst,
mp_bitcnt_t  bits,
mp_size_t  rn,
uint  n 
)

计算 n! 阶乘

参数
dst结果指针
bitsn! 的2的因子数
rn结果指针的 limb 长度
n阶乘的阶数
警告
dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

◆ lmmp_factorial_size_()

mp_size_t lmmp_factorial_size_ ( uint  n,
mp_bitcnt_t bits 
)

计算 n! 阶乘的 limb 缓冲区长度

参数
n阶乘的阶数
bits被修改为 n! 的2的因子数
警告
bits!=NULL
返回
n! 阶乘的 limb 缓冲区长度(比实际长度多)

被这些函数引用 lmmp_odd_nCr_uint_().

+ 这是这个函数的调用关系图:

◆ lmmp_gcd_11_()

mp_limb_t lmmp_gcd_11_ ( mp_limb_t  u,
mp_limb_t  v 
)

计算两个无符号整数的最大公约数

参数
u第一个无符号整数
v第二个无符号整数
返回
最大公约数
警告
u!=0, v!=0

计算两个无符号整数的最大公约数

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 gcd_1.c24 行定义.

24 {
25 lmmp_param_assert(u > 0 && v > 0);
26 int count, k;
30 while (u != v) {
31 if (u > v) {
32 u -= v;
34 u >>= count;
35 } else {
36 v -= u;
38 v >>= count;
39 }
40 }
41 return u << k;
42}
#define k
#define lmmp_tailing_zeros_
Definition inlines.h:161

引用了 k, lmmp_param_assert, lmmp_tailing_zeros_ , 以及 n.

被这些函数引用 lmmp_gcd_1_(), lmmp_gcd_22_() , 以及 lmmp_gcd_lehmer_().

+ 这是这个函数的调用关系图:

◆ lmmp_gcd_1_()

mp_limb_t lmmp_gcd_1_ ( mp_srcptr  up,
mp_size_t  un,
mp_limb_t  vlimb 
)

计算两个无符号整数的最大公约数

参数
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
v第二个无符号整数
警告
v!=0, up!=NULL, un>0
返回
最大公约数

在文件 gcd_1.c44 行定义.

44 {
48 if (un == 1) {
49 ulimb = up[0];
50 } else {
52 }
53 if (ulimb == 0)
54 return vlimb;
55 else
56 return lmmp_gcd_11_(ulimb, vlimb);
57}
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition gcd_1.c:24
mp_limb_t lmmp_mod_1_(mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数取余
Definition div.c:31

引用了 lmmp_gcd_11_(), lmmp_mod_1_(), lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_gcd_lehmer_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_gcd_22_()

mp_size_t lmmp_gcd_22_ ( mp_ptr  dst,
mp_srcptr  up,
mp_srcptr  vp 
)

计算两个无符号整数的最大公约数

参数
up第一个无符号整数指针,长度为 2
vp第二个无符号整数指针,长度为 2
dst结果指针(长度为 2,两个 limb 都会进行写入,即使最高位可能为0)
警告
up!=NULL, vp!=NULL, [up,2]!=0, [vp,2]!=0, dst!=NULL, eqsep(dst,[up|vp])
注解
我们不要求 up 和 vp 的高位不为 0,但要求两个数均不可以高低位全为 0
返回
dst 的实际 limb 长度

计算两个无符号整数的最大公约数

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 gcd_2.c27 行定义.

27 {
31 lmmp_param_assert(!(up[1] == 0 && up[0] == 0));
32 lmmp_param_assert(!(vp[1] == 0 && vp[0] == 0));
33 mp_limb_t u[2] = { up[0], up[1] };
34 mp_limb_t v[2] = { vp[0], vp[1] };
35 int k, cnt;
36
37 if (u[1] == 0 && v[1] == 0) {
38 dst[0] = lmmp_gcd_11_(u[0], v[0]);
39 dst[1] = 0;
40 return 1;
41 } else if (u[1] == 0) {
42 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
43 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
44 goto gcd_1_2;
45 } else if (v[1] == 0) {
46 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
47 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
48 goto gcd_2_1;
49 }
50
51 if (u[0] == 0 && v[0] == 0) {
52 dst[0] = lmmp_gcd_11_(u[1], v[1]);
53 dst[1] = 0;
54 return 1;
55 } else if (u[0] == 0) {
56 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
58 goto gcd_1_2;
59 } else if (v[0] == 0) {
60 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
62 goto gcd_2_1;
63 }
64 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
66
67 if (k > 0)
68 _u128lshr(u, u, k);
70 if (k > 0)
71 _u128lshr(v, v, k);
72 while (!(u[0] == v[0] && u[1] == v[1])) {
73 if (u[1] == 0 && v[1] != 0) goto gcd_1_2;
74 if (v[1] == 0 && u[1] != 0) goto gcd_2_1;
75 if (u[1] == 0 && v[1] == 0) goto gcd_1_1;
76
77 if (_u128cmp(u, v)) {
78 _u128sub(v, v, u);
79 if (v[0] == 0) {
80 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
81 goto gcd_2_1;
82 } else if (v[1] == 0) {
83 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
84 goto gcd_2_1;
85 }
87 // k > 0
88 _u128lshr(v, v, k);
89 } else {
90 _u128sub(u, u, v);
91 if (u[0] == 0) {
92 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
93 goto gcd_1_2;
94 } else if (u[1] == 0) {
95 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
96 goto gcd_1_2;
97 }
99 // k > 0
100 _u128lshr(u, u, k);
101 }
102 }
103 dst[0] = u[0];
104 dst[1] = u[1];
105 if (cnt > 0)
106 _u128lshl(dst, dst, cnt);
107 return 2;
108
109 gcd_1_2: // [u,1] , [v,2]
110 k = lmmp_tailing_zeros_(v[0]);
111 if (k > 0)
112 _u128lshr(v, v, k);
113 while (v[1] != 0) {
114 _u128sub64(v, v, u[0]);
115 if (v[1] == 0)
116 goto gcd_1_1;
117 if (v[0] == 0) {
118 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
119 goto gcd_1_1;
120 }
121 k = lmmp_tailing_zeros_(v[0]);
122 // k > 0
123 _u128lshr(v, v, k);
124 }
125 goto gcd_1_1;
126
127 gcd_2_1: // [u,2] , [v,1]
128 k = lmmp_tailing_zeros_(u[0]);
129 if (k > 0)
130 _u128lshr(u, u, k);
131 while (u[1] != 0) {
132 _u128sub64(u, u, v[0]);
133 if (u[1] == 0)
134 goto gcd_1_1;
135 if (u[0] == 0) {
136 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
137 goto gcd_1_1;
138 }
139 k = lmmp_tailing_zeros_(u[0]);
140 // k > 0
141 _u128lshr(u, u, k);
142 }
143 goto gcd_1_1;
144
145 gcd_1_1: // [u,1] , [v,1]
146 while (u[0] != v[0]) {
147 if (u[0] > v[0]) {
148 u[0] -= v[0];
149 u[0] >>= lmmp_tailing_zeros_(u[0]);
150 } else {
151 v[0] -= u[0];
152 v[0] >>= lmmp_tailing_zeros_(v[0]);
153 }
154 }
155 dst[0] = u[0];
156 dst[1] = 0;
157 if (cnt > 0)
158 _u128lshl(dst, dst, cnt);
159 return dst[1] == 0 ? 1 : 2;
160}
#define _u128lshl(x, y, n)
Definition longlong.h:330
#define _u128sub(r, x, y)
Definition longlong.h:368
#define _u128cmp(x, y)
Definition longlong.h:366
#define _u128lshr(x, y, n)
Definition longlong.h:336
#define _u128sub64(r, x, _i64)
Definition longlong.h:358
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算两个无符号整数的最大公约数
Definition gcd_1.c:24

引用了 _u128cmp, _u128lshl, _u128lshr, _u128sub, _u128sub64, k, lmmp_gcd_11_(), lmmp_param_assert, lmmp_tailing_zeros_ , 以及 n.

被这些函数引用 lmmp_gcd_2_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_gcd_2_()

mp_size_t lmmp_gcd_2_ ( mp_ptr  dst,
mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp 
)

计算两个无符号整数的最大公约数

参数
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
vp第二个无符号整数指针,长度为 2
dst结果指针(长度至少为 2,两个 limb 都会进行写入,即使最高位可能为0)
警告
up!=NULL, un>2, vp!=NULL, vp[1]!=0, dst!=NULL, eqsep(dst,[up|vp])
返回
dst 的实际 limb 长度

在文件 gcd_2.c162 行定义.

162 {
167 lmmp_param_assert(vp[1] != 0);
168 mp_limb_t u[2] = {vp[0], vp[1]};
169 lmmp_mod_2_(up, un, u);
170 if (u[1] == 0 && u[0] == 0) {
171 dst[0] = vp[0];
172 dst[1] = vp[1];
173 return 2;
174 } else {
175 return lmmp_gcd_22_(dst, vp, u);
176 }
177}
mp_size_t lmmp_gcd_22_(mp_ptr dst, mp_srcptr up, mp_srcptr vp)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition gcd_2.c:27
void lmmp_mod_2_(mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数取余 (除数为2个limb)
Definition div.c:155

引用了 lmmp_gcd_22_(), lmmp_mod_2_(), lmmp_param_assert , 以及 n.

+ 函数调用图:

◆ lmmp_gcd_basecase_()

mp_size_t lmmp_gcd_basecase_ ( mp_ptr  dst,
mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp,
mp_size_t  vn 
)

计算两个无符号整数的最大公约数(不建议使用此算法,更高版本可能被彻底弃用)

参数
dst结果指针(长度至少为 min(un,vn)
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
vp第二个无符号整数指针
vn第二个无符号整数的 limb 长度
警告
up!=NULL, un>0, vp!=NULL, vn>0, eqsep(dst,[up|vp]), dst!=NULL
注解
朴素的辗转相除法,与Lehmer算法具有相似的渐进时间复杂度,但Lehmer算法绝大多数场合更加优秀
返回
dst 的实际 limb 长度

计算两个无符号整数的最大公约数(不建议使用此算法,更高版本可能被彻底弃用)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 gcd_basecase.c20 行定义.

20 {
21 lmmp_param_assert(un > 0 && vn > 0);
22 if (un < vn) {
25 } else if (un == vn) {
26 int cmp = lmmp_cmp_(up, vp, un);
27 if (cmp < 0) {
29 } else if (cmp == 0) {
30 lmmp_copy(dst, up, un);
31 return un;
32 }
33 }
35#define an un
36#define bn vn
39 lmmp_copy(a, up, an);
40 lmmp_copy(b, vp, bn);
41 while (bn > 0 || (bn == 1 && b[0] == 0)) {
42 // dst = a % b;
43 lmmp_div_(NULL, dst, a, an, b, bn);
44 lmmp_copy(a, b, bn);
45 an = bn;
46 while (dst[bn - 1] == 0 && bn > 0) {
47 --bn;
48 }
49 lmmp_copy(b, dst, bn);
50 }
51 lmmp_copy(dst, a, an);
53 return an;
54#undef an
55#undef bn
56}
#define an
#define bn
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define LMMP_SWAP(x, y, type)
Definition lmmp.h:355
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
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
#define TEMP_DECL
Definition tmp_alloc.h:131
#define TEMP_FREE
Definition tmp_alloc.h:150
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:148

引用了 an, bn, lmmp_cmp_(), lmmp_copy, lmmp_div_(), lmmp_param_assert, LMMP_SWAP, n, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

+ 函数调用图:

◆ lmmp_gcd_lehmer_()

mp_size_t lmmp_gcd_lehmer_ ( mp_ptr  dst,
mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp,
mp_size_t  vn 
)

计算两个无符号整数的最大公约数(Lehmer算法)

参数
dst结果指针(长度至少为 min(un,vn)
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
vp第二个无符号整数指针
vn第二个无符号整数的 limb 长度
警告
up!=NULL, un>0, vp!=NULL, vn>0, eqsep(dst,[up|vp]), dst!=NULL
返回
dst 的实际 limb 长度

在文件 gcd_lehmer.c242 行定义.

242 {
243 lmmp_param_assert(un > 0 && vn > 0);
244 lmmp_param_assert(up != NULL && vp != NULL);
246
247 if (un < vn) {
250 } else if (un == vn) {
251 int cmp = lmmp_cmp_(up, vp, un);
252 if (cmp == 0) {
253 lmmp_copy(dst, up, un);
254 return un;
255 } else if (cmp < 0) {
257 }
258 }
259 // u > v
260
262 slong x = 0, y = 0;
263
264#define an un
265#define bn vn
267 // [a,an+1] [b,bn+1]
268 // A * a_old may overlow
272 mp_ptr temp = BALLOC_TYPE((an + 1) * 3, mp_limb_t);
273 ms.tp = temp;
274 ms.mp = temp + (an + 1);
275 ms.np = temp + (an + 1) * 2;
276
277 lmmp_copy(a, up, an);
278 lmmp_copy(b, vp, bn);
279
280 bool bzero = false;
281 while (bzero == false) {
282 if (an > 1 && bn == 1) {
283 dst[0] = lmmp_gcd_1_(a, an, b[0]);
284 return 1;
285 } else if (an == 1 && bn == 1) {
286 dst[0] = lmmp_gcd_11_(a[0], b[0]);
287 return 1;
288 }
289 // a > b
290 lmmp_lehmer_extract_(a, an, b, bn, &x, &y);
292
293 if (M.m21 == 0) {
294 lmmp_div_(NULL, dst, a, an, b, bn);
295 lmmp_copy(a, b, bn);
296 an = bn;
297 while (dst[bn - 1] == 0 && bn > 0) {
298 --bn;
299 }
300 if (bn == 0)
301 bzero = true;
302 else
303 lmmp_copy(b, dst, bn);
304 } else {
305 bzero = lmmp_lehmer_mul_(a, &an, b, &bn, &M, &ms);
306 if ((an < bn) || (an == bn && lmmp_cmp_(a, b, an) < 0)) {
307 LMMP_SWAP(a, b, mp_ptr);
309 }
310 }
311 }
312 lmmp_copy(dst, a, an);
314 return an;
315#undef an
316#undef bn
317}
static void lmmp_gcd_lehmer_step_(slong u, slong v, mp_gcd_lehmer_t *gcd)
Definition gcd_lehmer.c:28
static bool lmmp_lehmer_mul_(mp_ptr a, mp_size_t *an, mp_ptr b, mp_size_t *bn, mp_gcd_lehmer_t *M, lehmer_stack_t *ms)
/ a \ = / A B \ * / a \ \ b / \ C D / \ b /
Definition gcd_lehmer.c:106
#define an
static void lmmp_lehmer_extract_(mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn, slong *a, slong *b)
Definition gcd_lehmer.c:63
#define bn
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition gcd_lehmer.c:20
mp_limb_t lmmp_gcd_1_(mp_srcptr up, mp_size_t un, mp_limb_t vlimb)
计算两个无符号整数的最大公约数
Definition gcd_1.c:44
int64_t slong
Definition numth.h:34
#define TEMP_B_DECL
Definition tmp_alloc.h:132
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:146
#define TEMP_B_FREE
Definition tmp_alloc.h:159

引用了 an, BALLOC_TYPE, bn, lmmp_cmp_(), lmmp_copy, lmmp_div_(), lmmp_gcd_11_(), lmmp_gcd_1_(), lmmp_gcd_lehmer_step_(), lmmp_lehmer_extract_(), lmmp_lehmer_mul_(), lmmp_param_assert, LMMP_SWAP, n, TEMP_B_DECL , 以及 TEMP_B_FREE.

+ 函数调用图:

◆ lmmp_hyperfac_()

mp_size_t lmmp_hyperfac_ ( mp_ptr  dst,
mp_bitcnt_t  bits,
mp_size_t  rn,
ushort  n 
)

计算hyper阶乘(k^k累乘至n)

参数
dst结果指针
bitshyper阶乘的2的因子数
rn结果指针的 limb 长度
nhyper阶乘的阶数
警告
dst!=NULL, rn>0
返回
dst 的实际 limb 长度

◆ lmmp_hyperfac_size_()

mp_size_t lmmp_hyperfac_size_ ( ushort  n,
mp_bitcnt_t bits 
)

计算hyper阶乘的 limb 缓冲区长度

参数
nhyper阶乘的阶数
bits被修改为 hyper阶乘的2的因子数
警告
bits!=NULL
返回
hyper阶乘的 limb 缓冲区长度

◆ lmmp_is_prime_notrial_()

bool lmmp_is_prime_notrial_ ( ulong  n)

判断素数(无试除法)

参数
n待判断的数(建议为极有可能为素数的数)
注解
不进行试除法过滤,适用于判断已被小素数试除法过滤的数或强伪素数
警告
n>=2
返回
若 n 为素数,返回 true,否则返回 false

在文件 is_prime_ulong.c293 行定义.

293 {
294 lmmp_param_assert(n > 1);
295 if (n < 684630005672341) {
296 ushort bases[2];
297 bases[0] = 2;
298 bases[1] = dj_base49[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 21] + 3;
299 if (n % bases[0] == 0)
300 return false;
301 if (n % bases[1] == 0)
302 return false;
303
304 ulong one = 1;
305 ulong m_1 = n - 1;
307 m_inv = -m_inv;
308 ulong R2 = mont63_R2(n);
309 one = to_mont63(one, R2, n, m_inv);
310 m_1 = to_mont63(m_1, R2, n, m_inv);
311
312 ulong u = n - 1, t = 0;
313 while (u % 2 == 0) u /= 2, ++t;
314
315 if (miller_rabin_63(bases[0], t, u, n, m_inv, one, m_1))
316 if (miller_rabin_63(bases[1], t, u, n, m_inv, one, m_1))
317 return true;
318 else
319 return false;
320 else
321 return false;
322 } else {
323 ushort bases[3];
324 ulong bbmask = dj_base64[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 18];
325 bases[0] = 2;
326 bases[1] = (bbmask & 0x8000) ? 26460 : 9375;
327 bases[2] = (bbmask & 0x7FFF) + 3;
328
329 if (n % bases[0] == 0)
330 return false;
331 if (n % bases[1] == 0)
332 return false;
333 if (n % bases[2] == 0)
334 return false;
335
336 ulong one = 1;
337 ulong m_1 = n - 1;
339 m_inv = -m_inv;
340
341 if (n <= MONT63_MAX) {
342 ulong R2 = mont63_R2(n);
343 one = to_mont63(one, R2, n, m_inv);
344 m_1 = to_mont63(m_1, R2, n, m_inv);
345
346 ulong u = n - 1, t = 0;
347 while (u % 2 == 0) u /= 2, ++t;
348
349 if (miller_rabin_63(bases[0], t, u, n, m_inv, one, m_1))
350 if (miller_rabin_63(bases[1], t, u, n, m_inv, one, m_1))
351 if (miller_rabin_63(bases[2], t, u, n, m_inv, one, m_1))
352 return true;
353 else
354 return false;
355 else
356 return false;
357 else
358 return false;
359 } else {
360 ulong R2 = mont64_R2(n);
361 one = to_mont64(one, R2, n, m_inv);
362 m_1 = to_mont64(m_1, R2, n, m_inv);
363
364 ulong u = n - 1, t = 0;
365 while (u % 2 == 0) u /= 2, ++t;
366
367 if (miller_rabin_64(bases[0], t, u, n, m_inv, one, m_1))
368 if (miller_rabin_64(bases[1], t, u, n, m_inv, one, m_1))
369 if (miller_rabin_64(bases[2], t, u, n, m_inv, one, m_1))
370 return true;
371 else
372 return false;
373 else
374 return false;
375 else
376 return false;
377 }
378 }
379}
static const uint16_t dj_base49[2048]
Copyright (C) 2026 HJimmyK(Jericho Knox)
static const uint16_t dj_base64[16384]
static ulong mont64_R2(ulong m)
#define MONT63_MAX
Copyright (C) 2026 HJimmyK(Jericho Knox)
static ulong to_mont63(ulong x, ulong R2, ulong m, ulong m_inv)
static ulong mont63_R2(ulong m)
static int miller_rabin_64(ulong a, ulong t, ulong u, ulong m, ulong m_inv, ulong one, ulong m_1)
static ulong to_mont64(ulong x, ulong R2, ulong m, ulong m_inv)
static int miller_rabin_63(ulong a, ulong t, ulong u, ulong m, ulong m_inv, ulong one, ulong m_1)
ulong lmmp_binvert_ulong_(ulong a)
计算 a 在2^64下的逆元
Definition binvert_1.c:42
uint16_t ushort
Definition numth.h:29

引用了 dj_base49, dj_base64, lmmp_binvert_ulong_(), lmmp_param_assert, miller_rabin_63(), miller_rabin_64(), MONT63_MAX, mont63_R2(), mont64_R2(), n, t, to_mont63() , 以及 to_mont64().

被这些函数引用 lmmp_is_prime_ulong_(), lmmp_next_prime_ulong_() , 以及 lmmp_prev_prime_ulong_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_is_prime_uint_()

bool lmmp_is_prime_uint_ ( uint  n)

判断素数

参数
n待判断的数
返回
若 n 为素数,返回 true,否则返回 false

判断素数

Hashed 2-bases for n < 684630005672341 (slightly more than 2^49) Hashed 3-bases for n < 2^64

Based on Steve Worley's 2^32 example: http://www.mersenneforum.org/showthread.php?t=12209 With a 3-base encoding idea from Bradley Berg.

Copyright 2014, Dana Jacobsen dana@.nosp@m.acm..nosp@m.org

在文件 is_prime_ulong.c259 行定义.

259 {
260 if (n % 2 == 0 || n <= 1)
261 return false;
263 if (judge == 0) {
264 return false;
265 } else if (judge == 1) {
266 return true;
267 }
268
269 if (trial_div35711(n))
270 return false;
271
272 ushort bases[2];
273 bases[0] = 2;
274 bases[1] = dj_base49[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 21] + 3;
275 if (n % bases[0] == 0)
276 return false;
277 if (n % bases[1] == 0)
278 return false;
279
280 ulong u = n - 1, t = 0;
281 while (u % 2 == 0) u /= 2, ++t;
282
284 if (miller_rabin_32(bases[0], t, u, n, &binv))
285 if (miller_rabin_32(bases[1], t, u, n, &binv))
286 return true;
287 else
288 return false;
289 else
290 return false;
291}
static int miller_rabin_32(ulong a, ulong t, ulong u, uint m, _udiv64_t *binv)
static _udiv64_t _udiv64_gen(uint64_t d)
Definition longlong.h:530
static int trial_div35711(ulong n)
校验是否能被3,5,7,11整除,能够整除则返回1,否则返回0
int lmmp_is_prime_table_(uint p)
根据全局素数表判断一个数是否为素数

引用了 _udiv64_gen(), dj_base49, lmmp_is_prime_table_(), miller_rabin_32(), n, t , 以及 trial_div35711().

+ 函数调用图:

◆ lmmp_is_prime_ulong_()

bool lmmp_is_prime_ulong_ ( ulong  n)

判断素数

参数
n待判断的数
注解
如果 n 的实际值小于2^32,此函数不会调用 lmmp_is_prime_uint_, 如果你可以保证 n 的实际值小于2^32,使用 lmmp_is_prime_uint_ 将会更快
返回
若 n 为素数,返回 true,否则返回 false

在文件 is_prime_ulong.c381 行定义.

381 {
382 if (n % 2 == 0 || n <= 1)
383 return false;
385 if (judge == 0) {
386 return false;
387 } else if (judge == 1) {
388 return true;
389 }
390 if (trial_div35711(n))
391 return false;
393}
bool lmmp_is_prime_notrial_(ulong n)
判断素数(无试除法)

引用了 lmmp_is_prime_notrial_(), lmmp_is_prime_table_(), n , 以及 trial_div35711().

+ 函数调用图:

◆ lmmp_mulmod_ulong_()

ulong lmmp_mulmod_ulong_ ( ulong  a,
ulong  b,
ulong  mod,
ulongp  q 
)

计算两个无符号整数的乘积,对mod取模,商放入 q 中

参数
a第一个无符号整数
b第二个无符号整数
q商的结果指针
mod取模数
警告
a < mod, b < mod, q!=NULL
返回
余数

◆ lmmp_multinomial_()

mp_size_t lmmp_multinomial_ ( mp_ptr  dst,
mp_size_t  rn,
uint  n,
const uintp  r,
uint  m 
)

计算多项式系数

参数
dst结果指针
rn结果指针的 limb 长度
nr[i] 的总和
r需要计算的系数的数组
m系数的个数
警告
m>1, n>0
注解
多项式系数为 ( r1+r2+...+rm )! / ( r1! * r2! * ... * rm!)
返回
返回 dst 的实际 limb 长度

◆ lmmp_multinomial_size_()

mp_size_t lmmp_multinomial_size_ ( const uintp  r,
uint  m,
ulong n 
)

计算多项式系数的 limb 缓冲区长度

参数
r需要计算的系数的数组
m系数的个数
n输出变量,将会被修改为 r[i] 的总和,即r1+r2+...+rm
返回
多项式系数的 limb 缓冲区长度(比实际长度多 1-2 个 limb)
注解
多项式系数为 ( r1+r2+...+rm )! / ( r1! * r2! * ... * rm!)
警告
我们使用 ulong* n 来同时计算 r[i] 的总和,因为 n 可能超过 0xffffffff。 我们预计算 n,这不仅可以作为后续多项式系数函数的参数传入。 同时也请调用者注意判断 n 是否超过了 0xffffffff 这是 lmmp_multinomial_ 函数的限制。

◆ lmmp_nCr_()

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)!) )

参数
dst结果指针
bitsnCr 的2的因子数
rn结果指针的 limb 长度
n组合数的总数
r组合数的选择数
返回
返回 dst 的实际 limb 长度
警告
r<=n/2, n<=0xffffffff, dst!=NULL, rn>0

◆ lmmp_nCr_size_()

mp_size_t lmmp_nCr_size_ ( uint  n,
uint  r,
mp_bitcnt_t bits 
)

计算 nCr 组合数的 limb 缓冲区长度

参数
n组合数的总数
r组合数的选择数
bits被修改为 nCr 的2的因子数
警告
r<=n/2, bits!=NULL
返回
nCr 组合数的 limb 缓冲区长度(比实际长度多 1-2 个 limb)

◆ lmmp_next_prime_ulong_()

ulong lmmp_next_prime_ulong_ ( ulong  n)

大于n的下一个素数

参数
n起始点(不含)
警告
如果 n 大于等于ulong可表示最大的质数,则返回ulong_max
返回
大于n的下一个素数

在文件 is_prime_ulong.c455 行定义.

455 {
458 return prime_short_table[idx];
459 } else if (n >= ULONG_PRIME_MAX) {
460 return MP_ULONG_MAX;
461 } else {
462 n += (n % 2 == 0) ? 1 : 2;
463 while (1) {
464 if (trial_div35711(n)
465 || trial_div13(n)
466 || trial_div17(n)
467 || trial_div19(n)
468 || trial_div23(n)
469 || trial_div29(n)
470 || trial_div31(n)
471 || trial_div37(n)
472 || trial_div41(n)) {
473 n += 2;
474 } else {
476 return n;
477 } else {
478 n += 2;
479 }
480 }
481 }
482 }
483}
static bool trial_div31(ulong n)
static bool trial_div13(ulong n)
static bool trial_div41(ulong n)
static bool trial_div29(ulong n)
static bool trial_div37(ulong n)
#define ULONG_PRIME_MAX
static bool trial_div19(ulong n)
static bool trial_div23(ulong n)
static bool trial_div17(ulong n)
#define MP_ULONG_MAX
Definition mparam.h:137
#define PRIME_SHORT_TABLE_SIZE
Definition prime_table.h:29
const ushort prime_short_table[6542]
ushort lmmp_prime_cnt16_(ushort n)
计算小于等于 n 的素数数量

引用了 lmmp_is_prime_notrial_(), lmmp_prime_cnt16_(), MP_ULONG_MAX, n, prime_short_table, PRIME_SHORT_TABLE_SIZE, trial_div13(), trial_div17(), trial_div19(), trial_div23(), trial_div29(), trial_div31(), trial_div35711(), trial_div37(), trial_div41() , 以及 ULONG_PRIME_MAX.

+ 函数调用图:

◆ lmmp_nPr_()

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)! )

参数
dst结果指针
bitsnPr 的2的因子数
rn结果指针的 limb 长度
n排列数的总数
r排列数的选择数
警告
n>=r, dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

◆ lmmp_nPr_size_()

mp_size_t lmmp_nPr_size_ ( ulong  n,
ulong  r,
mp_bitcnt_t bits 
)

计算 nPr 排列数的 limb 缓冲区长度

参数
n排列数的总数
r排列数的选择数
bits被修改为 nPr 的2的因子数
警告
r<=n, bits!=NULL
返回
nPr 排列数的 limb 缓冲区长度(比实际长度多)

被这些函数引用 lmmp_odd_nCr_uint_() , 以及 pow_nPr_().

+ 这是这个函数的调用关系图:

◆ lmmp_nthroot_ulong_()

ulong lmmp_nthroot_ulong_ ( ulong  n,
ulong  root 
)

计算 floor(n^(1/root))

参数
n被开方数
root开方次数
返回
floor(n^(1/root))
注解
root=0时,返回0

在文件 nthroot.c55 行定义.

55 {
56 ulong x, currval, base, upper_limit;
57
58 if (n == 0 || root == 0)
59 return 0;
60 if (root == 1)
61 return n;
62 if (root == 2)
63 return lmmp_sqrt_ulong_(n);
64 if (root == 3)
65 return lmmp_cbrt_ulong_(n);
66
67 if (root >= LIMB_BITS || n < (1ULL << root))
68 return 1;
69
70 /* n <= upper_limit^root */
71 upper_limit = max_base[root - 4];
72
73 if (upper_limit == 2)
74 return upper_limit;
75
76 /* upper_limit = 2 for root >= 41 */
77 lmmp_debug_assert(root <= 40);
78
79 if (root == 4)
80 x = sqrt(sqrt(n));
81 else
82 x = expf(inv_table[root - 5] * logf(n));
83
84 base = x;
85
86 if (base >= upper_limit)
87 base = upper_limit - 1;
88
89 currval = pow_n(base, root);
90 if (currval == n)
91 return base;
92
93 while (currval <= n) {
94 base++;
95 currval = pow_n(base, root);
96 if (base == upper_limit)
97 break;
98 }
99
100 while (currval > n) {
101 base--;
102 currval = pow_n(base, root);
103 }
104
105 return base;
106}
static const float inv_table[]
Definition nthroot.c:40
static ulong pow_n(ulong x, ulong n)
Definition nthroot.c:32
ulong lmmp_sqrt_ulong_(ulong a)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition nthroot.c:21
static const uint16_t max_base[]
Definition nthroot.c:51
ulong lmmp_cbrt_ulong_(ulong n)
计算算数立方根 floor(cbrt(n))
Definition cbrt_1.c:133

引用了 inv_table, LIMB_BITS, lmmp_cbrt_ulong_(), lmmp_debug_assert, lmmp_sqrt_ulong_(), max_base, n , 以及 pow_n().

+ 函数调用图:

◆ lmmp_odd_factorial_uint_()

mp_size_t lmmp_odd_factorial_uint_ ( mp_ptr  dst,
mp_size_t  rn,
uint  n 
)

计算 n! 阶乘的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度(factorial_size_ 函数的返回值 - bits/LIMB_BITS)
n阶乘的阶数
警告
n>0xffff, dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 lmmp_2factorial_() , 以及 lmmp_odd_factorial_().

+ 这是这个函数的调用关系图:

◆ lmmp_odd_nCr_uint_()

mp_size_t lmmp_odd_nCr_uint_ ( mp_ptr  dst,
mp_size_t  rn,
uint  n,
uint  r 
)

计算 nCr 组合数的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度
n组合数的总数
r组合数的选择数
返回
返回 dst 的实际 limb 长度
警告
r<=n/2, 0xffff<n, dst!=NULL, rn>0

◆ lmmp_odd_nCr_ushort_()

mp_size_t lmmp_odd_nCr_ushort_ ( mp_ptr  dst,
mp_size_t  rn,
uint  n,
uint  r 
)

计算 nCr 组合数的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度
n组合数的总数
r组合数的选择数
返回
返回 dst 的实际 limb 长度
警告
r<=n/2, n<=0xffff, dst!=NULL, rn>0

◆ lmmp_odd_nPr_uint_()

mp_size_t lmmp_odd_nPr_uint_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  n,
ulong  r 
)

计算 nPr 排列数的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
n排列数的总数
r排列数的选择数
警告
0xffffffff>=n>=r, dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_nPr_().

+ 这是这个函数的调用关系图:

◆ lmmp_odd_nPr_ulong_()

mp_size_t lmmp_odd_nPr_ulong_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  n,
ulong  r 
)

计算 nPr 排列数的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
n排列数的总数
r排列数的选择数
警告
n>=r, dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

◆ lmmp_odd_nPr_ushort_()

mp_size_t lmmp_odd_nPr_ushort_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  n,
ulong  r 
)

计算 nPr 排列数的奇数部分

参数
dst结果指针
rn结果指针的 limb 长度(nPr_size_ 函数的返回值 - bits/LIMB_BITS)
n排列数的总数
r排列数的选择数
警告
0xffff>=n>=r, dst!=NULL, rn>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_nPr_(), lmmp_2factorial_(), lmmp_factorial_(), lmmp_odd_factorial_(), lmmp_odd_multinomial_ushort_() , 以及 lmmp_odd_nCr_ushort_().

+ 这是这个函数的调用关系图:

◆ lmmp_pow_()

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

参数
dst结果指针
rn结果指针的 limb 长度
base底数指针
n底数指针的 limb 长度
exp指数
警告
n>0, base[n-1]!=0, sep(dst,base), exp>0
返回
返回 dst 的实际 limb 长度

◆ lmmp_pow_1_()

mp_size_t lmmp_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
mp_limb_t  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
base底数
exp指数
警告
base>=1, exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 lmmp_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_pow_1_size_()

mp_size_t lmmp_pow_1_size_ ( mp_limb_t  base,
ulong  exp 
)

计算幂次方需要的limb缓冲区长度 base ^ exp

参数
base底数
exp指数
警告
exp>0, base>=1
返回
返回值为 base^exp 需要的 limb 缓冲区长度(比实际长度多)

计算幂次方需要的limb缓冲区长度 base ^ exp

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 pow.c25 行定义.

25 {
26 lmmp_param_assert(base >= 1);
28 if (base == 1) {
29 return 1;
30 } else if (exp <= 2) {
31 return 3;
32 } else if (exp <= MP_UINT_MAX) {
33 /*
34 base = b * 2^base_tz
35 */
37 uint32_t b;
38 if (base_tz < 32) {
39 b = base << (32 - base_tz);
40 } else {
41 b = base >> (base_tz - 32);
42 }
43 base_tz = base_tz - 32;
44 base_tz *= exp;
46 rn += base_tz;
47 rn = (rn + LIMB_BITS - 1) / LIMB_BITS;
48 return rn + 2;
49 } else {
50 /*
51 base = b * 2^base_tz
52 */
54 uint32_t b;
55 if (base_tz < 32) {
56 b = base << (32 - base_tz);
57 } else {
58 b = base >> (base_tz - 32);
59 }
60 base_tz = base_tz - 32;
61 base_tz *= exp;
62
64 /*
65 exp = exp' * 2^bits
66 exp*log2(base) = exp*log2(b*2^base_tz)
67 = exp*log2(b) + exp*base_tz
68 = exp'*log2(b)*2^bits + exp*base_tz
69 */
71 bits -= 32;
72 exp >>= bits;
73 exp++;
74 rn = xlog2n_ceil(exp, b) << bits;
75 rn += base_tz;
76 rn = (rn + LIMB_BITS - 1) / LIMB_BITS;
77 return rn + 2;
78 }
79}
static uint64_t xlog2n_ceil(uint32_t x, uint32_t n)
计算x*log2(n)的ceil值
Definition lglg.h:67
#define MP_UINT_MAX
Definition mparam.h:136

引用了 LIMB_BITS, lmmp_limb_bits_, lmmp_param_assert, MP_UINT_MAX, n , 以及 xlog2n_ceil().

被这些函数引用 lmmp_arith_seqprod_size_(), lmmp_nCr_size_(), lmmp_nPr_size_(), lmmp_pow_size_() , 以及 pow_nPr_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_pow_basecase_()

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

参数
dst结果指针
rn结果指针的 limb 缓冲区长度
base底数指针
n底数指针的 limb 长度
exp指数
警告
n>0, base[n-1]!=0, sep(dst,base), [base,n]>1, exp>=3, exp%2==1
返回
返回 dst 的实际 limb 长度

被这些函数引用 lmmp_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_pow_size_()

mp_size_t lmmp_pow_size_ ( mp_srcptr  base,
mp_size_t  n,
ulong  exp 
)

计算幂次方需要的limb缓冲区长度 [base,n] ^ exp

参数
base底数指针
n底数 limb 长度
exp指数
警告
n>0, base[n-1]!=0, [base,n]>1
返回
返回值为 [base,n]^exp 需要的 limb 缓冲区长度(比实际长度多)

在文件 pow.c81 行定义.

81 {
83 lmmp_param_assert(base[n - 1] != 0);
84 if (n == 1) {
85 return lmmp_pow_1_size_(base[0], exp);
86 }
87 if (exp == 1) {
88 return n;
89 } else if (exp == 2) {
90 return n * 2;
91 } else {
92 /*
93 base = b * 2^base_tz
94 */
96 uint32_t b;
97 if (base_tz < 32) {
98 b = base[n - 1] << (32 - base_tz);
99 b |= (base[n - 2] >> (LIMB_BITS - 32 + base_tz));
100 base_tz = (n - 2) * LIMB_BITS + LIMB_BITS - 32 + base_tz;
101 } else if (base_tz == 32) {
102 b = base[n - 1];
103 base_tz = (n - 1) * LIMB_BITS;
104 } else {
105 b = base[n - 1] >> (base_tz - 32);
106 base_tz = (n - 1) * LIMB_BITS + base_tz - 32;
107 }
108
110 if (exp <= MP_UINT_MAX) {
111 rn = exp * base_tz;
112 rn += xlog2n_ceil(exp, b);
113 } else {
114 /*
115 exp = exp' * 2^bits
116 exp*log2(base) = exp*log2(b*2^base_tz)
117 = exp*log2(b) + exp*base_tz
118 = exp'*log2(b)*2^bits + exp*base_tz
119 */
121 rn = exp * base_tz;
122 bits -= 32;
123 exp >>= bits;
124 exp++;
125 rn += xlog2n_ceil(exp, b) << bits;
126 }
127 rn = (rn + LIMB_BITS - 1) / LIMB_BITS;
128 return rn + 2;
129 }
130}
mp_size_t lmmp_pow_1_size_(mp_limb_t base, ulong exp)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition pow.c:25

引用了 LIMB_BITS, lmmp_limb_bits_, lmmp_param_assert, lmmp_pow_1_size_(), MP_UINT_MAX, n , 以及 xlog2n_ceil().

被这些函数引用 lmmp_pow_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_pow_win2_()

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

参数
dst结果指针
rn结果指针的 limb 长度
base底数指针
n底数指针的 limb 长度
exp指数
警告
n>0, base[n-1]!=0, sep(dst,base), exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 lmmp_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_powmod_uint_()

uint lmmp_powmod_uint_ ( uint  base,
ulong  exp,
uint  mod 
)

计算 base^exp 对 mod 取模

参数
base底数
exp指数
mod模数
警告
base < mod, mod > 1
返回
base^exp 对 mod 取模的结果

在文件 is_prime_ulong.c108 行定义.

108 {
109 lmmp_param_assert(mod > base);
111 ulong dst = 1;
112 ulong b = base;
114 ulong q;
115 while (1) {
116 if (exp & 1) {
117 dst *= b;
119 dst -= q * mod;
120 }
121 exp >>= 1;
122 if (exp == 0)
123 break;
124 b *= b;
126 b -= q * mod;
127 }
128 return dst;
129}
static uint64_t _udiv64by64_q_preinv(uint64_t numer, const _udiv64_t *denom)
Definition longlong.h:536

引用了 _udiv64_gen(), _udiv64by64_q_preinv(), lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_powmod_ulong_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_powmod_ulong_()

ulong lmmp_powmod_ulong_ ( ulong  base,
ulong  exp,
ulong  mod 
)

计算 base^exp 对 mod 取模

参数
base底数
exp指数
mod模数
警告
base < mod, mod > 1
返回
base^exp 对 mod 取模的结果

在文件 is_prime_ulong.c131 行定义.

131 {
132 if (mod <= MP_UINT_MAX)
133 return lmmp_powmod_uint_(base, exp, mod);
134 else if (mod <= MONT63_MAX) {
137 m_inv = -m_inv;
138 ulong dst = to_mont63(1, R2, mod, m_inv);
139 base = to_mont63(base, R2, mod, m_inv);
140 while (1) {
141 if (exp & 1)
142 dst = mont63_mul(dst, base, mod, m_inv);
143 exp >>= 1;
144 if (exp == 0)
145 break;
146 base = mont63_mul(base, base, mod, m_inv);
147 }
148 return from_mont63(dst, mod, m_inv);
149 } else {
152 m_inv = -m_inv;
153 ulong dst = to_mont64(1, R2, mod, m_inv);
154 base = to_mont64(base, R2, mod, m_inv);
155 while (1) {
156 if (exp & 1)
157 dst = mont64_mul(dst, base, mod, m_inv);
158 exp >>= 1;
159 if (exp == 0)
160 break;
161 base = mont64_mul(base, base, mod, m_inv);
162 }
163 return from_mont64(dst, mod, m_inv);
164 }
165}
static ulong from_mont64(ulong x, ulong m, ulong m_inv)
static ulong mont63_mul(ulong a, ulong b, ulong m, ulong m_inv)
uint lmmp_powmod_uint_(uint base, ulong exp, uint mod)
计算 base^exp 对 mod 取模
static ulong mont64_mul(ulong a, ulong b, ulong m, ulong m_inv)
static ulong from_mont63(ulong x, ulong m, ulong m_inv)

引用了 from_mont63(), from_mont64(), lmmp_binvert_ulong_(), lmmp_powmod_uint_(), MONT63_MAX, mont63_mul(), mont63_R2(), mont64_mul(), mont64_R2(), MP_UINT_MAX, n, to_mont63() , 以及 to_mont64().

+ 函数调用图:

◆ lmmp_prev_prime_ulong_()

ulong lmmp_prev_prime_ulong_ ( ulong  n)

小于等于n的上一个素数

参数
n起始点(含)
警告
如果 n 小于2,则返回 0
返回
小于等于n的上一个素数,如果n恰好为素数,则返回 n

在文件 is_prime_ulong.c485 行定义.

485 {
486 if (n < ULONG_PRIME_MIN) {
487 return 0;
488 } else if (n < PRIME_SHORT_TABLE_N) {
490 return prime_short_table[idx - 1];
491 } else {
492 n -= (n % 2 == 0) ? 1 : 0;
493 while (1) {
494 if (trial_div35711(n)
495 || trial_div13(n)
496 || trial_div17(n)
497 || trial_div19(n)
498 || trial_div23(n)
499 || trial_div29(n)
500 || trial_div31(n)
501 || trial_div37(n)
502 || trial_div41(n)) {
503 n -= 2;
504 } else {
506 return n;
507 } else {
508 n -= 2;
509 }
510 }
511 }
512 }
513}
#define ULONG_PRIME_MIN
#define PRIME_SHORT_TABLE_N
Definition prime_table.h:31

引用了 lmmp_is_prime_notrial_(), lmmp_prime_cnt16_(), n, prime_short_table, PRIME_SHORT_TABLE_N, trial_div13(), trial_div17(), trial_div19(), trial_div23(), trial_div29(), trial_div31(), trial_div35711(), trial_div37(), trial_div41() , 以及 ULONG_PRIME_MIN.

+ 函数调用图:

◆ lmmp_primefac_()

mp_size_t lmmp_primefac_ ( mp_ptr  dst,
mp_size_t  rn,
uint  n 
)

计算质数阶乘(不超过n的质数累乘)

参数
dst结果指针
rn结果指针的 limb 长度
n质数阶乘的阶数
警告
dst!=NULL, rn>0
返回
dst 的实际 limb 长度

◆ lmmp_primefac_size_()

mp_size_t lmmp_primefac_size_ ( uint  n)

计算质数阶乘的 limb 缓冲区长度

参数
n质数阶乘的阶数
返回
质数阶乘的 limb 缓冲区长度

在文件 factorial_extra.c435 行定义.

435 {
436 // Chebyshev's estimate
437 // pn# < exp(1.000028*n)
438 const double log2 = 0.69314718055994531; // log(2)
439 double l = 1.000028 * (double)n;
440 l /= log2;
442 rn = (rn + LIMB_BITS - 1) / LIMB_BITS + 2; // more two limbs
443 return rn;
444}

引用了 l, LIMB_BITS , 以及 n.

◆ lmmp_remove_()

mp_size_t lmmp_remove_ ( mp_ptr  np,
mp_size_t nn,
mp_srcptr  dp,
mp_size_t  dn 
)

除去[np,nn]中的[dp,dn]的因子

参数
np被除数指针,将会被修改为除去因子后的数
nn被除数指针的 limb 长度,将会被修改除去因子后的长度
dp除数指针
dn除数指针的 limb 长度
警告
np!=NULL, nn>0, dp!=NULL, dn>0
注解
如果[np,nn]能被[dp,dn]整除,则[np,nn]将被修改为除去因子后的数,nn将被修改为除去因子后的长度。 如果不能被整除,则[np,nn]保持不变,并返回0。
返回
[np,nn]中被[dp,dn]除去的因子的个数,如果不能被整除,则返回0

◆ lmmp_sqrt_ulong_()

ulong lmmp_sqrt_ulong_ ( ulong  a)

计算算术平方根 floor(sqrt(a))

参数
a被开方数
返回
floor(sqrt(a))

计算算术平方根 floor(sqrt(a))

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 nthroot.c21 行定义.

21 {
22 ulong is;
23
24 is = (ulong)sqrt((double)a);
25
26 is -= (is * is > a);
27 if (is == (1ULL << 32))
28 is--;
29 return is;
30}

引用了 n.

被这些函数引用 lmmp_nthroot_ulong_().

+ 这是这个函数的调用关系图:

◆ lmmp_superfac_()

mp_size_t lmmp_superfac_ ( mp_ptr  dst,
mp_bitcnt_t  bits,
mp_size_t  rn,
ushort  n 
)

计算super阶乘(k!累乘至n)

参数
dst结果指针
bitssuper阶乘的2的因子数
rn结果指针的 limb 长度
nsuper阶乘的阶数
警告
dst!=NULL, rn>0
返回
dst 的实际 limb 长度

◆ lmmp_superfac_size_()

mp_size_t lmmp_superfac_size_ ( ushort  n,
mp_bitcnt_t bits 
)

计算super阶乘的 limb 缓冲区长度

参数
nsuper阶乘的阶数
bits被修改为 super阶乘的2的因子数
警告
bits!=NULL
返回
super阶乘的 limb 缓冲区长度

◆ lmmp_trialdiv_()

ushortp lmmp_trialdiv_ ( mp_srcptr  np,
mp_size_t  nn,
ushort  N,
ushort rn 
)

试除法

参数
num被除数
nn被除数的 limb 长度
N试除法尝试的质数最大值
rn结果指针的 limb 长度
警告
num!=NULL, nn>0, N>2, rn!=NULL
注解
试除法尝试从 2-N 中所有质数进行试除,如果能整除则会插入到返回结果数组中,没有整除的则会返回 NULL。 结果指针请使用 lmmp_free() 函数进行释放。
返回
结果指针,返回不超过N,且能整除[np,nn]的素数(从小到大排列),若没有能够整除的素数,则返回NULL

◆ lmmp_u16_pow_1_()

mp_size_t lmmp_u16_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
rn结果指针的 limb 长度
base底数(16位无符号整数)
exp指数
警告
0<base<=0xffff, exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_u32_pow_1_()

mp_size_t lmmp_u32_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
rn结果指针的 limb 长度
base底数(32位无符号整数)
exp指数
警告
0<base<=2^32-1, exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_u4_pow_1_()

mp_size_t lmmp_u4_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
rn结果指针的 limb 长度
base底数(4位无符号整数)
exp指数
警告
1<=base<=0xf, exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_u64_pow_1_()

mp_size_t lmmp_u64_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
rn结果指针的 limb 长度
base底数(64位无符号整数)
exp指数
警告
2^32<=base<=2^64-1, exp>0
返回
返回 dst 的实际 limb 长度

◆ lmmp_u8_pow_1_()

mp_size_t lmmp_u8_pow_1_ ( mp_ptr  dst,
mp_size_t  rn,
ulong  base,
ulong  exp 
)

计算幂次方 [dst,rn] = [base,1] ^ exp

参数
dst结果指针
rn结果指针的 limb 长度
base底数(8位无符号整数)
exp指数
警告
0<base<=0xff, exp>0
返回
返回 dst 的实际 limb 长度

被这些函数引用 _odd_pow_().

+ 这是这个函数的调用关系图: