From 4ed0cebda869315a9e729daa55c50a16e2a5cde1 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 3 May 2011 01:52:13 -0700 Subject: [PATCH] * floatfns.c (Fexpt): Likewise. --- src/ChangeLog | 1 + src/floatfns.c | 46 +++++++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 435f90abad9..26b3af3225c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -7,6 +7,7 @@ (arith_driver, Fadd1, Fsub1): Use floating point if the result is out of Emacs fixnum range. * bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate. + * floatfns.c (Fexpt): Likewise. * callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering. diff --git a/src/floatfns.c b/src/floatfns.c index 1232fc0afa1..5c286772864 100644 --- a/src/floatfns.c +++ b/src/floatfns.c @@ -491,27 +491,39 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, y = XINT (arg2); acc = 1; - if (y < 0) - { - if (x == 1) - acc = 1; - else if (x == -1) - acc = (y & 1) ? -1 : 1; - else - acc = 0; - } - else + if ((x == 0 && y != 0) || x == 1 || (x == -1 && (y & 1))) + return arg1; + if (x == -1) + y = 0; + + while (1) { - while (y > 0) + if (y & 1) { - if (y & 1) - acc *= x; - x *= x; - y = (unsigned)y >> 1; + if (x < 0 + ? (acc < 0 + ? acc < MOST_POSITIVE_FIXNUM / x + : MOST_NEGATIVE_FIXNUM / x < acc) + : (acc < 0 + ? acc < MOST_NEGATIVE_FIXNUM / x + : MOST_POSITIVE_FIXNUM / x < acc)) + break; + acc *= x; } + + y >>= 1; + if (y == 0) + { + XSETINT (val, acc); + return val; + } + + if (x < 0 + ? x < MOST_POSITIVE_FIXNUM / x + : MOST_POSITIVE_FIXNUM / x < x) + break; + x *= x; } - XSETINT (val, acc); - return val; } f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1); f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2); -- 2.11.4.GIT