LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
arith_seqprod.c
浏览该文件的文档.
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#include "../../../include/lammp/impl/ele_mul.h"
17#include "../../../include/lammp/impl/mparam.h"
18#include "../../../include/lammp/impl/tmp_alloc.h"
19#include "../../../include/lammp/impl/longlong.h"
20#include "../../../include/lammp/lmmpn.h"
21#include "../../../include/lammp/numth.h"
22
23
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}
35
37 if (base <= 0xf)
38 return lmmp_u4_pow_1_(dst, rn, base, exp);
39 else if (base <= MP_UCHAR_MAX)
40 return lmmp_u8_pow_1_(dst, rn, base, exp);
41 else if (base <= MP_USHORT_MAX)
42 return lmmp_u16_pow_1_(dst, rn, base, exp);
43 else
44 return lmmp_u32_pow_1_(dst, rn, base, exp);
45}
46
48 if (n <= NPR_SHORT_LIMIT) {
49 return lmmp_odd_nPr_ushort_(dst, rn, n, r);
50 } else {
51 return lmmp_odd_nPr_uint_(dst, rn, n, r);
52 }
53}
54
55/*
56当x=p*m时,
57x(x+m)...(x+n*m) = p*m * (p+1)*m * ... * (p+n)*m
58 = m^(n+1) * p(p+1)...(p+n)
59分别计算幂和组合数,然后相乘
60*/
63 uint p = x / m;
64
66 mp_size_t tn = lmmp_nPr_size_(p + n, n + 1, &bits);
67 tn -= bits / LIMB_BITS;
69 tn = _odd_nPr_(tp, tn, p + n, n + 1);
70
72 m >>= tz;
75 mpown = _odd_pow_(mpow, mpown, m, n + 1);
76
77 bits += tz * (n + 1);
79 bits %= LIMB_BITS;
80
82 if (tn >= mpown)
83 lmmp_mul_(dst + shw, tp, tn, mpow, mpown);
84 else
85 lmmp_mul_(dst + shw, mpow, mpown, tp, tn);
86
87 rn = tn + mpown;
88 rn -= dst[shw + rn - 1] == 0 ? 1 : 0;
89 if (bits > 0) {
90 dst[shw + rn] = lmmp_shl_(dst + shw, dst + shw, rn, bits);
91 rn += shw + 1;
92 rn -= dst[rn - 1] == 0 ? 1 : 0;
93 } else {
94 rn += shw;
95 }
97 return rn;
98}
99
102 lmmp_param_assert(rn >= 1);
103 lmmp_param_assert(x >= 1);
104 lmmp_param_assert(n >= 1);
105 lmmp_param_assert(m > 1);
106
107 if (x % m == 0) {
108 return pow_nPr_(dst, rn, x, n, m);
109 }
110
111 mp_bitcnt_t bits = 0;
112 while ((x & 1) == 0 && (m & 1) == 0) {
113 x >>= 1;
114 m >>= 1;
115 bits++;
116 }
117 bits *= n + 1;
118
119 TEMP_DECL;
120 ulongp restrict limbs = TALLOC_TYPE((n + 1) / 2 + 1, ulong);
121 mp_size_t limbn = 0;
122 ulong t = 1, s, v;
124 for (uint i = 0; i <= n; i++) {
125 s = x + i * m;
126 ctz_shr_u64(v, s, cnt);
127 t *= v;
128 bits += cnt;
129 if (t > MP_UINT_MAX) {
130 limbs[limbn++] = t;
131 t = 1;
132 }
133 }
134 ctz_shr_u64(v, t, cnt);
135 bits += cnt;
136 if (v != 1) {
137 limbs[limbn++] = v;
138 }
140 bits %= LIMB_BITS;
143 lmmp_zero(dst, shw);
144 if (bits > 0) {
145 dst[shw + bn] = lmmp_shl_(dst + shw, b, bn, bits);
146 rn = bn + shw + 1;
147 rn -= dst[rn - 1] == 0 ? 1 : 0;
148 } else {
149 lmmp_copy(dst + shw, b, bn);
150 rn = bn + shw;
151 }
152 TEMP_FREE;
153 return rn;
154}
mp_size_t lmmp_arith_seqprod_size_(uint x, uint n, uint m)
Copyright (C) 2026 HJimmyK(Jericho Knox)
static mp_size_t _odd_pow_(mp_ptr restrict dst, mp_size_t rn, uint base, ulong exp)
static mp_size_t pow_nPr_(mp_ptr restrict dst, mp_size_t rn, uint x, uint n, uint m)
static mp_size_t _odd_nPr_(mp_ptr restrict dst, mp_size_t rn, ulong n, ulong r)
mp_size_t lmmp_arith_seqprod_(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
#define lmmp_tailing_zeros_
Definition inlines.h:161
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
uint64_t mp_limb_t
Definition lmmp.h:76
#define LMMP_MIN(l, o)
Definition lmmp.h:351
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
void lmmp_mul_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
不等长大数乘法操作 [dst,na+nb] = [numa,na] * [numb,nb]
mp_limb_t lmmp_shl_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
Definition shl.c:19
#define ctz_shr_u64(r, x, cnt)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition longlong.h:74
#define NPR_SHORT_LIMIT
Definition mparam.h:151
#define MP_UINT_MAX
Definition mparam.h:136
#define MP_UCHAR_MAX
Definition mparam.h:134
#define MP_USHORT_MAX
Definition mparam.h:135
#define t
#define tp
#define s
#define n
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
mp_size_t lmmp_odd_nPr_ushort_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
mp_size_t lmmp_u32_pow_1_(mp_ptr dst, mp_size_t rn, ulong base, ulong exp)
计算幂次方 [dst,rn] = [base,1] ^ exp
uint64_t * ulongp
Definition numth.h:41
uint32_t uint
Definition numth.h:31
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
mp_size_t lmmp_nPr_size_(ulong n, ulong r, mp_bitcnt_t *bits)
计算 nPr 排列数的 limb 缓冲区长度
uint64_t ulong
Definition numth.h:32
mp_size_t lmmp_odd_nPr_uint_(mp_ptr dst, mp_size_t rn, ulong n, ulong r)
计算 nPr 排列数的奇数部分
#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