LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
gcd_2.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/longlong.h"
17#include "../../../include/lammp/lmmpn.h"
18#include "../../../include/lammp/numth.h"
19
20
21
22/*
23 FIXME: 内联lmmp_tailing_zeros_()函数,使用编译器内置函数,可以显著提升性能。
24 尝试优化控制流,减少分支与跳转。
25 */
26
31 lmmp_param_assert(!(up[1] == 0 && up[0] == 0));
32 lmmp_param_assert(!(vp[1] == 0 && vp[0] == 0));
33 mp_limb_t u[2] = { up[0], up[1] };
34 mp_limb_t v[2] = { vp[0], vp[1] };
35 int k, cnt;
36
37 if (u[1] == 0 && v[1] == 0) {
38 dst[0] = lmmp_gcd_11_(u[0], v[0]);
39 dst[1] = 0;
40 return 1;
41 } else if (u[1] == 0) {
42 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
43 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
44 goto gcd_1_2;
45 } else if (v[1] == 0) {
46 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
47 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
48 goto gcd_2_1;
49 }
50
51 if (u[0] == 0 && v[0] == 0) {
52 dst[0] = lmmp_gcd_11_(u[1], v[1]);
53 dst[1] = 0;
54 return 1;
55 } else if (u[0] == 0) {
56 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
58 goto gcd_1_2;
59 } else if (v[0] == 0) {
60 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
62 goto gcd_2_1;
63 }
64 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
66
67 if (k > 0)
68 _u128lshr(u, u, k);
70 if (k > 0)
71 _u128lshr(v, v, k);
72 while (!(u[0] == v[0] && u[1] == v[1])) {
73 if (u[1] == 0 && v[1] != 0) goto gcd_1_2;
74 if (v[1] == 0 && u[1] != 0) goto gcd_2_1;
75 if (u[1] == 0 && v[1] == 0) goto gcd_1_1;
76
77 if (_u128cmp(u, v)) {
78 _u128sub(v, v, u);
79 if (v[0] == 0) {
80 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
81 goto gcd_2_1;
82 } else if (v[1] == 0) {
83 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
84 goto gcd_2_1;
85 }
87 // k > 0
88 _u128lshr(v, v, k);
89 } else {
90 _u128sub(u, u, v);
91 if (u[0] == 0) {
92 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
93 goto gcd_1_2;
94 } else if (u[1] == 0) {
95 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
96 goto gcd_1_2;
97 }
99 // k > 0
100 _u128lshr(u, u, k);
101 }
102 }
103 dst[0] = u[0];
104 dst[1] = u[1];
105 if (cnt > 0)
106 _u128lshl(dst, dst, cnt);
107 return 2;
108
109 gcd_1_2: // [u,1] , [v,2]
110 k = lmmp_tailing_zeros_(v[0]);
111 if (k > 0)
112 _u128lshr(v, v, k);
113 while (v[1] != 0) {
114 _u128sub64(v, v, u[0]);
115 if (v[1] == 0)
116 goto gcd_1_1;
117 if (v[0] == 0) {
118 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
119 goto gcd_1_1;
120 }
121 k = lmmp_tailing_zeros_(v[0]);
122 // k > 0
123 _u128lshr(v, v, k);
124 }
125 goto gcd_1_1;
126
127 gcd_2_1: // [u,2] , [v,1]
128 k = lmmp_tailing_zeros_(u[0]);
129 if (k > 0)
130 _u128lshr(u, u, k);
131 while (u[1] != 0) {
132 _u128sub64(u, u, v[0]);
133 if (u[1] == 0)
134 goto gcd_1_1;
135 if (u[0] == 0) {
136 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
137 goto gcd_1_1;
138 }
139 k = lmmp_tailing_zeros_(u[0]);
140 // k > 0
141 _u128lshr(u, u, k);
142 }
143 goto gcd_1_1;
144
145 gcd_1_1: // [u,1] , [v,1]
146 while (u[0] != v[0]) {
147 if (u[0] > v[0]) {
148 u[0] -= v[0];
149 u[0] >>= lmmp_tailing_zeros_(u[0]);
150 } else {
151 v[0] -= u[0];
152 v[0] >>= lmmp_tailing_zeros_(v[0]);
153 }
154 }
155 dst[0] = u[0];
156 dst[1] = 0;
157 if (cnt > 0)
158 _u128lshl(dst, dst, cnt);
159 return dst[1] == 0 ? 1 : 2;
160}
161
167 lmmp_param_assert(vp[1] != 0);
168 mp_limb_t u[2] = {vp[0], vp[1]};
169 lmmp_mod_2_(up, un, u);
170 if (u[1] == 0 && u[0] == 0) {
171 dst[0] = vp[0];
172 dst[1] = vp[1];
173 return 2;
174 } else {
175 return lmmp_gcd_22_(dst, vp, u);
176 }
177}
#define k
mp_size_t lmmp_gcd_2_(mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp)
计算两个无符号整数的最大公约数
Definition gcd_2.c:162
mp_size_t lmmp_gcd_22_(mp_ptr dst, mp_srcptr up, mp_srcptr vp)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition gcd_2.c:27
#define lmmp_tailing_zeros_
Definition inlines.h:161
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint64_t mp_size_t
Definition lmmp.h:77
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
uint64_t mp_limb_t
Definition lmmp.h:76
#define lmmp_param_assert(x)
Definition lmmp.h:401
void lmmp_mod_2_(mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数取余 (除数为2个limb)
Definition div.c:155
#define _u128lshl(x, y, n)
Definition longlong.h:330
#define _u128sub(r, x, y)
Definition longlong.h:368
#define _u128cmp(x, y)
Definition longlong.h:366
#define _u128lshr(x, y, n)
Definition longlong.h:336
#define _u128sub64(r, x, _i64)
Definition longlong.h:358
#define n
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算两个无符号整数的最大公约数
Definition gcd_1.c:24