]> git.eshelyaron.com Git - emacs.git/commitdiff
* floatfns.c (Fexpt): Likewise.
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 3 May 2011 08:52:13 +0000 (01:52 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 3 May 2011 08:52:13 +0000 (01:52 -0700)
src/ChangeLog
src/floatfns.c

index 435f90abad970204ba79191eef01e00e1dc78498..26b3af3225c6ab4046fa0a286cbedffda33f48a5 100644 (file)
@@ -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.
 
index 1232fc0afa1df4be7bb1e2efb294ee8b75bba492..5c28677286415dbab5f74d15d5ca704db8994b57 100644 (file)
@@ -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);