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

浏览源代码.

函数

mp_size_t lmmp_gcd_22_ (mp_ptr dst, mp_srcptr up, mp_srcptr vp)
 计算两个无符号整数的最大公约数
 
mp_size_t lmmp_gcd_2_ (mp_ptr dst, mp_srcptr up, mp_size_t un, mp_srcptr vp)
 计算两个无符号整数的最大公约数
 

函数说明

◆ lmmp_gcd_22_()

mp_size_t lmmp_gcd_22_ ( mp_ptr  dst,
mp_srcptr  up,
mp_srcptr  vp 
)

计算两个无符号整数的最大公约数

参数
up第一个无符号整数指针,长度为 2
vp第二个无符号整数指针,长度为 2
dst结果指针(长度为 2,两个 limb 都会进行写入,即使最高位可能为0)
警告
up!=NULL, vp!=NULL, [up,2]!=0, [vp,2]!=0, dst!=NULL, eqsep(dst,[up|vp])
注解
我们不要求 up 和 vp 的高位不为 0,但要求两个数均不可以高低位全为 0
返回
dst 的实际 limb 长度

在文件 gcd_2.c11 行定义.

11 {
12 lmmp_param_assert(dst != NULL);
13 lmmp_param_assert(up != NULL);
14 lmmp_param_assert(vp != NULL);
15 lmmp_param_assert(!(up[1] == 0 && up[0] == 0));
16 lmmp_param_assert(!(vp[1] == 0 && vp[0] == 0));
17 mp_limb_t u[2] = { up[0], up[1] };
18 mp_limb_t v[2] = { vp[0], vp[1] };
19 int k, cnt;
20
21 if (u[1] == 0 && v[1] == 0) {
22 dst[0] = lmmp_gcd_11_(u[0], v[0]);
23 dst[1] = 0;
24 return 1;
25 } else if (u[1] == 0) {
26 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
27 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
28 goto gcd_1_2;
29 } else if (v[1] == 0) {
30 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
31 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
32 goto gcd_2_1;
33 }
34
35 if (u[0] == 0 && v[0] == 0) {
36 dst[0] = lmmp_gcd_11_(u[1], v[1]);
37 dst[1] = 0;
38 return 1;
39 } else if (u[0] == 0) {
40 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
41 cnt = lmmp_tailing_zeros_(v[0]);
42 goto gcd_1_2;
43 } else if (v[0] == 0) {
44 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
45 cnt = lmmp_tailing_zeros_(u[0]);
46 goto gcd_2_1;
47 }
48 cnt = lmmp_tailing_zeros_(u[0] | v[0]);
49 k = lmmp_tailing_zeros_(u[0]);
50
51 if (k > 0)
52 _u128lshr(u, u, k);
53 k = lmmp_tailing_zeros_(v[0]);
54 if (k > 0)
55 _u128lshr(v, v, k);
56 while (!(u[0] == v[0] && u[1] == v[1])) {
57 if (u[1] == 0 && v[1] != 0) goto gcd_1_2;
58 if (v[1] == 0 && u[1] != 0) goto gcd_2_1;
59 if (u[1] == 0 && v[1] == 0) goto gcd_1_1;
60
61 if (_u128cmp(u, v)) {
62 _u128sub(v, v, u);
63 if (v[0] == 0) {
64 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
65 goto gcd_2_1;
66 } else if (v[1] == 0) {
67 v[0] = v[0] >> lmmp_tailing_zeros_(v[0]);
68 goto gcd_2_1;
69 }
70 k = lmmp_tailing_zeros_(v[0]);
71 // k > 0
72 _u128lshr(v, v, k);
73 } else {
74 _u128sub(u, u, v);
75 if (u[0] == 0) {
76 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
77 goto gcd_1_2;
78 } else if (u[1] == 0) {
79 u[0] = u[0] >> lmmp_tailing_zeros_(u[0]);
80 goto gcd_1_2;
81 }
82 k = lmmp_tailing_zeros_(u[0]);
83 // k > 0
84 _u128lshr(u, u, k);
85 }
86 }
87 dst[0] = u[0];
88 dst[1] = u[1];
89 if (cnt > 0)
90 _u128lshl(dst, dst, cnt);
91 return 2;
92
93 gcd_1_2: // [u,1] , [v,2]
94 k = lmmp_tailing_zeros_(v[0]);
95 if (k > 0)
96 _u128lshr(v, v, k);
97 while (v[1] != 0) {
98 _u128sub64(v, v, u[0]);
99 if (v[1] == 0)
100 goto gcd_1_1;
101 if (v[0] == 0) {
102 v[0] = v[1] >> lmmp_tailing_zeros_(v[1]);
103 goto gcd_1_1;
104 }
105 k = lmmp_tailing_zeros_(v[0]);
106 // k > 0
107 _u128lshr(v, v, k);
108 }
109 goto gcd_1_1;
110
111 gcd_2_1: // [u,2] , [v,1]
112 k = lmmp_tailing_zeros_(u[0]);
113 if (k > 0)
114 _u128lshr(u, u, k);
115 while (u[1] != 0) {
116 _u128sub64(u, u, v[0]);
117 if (u[1] == 0)
118 goto gcd_1_1;
119 if (u[0] == 0) {
120 u[0] = u[1] >> lmmp_tailing_zeros_(u[1]);
121 goto gcd_1_1;
122 }
123 k = lmmp_tailing_zeros_(u[0]);
124 // k > 0
125 _u128lshr(u, u, k);
126 }
127 goto gcd_1_1;
128
129 gcd_1_1: // [u,1] , [v,1]
130 while (u[0] != v[0]) {
131 if (u[0] > v[0]) {
132 u[0] -= v[0];
133 u[0] >>= lmmp_tailing_zeros_(u[0]);
134 } else {
135 v[0] -= u[0];
136 v[0] >>= lmmp_tailing_zeros_(v[0]);
137 }
138 }
139 dst[0] = u[0];
140 dst[1] = 0;
141 if (cnt > 0)
142 _u128lshl(dst, dst, cnt);
143 return dst[1] == 0 ? 1 : 2;
144}
#define k
uint64_t mp_limb_t
Definition lmmp.h:211
#define lmmp_param_assert(x)
Definition lmmp.h:398
int lmmp_tailing_zeros_(mp_limb_t x)
计算一个单精度数(limb)中末尾零的个数
Definition tiny.c:54
#define _u128lshl(x, y, n)
Definition longlong.h:244
#define _u128sub(r, x, y)
Definition longlong.h:282
#define _u128cmp(x, y)
Definition longlong.h:280
#define _u128lshr(x, y, n)
Definition longlong.h:250
#define _u128sub64(r, x, _i64)
Definition longlong.h:272
mp_limb_t lmmp_gcd_11_(mp_limb_t u, mp_limb_t v)
计算 [numa,na] 在B^n 下的逆元
Definition gcd_1.c:10

