zgcd.c - libzahl - big integer library | |
git clone git://git.suckless.org/libzahl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
zgcd.c (870B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "internals.h" | |
3 | |
4 #define u libzahl_tmp_gcd_u | |
5 #define v libzahl_tmp_gcd_v | |
6 | |
7 | |
8 void | |
9 zgcd(z_t a, z_t b, z_t c) | |
10 { | |
11 /* | |
12 * Binary GCD algorithm. | |
13 */ | |
14 | |
15 size_t shifts; | |
16 zahl_char_t *u_orig, *v_orig; | |
17 size_t u_lsb, v_lsb; | |
18 int neg, cmpmag; | |
19 | |
20 if (unlikely(zzero(b))) { | |
21 SET(a, c); | |
22 return; | |
23 } | |
24 if (unlikely(zzero(c))) { | |
25 SET(a, b); | |
26 return; | |
27 } | |
28 | |
29 neg = znegative2(b, c); | |
30 | |
31 u_lsb = zlsb(b); | |
32 v_lsb = zlsb(c); | |
33 shifts = MIN(u_lsb, v_lsb); | |
34 zrsh(u, b, u_lsb); | |
35 zrsh(v, c, v_lsb); | |
36 | |
37 u_orig = u->chars; | |
38 v_orig = v->chars; | |
39 | |
40 for (;;) { | |
41 if (likely((cmpmag = zcmpmag(u, v)) >= 0)) { | |
42 if (unlikely(cmpmag == 0)) | |
43 break; | |
44 zswap_tainted_unsigned(u, v); | |
45 } | |
46 zsub_positive_assign(v, u); | |
47 zrsh_taint(v, zlsb(v)); | |
48 } | |
49 | |
50 zlsh(a, u, shifts); | |
51 SET_SIGNUM(a, neg ? -1 : 1); | |
52 | |
53 u->chars = u_orig; | |
54 v->chars = v_orig; | |
55 } |