- if (XTYPE (arg) == Lisp_Float)
- IN_FLOAT (XSET (arg, Lisp_Int, floor (XFLOAT (arg)->data)), "floor", arg);
+ if (! NILP (divisor))
+ {
+ int i1, i2;
+
+ CHECK_NUMBER_OR_FLOAT (divisor, 1);
+
+#ifdef LISP_FLOAT_TYPE
+ if (FLOATP (arg) || FLOATP (divisor))
+ {
+ double f1, f2;
+
+ f1 = FLOATP (arg) ? XFLOAT (arg)->data : XINT (arg);
+ f2 = (FLOATP (divisor) ? XFLOAT (divisor)->data : XINT (divisor));
+ if (f2 == 0)
+ Fsignal (Qarith_error, Qnil);
+
+ IN_FLOAT2 (f1 = floor (f1 / f2), "floor", arg, divisor);
+ FLOAT_TO_INT2 (f1, arg, "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));
+
+ XSETINT (arg, i1);
+ return arg;
+ }
+
+#ifdef LISP_FLOAT_TYPE
+ if (FLOATP (arg))
+ {
+ double d;
+ IN_FLOAT (d = floor (XFLOAT (arg)->data), "floor", arg);
+ FLOAT_TO_INT (d, arg, "floor", arg);
+ }
+#endif