引用了 _u128cmp, _u128lshl, _u128lshr, _u128sub, _u128sub64, k, lmmp_gcd_11_(), lmmp_param_assert , 以及 lmmp_tailing_zeros_().

被这些函数引用 lmmp_gcd_2_().

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

◆ lmmp_gcd_2_()

mp_size_t lmmp_gcd_2_ ( mp_ptr  dst,
mp_srcptr  up,
mp_size_t  un,
mp_srcptr  vp 
)

计算两个无符号整数的最大公约数

参数
up第一个无符号整数指针
un第一个无符号整数的 limb 长度
vp第二个无符号整数指针,长度为 2
dst结果指针(长度至少为 2,两个 limb 都会进行写入,即使最高位可能为0)
警告
up!=NULL, un>2, vp!=NULL, vp[1]!=0, dst!=NULL, eqsep(dst,[up|vp])
返回
dst 的实际 limb 长度

在文件 gcd_2.c146 行定义.

146 {
147 lmmp_param_assert(dst != NULL);
148 lmmp_param_assert(up != NULL);
149 lmmp_param_assert(vp != NULL);
150 lmmp_param_assert(un > 2);
151 lmmp_param_assert(vp[1] != 0);
152 mp_limb_t u[2] = {vp[0], vp[1]};
153 lmmp_mod_2_(up, un, u);
154 if (u[1] == 0 && u[0] == 0) {
155 dst[0] = vp[0];
156 dst[1] = vp[1];
157 return 2;
158 } else {
159 return lmmp_gcd_22_(dst, vp, u);
160 }
161}
mp_size_t lmmp_gcd_22_(mp_ptr dst, mp_srcptr up, mp_srcptr vp)
计算两个无符号整数的最大公约数
Definition gcd_2.c:11
void lmmp_mod_2_(mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数取余 (除数为2个limb)
Definition div.c:144

引用了 lmmp_gcd_22_(), lmmp_mod_2_() , 以及 lmmp_param_assert.

+ 函数调用图: