* gud.el (gud-def): Doc fix.
[bpt/emacs.git] / src / floatfns.c
index 1cf132d..ca5b937 100644 (file)
@@ -1,11 +1,11 @@
 /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
-   Copyright (C) 1988 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -22,11 +22,28 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "config.h"
 #include "lisp.h"
+#include "syssignal.h"
 
 Lisp_Object Qarith_error;
 
 #ifdef LISP_FLOAT_TYPE
+
 #include <math.h>
+#include <errno.h>
+
+extern int errno;
+
+/* Avoid traps on VMS from sinh and cosh.
+   All the other functions set errno instead.  */
+
+#ifdef VMS
+#undef cosh
+#undef sinh
+#define cosh(x) ((exp(x)+exp(-x))*0.5)
+#define sinh(x) ((exp(x)-exp(-x))*0.5)
+#endif /* VMS */
+
+static SIGTYPE float_error ();
 
 /* Nonzero while executing in floating point.
    This tells float_error what to do.  */
@@ -34,13 +51,19 @@ Lisp_Object Qarith_error;
 static int in_float;
 
 /* If an argument is out of range for a mathematical function,
-   that is detected with a signal.  Here is the actual argument
-   value to use in the error message.  */
+   here is the actual argument value to use in the error message.  */
 
 static Lisp_Object float_error_arg;
 
-#define IN_FLOAT(d, num) \
-(in_float = 1, float_error_arg = num, (d), in_float = 0)
+/* Evaluate the floating point expression D, recording NUM
+   as the original argument for error messages.
+   D is normally an assignment expression.
+   Handle errors which may result in signals or may set errno.  */
+
+#define IN_FLOAT(D, NUM) \
+(in_float = 1, errno = 0, float_error_arg = NUM, (D),                  \
+ (errno == ERANGE || errno == EDOM ? float_error () : (SIGTYPE) 0),    \
+ in_float = 0)
 
 /* Extract a Lisp number as a `double', or signal an error.  */
 
@@ -54,6 +77,8 @@ extract_float (num)
     return XFLOAT (num)->data;
   return (double) XINT (num);
 }
+\f
+/* Trig functions.  */
 
 DEFUN ("acos", Facos, Sacos, 1, 1, 0,
   "Return the inverse cosine of ARG.")
@@ -65,56 +90,58 @@ DEFUN ("acos", Facos, Sacos, 1, 1, 0,
   return make_float (d);
 }
 
-DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
-  "Return the inverse hyperbolic cosine of ARG.")
+DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
+  "Return the inverse sine of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = acosh (d), num);
+  IN_FLOAT (d = asin (d), num);
   return make_float (d);
 }
 
-DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
-  "Return the inverse sine of ARG.")
+DEFUN ("atan", Fatan, Satan, 1, 1, 0,
+  "Return the inverse tangent of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = asin (d), num);
+  IN_FLOAT (d = atan (d), num);
   return make_float (d);
 }
 
-DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
-  "Return the inverse hyperbolic sine of ARG.")
+DEFUN ("cos", Fcos, Scos, 1, 1, 0,
+  "Return the cosine of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = asinh (d), num);
+  IN_FLOAT (d = cos (d), num);
   return make_float (d);
 }
 
-DEFUN ("atan", Fatan, Satan, 1, 1, 0,
-  "Return the inverse tangent of ARG.")
+DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
+  "Return the sine of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = atan (d), num);
+  IN_FLOAT (d = sin (d), num);
   return make_float (d);
 }
 
-DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
-  "Return the inverse hyperbolic tangent of ARG.")
+DEFUN ("tan", Ftan, Stan, 1, 1, 0,
+  "Return the tangent of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = atanh (d), num);
+  IN_FLOAT (d = tan (d), num);
   return make_float (d);
 }
 \f
+#if 0 /* Leave these out unless we find there's a reason for them.  */
+
 DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
   "Return the bessel function j0 of ARG.")
   (num)
@@ -180,36 +207,10 @@ The first arg (the order) is truncated to an integer.")
   IN_FLOAT (f2 = yn (i1, f2), num1);
   return make_float (f2);
 }
-\f
-DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
-  "Return the cube root of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = cbrt (d), num);
-  return make_float (d);
-}
-
-DEFUN ("cos", Fcos, Scos, 1, 1, 0,
-  "Return the cosine of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = cos (d), num);
-  return make_float (d);
-}
 
-DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
-  "Return the hyperbolic cosine of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = cosh (d), num);
-  return make_float (d);
-}
+#endif
+\f
+#if 0 /* Leave these out unless we see they are worth having.  */
 
 DEFUN ("erf", Ferf, Serf, 1, 1, 0,
   "Return the mathematical error function of ARG.")
@@ -231,26 +232,6 @@ DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
   return make_float (d);
 }
 
-DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
-  "Return the exponential base e of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = exp (d), num);
-  return make_float (d);
-}
-
-DEFUN ("expm1", Fexpm1, Sexpm1, 1, 1, 0,
-  "Return the exp (x)-1 of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = expm1 (d), num);
-  return make_float (d);
-}
-\f
 DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
   "Return the log gamma of ARG.")
   (num)
@@ -261,38 +242,30 @@ DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
   return make_float (d);
 }
 
-DEFUN ("log", Flog, Slog, 1, 1, 0,
-  "Return the natural logarithm of ARG.")
-  (num)
-     register Lisp_Object num;
-{
-  double d = extract_float (num);
-  IN_FLOAT (d = log (d), num);
-  return make_float (d);
-}
-
-DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
-  "Return the logarithm base 10 of ARG.")
+DEFUN ("cbrt", Fcbrt, Scbrt, 1, 1, 0,
+  "Return the cube root of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = log10 (d), num);
+  IN_FLOAT (d = cbrt (d), num);
   return make_float (d);
 }
 
-DEFUN ("log1p", Flog1p, Slog1p, 1, 1, 0,
-  "Return the log (1+x) of ARG.")
+#endif
+\f
+DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
+  "Return the exponential base e of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = log1p (d), num);
+  IN_FLOAT (d = exp (d), num);
   return make_float (d);
 }
 
 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
-  "Return the exponential x ** y.")
+  "Return the exponential X ** Y.")
   (num1, num2)
      register Lisp_Object num1, num2;
 {
@@ -326,24 +299,33 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
   IN_FLOAT (f1 = pow (f1, f2), num1);
   return make_float (f1);
 }
-\f
-DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
-  "Return the sine of ARG.")
-  (num)
+
+DEFUN ("log", Flog, Slog, 1, 2, 0,
+  "Return the natural logarithm of NUM.
+If second optional argument BASE is given, return log NUM using that base.")
+  (num, base)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = sin (d), num);
+
+  if (NILP (base))
+    IN_FLOAT (d = log (d), num);
+  else
+    {
+      double b = extract_float (base);
+
+      IN_FLOAT (d = log (num) / log (b), num);
+    }
   return make_float (d);
 }
 
-DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
-  "Return the hyperbolic sine of ARG.")
+DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
+  "Return the logarithm base 10 of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = sinh (d), num);
+  IN_FLOAT (d = log10 (d), num);
   return make_float (d);
 }
 
@@ -356,14 +338,56 @@ DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
   IN_FLOAT (d = sqrt (d), num);
   return make_float (d);
 }
+\f
+#if 0 /* Not clearly worth adding.  */
 
-DEFUN ("tan", Ftan, Stan, 1, 1, 0,
-  "Return the tangent of ARG.")
+DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
+  "Return the inverse hyperbolic cosine of ARG.")
   (num)
      register Lisp_Object num;
 {
   double d = extract_float (num);
-  IN_FLOAT (d = tan (d), num);
+  IN_FLOAT (d = acosh (d), num);
+  return make_float (d);
+}
+
+DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
+  "Return the inverse hyperbolic sine of ARG.")
+  (num)
+     register Lisp_Object num;
+{
+  double d = extract_float (num);
+  IN_FLOAT (d = asinh (d), num);
+  return make_float (d);
+}
+
+DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
+  "Return the inverse hyperbolic tangent of ARG.")
+  (num)
+     register Lisp_Object num;
+{
+  double d = extract_float (num);
+  IN_FLOAT (d = atanh (d), num);
+  return make_float (d);
+}
+
+DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
+  "Return the hyperbolic cosine of ARG.")
+  (num)
+     register Lisp_Object num;
+{
+  double d = extract_float (num);
+  IN_FLOAT (d = cosh (d), num);
+  return make_float (d);
+}
+
+DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
+  "Return the hyperbolic sine of ARG.")
+  (num)
+     register Lisp_Object num;
+{
+  double d = extract_float (num);
+  IN_FLOAT (d = sinh (d), num);
   return make_float (d);
 }
 
