zpow.c - libzahl - big integer library | |
git clone git://git.suckless.org/libzahl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
zpow.c (1157B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "internals.h" | |
3 | |
4 #define tb libzahl_tmp_pow_b | |
5 #define tc libzahl_tmp_pow_c | |
6 | |
7 | |
8 void | |
9 zpow(z_t a, z_t b, z_t c) | |
10 { | |
11 /* | |
12 * Exponentiation by squaring. | |
13 * | |
14 * 7↑19 = 7↑10011₂ = 7↑2⁰ ⋅ 7↑2¹ ⋅ 7↑2⁴ whe… | |
15 */ | |
16 | |
17 /* TODO use zpowu when possible */ | |
18 | |
19 size_t i, j, n, bits; | |
20 zahl_char_t x; | |
21 int neg; | |
22 | |
23 if (unlikely(zsignum(c) <= 0)) { | |
24 if (zzero(c)) { | |
25 if (check(zzero(b))) | |
26 libzahl_failure(-ZERROR_0_POW_0); | |
27 zsetu(a, 1); | |
28 } else if (check(zzero(b))) { | |
29 libzahl_failure(-ZERROR_DIV_0); | |
30 } else { | |
31 SET_SIGNUM(a, 0); | |
32 } | |
33 return; | |
34 } else if (unlikely(zzero(b))) { | |
35 SET_SIGNUM(a, 0); | |
36 return; | |
37 } | |
38 | |
39 bits = zbits(c); | |
40 n = FLOOR_BITS_TO_CHARS(bits); | |
41 | |
42 neg = znegative(b) && zodd(c); | |
43 zabs(tb, b); | |
44 zset(tc, c); | |
45 zsetu(a, 1); | |
46 | |
47 for (i = 0; i < n; i++) { /* Remember, n is floored. */ | |
48 x = tc->chars[i]; | |
49 for (j = BITS_PER_CHAR; j--; x >>= 1) { | |
50 if (x & 1) | |
51 zmul_ll(a, a, tb); | |
52 zsqr_ll(tb, tb); | |
53 } | |
54 } | |
55 x = tc->chars[i]; | |
56 for (; x; x >>= 1) { | |
57 if (x & 1) | |
58 zmul_ll(a, a, tb); | |
59 zsqr_ll(tb, tb); | |
60 } | |
61 | |
62 if (neg) | |
63 zneg(a, a); | |
64 } |