summaryrefslogtreecommitdiff
path: root/mpf
diff options
context:
space:
mode:
authorTorbjorn Granlund <torbjorng@google.com>2015-10-28 21:33:53 +0100
committerTorbjorn Granlund <torbjorng@google.com>2015-10-28 21:33:53 +0100
commita47f5429adb4a6240e9dc221f0343b30749bd7c0 (patch)
tree930f94039149509498ae82dd94f47b9691e19bb7 /mpf
parent5d6d6235fcb46be3c9d721f7502ec4fda5060411 (diff)
downloadgmp-a47f5429adb4a6240e9dc221f0343b30749bd7c0.tar.gz
Rewrite for accuracy and performance.
Diffstat (limited to 'mpf')
-rw-r--r--mpf/pow_ui.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/mpf/pow_ui.c b/mpf/pow_ui.c
index 89735f9ab..e5e5ff398 100644
--- a/mpf/pow_ui.c
+++ b/mpf/pow_ui.c
@@ -30,25 +30,44 @@ see https://www.gnu.org/licenses/. */
#include "gmp.h"
#include "gmp-impl.h"
+#include "longlong.h"
void
mpf_pow_ui (mpf_ptr r, mpf_srcptr b, unsigned long int e)
{
- mpf_t b2;
+ mpf_t t;
+ int cnt;
- mpf_init2 (b2, mpf_get_prec (r) + 1);
- mpf_set (b2, b);
+ if (e == 0)
+ {
+ mpf_set_ui (r, 1);
+ return;
+ }
+
+ count_leading_zeros (cnt, (mp_limb_t) e);
+ cnt = GMP_LIMB_BITS - 1 - cnt;
- if ((e & 1) != 0)
- mpf_set (r, b);
+ /* Use a temp for all intermediate result. We might want to add an exponent
+ derived # of bits here too, e.g. ((cnt >> GMP_LIMB_BITS/2) != 0). */
+ mpf_init2 (t, mpf_get_prec (r) + GMP_LIMB_BITS);
+
+ mpf_set (t, b); /* consume most significant bit */
+ while (--cnt > 0)
+ {
+ mpf_mul (t, t, t);
+ if ((e >> cnt) & 1)
+ mpf_mul (t, t, b);
+ }
+
+ if (e & 1)
+ {
+ mpf_mul (t, t, t);
+ mpf_mul (r, t, b);
+ }
else
- mpf_set_ui (r, 1);
- while (e >>= 1)
{
- mpf_mul (b2, b2, b2);
- if ((e & 1) != 0)
- mpf_mul (r, r, b2);
+ mpf_mul (r, t, t);
}
- mpf_clear (b2);
+ mpf_clear (t);
}