LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
gcd_lehmer.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/lmmpn.h"
17#include "../../../include/lammp/numth.h"
18#include "../../../include/lammp/impl/tmp_alloc.h"
19
20typedef struct {
21 slong m11, m12;
22 slong m21, m22;
24
25#define LEHMER_MIN_V 0x100000000ull
26#define LEHMER_EXACT_BITS 63
27
29#define A (gcd->m11)
30#define B (gcd->m12)
31#define C (gcd->m21)
32#define D (gcd->m22)
33
34 lmmp_debug_assert(u >= 0 && v >= 0);
36 A = 1; B = 0;
37 C = 0; D = 1;
38
39 while (v != 0) {
40 slong q = u / v;
41 slong t = u % v;
42
43 u = v;
44 v = t;
45
46 t = A - q * C;
47 A = C;
48 C = t;
49 t = B - q * D;
50 B = D;
51 D = t;
52
53 if (v < (slong)LEHMER_MIN_V) break;
54 }
55
56 return;
57#undef A
58#undef B
59#undef C
60#undef D
61}
62
64 lmmp_param_assert(un > 1 && vn > 1);
67 lmmp_param_assert(a != NULL && b != NULL);
68
69 int kz = lmmp_limb_bits_(up[un - 1]);
70 if (kz >= LEHMER_EXACT_BITS) {
71 *a = up[un - 1] >> (kz - LEHMER_EXACT_BITS);
72 if (vn == un)
73 *b = vp[vn - 1] >> (kz - LEHMER_EXACT_BITS);
74 else
75 *b = 0;
76 } else {
77 *a = up[un - 1] << (LEHMER_EXACT_BITS - kz);
78 *a |= up[un - 2] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
79 if (un > vn + 1) {
80 *b = 0;
81 } else if (un == vn + 1) {
82 *b = vp[vn - 1] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
83 } else {
84 *b = vp[vn - 1] << (LEHMER_EXACT_BITS - kz);
85 *b |= vp[vn - 2] >> (LIMB_BITS - (LEHMER_EXACT_BITS - kz));
86 }
87 }
88}
89
98
99/**
100 * @brief / a \ = / A B \ * / a \
101 * \ b / \ C D / \ b /
102 * @warning [a,an] > [b,bn]
103 * @note 不保证返回结果 [a,an] > [b,bn]
104 * @return a和b是否有一个为0
105 */
107#define A (M->m11)
108#define B (M->m12)
109#define C (M->m21)
110#define D (M->m22)
111#define an (*an)
112#define bn (*bn)
113 if (A == 0) {
114 /* / 0 1 \ / a \
115 \ 1 -q / \ b / */
116 lmmp_debug_assert(B == 1 && C == 1 && D < 0);
117 mp_limb_t c = lmmp_mul_1_(ms->tp, b, bn, -D);
118 if (c == 0)
119 ;
120 else {
121 ++bn;
122 (ms->tp)[bn - 1] = c;
123 }
124 if (an > bn) {
125 lmmp_sub_(a, a, an, b, bn);
126 } else if (an == bn) {
127 int cmp = lmmp_cmp_(a, b, an);
128 if (cmp >= 0)
129 lmmp_sub_(a, a, an, b, bn);
130 else
131 lmmp_sub_(a, b, bn, a, an);
132 } else {
133 lmmp_sub_(a, b, bn, a, an);
134 an = bn;
135 }
136 while (a[an - 1] == 0 && an > 0) {
137 --an;
138 }
139 // return b = b
140 // a = a - q * b
141 return an == 0;
142 } else {
143 if (A < 0) {
144 A = -A;
145 D = -D;
146 } else {
147 B = -B;
148 C = -C;
149 }
150 // A * a + B * b
151 mp_limb_t ca = lmmp_mul_1_(ms->tp, a, an, A);
152 if (ca == 0)
153 ms->tn = an;
154 else {
155 ms->tn = an + 1;
156 (ms->tp)[ms->tn - 1] = ca;
157 }
158 ca = lmmp_mul_1_(ms->mp, b, bn, B);
159 if (ca == 0)
160 ms->mn = bn;
161 else {
162 ms->mn = bn + 1;
163 (ms->mp)[ms->mn - 1] = ca;
164 }
165
166 if (ms->tn > ms->mn) {
167 lmmp_sub_(ms->np, ms->tp, ms->tn, ms->mp, ms->mn);
168 ms->nn = ms->tn;
169 } else if (ms->mn > ms->tn) {
170 lmmp_sub_(ms->np, ms->mp, ms->mn, ms->tp, ms->tn);
171 ms->nn = ms->mn;
172 } else {
173 int cmp = lmmp_cmp_(ms->tp, ms->mp, ms->tn);
174 if (cmp >= 0) {
175 lmmp_sub_(ms->np, ms->tp, ms->tn, ms->mp, ms->mn);
176 ms->nn = ms->tn;
177 } else {
178 lmmp_sub_(ms->np, ms->mp, ms->mn, ms->tp, ms->tn);
179 ms->nn = ms->mn;
180 }
181 }
182 while (ms->np[ms->nn - 1] == 0 && ms->nn > 0) {
183 --(ms->nn);
184 }
185
186 // C * a + D * b
187 ca = lmmp_mul_1_(ms->tp, a, an, C);
188 if (ca == 0)
189 ms->tn = an;
190 else {
191 ms->tn = an + 1;
192 (ms->tp)[ms->tn - 1] = ca;
193 }
194 ca = lmmp_mul_1_(ms->mp, b, bn, D);
195 if (ca == 0)
196 ms->mn = bn;
197 else {
198 ms->mn = bn + 1;
199 (ms->mp)[ms->mn - 1] = ca;
200 }
201
202 if (ms->tn > ms->mn) {
203 lmmp_sub_(a, ms->tp, ms->tn, ms->mp, ms->mn);
204 an = ms->tn;
205 } else if (ms->mn > ms->tn) {
206 lmmp_sub_(a, ms->mp, ms->mn, ms->tp, ms->tn);
207 an = ms->mn;
208 } else {
209 int cmp = lmmp_cmp_(ms->tp, ms->mp, ms->tn);
210 if (cmp >= 0) {
211 lmmp_sub_(a, ms->tp, ms->tn, ms->mp, ms->mn);
212 an = ms->tn;
213 } else {
214 lmmp_sub_(a, ms->mp, ms->mn, ms->tp, ms->tn);
215 an = ms->mn;
216 }
217 }
218 while (a[an - 1] == 0 && an > 0) {
219 --an;
220 }
221
222 // now a = C * a + D * b
223 // ms->np = A * a + B * b
224 if (ms->nn > 0) {
225 lmmp_copy(b, ms->np, ms->nn);
226 bn = ms->nn;
227 return an == 0;
228 } else {
229 b[0] = 0;
230 bn = 0;
231 return true;
232 }
233 }
234#undef A
235#undef B
236#undef C
237#undef D
238#undef an
239#undef bn
240}
241
243 lmmp_param_assert(un > 0 && vn > 0);
244 lmmp_param_assert(up != NULL && vp != NULL);
246
247 if (un < vn) {
250 } else if (un == vn) {
251 int cmp = lmmp_cmp_(up, vp, un);
252 if (cmp == 0) {
253 lmmp_copy(dst, up, un);
254 return un;
255 } else if (cmp < 0) {
257 }
258 }
259 // u > v
260
262 slong x = 0, y = 0;
263
264#define an un
265#define bn vn
267 // [a,an+1] [b,bn+1]
268 // A * a_old may overlow
272 mp_ptr temp = BALLOC_TYPE((an + 1) * 3, mp_limb_t);
273 ms.tp = temp;
274 ms.mp = temp + (an + 1);
275 ms.np = temp + (an + 1) * 2;
276
277 lmmp_copy(a, up, an);
278 lmmp_copy(b, vp, bn);
279
280 bool bzero = false;
281 while (bzero == false) {
282 if (an > 1 && bn == 1) {
283 dst[0] = lmmp_gcd_1_(a, an, b[0]);
284 return 1;
285 } else if (an == 1 && bn == 1) {
286 dst[0] = lmmp_gcd_11_(a[0], b[0]);
287 return 1;
288 }
289 // a > b
290 lmmp_lehmer_extract_(a, an, b, bn, &x, &y);
292
293 if (M.m21 == 0) {
294 lmmp_div_(NULL, dst, a, an, b, bn);
295 lmmp_copy(a, b, bn);
296 an = bn;
297 while (dst[bn - 1] == 0 && bn > 0) {
298 --bn;
299 }
300 if (bn == 0)
301 bzero = true;
302 else
303 lmmp_copy(b, dst, bn);
304 } else {
305 bzero = lmmp_lehmer_mul_(a, &an, b, &bn, &M, &ms);
306 if ((an < bn) || (an == bn && lmmp_cmp_(a, b, an) < 0)) {
307 LMMP_SWAP(a, b, mp_ptr);
309 }
310 }
311 }
312 lmmp_copy(dst, a, an);
314 return an;
315#undef an
316#undef bn
317}
#define c
mp_size_t mn
Definition gcd_lehmer.c:95
static void lmmp_gcd_lehmer_step_(slong u, slong v, mp_gcd_lehmer_t *gcd)
Definition gcd_lehmer.c:28
#define B
mp_size_t lmmp_gcd_lehmer_(mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
计算两个无符号整数的最大公约数(Lehmer算法)
Definition gcd_lehmer.c:242
#define LEHMER_MIN_V
Definition gcd_lehmer.c:25
#define LEHMER_EXACT_BITS
Definition gcd_lehmer.c:26
#define A
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:106
mp_size_t nn
Definition gcd_lehmer.c:96
#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:63
#define C
#define bn
mp_size_t tn
Definition gcd_lehmer.c:94
#define D
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition gcd_lehmer.c:20
#define lmmp_limb_bits_
Definition inlines.h:162
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define LMMP_SWAP(x, y, type)
Definition lmmp.h:355
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
uint64_t mp_size_t
Definition lmmp.h:77
#define lmmp_debug_assert(x)
Definition lmmp.h:390
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
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:1064
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
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:74
#define t
#define n
mp_limb_t lmmp_gcd_1_(mp_srcptr up, mp_size_t un, mp_limb_t vlimb)
计算两个无符号整数的最大公约数
Definition gcd_1.c:44
int64_t slong
Definition numth.h:34
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算两个无符号整数的最大公约数
Definition gcd_1.c:24
#define TEMP_B_DECL
Definition tmp_alloc.h:132
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:146
#define TEMP_B_FREE
Definition tmp_alloc.h:159