LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
factorial.c 文件参考
+ factorial.c 的引用(Include)关系图:

浏览源代码.

宏定义

#define MAX_T   0xffffffffffff
 
#define MUL(dst, ap, an, bp, bn)
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 
#define mul_1(dst, rn, v)
 

函数

static void count_factors (fac_ptr fac, uint nfactors, uint n, uint p)
 
mp_size_t lmmp_factorial_ (mp_ptr restrict dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
 
mp_size_t lmmp_factorial_size_ (uint n, mp_bitcnt_t *restrict bits)
 
mp_size_t lmmp_factors_mul_ (mp_ptr restrict dst, mp_size_t rn, fac_ptr restrict fac, uint nfactors)
 
mp_size_t lmmp_odd_factorial_uint_ (mp_ptr restrict dst, mp_size_t rn, uint n)
 

宏定义说明

◆ MAX_T

#define MAX_T   0xffffffffffff

◆ MUL

#define MUL (   dst,
  ap,
  an,
  bp,
  bn 
)
值:
if (an >= bn) \
#define an
#define bn
#define n

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/.

在文件 factorial.c26 行定义.

34 { \
36 dst[rn] = _c_; \
37 rn += _c_ > 0; \
38 } while (0)
39
42 if (n < 20) {
43 rn = 64;
44 } else {
46 }
47 rn = (rn + LIMB_BITS - 1) / LIMB_BITS + 2; // more two limbs
49 return rn;
50}
51
52/*
53 N N/2 N
54 +--+ / +--+ \ 2 / +--+ \
55 | | P_i ^ (e_i) = | | | P_i ^ (e_i / 2) | * | | | P_i ^ ( e_i mod 2) |
56 | | \ | | / \ | | /
57 i=0 i=0 i=0
58*/
59
62 lmmp_param_assert(rn > 0 && nfactors > 0);
64 // 绝大多数情况下,大的质因数的指数都很小,所以这里只需要考虑小的质因数。
65 dst[0] = 1;
66 rn = 1;
67 mp_limb_t t = 1;
68 for (uint i = 0; i < nfactors; i++) {
69 uint f = fac[i].f;
70 uint j = fac[i].j;
71 lmmp_debug_assert(j != 0 && f <= MP_USHORT_MAX);
72#define MAX_T 0xffffffffffff
73 for (uint e = 0; e < j; e++) {
74 t *= f;
75 if (t > MAX_T) {
76 mul_1(dst, rn, t);
77 t = 1;
78 }
79 }
80 }
81 if (t != 1) {
82 mul_1(dst, rn, t);
83 }
84#undef MAX_T
85 return rn;
86 } else {
90 ulong t = 1;
91 mp_size_t limbn = 0;
92 for (uint i = 0; i < nfactors; ++i) {
93 uint f = fac[i].f;
94 uint j = fac[i].j;
95 if (j > 1) {
96 fac[new_nfactors].f = f;
97 fac[new_nfactors++].j = j >> 1;
98 }
99 if (j & 1) {
100 t *= f;
101 if (t > MP_UINT_MAX) {
102 limbs[limbn++] = t;
103 t = 1;
104 }
105 }
106 }
107 if (t != 1) {
108 limbs[limbn++] = t;
109 }
110
112 mp_size_t mpn = 0;
113
114 if (new_nfactors > 0) {
115 if (limbn > 0) {
118 mp_size_t tn = ((rn - mpn) >> 1) + 1;
119 // 这里根据mpn的大小估计剩余因子乘积的长度,额外分配两倍的tn,以进行平方。
120 mp_ptr restrict tp = BALLOC_TYPE(3 * tn + 3, mp_limb_t);
122
123 mp_ptr restrict tp2 = tp + tn + 1;
124 lmmp_sqr_(tp2, tp, tn);
125 tn <<= 1;
126 tn -= tp2[tn - 1] == 0;
127 MUL(dst, tp2, tn, mp, mpn);
128 rn = tn + mpn;
129 rn -= dst[rn - 1] == 0;
130 } else {
131 mp_size_t tn = (rn >> 1) + 1;
134 lmmp_sqr_(dst, tp, tn);
135 rn = tn << 1;
136 rn -= dst[rn - 1] == 0;
137 }
138 } else {
140 // 这里不能直接乘入dst,因为dst的大小可能小于limbn,导致溢出
141 if (rn >= limbn) {
143 } else {
145 lmmp_copy(dst, mp, rn);
146 }
147 }
148 TEMP_FREE;
149 return rn;
150 }
151}
152
153static inline void count_factors(fac_ptr fac, uint nfactors, uint n, uint p) {
154 uint pn = n;
155 uint e = 0;
156 while (pn > 0) {
157 pn /= p;
158 e += pn;
159 }
160 fac[nfactors].f = p;
161 fac[nfactors].j = e;
162}
163
168
173 nfactors = 0;
174
177 while (cache.is_end == 0) {
179 for (uint i = 0; i < cache.size; i++) {
180 // 对于阶乘n!,对于所有小于等于n的质数,贡献都至少为1
181 count_factors(fac, nfactors++, n, cache.pp[i]);
182 }
183 }
185
187
189 return rn;
190}
191
196 bits %= LIMB_BITS;
197 lmmp_zero(dst, shw);
198
199 if (n <= NPR_SHORT_LIMIT)
201 else
203
204 if (bits > 0) {
205 dst[shw + rn] = lmmp_shl_(dst + shw, dst + shw, rn, bits);
206 rn += shw + 1;
207 rn -= dst[rn - 1] == 0;
208 } else {
209 rn += shw;
210 }
211 return rn;
212}
mp_size_t lmmp_elem_mul_ulong_(mp_ptr dst, const ulongp limbs, mp_size_t n, mp_ptr tp)
计算limbs数组的累乘积
mp_size_t lmmp_factorial_(mp_ptr restrict dst, mp_bitcnt_t bits, mp_size_t rn, uint n)
Definition factorial.c:192
#define MUL(dst, ap, an, bp, bn)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition factorial.c:26
#define MAX_T
#define mul_1(dst, rn, v)
Definition factorial.c:33
mp_size_t lmmp_odd_factorial_uint_(mp_ptr restrict dst, mp_size_t rn, uint n)
Definition factorial.c:164
static void count_factors(fac_ptr fac, uint nfactors, uint n, uint p)
Definition factorial.c:153
mp_size_t lmmp_factorial_size_(uint n, mp_bitcnt_t *restrict bits)
Definition factorial.c:40
mp_size_t lmmp_factors_mul_(mp_ptr restrict dst, mp_size_t rn, fac_ptr restrict fac, uint nfactors)
Definition factorial.c:60
#define lmmp_sqr_
Definition inlines.h:166
#define lmmp_limb_popcnt_
Definition inlines.h:163
static uint64_t log2_fac_ceil(uint32_t n)
计算 log2(n!)的ceil值
Definition lglg.h:241
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#define lmmp_zero(dst, n)
Definition lmmp.h:369
size_t mp_bitcnt_t
Definition lmmp.h:82
uint64_t mp_size_t
Definition lmmp.h:77
#define lmmp_debug_assert(x)
Definition lmmp.h:390
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
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
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
#define NPR_SHORT_LIMIT
Definition mparam.h:151
#define FACTORS_MUL_N_THRESHOLD
Definition mparam.h:107
#define MP_UINT_MAX
Definition mparam.h:136
#define MP_USHORT_MAX
Definition mparam.h:135
#define t
#define tp
mp_size_t lmmp_odd_nPr_ushort_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
uint64_t * ulongp
Definition numth.h:41
uint32_t uint
Definition numth.h:31
uint64_t ulong
Definition numth.h:32
void lmmp_prime_cache_free_(prime_cache_t *cache)
释放素数表缓存
void lmmp_prime_cache_next_(prime_cache_t *cache)
素数表缓存更新(从小到大遍历全局质数表)
static ulong lmmp_prime_size_(ulong n)
估计 n 范围内的素数数量
Definition prime_table.h:57
void lmmp_prime_int_table_init_(uint n)
初始化全局素数表
Definition prime_table.c:99
void lmmp_prime_cache_init_(prime_cache_t *cache, uint n)
初始化素数表缓存
#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
#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

