1 /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
2
3 Copyright (C) 1988, 1993-1994, 1999, 2001-2021 Free Software Foundation,
4 Inc.
5
6 Author: Wolfgang Rupprecht (according to ack.texi)
7
8 This file is part of GNU Emacs.
9
10 GNU Emacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or (at
13 your option) any later version.
14
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
22
23
24 /* C89 requires only the following math.h functions, and Emacs omits
25 the starred functions since we haven't found a use for them:
26 acos, asin, atan, atan2, ceil, cos, *cosh, exp, fabs, floor, fmod,
27 frexp, ldexp, log, log10 [via (log X 10)], *modf, pow, sin, *sinh,
28 sqrt, tan, *tanh.
29
30 C99 and C11 require the following math.h functions in addition to
31 the C89 functions. Of these, Emacs currently exports only the
32 starred ones to Lisp, since we haven't found a use for the others:
33 acosh, atanh, cbrt, *copysign, erf, erfc, exp2, expm1, fdim, fma,
34 fmax, fmin, fpclassify, hypot, ilogb, isfinite, isgreater,
35 isgreaterequal, isinf, isless, islessequal, islessgreater, *isnan,
36 isnormal, isunordered, lgamma, log1p, *log2 [via (log X 2)], *logb
37 (approximately), lrint/llrint, lround/llround, nan, nearbyint,
38 nextafter, nexttoward, remainder, remquo, *rint, round, scalbln,
39 scalbn, signbit, tgamma, *trunc.
40 */
41
42 #include <config.h>
43
44 #include "lisp.h"
45 #include "bignum.h"
46
47 #include <math.h>
48
49 #include <count-leading-zeros.h>
50
51 /* Emacs needs proper handling of +/-inf; correct printing as well as
52 important packages depend on it. Make sure the user didn't specify
53 -ffinite-math-only, either directly or implicitly with -Ofast or
54 -ffast-math. */
55 #if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__
56 #error Emacs cannot be built with -ffinite-math-only
57 #endif
58
59 /* Check that X is a floating point number. */
60
61 static void
CHECK_FLOAT(Lisp_Object x)62 CHECK_FLOAT (Lisp_Object x)
63 {
64 CHECK_TYPE (FLOATP (x), Qfloatp, x);
65 }
66
67 /* Extract a Lisp number as a `double', or signal an error. */
68
69 double
extract_float(Lisp_Object num)70 extract_float (Lisp_Object num)
71 {
72 CHECK_NUMBER (num);
73 return XFLOATINT (num);
74 }
75
76 /* Trig functions. */
77
78 DEFUN ("acos", Facos, Sacos, 1, 1, 0,
79 doc: /* Return the inverse cosine of ARG. */)
80 (Lisp_Object arg)
81 {
82 double d = extract_float (arg);
83 d = acos (d);
84 return make_float (d);
85 }
86
87 DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
88 doc: /* Return the inverse sine of ARG. */)
89 (Lisp_Object arg)
90 {
91 double d = extract_float (arg);
92 d = asin (d);
93 return make_float (d);
94 }
95
96 DEFUN ("atan", Fatan, Satan, 1, 2, 0,
97 doc: /* Return the inverse tangent of the arguments.
98 If only one argument Y is given, return the inverse tangent of Y.
99 If two arguments Y and X are given, return the inverse tangent of Y
100 divided by X, i.e. the angle in radians between the vector (X, Y)
101 and the x-axis. */)
102 (Lisp_Object y, Lisp_Object x)
103 {
104 double d = extract_float (y);
105
106 if (NILP (x))
107 d = atan (d);
108 else
109 {
110 double d2 = extract_float (x);
111 d = atan2 (d, d2);
112 }
113 return make_float (d);
114 }
115
116 DEFUN ("cos", Fcos, Scos, 1, 1, 0,
117 doc: /* Return the cosine of ARG. */)
118 (Lisp_Object arg)
119 {
120 double d = extract_float (arg);
121 d = cos (d);
122 return make_float (d);
123 }
124
125 DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
126 doc: /* Return the sine of ARG. */)
127 (Lisp_Object arg)
128 {
129 double d = extract_float (arg);
130 d = sin (d);
131 return make_float (d);
132 }
133
134 DEFUN ("tan", Ftan, Stan, 1, 1, 0,
135 doc: /* Return the tangent of ARG. */)
136 (Lisp_Object arg)
137 {
138 double d = extract_float (arg);
139 d = tan (d);
140 return make_float (d);
141 }
142
143 DEFUN ("isnan", Fisnan, Sisnan, 1, 1, 0,
144 doc: /* Return non-nil if argument X is a NaN. */)
145 (Lisp_Object x)
146 {
147 CHECK_FLOAT (x);
148 return isnan (XFLOAT_DATA (x)) ? Qt : Qnil;
149 }
150
151 /* Although the substitute does not work on NaNs, it is good enough
152 for platforms lacking the signbit macro. */
153 #ifndef signbit
154 # define signbit(x) ((x) < 0 || (IEEE_FLOATING_POINT && !(x) && 1 / (x) < 0))
155 #endif
156
157 DEFUN ("copysign", Fcopysign, Scopysign, 2, 2, 0,
158 doc: /* Copy sign of X2 to value of X1, and return the result.
159 Cause an error if X1 or X2 is not a float. */)
160 (Lisp_Object x1, Lisp_Object x2)
161 {
162 double f1, f2;
163
164 CHECK_FLOAT (x1);
165 CHECK_FLOAT (x2);
166
167 f1 = XFLOAT_DATA (x1);
168 f2 = XFLOAT_DATA (x2);
169
170 /* Use signbit instead of copysign, to avoid calling make_float when
171 the result is X1. */
172 return signbit (f1) != signbit (f2) ? make_float (-f1) : x1;
173 }
174
175 DEFUN ("frexp", Ffrexp, Sfrexp, 1, 1, 0,
176 doc: /* Get significand and exponent of a floating point number.
177 Breaks the floating point number X into its binary significand SGNFCAND
178 \(a floating point value between 0.5 (included) and 1.0 (excluded))
179 and an integral exponent EXP for 2, such that:
180
181 X = SGNFCAND * 2^EXP
182
183 The function returns the cons cell (SGNFCAND . EXP).
184 If X is zero, both parts (SGNFCAND and EXP) are zero. */)
185 (Lisp_Object x)
186 {
187 double f = extract_float (x);
188 int exponent;
189 double sgnfcand = frexp (f, &exponent);
190 return Fcons (make_float (sgnfcand), make_fixnum (exponent));
191 }
192
193 DEFUN ("ldexp", Fldexp, Sldexp, 2, 2, 0,
194 doc: /* Return SGNFCAND * 2**EXPONENT, as a floating point number.
195 EXPONENT must be an integer. */)
196 (Lisp_Object sgnfcand, Lisp_Object exponent)
197 {
198 CHECK_FIXNUM (exponent);
199 int e = min (max (INT_MIN, XFIXNUM (exponent)), INT_MAX);
200 return make_float (ldexp (extract_float (sgnfcand), e));
201 }
202
203 DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
204 doc: /* Return the exponential base e of ARG. */)
205 (Lisp_Object arg)
206 {
207 double d = extract_float (arg);
208 d = exp (d);
209 return make_float (d);
210 }
211
212 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
213 doc: /* Return the exponential ARG1 ** ARG2. */)
214 (Lisp_Object arg1, Lisp_Object arg2)
215 {
216 CHECK_NUMBER (arg1);
217 CHECK_NUMBER (arg2);
218
219 /* Common Lisp spec: don't promote if both are integers, and if the
220 result is not fractional. */
221 if (INTEGERP (arg1) && !NILP (Fnatnump (arg2)))
222 return expt_integer (arg1, arg2);
223
224 return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2)));
225 }
226
227 DEFUN ("log", Flog, Slog, 1, 2, 0,
228 doc: /* Return the natural logarithm of ARG.
229 If the optional argument BASE is given, return log ARG using that base. */)
230 (Lisp_Object arg, Lisp_Object base)
231 {
232 double d = extract_float (arg);
233
234 if (NILP (base))
235 d = log (d);
236 else
237 {
238 double b = extract_float (base);
239
240 if (b == 10.0)
241 d = log10 (d);
242 #if HAVE_LOG2
243 else if (b == 2.0)
244 d = log2 (d);
245 #endif
246 else
247 d = log (d) / log (b);
248 }
249 return make_float (d);
250 }
251
252 DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
253 doc: /* Return the square root of ARG. */)
254 (Lisp_Object arg)
255 {
256 double d = extract_float (arg);
257 d = sqrt (d);
258 return make_float (d);
259 }
260
261 DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
262 doc: /* Return the absolute value of ARG. */)
263 (Lisp_Object arg)
264 {
265 CHECK_NUMBER (arg);
266
267 if (FIXNUMP (arg))
268 {
269 if (XFIXNUM (arg) < 0)
270 arg = make_int (-XFIXNUM (arg));
271 }
272 else if (FLOATP (arg))
273 {
274 if (signbit (XFLOAT_DATA (arg)))
275 arg = make_float (- XFLOAT_DATA (arg));
276 }
277 else
278 {
279 if (mpz_sgn (*xbignum_val (arg)) < 0)
280 {
281 mpz_neg (mpz[0], *xbignum_val (arg));
282 arg = make_integer_mpz ();
283 }
284 }
285
286 return arg;
287 }
288
289 DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
290 doc: /* Return the floating point number equal to ARG. */)
291 (register Lisp_Object arg)
292 {
293 CHECK_NUMBER (arg);
294 /* If ARG is a float, give 'em the same float back. */
295 return FLOATP (arg) ? arg : make_float (XFLOATINT (arg));
296 }
297
298 static int
ecount_leading_zeros(EMACS_UINT x)299 ecount_leading_zeros (EMACS_UINT x)
300 {
301 return (EMACS_UINT_WIDTH == UINT_WIDTH ? count_leading_zeros (x)
302 : EMACS_UINT_WIDTH == ULONG_WIDTH ? count_leading_zeros_l (x)
303 : count_leading_zeros_ll (x));
304 }
305
306 DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
307 doc: /* Returns largest integer <= the base 2 log of the magnitude of ARG.
308 This is the same as the exponent of a float. */)
309 (Lisp_Object arg)
310 {
311 EMACS_INT value;
312 CHECK_NUMBER (arg);
313
314 if (FLOATP (arg))
315 {
316 double f = XFLOAT_DATA (arg);
317 if (f == 0)
318 return make_float (-HUGE_VAL);
319 if (!isfinite (f))
320 return f < 0 ? make_float (-f) : arg;
321 int ivalue;
322 frexp (f, &ivalue);
323 value = ivalue - 1;
324 }
325 else if (!FIXNUMP (arg))
326 value = mpz_sizeinbase (*xbignum_val (arg), 2) - 1;
327 else
328 {
329 EMACS_INT i = XFIXNUM (arg);
330 if (i == 0)
331 return make_float (-HUGE_VAL);
332 value = EMACS_UINT_WIDTH - 1 - ecount_leading_zeros (eabs (i));
333 }
334
335 return make_fixnum (value);
336 }
337
338 /* Return the integer exponent E such that D * FLT_RADIX**E (i.e.,
339 scalbn (D, E)) is an integer that has precision equal to D and is
340 representable as a double.
341
342 Return DBL_MANT_DIG - DBL_MIN_EXP (the maximum possible valid
343 scale) if D is zero or tiny. Return one greater than that if
344 D is infinite, and two greater than that if D is a NaN. */
345
346 int
double_integer_scale(double d)347 double_integer_scale (double d)
348 {
349 int exponent = ilogb (d);
350 #ifdef HAIKU
351 /* On Haiku, the values returned by ilogb are nonsensical when
352 confronted with tiny numbers, inf, or NaN, which breaks the trick
353 used by code on other platforms, so we have to test for each case
354 manually, and return the appropriate value. */
355 if (exponent == FP_ILOGB0)
356 {
357 if (isnan (d))
358 return (DBL_MANT_DIG - DBL_MIN_EXP) + 2;
359 if (isinf (d))
360 return (DBL_MANT_DIG - DBL_MIN_EXP) + 1;
361
362 return (DBL_MANT_DIG - DBL_MIN_EXP);
363 }
364 #endif
365 return (DBL_MIN_EXP - 1 <= exponent && exponent < INT_MAX
366 ? DBL_MANT_DIG - 1 - exponent
367 : (DBL_MANT_DIG - DBL_MIN_EXP
368 + (isnan (d) ? 2 : exponent == INT_MAX)));
369 }
370
371 /* Convert the Lisp number N to an integer and return a pointer to the
372 converted integer, represented as an mpz_t *. Use *T as a
373 temporary; the returned value might be T. Scale N by the maximum
374 of NSCALE and DSCALE while converting. If NSCALE is nonzero, N
375 must be a float; signal an overflow if NSCALE is greater than
376 DBL_MANT_DIG - DBL_MIN_EXP, otherwise scalbn (XFLOAT_DATA (N), NSCALE)
377 must return an integer value, without rounding or overflow. */
378
379 static mpz_t const *
rescale_for_division(Lisp_Object n,mpz_t * t,int nscale,int dscale)380 rescale_for_division (Lisp_Object n, mpz_t *t, int nscale, int dscale)
381 {
382 mpz_t const *pn;
383
384 if (FLOATP (n))
385 {
386 if (DBL_MANT_DIG - DBL_MIN_EXP < nscale)
387 overflow_error ();
388 mpz_set_d (*t, scalbn (XFLOAT_DATA (n), nscale));
389 pn = t;
390 }
391 else
392 pn = bignum_integer (t, n);
393
394 if (nscale < dscale)
395 {
396 emacs_mpz_mul_2exp (*t, *pn, (dscale - nscale) * LOG2_FLT_RADIX);
397 pn = t;
398 }
399 return pn;
400 }
401
402 /* the rounding functions */
403
404 static Lisp_Object
rounding_driver(Lisp_Object n,Lisp_Object d,double (* double_round)(double),void (* int_divide)(mpz_t,mpz_t const,mpz_t const),EMACS_INT (* fixnum_divide)(EMACS_INT,EMACS_INT))405 rounding_driver (Lisp_Object n, Lisp_Object d,
406 double (*double_round) (double),
407 void (*int_divide) (mpz_t, mpz_t const, mpz_t const),
408 EMACS_INT (*fixnum_divide) (EMACS_INT, EMACS_INT))
409 {
410 CHECK_NUMBER (n);
411
412 if (NILP (d))
413 return FLOATP (n) ? double_to_integer (double_round (XFLOAT_DATA (n))) : n;
414
415 CHECK_NUMBER (d);
416
417 int dscale = 0;
418 if (FIXNUMP (d))
419 {
420 if (XFIXNUM (d) == 0)
421 xsignal0 (Qarith_error);
422
423 /* Divide fixnum by fixnum specially, for speed. */
424 if (FIXNUMP (n))
425 return make_int (fixnum_divide (XFIXNUM (n), XFIXNUM (d)));
426 }
427 else if (FLOATP (d))
428 {
429 if (XFLOAT_DATA (d) == 0)
430 xsignal0 (Qarith_error);
431 dscale = double_integer_scale (XFLOAT_DATA (d));
432 }
433
434 int nscale = FLOATP (n) ? double_integer_scale (XFLOAT_DATA (n)) : 0;
435
436 /* If the numerator is finite and the denominator infinite, the
437 quotient is zero and there is no need to try the impossible task
438 of rescaling the denominator. */
439 if (dscale == DBL_MANT_DIG - DBL_MIN_EXP + 1 && nscale < dscale)
440 return make_fixnum (0);
441
442 int_divide (mpz[0],
443 *rescale_for_division (n, &mpz[0], nscale, dscale),
444 *rescale_for_division (d, &mpz[1], dscale, nscale));
445 return make_integer_mpz ();
446 }
447
448 static EMACS_INT
ceiling2(EMACS_INT n,EMACS_INT d)449 ceiling2 (EMACS_INT n, EMACS_INT d)
450 {
451 return n / d + ((n % d != 0) & ((n < 0) == (d < 0)));
452 }
453
454 static EMACS_INT
floor2(EMACS_INT n,EMACS_INT d)455 floor2 (EMACS_INT n, EMACS_INT d)
456 {
457 return n / d - ((n % d != 0) & ((n < 0) != (d < 0)));
458 }
459
460 static EMACS_INT
truncate2(EMACS_INT n,EMACS_INT d)461 truncate2 (EMACS_INT n, EMACS_INT d)
462 {
463 return n / d;
464 }
465
466 static EMACS_INT
round2(EMACS_INT n,EMACS_INT d)467 round2 (EMACS_INT n, EMACS_INT d)
468 {
469 /* The C language's division operator gives us the remainder R
470 corresponding to truncated division, but we want the remainder R1
471 on the other side of 0 if R1 is closer to 0 than R is; because we
472 want to round to even, we also want R1 if R and R1 are the same
473 distance from 0 and if the truncated quotient is odd. */
474 EMACS_INT q = n / d;
475 EMACS_INT r = n % d;
476 bool neg_d = d < 0;
477 bool neg_r = r < 0;
478 EMACS_INT abs_r = eabs (r);
479 EMACS_INT abs_r1 = eabs (d) - abs_r;
480 if (abs_r1 < abs_r + (q & 1))
481 q += neg_d == neg_r ? 1 : -1;
482 return q;
483 }
484
485 static void
rounddiv_q(mpz_t q,mpz_t const n,mpz_t const d)486 rounddiv_q (mpz_t q, mpz_t const n, mpz_t const d)
487 {
488 /* Mimic the source code of round2, using mpz_t instead of EMACS_INT. */
489 mpz_t *r = &mpz[2], *abs_r = r, *abs_r1 = &mpz[3];
490 mpz_tdiv_qr (q, *r, n, d);
491 bool neg_d = mpz_sgn (d) < 0;
492 bool neg_r = mpz_sgn (*r) < 0;
493 mpz_abs (*abs_r, *r);
494 mpz_abs (*abs_r1, d);
495 mpz_sub (*abs_r1, *abs_r1, *abs_r);
496 if (mpz_cmp (*abs_r1, *abs_r) < (mpz_odd_p (q) != 0))
497 (neg_d == neg_r ? mpz_add_ui : mpz_sub_ui) (q, q, 1);
498 }
499
500 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
501 if `rint' exists but does not work right. */
502 #ifdef HAVE_RINT
503 #define emacs_rint rint
504 #else
505 static double
emacs_rint(double d)506 emacs_rint (double d)
507 {
508 double d1 = d + 0.5;
509 double r = floor (d1);
510 return r - (r == d1 && fmod (r, 2) != 0);
511 }
512 #endif
513
514 #ifndef HAVE_TRUNC
515 double
trunc(double d)516 trunc (double d)
517 {
518 return (d < 0 ? ceil : floor) (d);
519 }
520 #endif
521
522 DEFUN ("ceiling", Fceiling, Sceiling, 1, 2, 0,
523 doc: /* Return the smallest integer no less than ARG.
524 This rounds the value towards +inf.
525 With optional DIVISOR, return the smallest integer no less than ARG/DIVISOR. */)
526 (Lisp_Object arg, Lisp_Object divisor)
527 {
528 return rounding_driver (arg, divisor, ceil, mpz_cdiv_q, ceiling2);
529 }
530
531 DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
532 doc: /* Return the largest integer no greater than ARG.
533 This rounds the value towards -inf.
534 With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR. */)
535 (Lisp_Object arg, Lisp_Object divisor)
536 {
537 return rounding_driver (arg, divisor, floor, mpz_fdiv_q, floor2);
538 }
539
540 DEFUN ("round", Fround, Sround, 1, 2, 0,
541 doc: /* Return the nearest integer to ARG.
542 With optional DIVISOR, return the nearest integer to ARG/DIVISOR.
543
544 Rounding a value equidistant between two integers may choose the
545 integer closer to zero, or it may prefer an even integer, depending on
546 your machine. For example, (round 2.5) can return 3 on some
547 systems, but 2 on others. */)
548 (Lisp_Object arg, Lisp_Object divisor)
549 {
550 return rounding_driver (arg, divisor, emacs_rint, rounddiv_q, round2);
551 }
552
553 /* Since rounding_driver truncates anyway, no need to call 'trunc'. */
554 static double
identity(double x)555 identity (double x)
556 {
557 return x;
558 }
559
560 DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0,
561 doc: /* Truncate a floating point number to an int.
562 Rounds ARG toward zero.
563 With optional DIVISOR, truncate ARG/DIVISOR. */)
564 (Lisp_Object arg, Lisp_Object divisor)
565 {
566 return rounding_driver (arg, divisor, identity, mpz_tdiv_q, truncate2);
567 }
568
569
570 Lisp_Object
fmod_float(Lisp_Object x,Lisp_Object y)571 fmod_float (Lisp_Object x, Lisp_Object y)
572 {
573 double f1 = XFLOATINT (x);
574 double f2 = XFLOATINT (y);
575
576 f1 = fmod (f1, f2);
577
578 /* If the "remainder" comes out with the wrong sign, fix it. */
579 if (f2 < 0 ? f1 > 0 : f1 < 0)
580 f1 += f2;
581
582 return make_float (f1);
583 }
584
585 DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
586 doc: /* Return the smallest integer no less than ARG, as a float.
587 \(Round toward +inf.) */)
588 (Lisp_Object arg)
589 {
590 CHECK_FLOAT (arg);
591 double d = XFLOAT_DATA (arg);
592 d = ceil (d);
593 return make_float (d);
594 }
595
596 DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
597 doc: /* Return the largest integer no greater than ARG, as a float.
598 \(Round toward -inf.) */)
599 (Lisp_Object arg)
600 {
601 CHECK_FLOAT (arg);
602 double d = XFLOAT_DATA (arg);
603 d = floor (d);
604 return make_float (d);
605 }
606
607 DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
608 doc: /* Return the nearest integer to ARG, as a float. */)
609 (Lisp_Object arg)
610 {
611 CHECK_FLOAT (arg);
612 double d = XFLOAT_DATA (arg);
613 d = emacs_rint (d);
614 return make_float (d);
615 }
616
617 DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
618 doc: /* Truncate a floating point number to an integral float value.
619 \(Round toward zero.) */)
620 (Lisp_Object arg)
621 {
622 CHECK_FLOAT (arg);
623 double d = XFLOAT_DATA (arg);
624 d = trunc (d);
625 return make_float (d);
626 }
627
628 void
syms_of_floatfns(void)629 syms_of_floatfns (void)
630 {
631 defsubr (&Sacos);
632 defsubr (&Sasin);
633 defsubr (&Satan);
634 defsubr (&Scos);
635 defsubr (&Ssin);
636 defsubr (&Stan);
637 defsubr (&Sisnan);
638 defsubr (&Scopysign);
639 defsubr (&Sfrexp);
640 defsubr (&Sldexp);
641 defsubr (&Sfceiling);
642 defsubr (&Sffloor);
643 defsubr (&Sfround);
644 defsubr (&Sftruncate);
645 defsubr (&Sexp);
646 defsubr (&Sexpt);
647 defsubr (&Slog);
648 defsubr (&Ssqrt);
649
650 defsubr (&Sabs);
651 defsubr (&Sfloat);
652 defsubr (&Slogb);
653 defsubr (&Sceiling);
654 defsubr (&Sfloor);
655 defsubr (&Sround);
656 defsubr (&Struncate);
657 }
658