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

浏览源代码.

函数

void lmmp_div_ (mp_ptr dstq, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 大数除法和取模操作
 
mp_limb_t lmmp_div_s_ (mp_ptr restrict dstq, mp_ptr restrict numa, mp_size_t na, mp_srcptr restrict numb, mp_size_t nb)
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 

函数说明

◆ lmmp_div_()

void lmmp_div_ ( mp_ptr  dstq,
mp_ptr  dstr,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

大数除法和取模操作

注解
如果dstq不为NULL: [dstq,na-nb+1] = [numa,na] / [numb,nb] (商) 如果dstr不为NULL: [dstr,nb] = [numa,na] mod [numb,nb] (余数)
警告
0<nb<=na, numb[nb-1]!=0, sep(dstq,[numa|numb]), eqsep(dstr,[numa|numb])) 特殊情况: nb==1时, dstq>=numa-1 是允许的 nb==2时, dstq>=numa 是允许的
参数
dstq商结果输出指针(NULL表示不计算商)
dstr余数结果输出指针(NULL表示不计算余数)
numa被除数指针
na被除数的 limb 长度
numb除数指针
nb除数的 limb 长度

在文件 div.c74 行定义.

74 {
75 if (nb == 1) {
77 if (dstr)
78 *dstr = rem;
79 } else if (nb == 2) {
80 mp_limb_t brem[2];
81 brem[0] = numb[0];
82 brem[1] = numb[1];
84 if (dstr) {
85 dstr[0] = brem[0];
86 dstr[1] = brem[1];
87 }
88 } else {
89 int adjust = numa[na - 1] >= numb[nb - 1];
90 int cnt = lmmp_leading_zeros_(numb[nb - 1]);
91 mp_size_t nq = na + adjust - nb;
92 if (nq == 0) {
93 if (dstr && dstr != numa)
95 if (dstq)
96 dstq[0] = 0;
97 return;
98 }
100
101 if (!dstq)
102 dstq = TALLOC_TYPE(na - nb + 1, mp_limb_t);
103 dstq[na - nb] = 0;
104
105 if (nq >= nb) {
108 if (cnt) {
112 } else {
113 numa2[na] = 0;
115 numb2 = (mp_ptr)numb;
116 }
117
119 na += adjust;
120
125 else {
130 }
131
132 if (dstr) {
133 if (cnt)
135 else
137 }
138 } else {
139 // nq=na-nb+adj<nb
140 //-> na+adj>=2nq+1
141 mp_size_t ni = nb - nq;
145
146 numa2 = TALLOC_TYPE(nq * 2 + 1, mp_limb_t);
147 if (cnt) {
149 lmmp_shl_(numb2, numb + ni, nq, cnt);
150 numb2[0] |= numb[ni - 1] >> (LIMB_BITS - cnt);
151 cy = lmmp_shl_(numa2, numa + na - 2 * nq, 2 * nq, cnt);
152 if (adjust) {
153 numa2[2 * nq] = cy;
154 ++numa2; // numa2[0] is as significant as numa[ni=na-2nq+adjust]
155 } else
156 numa2[0] |= numa[na - 2 * nq - 1] >> (LIMB_BITS - cnt);
157 } else {
158 numb2 = (mp_ptr)numb + ni;
159 lmmp_copy(numa2, numa + na - 2 * nq, 2 * nq);
160 if (adjust) {
161 numa2[2 * nq] = 0;
162 ++numa2;
163 }
164 }
165
166 // now: 0<=numa2<B^2nq, B^nq/2<=numb2<B^nq, and 0<=numa2/numb2<B^nq
167 // ignored bits could be seen as fraction part of numa and numb
168 // we can prove: Q<=Qh<=Q+2
169 // where Q=floor(numa/numb) is the real quotient
170 // Qh=floor(floor(numa)/floor(numb)) as below
171
172 if (nq == 1) {
174 } else if (nq == 2) {
176 } else {
178
181 else if (nq < DIV_MULINV_N_THRESHOLD)
183 else {
185 mp_ptr invappr = tp;
188 }
189 }
190 /*
191 true remainder = partial remainder - quotient * ignored divisor limbs
192
193 Multiply the first ignored divisor limb by the most significant
194 quotient limb. If that product is > the partial remainder's
195 most significant limb, we know the quotient is too large. This
196 test quickly catches most cases where the quotient is too large;
197 it catches all cases where the quotient is 2 too large.*/
198
199 mp_limb_t x;
200 if (cnt) {
202 if (ni < 2)
203 dl = 0;
204 else
205 dl = numb[ni - 2];
206 x = (numb[ni - 1] << cnt) | (dl >> (LIMB_BITS - cnt));
207 } else
208 x = numb[ni - 1];
209 mp_limb_t h = (x >> LIMB_BITS / 2) * (dstq[nq - 1] >> LIMB_BITS / 2);
210 mp_limb_t rnb = 0; // remainder[nb]
211 mp_size_t nr = nq; // remainder=rnb:[numa2,nr]:[...,ni]
212
213 if (h > numa2[nq - 1]) {
214 lmmp_dec(dstq);
216 }
217
218 // if cnt, recover the shift of partial remainder
219 // and remove the effect of the partial-ignored numa[ni-1] and numb[ni-1]
220 if (cnt) {
221 numa2[nq] = rnb;
222 ++nr;
223 --ni;
225 numa2[0] |= numa[ni] & (LIMB_MAX >> cnt);
226 cy = lmmp_submul_1_(numa2, dstq, nq, numb[ni] & (LIMB_MAX >> cnt));
227 rnb = -(numa2[nq] < cy);
228 numa2[nq] -= cy;
229 }
230
231 if (ni == 0) {
232 if (dstr) {
233 if (rnb)
235 else
237 }
238 } else {
239 tp[nb - 1] = 0;
240 if (ni < nq)
241 lmmp_mul_(tp, dstq, nq, numb, ni);
242 else
243 lmmp_mul_(tp, numb, ni, dstq, nq);
244
245 if (dstr) {
246 mp_ptr remptr = dstr == numb ? tp : dstr;
247 cy = lmmp_sub_n_(remptr, numa, tp, ni);
248 rnb -= lmmp_sub_nc_(remptr + ni, numa2, tp + ni, nr, cy);
249 if (rnb)
251 else if (dstr != remptr)
253 } else {
254 int hcmp = lmmp_cmp_(numa2, tp + ni, nr);
255 if (hcmp < 0)
256 --rnb;
257 else if (hcmp == 0)
258 rnb -= (lmmp_cmp_(numa, tp, ni) < 0);
259 }
260 }
261
262 if (rnb)
263 lmmp_dec(dstq);
264 }
265
266 TEMP_FREE;
267 }
268}
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_leading_zeros_
Definition inlines.h:160
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
uint64_t mp_size_t
Definition lmmp.h:77
#define LIMB_MAX
Definition lmmp.h:89
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
static mp_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:804
mp_limb_t lmmp_div_1_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
单精度数除法(除数为1个limb)
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
#define lmmp_dec(p)
大数减1宏(预期无借位)
Definition lmmpn.h:965
void lmmp_inv_prediv_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t ni)
除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
Definition div_mulinv.c:22
void lmmp_div_2_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数除法 (除数为2个limb)
Definition div.c:234
mp_limb_t lmmp_shr_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr)
大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
Definition shr.c:19
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
mp_limb_t lmmp_div_mulinv_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_srcptr invappr, mp_size_t ni)
乘法逆元除法
mp_limb_t lmmp_div_2_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb)
双精度数除法(除数为2个limb)
mp_limb_t lmmp_submul_1_(mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b
mp_limb_t lmmp_sub_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
Definition sub_n.c:80
mp_limb_t lmmp_inv_2_1_(mp_limb_t xh, mp_limb_t xl)
2-1阶逆元计算 (inv21)
Definition inv.c:20
mp_limb_t lmmp_div_basecase_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
基础除法运算
mp_limb_t lmmp_sub_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
Definition sub_n.c:19
mp_limb_t lmmp_div_divide_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
分治除法运算
mp_limb_t lmmp_add_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
Definition add_n.c:81
#define DIV_DIVIDE_THRESHOLD
Definition mparam.h:26
#define DIV_MULINV_N_THRESHOLD
Definition mparam.h:30
#define DIV_MULINV_L_THRESHOLD
Definition mparam.h:28
#define numb
#define tp
#define 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

引用了 DIV_DIVIDE_THRESHOLD, DIV_MULINV_L_THRESHOLD, DIV_MULINV_N_THRESHOLD, LIMB_BITS, LIMB_MAX, lmmp_add_n_(), lmmp_cmp_(), lmmp_copy, lmmp_dec, lmmp_div_1_(), lmmp_div_1_s_(), lmmp_div_2_(), lmmp_div_2_s_(), lmmp_div_basecase_(), lmmp_div_divide_(), lmmp_div_inv_size_(), lmmp_div_mulinv_(), lmmp_inv_2_1_(), lmmp_inv_prediv_(), lmmp_leading_zeros_, lmmp_mul_(), lmmp_shl_(), lmmp_shr_(), lmmp_sub_n_(), lmmp_sub_nc_(), lmmp_submul_1_(), n, numb, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_bninv_(), lmmp_gcd_basecase_(), lmmp_gcd_lehmer_(), lmmp_trialdiv_() , 以及 try_div_().

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

◆ lmmp_div_s_()

mp_limb_t lmmp_div_s_ ( mp_ptr restrict  dstq,
mp_ptr restrict  numa,
mp_size_t  na,
mp_srcptr restrict  numb,
mp_size_t  nb 
)

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

在文件 div.c22 行定义.

28 {
30 mp_limb_t nq = na - nb;
32 if (nq == 0) {
33 qh = lmmp_cmp_(numa, numb, nb) >= 0;
34 if (qh)
36 } else if (nb == 1) {
38 } else if (nb == 2) {
40 } else if (nq < nb) {
41 qh = lmmp_div_s_(dstq, numa + na - 2 * nq, 2 * nq, numb + nb - nq, nq);
42
44 if (nq > nb - nq)
45 lmmp_mul_(tp, dstq, nq, numb, nb - nq);
46 else
47 lmmp_mul_(tp, numb, nb - nq, dstq, nq);
48
50 if (qh)
51 cy += lmmp_sub_n_(numa + nq, numa + nq, numb, nb - nq);
52
53 while (cy) {
54 qh -= lmmp_sub_1_(dstq, dstq, nq, 1);
56 }
57 } else {
63 else {
68 }
69 }
71 return qh;
72}
mp_limb_t lmmp_div_s_(mp_ptr restrict dstq, mp_ptr restrict numa, mp_size_t na, mp_srcptr restrict numb, mp_size_t nb)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition div.c:22
static mp_limb_t lmmp_sub_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
Definition lmmpn.h:1114

引用了 DIV_DIVIDE_THRESHOLD, DIV_MULINV_L_THRESHOLD, DIV_MULINV_N_THRESHOLD, lmmp_add_n_(), lmmp_cmp_(), lmmp_div_1_s_(), lmmp_div_2_s_(), lmmp_div_basecase_(), lmmp_div_divide_(), lmmp_div_inv_size_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_inv_2_1_(), lmmp_inv_prediv_(), lmmp_mul_(), lmmp_sub_1_(), lmmp_sub_n_(), n, numb, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_div_s_().

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