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

浏览源代码.

函数

static mp_size_t _odd_nPr_ (mp_ptr restrict dst, mp_size_t rn, ulong n, ulong r)
 
static mp_size_t _odd_pow_ (mp_ptr dst, mp_size_t rn, uint base, ulong exp)
 
mp_size_t lmmp_arith_seqprod_ (mp_ptr restrict dst, mp_size_t rn, uint x, uint n, uint m)
 
mp_size_t lmmp_arith_seqprod_size_ (uint x, uint n, uint m)
 计算等差数列乘积 x(x+m)...(x+n*m)的 limb 缓冲区长度
 
static mp_size_t pow_nPr_ (mp_ptr restrict dst, mp_size_t rn, uint x, uint n, uint m)
 

函数说明

◆ _odd_nPr_()

static mp_size_t _odd_nPr_ ( mp_ptr restrict  dst,
mp_size_t  rn,
ulong  n,
ulong  r 
)
inlinestatic

在文件 arith_seqprod.c33 行定义.

33 {
34 if (n <= NPR_SHORT_LIMIT) {
35 return lmmp_odd_nPr_ushort_(dst, rn, n, r);
36 } else {
37 return lmmp_odd_nPr_uint_(dst, rn, n, r);
38 }
39}
#define NPR_SHORT_LIMIT
Definition mparam.h:154
mp_size_t lmmp_odd_nPr_ushort_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
mp_size_t lmmp_odd_nPr_uint_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分

引用了 lmmp_odd_nPr_uint_(), lmmp_odd_nPr_ushort_() , 以及 NPR_SHORT_LIMIT.

被这些函数引用 pow_nPr_().

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

◆ _odd_pow_()

static mp_size_t _odd_pow_ ( mp_ptr  dst,
mp_size_t  rn,
uint  base,
ulong  exp 
)
inlinestatic

在文件 arith_seqprod.c22 行定义.

22 {
23 if (base <= 0xf)
24 return lmmp_u4_pow_1_(dst, rn, base, exp);
25 else if (base <= MP_UCHAR_MAX)
26 return lmmp_u8_pow_1_(dst, rn, base, exp);
27 else if (base <= MP_USHORT_MAX)
28 return lmmp_u16_pow_1_(dst, rn, base, exp);
29 else
30 return lmmp_u32_pow_1_(dst, rn, base, exp);
31}
#define MP_UCHAR_MAX
Definition mparam.h:137
#define MP_USHORT_MAX
Definition mparam.h:138
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_u32_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
mp_size_t lmmp_u16_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp

引用了 lmmp_u16_pow_1_(), lmmp_u32_pow_1_(), lmmp_u4_pow_1_(), lmmp_u8_pow_1_(), MP_UCHAR_MAX , 以及 MP_USHORT_MAX.

被这些函数引用 pow_nPr_().

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

◆ lmmp_arith_seqprod_()

mp_size_t lmmp_arith_seqprod_ ( mp_ptr restrict  dst,
mp_size_t  rn,
uint  x,
uint  n,
uint  m 
)

在文件 arith_seqprod.c86 行定义.

86 {
87 lmmp_param_assert(dst != NULL);
88 lmmp_param_assert(rn >= 1);
89 lmmp_param_assert(x >= 1);
90 lmmp_param_assert(n >= 1);
91 lmmp_param_assert(m > 1);
92
93 if (x % m == 0) {
94 return pow_nPr_(dst, rn, x, n, m);
95 }
96
97 mp_bitcnt_t bits = 0;
98 while ((x & 1) == 0 && (m & 1) == 0) {
99 x >>= 1;
100 m >>= 1;
101 bits++;
102 }
103 bits *= n + 1;
104
105 TEMP_DECL;
106 ulongp restrict limbs = TALLOC_TYPE((n + 1) / 2 + 1, ulong);
107 mp_size_t limbn = 0;
108 ulong t = 1, s, v;
109 mp_bitcnt_t cnt;
110 for (uint i = 0; i <= n; i++) {
111 s = x + i * m;
112 ctz_shl(v, s, cnt);
113 t *= v;
114 bits += cnt;
115 if (t > MP_UINT_MAX) {
116 limbs[limbn++] = t;
117 t = 1;
118 }
119 }
120 ctz_shl(v, t, cnt);
121 bits += cnt;
122 if (v != 1) {
123 limbs[limbn++] = v;
124 }
125 mp_size_t shw = bits / LIMB_BITS;
126 bits %= LIMB_BITS;
127 mp_ptr restrict b = TALLOC_TYPE(limbn * 2, mp_limb_t);
128 mp_size_t bn = lmmp_elem_mul_ulong_(b, limbs, limbn, b + limbn);
129 lmmp_zero(dst, shw);
130 if (bits > 0) {
131 dst[shw + bn] = lmmp_shl_(dst + shw, b, bn, bits);
132 rn = bn + shw + 1;
133 rn -= dst[rn - 1] == 0 ? 1 : 0;
134 } else {
135 lmmp_copy(dst + shw, b, bn);
136 rn = bn + shw;
137 }
138 TEMP_FREE;
139 return rn;
140}
static mp_size_t pow_nPr_(mp_ptr restrict dst, mp_size_t rn, uint x, uint n, uint m)
mp_size_t lmmp_elem_mul_ulong_(mp_ptr dst, const ulongp limbs, mp_size_t n, mp_ptr tp)
计算limbs数组的累乘积
#define bn
mp_limb_t * mp_ptr
Definition lmmp.h:215
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
#define lmmp_zero(dst, n)
Definition lmmp.h:366
size_t mp_bitcnt_t
Definition lmmp.h:217
uint64_t mp_size_t
Definition lmmp.h:212
uint64_t mp_limb_t
Definition lmmp.h:211
#define LIMB_BITS
Definition lmmp.h:221
#define lmmp_param_assert(x)
Definition lmmp.h:398
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:9
#define ctz_shl(r, x, cnt)
Definition longlong.h:229
#define MP_UINT_MAX
Definition mparam.h:139
uint64_t * ulongp
Definition numth.h:45
uint32_t uint
Definition numth.h:35
uint64_t ulong
Definition numth.h:36
#define TEMP_DECL
Definition tmp_alloc.h:72
#define TEMP_FREE
Definition tmp_alloc.h:93
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:91

