zdivmod.c - libzahl - big integer library | |
git clone git://git.suckless.org/libzahl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
zdivmod.c (1979B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "internals.h" | |
3 | |
4 #define ta libzahl_tmp_divmod_a | |
5 #define tb libzahl_tmp_divmod_b | |
6 #define td libzahl_tmp_divmod_d | |
7 #define tds_proper libzahl_tmp_divmod_ds | |
8 | |
9 | |
10 static inline void | |
11 zdivmod_impl(z_t a, z_t b, z_t c, z_t d) | |
12 { | |
13 size_t c_bits, d_bits, bit, i; | |
14 static z_t tds[BITS_PER_CHAR]; | |
15 | |
16 c_bits = zbits(c); | |
17 d_bits = zbits(d); | |
18 | |
19 bit = c_bits - d_bits; | |
20 zlsh(td, d, bit); | |
21 SET_SIGNUM(td, 1); | |
22 if (zcmpmag(td, c) > 0) { | |
23 zrsh(td, td, 1); | |
24 bit -= 1; | |
25 } | |
26 | |
27 SET_SIGNUM(ta, 0); | |
28 zabs(tb, c); | |
29 | |
30 if (unlikely(bit <= BITS_PER_CHAR)) { | |
31 for (;;) { | |
32 if (zcmpmag(td, tb) <= 0) { | |
33 zsub_unsigned(tb, tb, td); | |
34 zbset(ta, ta, bit, 1); | |
35 } | |
36 if (!bit-- || zzero(tb)) | |
37 goto done; | |
38 zrsh(td, td, 1); | |
39 } | |
40 } else { | |
41 for (i = 0; i < BITS_PER_CHAR; i++) { | |
42 zrsh(tds_proper[i], td, i); | |
43 tds[i]->used = tds_proper[i]->used; | |
44 tds[i]->sign = tds_proper[i]->sign; | |
45 tds[i]->chars = tds_proper[i]->chars; | |
46 } | |
47 for (;;) { | |
48 for (i = 0; i < BITS_PER_CHAR; i++) { | |
49 if (zcmpmag(tds[i], tb) <= 0) { | |
50 zsub_unsigned(tb, tb, tds[i]); | |
51 zbset(ta, ta, bit, 1); | |
52 } | |
53 if (!bit-- || zzero(tb)) | |
54 goto done; | |
55 } | |
56 for (i = MIN(bit, BITS_PER_CHAR - 1) + 1; i--;) | |
57 zrsh_taint(tds[i], BITS_PER_CHAR); | |
58 } | |
59 } | |
60 done: | |
61 | |
62 zswap(a, ta); | |
63 zswap(b, tb); | |
64 } | |
65 | |
66 | |
67 void | |
68 zdivmod(z_t a, z_t b, z_t c, z_t d) | |
69 { | |
70 int c_sign, sign, cmpmag; | |
71 | |
72 c_sign = zsignum(c); | |
73 sign = c_sign * zsignum(d); | |
74 | |
75 if (unlikely(!sign)) { | |
76 if (check(!zzero(c))) { | |
77 libzahl_failure(-ZERROR_DIV_0); | |
78 } else if (check(zzero(d))) { | |
79 libzahl_failure(-ZERROR_0_DIV_0); | |
80 } else { | |
81 SET_SIGNUM(a, 0); | |
82 SET_SIGNUM(b, 0); | |
83 } | |
84 return; | |
85 } else if (cmpmag = zcmpmag(c, d), unlikely(cmpmag <= 0)) { | |
86 if (unlikely(cmpmag == 0)) { | |
87 zseti(a, sign); | |
88 SET_SIGNUM(b, 0); | |
89 } else { | |
90 SET(b, c); | |
91 SET_SIGNUM(a, 0); | |
92 } | |
93 return; | |
94 } | |
95 | |
96 zdivmod_impl(a, b, c, d); | |
97 SET_SIGNUM(a, sign); | |
98 if (zsignum(b) > 0) | |
99 SET_SIGNUM(b, c_sign); | |
100 } |