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.c78 行定义.

78 {
80 lmmp_param_assert(numa != NULL && numb != NULL && nb > 0);
81 lmmp_param_assert(numb[nb - 1] > 0);
82 if (nb == 1) {
84 if (dstr)
85 *dstr = rem;
86 } else if (nb == 2) {
87 mp_limb_t brem[2];
88 brem[0] = numb[0];
89 brem[1] = numb[1];
91 if (dstr) {
92 dstr[0] = brem[0];
93 dstr[1] = brem[1];
94 }
95 } else {
96 int adjust = numa[na - 1] >= numb[nb - 1];
97 int cnt = lmmp_leading_zeros_(numb[nb - 1]);
98 mp_size_t nq = na + adjust - nb;
99 if (nq == 0) {
100 if (dstr && dstr != numa)
102 if (dstq)
103 dstq[0] = 0;
104 return;
105 }
106 TEMP_DECL;
107
108 if (!dstq)
109 dstq = TALLOC_TYPE(na - nb + 1, mp_limb_t);
110 dstq[na - nb] = 0;
111
112 if (nq >= nb) {
115 if (cnt) {
119 } else {
120 numa2[na] = 0;
122 numb2 = (mp_ptr)numb;
123 }
124
126 na += adjust;
127
132 else {
137 }
138
139 if (dstr) {
140 if (cnt)
142 else
144 }
145 } else {
146 // nq=na-nb+adj<nb
147 //-> na+adj>=2nq+1
148 mp_size_t ni = nb - nq;
152
153 numa2 = TALLOC_TYPE(nq * 2 + 1, mp_limb_t);
154 if (cnt) {
156 lmmp_shl_(numb2, numb + ni, nq, cnt);
157 numb2[0] |= numb[ni - 1] >> (LIMB_BITS - cnt);
158 cy = lmmp_shl_(numa2, numa + na - 2 * nq, 2 * nq, cnt);
159 if (adjust) {
160 numa2[2 * nq] = cy;
161 ++numa2; // numa2[0] is as significant as numa[ni=na-2nq+adjust]
162 } else
163 numa2[0] |= numa[na - 2 * nq - 1] >> (LIMB_BITS - cnt);
164 } else {
165 numb2 = (mp_ptr)numb + ni;
166 lmmp_copy(numa2, numa + na - 2 * nq, 2 * nq);
167 if (adjust) {
168 numa2[2 * nq] = 0;
169 ++numa2;
170 }
171 }
172
173 // now: 0<=numa2<B^2nq, B^nq/2<=numb2<B^nq, and 0<=numa2/numb2<B^nq
174 // ignored bits could be seen as fraction part of numa and numb
175 // we can prove: Q<=Qh<=Q+2
176 // where Q=floor(numa/numb) is the real quotient
177 // Qh=floor(floor(numa)/floor(numb)) as below
178
179 if (nq == 1) {
181 } else if (nq == 2) {
183 } else {
185
188 else if (nq < DIV_MULINV_N_THRESHOLD)
190 else {
192 mp_ptr invappr = tp;
195 }
196 }
197 /*
198 true remainder = partial remainder - quotient * ignored divisor limbs
199
200 Multiply the first ignored divisor limb by the most significant
201 quotient limb. If that product is > the partial remainder's
202 most significant limb, we know the quotient is too large. This
203 test quickly catches most cases where the quotient is too large;
204 it catches all cases where the quotient is 2 too large.*/
205
206 mp_limb_t x;
207 if (cnt) {
209 if (ni < 2)
210 dl = 0;
211 else
212 dl = numb[ni - 2];
213 x = (numb[ni - 1] << cnt) | (dl >> (LIMB_BITS - cnt));
214 } else
215 x = numb[ni - 1];
216 mp_limb_t h = (x >> LIMB_BITS / 2) * (dstq[nq - 1] >> LIMB_BITS / 2);
217 mp_limb_t rnb = 0; // remainder[nb]
218 mp_size_t nr = nq; // remainder=rnb:[numa2,nr]:[...,ni]
219
220 if (h > numa2[nq - 1]) {
221 lmmp_dec(dstq);
223 }
224
225 // if cnt, recover the shift of partial remainder
226 // and remove the effect of the partial-ignored numa[ni-1] and numb[ni-1]
227 if (cnt) {
228 numa2[nq] = rnb;
229 ++nr;
230 --ni;
232 numa2[0] |= numa[ni] & (LIMB_MAX >> cnt);
233 cy = lmmp_submul_1_(numa2, dstq, nq, numb[ni] & (LIMB_MAX >> cnt));
234 rnb = -(numa2[nq] < cy);
235 numa2[nq] -= cy;
236 }
237
238 if (ni == 0) {
239 if (dstr) {
240 if (rnb)
242 else
244 }
245 } else {
246 tp[nb - 1] = 0;
247 if (ni < nq)
248 lmmp_mul_(tp, dstq, nq, numb, ni);
249 else
250 lmmp_mul_(tp, numb, ni, dstq, nq);
251
252 if (dstr) {
253 mp_ptr remptr = dstr == numb ? tp : dstr;
254 cy = lmmp_sub_n_(remptr, numa, tp, ni);
255 rnb -= lmmp_sub_nc_(remptr + ni, numa2, tp + ni, nr, cy);
256 if (rnb)
258 else if (dstr != remptr)
260 } else {
261 int hcmp = lmmp_cmp_(numa2, tp + ni, nr);
262 if (hcmp < 0)
263 --rnb;
264 else if (hcmp == 0)
265 rnb -= (lmmp_cmp_(numa, tp, ni) < 0);
266 }
267 }
268
269 if (rnb)
270 lmmp_dec(dstq);
271 }
272
273 TEMP_FREE;
274 }
275}
#define lmmp_leading_zeros_
Definition inlines.h:160
mp_limb_t * mp_ptr
Definition lmmp.h:117
#define lmmp_copy(dst, src, n)
Definition lmmp.h:461
uint64_t mp_size_t
Definition lmmp.h:114
#define LIMB_MAX
Definition lmmp.h:126
uint64_t mp_limb_t
Definition lmmp.h:113
#define LIMB_BITS
Definition lmmp.h:123
#define lmmp_param_assert(x)
Definition lmmp.h:496
static mp_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:782
mp_limb_t lmmp_div_1_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
单精度数除法(除数为1个limb)
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:77
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
比较函数(内联)
Definition lmmpn.h:959
#define lmmp_dec(p)
减1宏(预期无借位)
Definition lmmpn.h:928
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:158
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:156