引用了 bn, ctz_shl, LIMB_BITS, lmmp_copy, lmmp_elem_mul_ulong_(), lmmp_param_assert, lmmp_shl_(), lmmp_zero, MP_UINT_MAX, pow_nPr_(), TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

+ 函数调用图:

◆ 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
返回
等差数列乘积的 limb 缓冲区长度(比实际长度多 1-2 个 limb)

在文件 arith_seqprod.c14 行定义.

14 {
15 double x_m = (double)x / m;
16 double log_l = (n + 1) * log(m) + lgamma(x_m + n + 1) - lgamma(x_m);
17 double log2_l = log_l / LOG2_;
18 mp_size_t rn = ceil(log2_l / LIMB_BITS) + 2; /* more two limbs */
19 return rn;
20}
#define LOG2_
Definition mparam.h:165

引用了 LIMB_BITS , 以及 LOG2_.

◆ pow_nPr_()

static mp_size_t pow_nPr_ ( mp_ptr restrict  dst,
mp_size_t  rn,
uint  x,
uint  n,
uint  m 
)
inlinestatic

在文件 arith_seqprod.c47 行定义.

47 {
49 uint p = x / m;
50
51 mp_bitcnt_t bits;
52 mp_size_t tn = lmmp_nPr_size_(p + n, n + 1, &bits);
53 tn -= bits / LIMB_BITS;
54 mp_ptr restrict tp = TALLOC_TYPE(tn, mp_limb_t);
55 tn = _odd_nPr_(tp, tn, p + n, n + 1);
56
58 m >>= tz;
59 mp_size_t mpown = lmmp_pow_1_size_(m, n + 1);
60 mp_ptr restrict mpow = TALLOC_TYPE(mpown, mp_limb_t);
61 mpown = _odd_pow_(mpow, mpown, m, n + 1);
62
63 bits += tz * (n + 1);
64 mp_size_t shw = bits / LIMB_BITS;
65 bits %= LIMB_BITS;
66
67 lmmp_zero(dst, shw);
68 if (tn >= mpown)
69 lmmp_mul_(dst + shw, tp, tn, mpow, mpown);
70 else
71 lmmp_mul_(dst + shw, mpow, mpown, tp, tn);
72
73 rn = tn + mpown;
74 rn -= dst[shw + rn - 1] == 0 ? 1 : 0;
75 if (bits > 0) {
76 dst[shw + rn] = lmmp_shl_(dst + shw, dst + shw, rn, bits);
77 rn += shw + 1;
78 rn -= dst[rn - 1] == 0 ? 1 : 0;
79 } else {
80 rn += shw;
81 }
83 return rn;
84}
static mp_size_t _odd_pow_(mp_ptr dst, mp_size_t rn, uint base, ulong exp)
static mp_size_t _odd_nPr_(mp_ptr restrict dst, mp_size_t rn, ulong n, ulong r)
int lmmp_tailing_zeros_(mp_limb_t x)
计算一个单精度数(limb)中末尾零的个数
Definition tiny.c:54
void lmmp_mul_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
不等长大数乘法操作 [dst,na+nb] = [numa,na] * [numb,nb]
#define tp
static mp_size_t lmmp_pow_1_size_(mp_limb_t base, ulong exp)
计算幂次方需要的limb缓冲区长度 base ^ exp
Definition numth.h:264
mp_size_t lmmp_nPr_size_(ulong n, ulong r, mp_bitcnt_t *bits)
计算 nPr 排列数的 limb 缓冲区长度

引用了 _odd_nPr_(), _odd_pow_(), LIMB_BITS, lmmp_mul_(), lmmp_nPr_size_(), lmmp_pow_1_size_(), lmmp_shl_(), lmmp_tailing_zeros_(), lmmp_zero, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_arith_seqprod_().

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