aboutsummaryrefslogtreecommitdiffstats
path: root/src/zpow.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-03-16 14:30:29 +0100
committerMattias Andrée <maandree@kth.se>2016-03-16 14:30:29 +0100
commit3e3b44d087ab616089402129b2bc4c4831c6b33a (patch)
tree2c0a6e9550dded9e336906514c6ad7343dc8257d /src/zpow.c
parentFix bug in libzahl_msb_nz_* and optimise and simplify libzahl_realloc (diff)
downloadlibzahl-3e3b44d087ab616089402129b2bc4c4831c6b33a.tar.gz
libzahl-3e3b44d087ab616089402129b2bc4c4831c6b33a.tar.bz2
libzahl-3e3b44d087ab616089402129b2bc4c4831c6b33a.tar.xz
Optimise zsqr, zmul, zstr, zdivmod, zpow, and zpowu
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/zpow.c')
-rw-r--r--src/zpow.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/zpow.c b/src/zpow.c
index 81f8098..84f4927 100644
--- a/src/zpow.c
+++ b/src/zpow.c
@@ -5,6 +5,9 @@
#define tc libzahl_tmp_pow_c
+extern void zmul_impl(z_t a, z_t b, z_t c);
+extern void zsqr_impl(z_t a, z_t b);
+
void
zpow(z_t a, z_t b, z_t c)
{
@@ -16,6 +19,7 @@ zpow(z_t a, z_t b, z_t c)
size_t i, j, n, bits;
zahl_char_t x;
+ int neg;
if (unlikely(zsignum(c) <= 0)) {
if (zzero(c)) {
@@ -36,7 +40,8 @@ zpow(z_t a, z_t b, z_t c)
bits = zbits(c);
n = FLOOR_BITS_TO_CHARS(bits);
- zset(tb, b);
+ neg = znegative(b) && zodd(c);
+ zabs(tb, b);
zset(tc, c);
zsetu(a, 1);
@@ -44,14 +49,17 @@ zpow(z_t a, z_t b, z_t c)
x = tc->chars[i];
for (j = BITS_PER_CHAR; j--; x >>= 1) {
if (x & 1)
- zmul(a, a, tb);
- zsqr(tb, tb);
+ zmul_impl(a, a, tb);
+ zsqr_impl(tb, tb);
}
}
x = tc->chars[i];
for (; x; x >>= 1) {
if (x & 1)
- zmul(a, a, tb);
- zsqr(tb, tb);
+ zmul_impl(a, a, tb);
+ zsqr_impl(tb, tb);
}
+
+ if (neg)
+ zneg(a, a);
}