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

浏览源代码.

结构体

struct  lehmer_stack_t
 
struct  mp_gcd_lehmer_t
 

宏定义

#define A   (gcd->m11)
 
#define A   (M->m11)
 
#define an   (*an)
 
#define an   un
 
#define B   (gcd->m12)
 
#define B   (M->m12)
 
#define bn   (*bn)
 
#define bn   vn
 
#define C   (gcd->m21)
 
#define C   (M->m21)
 
#define D   (gcd->m22)
 
#define D   (M->m22)
 
#define LEHMER_EXACT_BITS   63
 
#define LEHMER_MIN_V   0x100000000ull
 

函数

mp_size_t lmmp_gcd_lehmer_ (mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
 计算两个无符号整数的最大公约数(Lehmer算法)
 
static void lmmp_gcd_lehmer_step_ (slong u, slong v, mp_gcd_lehmer_t *gcd)
 
static void lmmp_lehmer_extract_ (mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn, slong *a, slong *b)
 
static bool lmmp_lehmer_mul_ (mp_ptr a, mp_size_t *an, mp_ptr b, mp_size_t *bn, mp_gcd_lehmer_t *M, lehmer_stack_t *ms)
 / a \ = / A B \ * / a \ \ b / \ C D / \ b /

 

结构体说明

◆ lehmer_stack_t

struct lehmer_stack_t

在文件 gcd_lehmer.c81 行定义.

+ lehmer_stack_t 的协作图:
成员变量
mp_size_t mn
mp_ptr mp
mp_size_t nn
mp_ptr np
mp_size_t tn
mp_ptr tp

◆ mp_gcd_lehmer_t

struct mp_gcd_lehmer_t

在文件 gcd_lehmer.c11 行定义.

+ mp_gcd_lehmer_t 的协作图:
成员变量
slong m11
slong m12
slong m21
slong m22

宏定义说明

◆ A [1/2]

#define A   (gcd->m11)

◆ A [2/2]

#define A   (M->m11)

◆ an [1/2]

#define an   (*an)

◆ an [2/2]

#define an   un

◆ B [1/2]

#define B   (gcd->m12)

◆ B [2/2]

#define B   (M->m12)

◆ bn [1/2]

#define bn   (*bn)

◆ bn [2/2]

#define bn   vn

◆ C [1/2]

#define C   (gcd->m21)

◆ C [2/2]

#define C   (M->m21)

◆ D [1/2]

#define D   (gcd->m22)

◆ D [2/2]

#define D   (M->m22)

◆ LEHMER_EXACT_BITS

#define LEHMER_EXACT_BITS   63

在文件 gcd_lehmer.c17 行定义.

◆ LEHMER_MIN_V

#define LEHMER_MIN_V   0x100000000ull

在文件 gcd_lehmer.c16 行定义.

函数说明

◆ lmmp_gcd_lehmer_()

mp_size_t lmmp_gcd_lehmer_ ( mp_ptr  dst,
mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp,
mp_size_t  vn 
)

计算两个无符号整数的最大公约数(Lehmer算法)

参数
dst结果指针(长度至少为 min(un,vn))
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
vp第二个无符号整数指针
vn第二个无符号整数的 limb 长度
警告
up!=NULL, un>0, vp!=NULL, vn>0, eqsep(dst,[up|vp]), dst!=NULL
返回
dst 的实际 limb 长度

在文件 gcd_lehmer.c233 行定义.

233 {
234 lmmp_param_assert(un > 0 && vn > 0);
235 lmmp_param_assert(up != NULL && vp != NULL);
236 lmmp_param_assert(dst != NULL);
237
238 if (un < vn) {
239 LMMP_SWAP(up, vp, mp_srcptr);
240 LMMP_SWAP(un, vn, mp_size_t);
241 } else if (un == vn) {
242 int cmp = lmmp_cmp_(up, vp, un);
243 if (cmp == 0) {
244 lmmp_copy(dst, up, un);
245 return un;
246 } else if (cmp < 0) {
247 LMMP_SWAP(up, vp, mp_srcptr);
248 }
249 }
250 // u > v
251
253 slong x = 0, y = 0;
254
255#define an un
256#define bn vn
258 // [a,an+1] [b,bn+1]
259 // A * a_old may overlow
260 mp_ptr a = BALLOC_TYPE(an + 1, mp_limb_t);
261 mp_ptr b = BALLOC_TYPE(bn + 1, mp_limb_t);
263 mp_ptr temp = BALLOC_TYPE((an + 1) * 3, mp_limb_t);
264 ms.tp = temp;
265 ms.mp = temp + (an + 1);
266 ms.np = temp + (an + 1) * 2;
267
268 lmmp_copy(a, up, an);
269 lmmp_copy(b, vp, bn);
270
271 bool bzero = false;
272 while (bzero == false) {
273 if (an > 1 && bn == 1) {
274 dst[0] = lmmp_gcd_1_(a, an, b[0]);
275 return 1;
276 } else if (an == 1 && bn == 1) {
277 dst[0] = lmmp_gcd_11_(a[0], b[0]);
278 return 1;
279 }
280 // a > b
281 lmmp_lehmer_extract_(a, an, b, bn, &x, &y);
282 lmmp_gcd_lehmer_step_(x, y, &M);
283
284 if (M.m21 == 0) {
285 lmmp_div_(NULL, dst, a, an, b, bn);
286 lmmp_copy(a, b, bn);
287 an = bn;
288 while (dst[bn - 1] == 0 && bn > 0) {
289 --bn;
290 }
291 if (bn == 0)
292 bzero = true;
293 else
294 lmmp_copy(b, dst, bn);
295 } else {
296 bzero = lmmp_lehmer_mul_(a, &an, b, &bn, &M, &ms);
297 if ((an < bn) || (an == bn && lmmp_cmp_(a, b, an) < 0)) {
298 LMMP_SWAP(a, b, mp_ptr);
300 }
301 }
302 }
303 lmmp_copy(dst, a, an);
305 return an;
306#undef an
307#undef bn
308}
static void lmmp_gcd_lehmer_step_(slong u, slong v, mp_gcd_lehmer_t *gcd)
Definition gcd_lehmer.c:19
static bool lmmp_lehmer_mul_(mp_ptr a, mp_size_t *an, mp_ptr b, mp_size_t *bn, mp_gcd_lehmer_t *M, lehmer_stack_t *ms)
/ a \ = / A B \ * / a \ \ b / \ C D / \ b /
Definition gcd_lehmer.c:97
#define an
static void lmmp_lehmer_extract_(mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn, slong *a, slong *b)
Definition gcd_lehmer.c:54
#define bn
mp_limb_t * mp_ptr
Definition lmmp.h:215
#define LMMP_SWAP(x, y, type)
Definition lmmp.h:352
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
uint64_t mp_size_t
Definition lmmp.h:212
const mp_limb_t * mp_srcptr
Definition lmmp.h:216
uint64_t mp_limb_t
Definition lmmp.h:211
#define lmmp_param_assert(x)
Definition lmmp.h:398
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:1004
void lmmp_div_(mp_ptr dstq, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数除法和取模操作
Definition div.c:57
mp_limb_t lmmp_gcd_1_(mp_srcptr up, mp_size_t un, mp_limb_t vlimb)
计算两个无符号整数的最大公约数
Definition gcd_1.c:30
int64_t slong
Definition numth.h:38
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算 [numa,na] 在B^n 下的逆元
Definition gcd_1.c:10
#define TEMP_B_DECL
Definition tmp_alloc.h:75
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:89
#define TEMP_B_FREE
Definition tmp_alloc.h:100

引用了 an, BALLOC_TYPE, bn, lmmp_cmp_(), lmmp_copy, lmmp_div_(), lmmp_gcd_11_(), lmmp_gcd_1_(), lmmp_gcd_lehmer_step_(), lmmp_lehmer_extract_(), lmmp_lehmer_mul_(), lmmp_param_assert, LMMP_SWAP, mp_gcd_lehmer_t::m21, lehmer_stack_t::mp, lehmer_stack_t::np, TEMP_B_DECL, TEMP_B_FREE , 以及 lehmer_stack_t::tp.

+ 函数调用图:

◆ lmmp_gcd_lehmer_step_()

static void lmmp_gcd_lehmer_step_ ( slong  u,
slong  v,
mp_gcd_lehmer_t gcd 
)
static

在文件 gcd_lehmer.c19 行定义.

19 {
20#define A (gcd->m11)
21#define B (gcd->m12)
22#define C (gcd->m21)
23#define D (gcd->m22)
24
25 lmmp_debug_assert(u >= 0 && v >= 0);
26 lmmp_debug_assert(u >= v);
27 A = 1; B = 0;
28 C = 0; D = 1;
29
30 while (v != 0) {
31 slong q = u / v;
32 slong t = u % v;
33
34 u = v;
35 v = t;
36
37 t = A - q * C;
38 A = C;
39 C = t;
40 t = B - q * D;
41 B = D;
42 D = t;
43
44 if (v < (slong)LEHMER_MIN_V) break;
45 }
46
47 return;
48#undef A
49#undef B
50#undef C
51#undef D
52}
#define B
#define LEHMER_MIN_V
Definition gcd_lehmer.c:16
#define A
#define C
#define D
#define lmmp_debug_assert(x)
Definition lmmp.h:387

引用了 A, B, C, D, LEHMER_MIN_V , 以及 lmmp_debug_assert.

被这些函数引用 lmmp_gcd_lehmer_().

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

◆ lmmp_lehmer_extract_()

static void lmmp_lehmer_extract_ ( mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp,
mp_size_t  vn,
slong a,
slong b 
)
static

在文件 gcd_lehmer.c54 行定义.

54 {
55 lmmp_param_assert(un > 1 && vn > 1);
56 lmmp_param_assert(un >= vn);
57 lmmp_param_assert(up != NULL && vp != NULL);
58 lmmp_param_assert(a != NULL && b != NULL);
59
60 int kz = lmmp_limb_bits_(up[un - 1]);
61 if (kz >= LEHMER_EXACT_BITS) {
62 *a = up[un - 1] >> (kz - LEHMER_EXACT_BITS);
63 if (vn == un)
64 *b = vp[vn - 1] >> (kz - LEHMER_EXACT_BITS);
65 else
66 *b = 0;
67 } else {
68 *a = up[un - 1] << (LEHMER_EXACT_BITS - kz);
69 *a |= up[un - 2] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
70 if (un > vn + 1) {
71 *b = 0;
72 } else if (un == vn + 1) {
73 *b = vp[vn - 1] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
74 } else {
75 *b = vp[vn - 1] << (LEHMER_EXACT_BITS - kz);
76 *b |= vp[vn - 2] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
77 }
78 }
79}
#define LEHMER_EXACT_BITS
Definition gcd_lehmer.c:17
#define LIMB_BITS
Definition lmmp.h:221
int lmmp_limb_bits_(mp_limb_t x)
计算满足 2^k > x 的最小自然数k
Definition tiny.c:11

引用了 LEHMER_EXACT_BITS, LIMB_BITS, lmmp_limb_bits_() , 以及 lmmp_param_assert.

被这些函数引用 lmmp_gcd_lehmer_().

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

◆ lmmp_lehmer_mul_()

static bool lmmp_lehmer_mul_ ( mp_ptr  a,
mp_size_t an,
mp_ptr  b,
mp_size_t bn,
mp_gcd_lehmer_t M,
lehmer_stack_t ms 
)
static

/ a \ = / A B \ * / a \ \ b / \ C D / \ b /

警告
[a,an] > [b,bn]
注解
不保证返回结果 [a,an] > [b,bn]
返回
a和b是否有一个为0

在文件 gcd_lehmer.c97 行定义.

97 {
98#define A (M->m11)
99#define B (M->m12)
100#define C (M->m21)
101#define D (M->m22)
102#define an (*an)
103#define bn (*bn)
104 if (A == 0) {
105 /* / 0 1 \ / a \
106 \ 1 -q / \ b / */
107 lmmp_debug_assert(B == 1 && C == 1 && D < 0);
108 mp_limb_t c = lmmp_mul_1_(ms->tp, b, bn, -D);
109 if (c == 0)
110 ;
111 else {
112 ++bn;
113 (ms->tp)[bn - 1] = c;
114 }
115 if (an > bn) {
116 lmmp_sub_(a, a, an, b, bn);
117 } else if (an == bn) {
118 int cmp = lmmp_cmp_(a, b, an);
119 if (cmp >= 0)
120 lmmp_sub_(a, a, an, b, bn);
121 else
122 lmmp_sub_(a, b, bn, a, an);
123 } else {
124 lmmp_sub_(a, b, bn, a, an);
125 an = bn;
126 }
127 while (a[an - 1] == 0 && an > 0) {
128 --an;
129 }
130 // return b = b
131 // a = a - q * b
132 return an == 0;
133 } else {
134 if (A < 0) {
135 A = -A;
136 D = -D;
137 } else {
138 B = -B;
139 C = -C;
140 }
141 // A * a + B * b
142 mp_limb_t ca = lmmp_mul_1_(ms->tp, a, an, A);
143 if (ca == 0)
144 ms->tn = an;
145 else {
146 ms->tn = an + 1;
147 (ms->tp)[ms->tn - 1] = ca;
148 }
149 ca = lmmp_mul_1_(ms->mp, b, bn, B);
150 if (ca == 0)
151 ms->mn = bn;
152 else {
153 ms->mn = bn + 1;
154 (ms->mp)[ms->mn - 1] = ca;
155 }
156
157 if (ms->tn > ms->mn) {
158 lmmp_sub_(ms->np, ms->tp, ms->tn, ms->mp, ms->mn);
159 ms->nn = ms->tn;
160 } else if (ms->mn > ms->tn) {
161 lmmp_sub_(ms->np, ms->mp, ms->mn, ms->tp, ms->tn);
162 ms->nn = ms->mn;
163 } else {
164 int cmp = lmmp_cmp_(ms->tp, ms->mp, ms->tn);
165 if (cmp >= 0) {
166 lmmp_sub_(ms->np, ms->tp, ms->tn, ms->mp, ms->mn);
167 ms->nn = ms->tn;
168 } else {
169 lmmp_sub_(ms->np, ms->mp, ms->mn, ms->tp, ms->tn);
170 ms->nn = ms->mn;
171 }
172 }
173 while (ms->np[ms->nn - 1] == 0 && ms->nn > 0) {
174 --(ms->nn);
175 }
176
177 // C * a + D * b
178 ca = lmmp_mul_1_(ms->tp, a, an, C);
179 if (ca == 0)
180 ms->tn = an;
181 else {
182 ms->tn = an + 1;
183 (ms->tp)[ms->tn - 1] = ca;
184 }
185 ca = lmmp_mul_1_(ms->mp, b, bn, D);
186 if (ca == 0)
187 ms->mn = bn;
188 else {
189 ms->mn = bn + 1;
190 (ms->mp)[ms->mn - 1] = ca;
191 }
192
193 if (ms->tn > ms->mn) {
194 lmmp_sub_(a, ms->tp, ms->tn, ms->mp, ms->mn);
195 an = ms->tn;
196 } else if (ms->mn > ms->tn) {
197 lmmp_sub_(a, ms->mp, ms->mn, ms->tp, ms->tn);
198 an = ms->mn;
199 } else {
200 int cmp = lmmp_cmp_(ms->tp, ms->mp, ms->tn);
201 if (cmp >= 0) {
202 lmmp_sub_(a, ms->tp, ms->tn, ms->mp, ms->mn);
203 an = ms->tn;
204 } else {
205 lmmp_sub_(a, ms->mp, ms->mn, ms->tp, ms->tn);
206 an = ms->mn;
207 }
208 }
209 while (a[an - 1] == 0 && an > 0) {
210 --an;
211 }
212
213 // now a = C * a + D * b
214 // ms->np = A * a + B * b
215 if (ms->nn > 0) {
216 lmmp_copy(b, ms->np, ms->nn);
217 bn = ms->nn;
218 return an == 0;
219 } else {
220 b[0] = 0;
221 bn = 0;
222 return true;
223 }
224 }
225#undef A
226#undef B
227#undef C
228#undef D
229#undef an
230#undef bn
231}
mp_size_t mn
Definition gcd_lehmer.c:86
mp_size_t nn
Definition gcd_lehmer.c:87
mp_size_t tn
Definition gcd_lehmer.c:85
static mp_limb_t lmmp_sub_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]
Definition lmmpn.h:1072
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

引用了 A, an, B, bn, C, D, lmmp_cmp_(), lmmp_copy, lmmp_debug_assert, lmmp_mul_1_(), lmmp_sub_(), lehmer_stack_t::mn, lehmer_stack_t::mp, lehmer_stack_t::nn, lehmer_stack_t::np, lehmer_stack_t::tn , 以及 lehmer_stack_t::tp.

被这些函数引用 lmmp_gcd_lehmer_().

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