◆ mul_1

#define mul_1 (   dst,
  rn,
  v 
)
值:
do { \
dst[rn] = _c_; \
rn += _c_ > 0; \
} while (0)

在文件 factorial.c33 行定义.

34 { \
36 dst[rn] = _c_; \
37 rn += _c_ > 0; \
38 } while (0)

函数说明

◆ count_factors()

static void count_factors ( fac_ptr  fac,
uint  nfactors,
uint  n,
uint  p 
)
inlinestatic

在文件 factorial.c153 行定义.

153 {
154 uint pn = n;
155 uint e = 0;
156 while (pn > 0) {
157 pn /= p;
158 e += pn;
159 }
160 fac[nfactors].f = p;
161 fac[nfactors].j = e;
162}

引用了 n.

被这些函数引用 lmmp_odd_factorial_uint_().

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

◆ lmmp_factorial_()

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

在文件 factorial.c192 行定义.

192 {
196 bits %= LIMB_BITS;
197 lmmp_zero(dst, shw);
198
199 if (n <= NPR_SHORT_LIMIT)
201 else
203
204 if (bits > 0) {
205 dst[shw + rn] = lmmp_shl_(dst + shw, dst + shw, rn, bits);
206 rn += shw + 1;
207 rn -= dst[rn - 1] == 0;
208 } else {
209 rn += shw;
210 }
211 return rn;
212}

引用了 LIMB_BITS, lmmp_odd_factorial_uint_(), lmmp_odd_nPr_ushort_(), lmmp_param_assert, lmmp_shl_(), lmmp_zero, n , 以及 NPR_SHORT_LIMIT.

