changeset 4506:6131dad14f6f

(Ffloor): Optional second operand specifies divisor, as in Common Lisp. (syms_of_floatfns): Invoke syms_of_floatfns even if LISP_FLOAT_TYPE isn't defined, since `(floor A B)' is now needed for integers.
author Paul Eggert <eggert@twinsun.com>
date Tue, 10 Aug 1993 04:14:17 +0000
parents 348f6a32d9b5
children e61769cebbd4
files src/floatfns.c
diffstat 1 files changed, 61 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/floatfns.c	Tue Aug 10 01:32:23 1993 +0000
+++ b/src/floatfns.c	Tue Aug 10 04:14:17 1993 +0000
@@ -669,19 +669,66 @@
   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)
@@ -827,8 +874,16 @@
   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);
@@ -867,17 +922,8 @@
   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 */