home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / floatfns.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-11  |  15.0 KB  |  664 lines

  1. /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
  2.    Copyright (C) 1988-1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* ANSI C requires only these float functions:
  21.    acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
  22.    frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
  23.  
  24.    Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
  25.    Define HAVE_CBRT if you have cbrt().
  26.    Define HAVE_RINT if you have rint().
  27.    If you don't define these, then the appropriate routines will be simulated.
  28.  
  29.    Define HAVE_MATHERR if on a system supporting the SysV matherr() callback.
  30.    (This should happen automatically.)
  31.  
  32.    Define FLOAT_CHECK_ERRNO if the float library routines set errno.
  33.    This has no effect if HAVE_MATHERR is defined.
  34.  
  35.    Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
  36.    (What systems actually do this?  Let me know. -jwz)
  37.  
  38.    Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
  39.    either setting errno, or signalling SIGFPE/SIGILL.  Otherwise, domain and
  40.    range checking will happen before calling the float routines.  This has
  41.    no effect if HAVE_MATHERR is defined (since matherr will be called when
  42.    a domain error occurs.)
  43.  */
  44.  
  45. #include <signal.h>
  46.  
  47. #include "config.h"
  48. #include "lisp.h"
  49.  
  50. #ifdef LISP_FLOAT_TYPE
  51.  
  52. #include <math.h>
  53.  
  54. #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
  55.     /* If those are defined, then this is probably a `matherr' machine. */
  56. # ifndef HAVE_MATHERR
  57. #  define HAVE_MATHERR
  58. # endif
  59. #endif
  60.  
  61. #ifdef HAVE_MATHERR
  62. # ifdef FLOAT_CHECK_ERRNO
  63. #  undef FLOAT_CHECK_ERRNO
  64. # endif
  65. # ifdef FLOAT_CHECK_DOMAIN
  66. #  undef FLOAT_CHECK_DOMAIN
  67. # endif
  68. #endif
  69.  
  70. #ifdef FLOAT_CHECK_ERRNO
  71. # include <errno.h>
  72. #endif
  73.  
  74. extern Lisp_Object Qarith_error, Qrange_error, Qdomain_error;
  75. extern Lisp_Object Qsingularity_error, Qoverflow_error, Qunderflow_error;
  76.  
  77. /* Nonzero while executing in floating point.
  78.    This tells float_error what to do.  */
  79. static int in_float;
  80.  
  81. #ifdef FLOAT_CHECK_ERRNO
  82. #define IN_FLOAT(d)                    \
  83.   do {                            \
  84.     in_float = 1; errno = 0; (d); in_float = 0;        \
  85.     switch (errno) {                    \
  86.     case 0: break;                    \
  87.     case EDOM:     Fsignal (Qdomain_error, Qnil); break;    \
  88.     case ERANGE: Fsignal (Qrange_error, Qnil); break;     \
  89.     default:     Fsignal (Qarith_error, Qnil); break;     \
  90.     }                            \
  91.   } while (0)
  92. #else
  93. #define IN_FLOAT(d) (in_float = 1, (d), in_float = 0)
  94. #endif
  95.  
  96. #ifndef HAVE_RINT
  97. #define rint(x) (floor((x)+0.5))
  98. #endif
  99.  
  100. #define range_error(op,arg) \
  101.     Fsignal (Qrange_error, list2 (build_string ((op)), (arg)))
  102. #define domain_error(op,arg) \
  103.     Fsignal (Qdomain_error, list2 (build_string ((op)), (arg)))
  104. #define domain_error2(op,a1,a2) \
  105.     Fsignal (Qdomain_error, list3 (build_string ((op)), (a1), (a2)))
  106.  
  107. /* Extract a Lisp number as a `double', or signal an error.  */
  108.  
  109. double
  110. extract_float (arg)
  111.      Lisp_Object arg;
  112. {
  113.   CHECK_NUMBER (arg, 0);
  114.  
  115.   if (FLOATP (arg))
  116.     return XFLOAT (arg)->data;
  117.   return (double) XINT (arg);
  118. }
  119.  
  120. DEFUN ("acos", Facos, Sacos, 1, 1, 0,
  121.   "Return the inverse cosine of ARG.")
  122.   (arg)
  123.      register Lisp_Object arg;
  124. {
  125.   double d = extract_float (arg);
  126. #ifdef FLOAT_CHECK_DOMAIN
  127.   if (d > 1.0 || d < -1.0)
  128.     domain_error ("acos", arg);
  129. #endif
  130.   IN_FLOAT (d = acos (d));
  131.   return make_float (d);
  132. }
  133.  
  134. DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
  135.   "Return the inverse hyperbolic cosine of ARG.")
  136.   (arg)
  137.      register Lisp_Object arg;
  138. {
  139.   double d = extract_float (arg);
  140. #ifdef FLOAT_CHECK_DOMAIN
  141.   if (d < 1.0)
  142.     domain_error ("acosh", arg);
  143. #endif
  144. #ifdef HAVE_INVERSE_HYPERBOLIC
  145.   IN_FLOAT (d = acosh (d));
  146. #else
  147.   IN_FLOAT (d = log (d + sqrt (d*d - 1.0)));
  148. #endif
  149.   return make_float (d);
  150. }
  151.  
  152. DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
  153.   "Return the inverse sine of ARG.")
  154.   (arg)
  155.      register Lisp_Object arg;
  156. {
  157.   double d = extract_float (arg);
  158. #ifdef FLOAT_CHECK_DOMAIN
  159.   if (d > 1.0 || d < -1.0)
  160.     domain_error ("asin", arg);
  161. #endif
  162.   IN_FLOAT (d = asin (d));
  163.   return make_float (d);
  164. }
  165.  
  166. DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
  167.   "Return the inverse hyperbolic sine of ARG.")
  168.   (arg)
  169.      register Lisp_Object arg;
  170. {
  171.   double d = extract_float (arg);
  172. #ifdef HAVE_INVERSE_HYPERBOLIC
  173.   IN_FLOAT (d = asinh (d));
  174. #else
  175.   IN_FLOAT (d = log (d + sqrt (d*d + 1.0)));
  176. #endif
  177.   return make_float (d);
  178. }
  179.  
  180. DEFUN ("atan", Fatan, Satan, 1, 2, 0,
  181.   "Return the inverse tangent of ARG.")
  182.   (arg1, arg2)
  183.      register Lisp_Object arg1, arg2;
  184. {
  185.   double d = extract_float (arg1);
  186.   if (NILP (arg2))
  187.     IN_FLOAT (d = atan (d));
  188.   else
  189.     {
  190.       double d2 = extract_float (arg2);
  191. #ifdef FLOAT_CHECK_DOMAIN
  192.       if (d == 0.0 && d2 == 0.0)
  193.     domain_error2 ("atan", arg1, arg2);
  194. #endif
  195.       IN_FLOAT (d = atan2 (d, d2));
  196.     }
  197.   return make_float (d);
  198. }
  199.  
  200. DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
  201.   "Return the inverse hyperbolic tangent of ARG.")
  202.   (arg)
  203.      register Lisp_Object arg;
  204. {
  205.   double d = extract_float (arg);
  206. #ifdef FLOAT_CHECK_DOMAIN
  207.   if (d >= 1.0 || d <= -1.0)
  208.     domain_error ("atanh", arg);
  209. #endif
  210. #ifdef HAVE_INVERSE_HYPERBOLIC
  211.   IN_FLOAT (d = atanh (d));
  212. #else
  213.   IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)));
  214. #endif
  215.   return make_float (d);
  216. }
  217.  
  218. DEFUN ("cos", Fcos, Scos, 1, 1, 0,
  219.   "Return the cosine of ARG.")
  220.   (arg)
  221.      register Lisp_Object arg;
  222. {
  223.   double d = extract_float (arg);
  224.   IN_FLOAT (d = cos (d));
  225.   return make_float (d);
  226. }
  227.  
  228. DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
  229.   "Return the hyperbolic cosine of ARG.")
  230.   (arg)
  231.      register Lisp_Object arg;
  232. {
  233.   double d = extract_float (arg);
  234. #ifdef FLOAT_CHECK_DOMAIN
  235.   if (d > 710.0 || d < -710.0)
  236.     range_error ("cosh", arg);
  237. #endif
  238.   IN_FLOAT (d = cosh (d));
  239.   return make_float (d);
  240. }
  241.  
  242. DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
  243.   "Return the cube root of ARG.")
  244.   (arg)
  245.      register Lisp_Object arg;
  246. {
  247.   double d = extract_float (arg);
  248. #ifdef HAVE_CBRT
  249.   IN_FLOAT (d = cbrt (d));
  250. #else
  251.   if (d >= 0.0)
  252.     IN_FLOAT (d = pow (d, 1.0/3.0));
  253.   else
  254.     IN_FLOAT (d = -pow (-d, 1.0/3.0));
  255. #endif
  256.   return make_float (d);
  257. }
  258.  
  259. DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
  260.   "Return the exponential base e of ARG.")
  261.   (arg)
  262.      register Lisp_Object arg;
  263. {
  264.   double d = extract_float (arg);
  265. #ifdef FLOAT_CHECK_DOMAIN
  266.   if (d > 709.7827)   /* Assume IEEE doubles here */
  267.     range_error ("exp", arg);
  268.   else if (d < -709.0)
  269.     return make_float (0.0);
  270.   else
  271. #endif
  272.     IN_FLOAT (d = exp (d));
  273.   return make_float (d);
  274. }
  275.  
  276. DEFUN ("log", Flog, Slog, 1, 2, 0,
  277.   "Return the natural logarithm of ARG.\n\
  278. With two arguments, return the logarithm of ARG to the base ARG2.")
  279.   (arg1, arg2)
  280.      register Lisp_Object arg1, arg2;
  281. {
  282.   double d = extract_float (arg1);
  283. #ifdef FLOAT_CHECK_DOMAIN
  284.   if (d <= 0.0)
  285.     domain_error2 ("log", arg1, arg2);
  286. #endif
  287.   if (NILP (arg2))
  288.     IN_FLOAT (d = log (d));
  289.   else
  290.     {
  291.       double d2 = extract_float (arg2);
  292. #ifdef FLOAT_CHECK_DOMAIN
  293.       if (d2 <= 0.0 || d2 == 1.0)
  294.     domain_error2 ("log", arg1, arg2);
  295. #endif
  296.       if (d2 == 10.0)
  297.     IN_FLOAT (d = log10 (d));
  298.       else
  299.     IN_FLOAT (d = log (d) / log (d2));
  300.     }
  301.   return make_float (d);
  302. }
  303.  
  304. DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
  305.   "Return the logarithm base 10 of ARG.")
  306.   (arg)
  307.      register Lisp_Object arg;
  308. {
  309.   double d = extract_float (arg);
  310. #ifdef FLOAT_CHECK_DOMAIN
  311.   if (d <= 0.0)
  312.     domain_error ("log10", arg);
  313. #endif
  314.   IN_FLOAT (d = log10 (d));
  315.   return make_float (d);
  316. }
  317.  
  318. DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
  319.   "Return the exponential x ** y.")
  320.   (arg1, arg2)
  321.      register Lisp_Object arg1, arg2;
  322. {
  323.   double f1, f2;
  324.  
  325.   CHECK_NUMBER (arg1, 0);
  326.   CHECK_NUMBER (arg2, 0);
  327.   if ((FIXNUMP (arg1)) && /* common lisp spec */
  328.       (FIXNUMP (arg2))) /* don't promote, if both are ints */
  329.     {
  330.       int acc, x, y;
  331.       x = XINT (arg1);
  332.       y = XINT (arg2);
  333.       
  334.       if (y < 0)
  335.     {
  336.       if (x == 1)
  337.         acc = 1;
  338.       else if (x == -1)
  339.         acc = (y & 1) ? -1 : 1;
  340.       else
  341.         acc = 0;
  342.     }
  343.       else
  344.     {
  345.       acc = 1;
  346.       while (y > 0)
  347.         {
  348.           if (y & 1)
  349.         acc *= x;
  350.           x *= x;
  351.           y = (unsigned)y >> 1;
  352.         }
  353.     }
  354.       return XSET (x, Lisp_Int, acc);
  355.     }
  356.   f1 = (FLOATP (arg1)) ? XFLOAT (arg1)->data : XINT (arg1);
  357.   f2 = (FLOATP (arg2)) ? XFLOAT (arg2)->data : XINT (arg2);
  358.   /* Really should check for overflow, too */
  359.   if (f1 == 0.0 && f2 == 0.0)
  360.     f1 = 1.0;
  361. #ifdef FLOAT_CHECK_DOMAIN
  362.   else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
  363.     domain_error2 ("pow", arg1, arg2);
  364. #endif
  365.   IN_FLOAT (f1 = pow (f1, f2));
  366.   return make_float (f1);
  367. }
  368.  
  369. DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
  370.   "Return the sine of ARG.")
  371.   (arg)
  372.      register Lisp_Object arg;
  373. {
  374.   double d = extract_float (arg);
  375.   IN_FLOAT (d = sin (d));
  376.   return make_float (d);
  377. }
  378.  
  379. DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
  380.   "Return the hyperbolic sine of ARG.")
  381.   (arg)
  382.      register Lisp_Object arg;
  383. {
  384.   double d = extract_float (arg);
  385. #ifdef FLOAT_CHECK_DOMAIN
  386.   if (d > 710.0 || d < -710.0)
  387.     range_error ("sinh", arg);
  388. #endif
  389.   IN_FLOAT (d = sinh (d));
  390.   return make_float (d);
  391. }
  392.  
  393. DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
  394.   "Return the square root of ARG.")
  395.   (arg)
  396.      register Lisp_Object arg;
  397. {
  398.   double d = extract_float (arg);
  399. #ifdef FLOAT_CHECK_DOMAIN
  400.   if (d < 0.0)
  401.     domain_error ("sqrt", arg);
  402. #endif
  403.   IN_FLOAT (d = sqrt (d));
  404.   return make_float (d);
  405. }
  406.  
  407. DEFUN ("tan", Ftan, Stan, 1, 1, 0,
  408.   "Return the tangent of ARG.")
  409.   (arg)
  410.      register Lisp_Object arg;
  411. {
  412.   double d = extract_float (arg);
  413.   double c = cos (d);
  414. #ifdef FLOAT_CHECK_DOMAIN
  415.   if (c == 0.0)
  416.     domain_error ("tan", arg);
  417. #endif
  418.   IN_FLOAT (d = sin (d) / c);
  419.   return make_float (d);
  420. }
  421.  
  422. DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
  423.   "Return the hyperbolic tangent of ARG.")
  424.   (arg)
  425.      register Lisp_Object arg;
  426. {
  427.   double d = extract_float (arg);
  428.   IN_FLOAT (d = tanh (d));
  429.   return make_float (d);
  430. }
  431.  
  432. DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
  433.   "Return the absolute value of ARG.")
  434.   (arg)
  435.      register Lisp_Object arg;
  436. {
  437.   CHECK_NUMBER (arg, 0);
  438.  
  439.   if (FLOATP (arg))
  440.     IN_FLOAT (arg = make_float ((double) fabs (XFLOAT (arg)->data)));
  441.   else if (XINT (arg) < 0)
  442.     XSETINT (arg, - XFASTINT (arg));
  443.  
  444.   return arg;
  445. }
  446.  
  447. DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
  448.   "Return the floating point number equal to ARG.")
  449.   (arg)
  450.      register Lisp_Object arg;
  451. {
  452.   CHECK_NUMBER (arg, 0);
  453.  
  454.   if (FIXNUMP (arg))
  455.     return make_float ((double) XINT (arg));
  456.   else                /* give 'em the same float back */
  457.     return arg;
  458. }
  459.  
  460. /* the rounding functions  */
  461.  
  462. DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
  463.   "Return the smallest integer no less than ARG.  (Round toward +inf.)")
  464.   (arg)
  465.      register Lisp_Object arg;
  466. {
  467.   CHECK_NUMBER (arg, 0);
  468.  
  469.   if (FLOATP (arg))
  470.     IN_FLOAT (XSET (arg, Lisp_Int, ceil (XFLOAT (arg)->data)));
  471.  
  472.   return arg;
  473. }
  474.  
  475. DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0,
  476.   "Return the largest integer no greater than ARG.  (Round towards -inf.)")
  477.   (arg)
  478.      register Lisp_Object arg;
  479. {
  480.   CHECK_NUMBER (arg, 0);
  481.  
  482.   if (FLOATP (arg))
  483.     IN_FLOAT (XSET (arg, Lisp_Int, floor (XFLOAT (arg)->data)));
  484.  
  485.   return arg;
  486. }
  487.  
  488. DEFUN ("round", Fround, Sround, 1, 1, 0,
  489.   "Return the nearest integer to ARG.")
  490.   (arg)
  491.      register Lisp_Object arg;
  492. {
  493.   CHECK_NUMBER (arg, 0);
  494.  
  495.   if (FLOATP (arg))
  496.     IN_FLOAT (XSET (arg, Lisp_Int, rint (XFLOAT (arg)->data)));
  497.  
  498.   return arg;
  499. }
  500.  
  501. DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0,
  502.        "Truncate a floating point number to an int.\n\
  503. Rounds the value toward zero.")
  504.   (arg)
  505.      register Lisp_Object arg;
  506. {
  507.   CHECK_NUMBER (arg, 0);
  508.  
  509.   if (FLOATP (arg))
  510.     XSET (arg, Lisp_Int, (int) XFLOAT (arg)->data);
  511.  
  512.   return arg;
  513. }
  514.  
  515. DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
  516.   "Return the smallest integer no less than ARG, as a float.\n\
  517. \(Round toward +inf.\)")
  518.   (arg)
  519.      register Lisp_Object arg;
  520. {
  521.   double d = extract_float (arg);
  522.   IN_FLOAT (d = ceil (d));
  523.   return make_float (d);
  524. }
  525.  
  526. DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
  527.   "Return the largest integer no greater than ARG, as a float.\n\
  528. \(Round towards -inf.\)")
  529.   (arg)
  530.      register Lisp_Object arg;
  531. {
  532.   double d = extract_float (arg);
  533.   IN_FLOAT (d = floor (d));
  534.   return make_float (d);
  535. }
  536.  
  537. DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
  538.   "Return the nearest integer to ARG, as a float.")
  539.   (arg)
  540.      register Lisp_Object arg;
  541. {
  542.   double d = extract_float (arg);
  543.   IN_FLOAT (d = rint (d));
  544.   return make_float (d);
  545. }
  546.  
  547. DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
  548.        "Truncate a floating point number to an integral float value.\n\
  549. Rounds the value toward zero.")
  550.   (arg)
  551.      register Lisp_Object arg;
  552. {
  553.   double d = extract_float (arg);
  554.   if (d >= 0.0)
  555.     IN_FLOAT (d = floor (d));
  556.   else
  557.     IN_FLOAT (d = ceil (d));
  558.   return make_float (d);
  559. }
  560.  
  561. #ifdef FLOAT_CATCH_SIGILL
  562. static void
  563. float_error (signo)
  564.      int signo;
  565. {
  566.   if (! in_float)
  567.     fatal_error_signal (signo);
  568.  
  569. #ifdef BSD4_1
  570.   sigrelse (SIGILL);
  571. #else /* not BSD4_1 */
  572.   sigsetmask (0);
  573. #endif /* not BSD4_1 */
  574.  
  575.   in_float = 0;
  576.  
  577.   Fsignal (Qarith_error, Qnil);
  578. }
  579.  
  580. /* Another idea was to replace the library function `infnan'
  581.    where SIGILL is signaled.  */
  582.  
  583. #endif /* FLOAT_CATCH_SIGILL */
  584.  
  585. #ifdef HAVE_MATHERR
  586. int 
  587. matherr (x)
  588.      struct exception *x;
  589. {
  590.   Lisp_Object args;
  591.   if (! in_float)
  592.     /* Not called from emacs-lisp float routines; do the default thing. */
  593.     return 0;
  594.   args =
  595.     Fcons (build_string (x->name),
  596.        Fcons (make_float (x->arg1),
  597.           ((!strcmp (x->name, "log") || !strcmp (x->name, "pow"))
  598.            ? Fcons (make_float (x->arg2), Qnil)
  599.            : Qnil)));
  600.   switch (x->type)
  601.     {
  602.     case DOMAIN:    Fsignal (Qdomain_error, args);        break;
  603.     case SING:        Fsignal (Qsingularity_error, args);    break;
  604.     case OVERFLOW:    Fsignal (Qoverflow_error, args);    break;
  605.     case UNDERFLOW:    Fsignal (Qunderflow_error, args);    break;
  606.     default:        Fsignal (Qarith_error, args);        break;
  607.     }
  608.   return (1);    /* don't set errno or print a message */
  609. }
  610. #endif /* HAVE_MATHERR */
  611.  
  612. void
  613. init_floatfns ()
  614. {
  615. #ifdef FLOAT_CATCH_SIGILL
  616.   signal (SIGILL, float_error);
  617. #endif 
  618.   in_float = 0;
  619. }
  620.  
  621. void
  622. syms_of_floatfns ()
  623. {
  624.   defsubr (&Sacos);
  625.   defsubr (&Sacosh);
  626.   defsubr (&Sasin);
  627.   defsubr (&Sasinh);
  628.   defsubr (&Satan);
  629.   defsubr (&Satanh);
  630.   defsubr (&Scos);
  631.   defsubr (&Scosh);
  632.   defsubr (&Scube_root);
  633.   defsubr (&Sexp);
  634.   defsubr (&Slog);
  635.   defsubr (&Slog10);
  636.   defsubr (&Sexpt);
  637.   defsubr (&Ssin);
  638.   defsubr (&Ssinh);
  639.   defsubr (&Ssqrt);
  640.   defsubr (&Stan);
  641.   defsubr (&Stanh);
  642.  
  643.   defsubr (&Sabs);
  644.   defsubr (&Sfloat);
  645.   defsubr (&Sceiling);
  646.   defsubr (&Sfloor);
  647.   defsubr (&Sround);
  648.   defsubr (&Struncate);
  649.   defsubr (&Sfceiling);
  650.   defsubr (&Sffloor);
  651.   defsubr (&Sfround);
  652.   defsubr (&Sftruncate);
  653. }
  654.  
  655. #else /* not LISP_FLOAT_TYPE */
  656.  
  657. init_floatfns ()
  658. {}
  659.  
  660. syms_of_floatfns ()
  661. {}
  662.  
  663. #endif /* not LISP_FLOAT_TYPE */
  664.