@@ -376,6 +400,7 @@ DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
   IN_FLOAT (d = tanh (d), num);
   return make_float (d);
 }
+#endif
 \f
 DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
   "Return the absolute value of ARG.")
@@ -411,14 +436,17 @@ This is the same as the exponent of a float.")
      (num)
 Lisp_Object num;
 {
+#ifdef USG
+  /* System V apparently doesn't have a `logb' function.  */
+  return Flog (num, make_number (2));
+#else
   Lisp_Object val;
-  double f;
+  double f = extract_float (num);
 
-  CHECK_NUMBER_OR_FLOAT (num, 0);
-  f = (XTYPE (num) == Lisp_Float) ? XFLOAT (num)->data : XINT (num);
   IN_FLOAT (val = logb (f), num);
   XSET (val, Lisp_Int, val);
   return val;
+#endif
 }
 
 /* the rounding functions  */
@@ -457,7 +485,14 @@ DEFUN ("round", Fround, Sround, 1, 1, 0,
   CHECK_NUMBER_OR_FLOAT (num, 0);
 
   if (XTYPE (num) == Lisp_Float)
-    IN_FLOAT (XSET (num, Lisp_Int, rint (XFLOAT (num)->data)), num);
+    {
+#ifdef USG
+      /* Screw the prevailing rounding mode.  */
+      IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data + 0.5)), num);
+#else
+      IN_FLOAT (XSET (num, Lisp_Int, rint (XFLOAT (num)->data)), num);
+#endif
+    }
 
   return num;
 }
@@ -476,30 +511,29 @@ Rounds the value toward zero.")
   return num;
 }
 \f
-#ifdef BSD
-static
+static SIGTYPE
 float_error (signo)
      int signo;
 {
   if (! in_float)
     fatal_error_signal (signo);
 
+#ifdef BSD
 #ifdef BSD4_1
   sigrelse (SIGILL);
 #else /* not BSD4_1 */
-  sigsetmask (0);
+  sigsetmask (SIGEMPTYMASK);
 #endif /* not BSD4_1 */
+#else
+  /* Must reestablish handler each time it is called.  */
+  signal (SIGILL, float_error);
+#endif /* BSD */
 
   in_float = 0;
 
   Fsignal (Qarith_error, Fcons (float_error_arg, Qnil));
 }
 
-/* Another idea was to replace the library function `infnan'
-   where SIGILL is signaled.  */
-
-#endif /* BSD */
-
 init_floatfns ()
 {
   signal (SIGILL, float_error);
@@ -509,34 +543,34 @@ init_floatfns ()
 syms_of_floatfns ()
 {
   defsubr (&Sacos);
-  defsubr (&Sacosh);
   defsubr (&Sasin);
-  defsubr (&Sasinh);
   defsubr (&Satan);
+  defsubr (&Scos);
+  defsubr (&Ssin);
+  defsubr (&Stan);
+#if 0
+  defsubr (&Sacosh);
+  defsubr (&Sasinh);
   defsubr (&Satanh);
+  defsubr (&Scosh);
+  defsubr (&Ssinh);
+  defsubr (&Stanh);
   defsubr (&Sbessel_y0);
   defsubr (&Sbessel_y1);
   defsubr (&Sbessel_yn);
   defsubr (&Sbessel_j0);
   defsubr (&Sbessel_j1);
   defsubr (&Sbessel_jn);
-  defsubr (&Scube_root);
-  defsubr (&Scos);
-  defsubr (&Scosh);
   defsubr (&Serf);
   defsubr (&Serfc);
-  defsubr (&Sexp);
-  defsubr (&Sexpm1);
   defsubr (&Slog_gamma);
+  defsubr (&Scbrt);
+#endif
+  defsubr (&Sexp);
+  defsubr (&Sexpt);
   defsubr (&Slog);
   defsubr (&Slog10);
-  defsubr (&Slog1p);
-  defsubr (&Sexpt);
-  defsubr (&Ssin);
-  defsubr (&Ssinh);
   defsubr (&Ssqrt);
-  defsubr (&Stan);
-  defsubr (&Stanh);
 
   defsubr (&Sabs);
   defsubr (&Sfloat);