引用了 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_param_assert, 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_cbrtapprox_(), 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 lmmp_param_assert(numa != NULL && numb != NULL && nb > 0);
32
34 mp_limb_t nq = na - nb;
36 if (nq == 0) {
37 qh = lmmp_cmp_(numa, numb, nb) >= 0;
38 if (qh)
40 } else if (nb == 1) {
42 } else if (nb == 2) {
44 } else if (nq < nb) {
45 qh = lmmp_div_s_(dstq, numa + na - 2 * nq, 2 * nq, numb + nb - nq, nq);
46
48 if (nq > nb - nq)
49 lmmp_mul_(tp, dstq, nq, numb, nb - nq);
50 else
51 lmmp_mul_(tp, numb, nb - nq, dstq, nq);
52
54 if (qh)
55 cy += lmmp_sub_n_(numa + nq, numa + nq, numb, nb - nq);
56
57 while (cy) {
58 qh -= lmmp_sub_1_(dstq, dstq, nq, 1);
60 }
61 } else {
67 else {
72 }
73 }
75 return qh;
76}
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:1077
#define LIMB_B_2
Definition mparam.h:157

引用了 DIV_DIVIDE_THRESHOLD, DIV_MULINV_L_THRESHOLD, DIV_MULINV_N_THRESHOLD, LIMB_B_2, 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_param_assert, lmmp_sub_1_(), lmmp_sub_n_(), n, numb, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_div_s_().

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