Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / floatfns.c
index 999d0a8..da91b97 100644 (file)
@@ -45,7 +45,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <signal.h>
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "syssignal.h"
 
@@ -55,8 +55,10 @@ Lisp_Object Qarith_error;
 
 #include <math.h>
 
+#ifndef hpux
 /* These declarations are omitted on some systems, like Ultrix.  */
 extern double logb ();
+#endif
 
 #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
     /* If those are defined, then this is probably a `matherr' machine. */
@@ -152,6 +154,7 @@ static char *float_error_fn_name;
     }                                                  \
   } while (0)
 #else
+#define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
 #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
 #endif
 
@@ -399,11 +402,12 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
 
   CHECK_NUMBER_OR_FLOAT (arg1, 0);
   CHECK_NUMBER_OR_FLOAT (arg2, 0);
-  if ((XTYPE (arg1) == Lisp_Int) && /* common lisp spec */
-      (XTYPE (arg2) == Lisp_Int)) /* don't promote, if both are ints */
+  if (XTYPE (arg1) == Lisp_Int     /* common lisp spec */
+      && XTYPE (arg2) == Lisp_Int) /* don't promote, if both are ints */
     {                          /* this can be improved by pre-calculating */
-      int acc, x, y;           /* some binary powers of x then acumulating */
-      /* these, therby saving some time. -wsr */
+      int acc, x, y;           /* some binary powers of x then accumulating */
+      Lisp_Object val;
+
       x = XINT (arg1);
       y = XINT (arg2);
       acc = 1;
@@ -428,8 +432,8 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
              y = (unsigned)y >> 1;
            }
        }
-      XSET (x, Lisp_Int, acc);
-      return x;
+      XSET (val, Lisp_Int, acc);
+      return val;
     }
   f1 = (XTYPE (arg1) == Lisp_Float) ? XFLOAT (arg1)->data : XINT (arg1);
   f2 = (XTYPE (arg2) == Lisp_Float) ? XFLOAT (arg2)->data : XINT (arg2);
@@ -440,7 +444,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
   else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
     domain_error2 ("expt", arg1, arg2);
 #endif
-  IN_FLOAT (f1 = pow (f1, f2), "expt", arg1);
+  IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2);
   return make_float (f1);
 }
 
@@ -469,7 +473,7 @@ If second optional argument BASE is given, return log ARG using that base.")
       if (b == 10.0)
        IN_FLOAT2 (d = log10 (d), "log", arg, base);
       else
-       IN_FLOAT2 (d = log (arg) / log (b), "log", arg, base);
+       IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
     }
   return make_float (d);
 }
@@ -622,7 +626,7 @@ DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
 }
 
 DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
-  "Returns the integer not greater than the base 2 log of the magnitude of ARG.\n\
+  "Returns largest integer <= the base 2 log of the magnitude of ARG.\n\
 This is the same as the exponent of a float.")
      (arg)
      Lisp_Object arg;
@@ -631,7 +635,11 @@ This is the same as the exponent of a float.")
   int value;
   double f = extract_float (arg);
 
-#ifdef USG
+#ifdef HAVE_LOGB
+  IN_FLOAT (value = logb (f), "logb", arg);
+  XSET (val, Lisp_Int, value);
+#else
+#ifdef HAVE_FREXP
   {
     int exp;  
 
@@ -639,8 +647,9 @@ This is the same as the exponent of a float.")
     XSET (val, Lisp_Int, exp-1);
   }
 #else
-  IN_FLOAT (value = logb (f), "logb", arg);
-  XSET (val, Lisp_Int, value);
+  /* Would someone like to write code to emulate logb?  */
+  error ("`logb' not implemented on this operating system");
+#endif
 #endif
 
   return val;
@@ -656,24 +665,71 @@ DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
   CHECK_NUMBER_OR_FLOAT (arg, 0);
 
   if (XTYPE (arg) == Lisp_Float)
-    IN_FLOAT (XSET (arg, Lisp_Int, ceil (XFLOAT (arg)->data)), "celing", arg);
+    IN_FLOAT (XSET (arg, Lisp_Int, ceil (XFLOAT (arg)->data)), "ceiling", arg);
 
   return arg;
 }
 
-DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0,
-  "Return the largest integer no greater than ARG.  (Round towards -inf.)")
-  (arg)
-     register Lisp_Object arg;
+#endif /* LISP_FLOAT_TYPE */
+
+
+DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
+  "Return the largest integer no greater than ARG.  (Round towards -inf.)\n\
+With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR.")
+  (arg, divisor)
+     register Lisp_Object arg, divisor;
 {
   CHECK_NUMBER_OR_FLOAT (arg, 0);
 
+  if (! NILP (divisor))
+    {
+      int i1, i2;
+
+      CHECK_NUMBER_OR_FLOAT (divisor, 1);
+
+#ifdef LISP_FLOAT_TYPE
+      if (XTYPE (arg) == Lisp_Float || XTYPE (divisor) == Lisp_Float)
+       {
+         double f1, f2;
+
+         f1 = XTYPE (arg) == Lisp_Float ? XFLOAT (arg)->data : XINT (arg);
+         f2 = (XTYPE (divisor) == Lisp_Float
+               ? XFLOAT (divisor)->data : XINT (divisor));
+         if (f2 == 0)
+           Fsignal (Qarith_error, Qnil);
+
+         IN_FLOAT2 (XSET (arg, Lisp_Int, floor (f1 / f2)),
+                    "floor", arg, divisor);
+         return arg;
+       }
+#endif
+
+      i1 = XINT (arg);
+      i2 = XINT (divisor);
+
+      if (i2 == 0)
+       Fsignal (Qarith_error, Qnil);
+
+      /* With C's /, the result is implementation-defined if either operand
+        is negative, so use only nonnegative operands.  */
+      i1 = (i2 < 0
+           ? (i1 <= 0  ?  -i1 / -i2  :  -1 - ((i1 - 1) / -i2))
+           : (i1 < 0  ?  -1 - ((-1 - i1) / i2)  :  i1 / i2));
+
+      XSET (arg, Lisp_Int, i1);
+      return arg;
+    }
+
+#ifdef LISP_FLOAT_TYPE
   if (XTYPE (arg) == Lisp_Float)
     IN_FLOAT (XSET (arg, Lisp_Int, floor (XFLOAT (arg)->data)), "floor", arg);
+#endif
 
   return arg;
 }
 
+#ifdef LISP_FLOAT_TYPE
+
 DEFUN ("round", Fround, Sround, 1, 1, 0,
   "Return the nearest integer to ARG.")
   (arg)
@@ -819,8 +875,16 @@ init_floatfns ()
   in_float = 0;
 }
 
+#else /* not LISP_FLOAT_TYPE */
+
+init_floatfns ()
+{}
+
+#endif /* not LISP_FLOAT_TYPE */
+
 syms_of_floatfns ()
 {
+#ifdef LISP_FLOAT_TYPE
   defsubr (&Sacos);
   defsubr (&Sasin);
   defsubr (&Satan);
@@ -859,17 +923,8 @@ syms_of_floatfns ()
   defsubr (&Sfloat);
   defsubr (&Slogb);
   defsubr (&Sceiling);
-  defsubr (&Sfloor);
   defsubr (&Sround);
   defsubr (&Struncate);
+#endif /* LISP_FLOAT_TYPE */
+  defsubr (&Sfloor);
 }
-
-#else /* not LISP_FLOAT_TYPE */
-
-init_floatfns ()
-{}
-
-syms_of_floatfns ()
-{}
-
-#endif /* not LISP_FLOAT_TYPE */