+ 函数调用图:

◆ lmmp_factorial_size_()

mp_size_t lmmp_factorial_size_ ( uint  n,
mp_bitcnt_t *restrict  bits 
)

在文件 factorial.c40 行定义.

40 {
42 if (n < 20) {
43 rn = 64;
44 } else {
46 }
47 rn = (rn + LIMB_BITS - 1) / LIMB_BITS + 2; // more two limbs
49 return rn;
50}

引用了 LIMB_BITS, lmmp_limb_popcnt_, log2_fac_ceil() , 以及 n.

+ 函数调用图:

◆ lmmp_factors_mul_()

mp_size_t lmmp_factors_mul_ ( mp_ptr restrict  dst,
mp_size_t  rn,
fac_ptr restrict  fac,
uint  nfactors 
)

在文件 factorial.c60 行定义.

60 {
62 lmmp_param_assert(rn > 0 && nfactors > 0);
64 // 绝大多数情况下,大的质因数的指数都很小,所以这里只需要考虑小的质因数。
65 dst[0] = 1;
66 rn = 1;
67 mp_limb_t t = 1;
68 for (uint i = 0; i < nfactors; i++) {
69 uint f = fac[i].f;
70 uint j = fac[i].j;
71 lmmp_debug_assert(j != 0 && f <= MP_USHORT_MAX);
72#define MAX_T 0xffffffffffff
73 for (uint e = 0; e < j; e++) {
74 t *= f;
75 if (t > MAX_T) {
76 mul_1(dst, rn, t);
77 t = 1;
78 }
79 }
80 }
81 if (t != 1) {
82 mul_1(dst, rn, t);
83 }
84#undef MAX_T
85 return rn;
86 } else {
90 ulong t = 1;
91 mp_size_t limbn = 0;
92 for (uint i = 0; i < nfactors; ++i) {
93 uint f = fac[i].f;
94 uint j = fac[i].j;
95 if (j > 1) {
96 fac[new_nfactors].f = f;
97 fac[new_nfactors++].j = j >> 1;
98 }
99 if (j & 1) {
100 t *= f;
101 if (t > MP_UINT_MAX) {
102 limbs[limbn++] = t;
103 t = 1;
104 }
105 }
106 }
107 if (t != 1) {
108 limbs[limbn++] = t;
109 }
110
112 mp_size_t mpn = 0;
113
114 if (new_nfactors > 0) {
115 if (limbn > 0) {
118 mp_size_t tn = ((rn - mpn) >> 1) + 1;
119 // 这里根据mpn的大小估计剩余因子乘积的长度,额外分配两倍的tn,以进行平方。
120 mp_ptr restrict tp = BALLOC_TYPE(3 * tn + 3, mp_limb_t);
122
123 mp_ptr restrict tp2 = tp + tn + 1;
124 lmmp_sqr_(tp2, tp, tn);
125 tn <<= 1;
126 tn -= tp2[tn - 1] == 0;
127 MUL(dst, tp2, tn, mp, mpn);
128 rn = tn + mpn;
129 rn -= dst[rn - 1] == 0;
130 } else {
131 mp_size_t tn = (rn >> 1) + 1;
134 lmmp_sqr_(dst, tp, tn);
135 rn = tn << 1;
136 rn -= dst[rn - 1] == 0;
137 }
138 } else {
140 // 这里不能直接乘入dst,因为dst的大小可能小于limbn,导致溢出
141 if (rn >= limbn) {
143 } else {
145 lmmp_copy(dst, mp, rn);
146 }
147 }
148 TEMP_FREE;
149 return rn;
150 }
151}

引用了 BALLOC_TYPE, FACTORS_MUL_N_THRESHOLD, lmmp_copy, lmmp_debug_assert, lmmp_elem_mul_ulong_(), lmmp_factors_mul_(), lmmp_param_assert, lmmp_sqr_, MAX_T, MP_UINT_MAX, MP_USHORT_MAX, MUL, mul_1, n, t, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_factors_mul_() , 以及 lmmp_odd_factorial_uint_().

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

◆ lmmp_odd_factorial_uint_()

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

在文件 factorial.c164 行定义.

164 {
168
173 nfactors = 0;
174
177 while (cache.is_end == 0) {
179 for (uint i = 0; i < cache.size; i++) {
180 // 对于阶乘n!,对于所有小于等于n的质数,贡献都至少为1
181 count_factors(fac, nfactors++, n, cache.pp[i]);
182 }
183 }
185
187
189 return rn;
190}

引用了 BALLOC_TYPE, count_factors(), lmmp_factors_mul_(), lmmp_param_assert, lmmp_prime_cache_free_(), lmmp_prime_cache_init_(), lmmp_prime_cache_next_(), lmmp_prime_int_table_init_(), lmmp_prime_size_(), MP_USHORT_MAX, n, TEMP_B_DECL , 以及 TEMP_B_FREE.

被这些函数引用 lmmp_factorial_().

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