1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48: #include <config.h>
49: #include <signal.h>
50: #include "lisp.h"
51: #include "syssignal.h"
52:
53: #if STDC_HEADERS
54: #include <float.h>
55: #endif
56:
57:
58: #ifndef IEEE_FLOATING_POINT
59: #if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
60: && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
61: #define IEEE_FLOATING_POINT 1
62: #else
63: #define IEEE_FLOATING_POINT 0
64: #endif
65: #endif
66:
67:
68:
69:
70:
71:
72: #if defined (HPUX) && !defined (HPUX8)
73: #define _MAXLDBL floatfns_maxldbl
74: #define _NMAXLDBL floatfns_nmaxldbl
75: #endif
76:
77: #include <math.h>
78:
79:
80: #if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
81: extern double logb ();
82: #endif
83:
84: #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
85:
86: # ifndef HAVE_MATHERR
87: # define HAVE_MATHERR
88: # endif
89: #endif
90:
91: #ifdef NO_MATHERR
92: #undef HAVE_MATHERR
93: #endif
94:
95: #ifdef HAVE_MATHERR
96: # ifdef FLOAT_CHECK_ERRNO
97: # undef FLOAT_CHECK_ERRNO
98: # endif
99: # ifdef FLOAT_CHECK_DOMAIN
100: # undef FLOAT_CHECK_DOMAIN
101: # endif
102: #endif
103:
104: #ifndef NO_FLOAT_CHECK_ERRNO
105: #define FLOAT_CHECK_ERRNO
106: #endif
107:
108: #ifdef FLOAT_CHECK_ERRNO
109: # include <errno.h>
110:
111: #ifndef USE_CRT_DLL
112: extern int errno;
113: #endif
114: #endif
115:
116:
117:
118:
119: #ifdef VMS
120: #undef cosh
121: #undef sinh
122: #define cosh(x) ((exp(x)+exp(-x))*0.5)
123: #define sinh(x) ((exp(x)-exp(-x))*0.5)
124: #endif
125:
126: #ifdef FLOAT_CATCH_SIGILL
127: static SIGTYPE float_error ();
128: #endif
129:
130:
131:
132:
133: static int in_float;
134:
135:
136:
137:
138:
139:
140: static Lisp_Object float_error_arg, float_error_arg2;
141:
142: static char *float_error_fn_name;
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153: #ifdef FLOAT_CHECK_ERRNO
154: #define IN_FLOAT(d, name, num) \
155: do { \
156: float_error_arg = num; \
157: float_error_fn_name = name; \
158: in_float = 1; errno = 0; (d); in_float = 0; \
159: switch (errno) { \
160: case 0: break; \
161: case EDOM: domain_error (float_error_fn_name, float_error_arg); \
162: case ERANGE: range_error (float_error_fn_name, float_error_arg); \
163: default: arith_error (float_error_fn_name, float_error_arg); \
164: } \
165: } while (0)
166: #define IN_FLOAT2(d, name, num, num2) \
167: do { \
168: float_error_arg = num; \
169: float_error_arg2 = num2; \
170: float_error_fn_name = name; \
171: in_float = 1; errno = 0; (d); in_float = 0; \
172: switch (errno) { \
173: case 0: break; \
174: case EDOM: domain_error (float_error_fn_name, float_error_arg); \
175: case ERANGE: range_error (float_error_fn_name, float_error_arg); \
176: default: arith_error (float_error_fn_name, float_error_arg); \
177: } \
178: } while (0)
179: #else
180: #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
181: #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
182: #endif
183:
184:
185:
186: #define FLOAT_TO_INT(x, i, name, num) \
187: do \
188: { \
189: if (FIXNUM_OVERFLOW_P (x)) \
190: range_error (name, num); \
191: XSETINT (i, (EMACS_INT)(x)); \
192: } \
193: while (0)
194: #define FLOAT_TO_INT2(x, i, name, num1, num2) \
195: do \
196: { \
197: if (FIXNUM_OVERFLOW_P (x)) \
198: range_error2 (name, num1, num2); \
199: XSETINT (i, (EMACS_INT)(x)); \
200: } \
201: while (0)
202:
203: #define arith_error(op,arg) \
204: xsignal2 (Qarith_error, build_string ((op)), (arg))
205: #define range_error(op,arg) \
206: xsignal2 (Qrange_error, build_string ((op)), (arg))
207: #define range_error2(op,a1,a2) \
208: xsignal3 (Qrange_error, build_string ((op)), (a1), (a2))
209: #define domain_error(op,arg) \
210: xsignal2 (Qdomain_error, build_string ((op)), (arg))
211: #define domain_error2(op,a1,a2) \
212: xsignal3 (Qdomain_error, build_string ((op)), (a1), (a2))
213:
214:
215:
216: double
217: extract_float (num)
218: Lisp_Object num;
219: {
220: CHECK_NUMBER_OR_FLOAT (num);
221:
222: if (FLOATP (num))
223: return XFLOAT_DATA (num);
224: return (double) XINT (num);
225: }
226: ^L
227:
228:
229: DEFUN ("acos", Facos, Sacos, 1, 1, 0,
230: doc: )
231: (arg)
232: register Lisp_Object arg;
233: {
234: double d = extract_float (arg);
235: #ifdef FLOAT_CHECK_DOMAIN
236: if (d > 1.0 || d < -1.0)
237: domain_error ("acos", arg);
238: #endif
239: IN_FLOAT (d = acos (d), "acos", arg);
240: return make_float (d);
241: }
242:
243: DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
244: doc: )
245: (arg)
246: register Lisp_Object arg;
247: {
248: double d = extract_float (arg);
249: #ifdef FLOAT_CHECK_DOMAIN
250: if (d > 1.0 || d < -1.0)
251: domain_error ("asin", arg);
252: #endif
253: IN_FLOAT (d = asin (d), "asin", arg);
254: return make_float (d);
255: }
256:
257: DEFUN ("atan", Fatan, Satan, 1, 2, 0,
258: doc:
259:
260:
261:
262: )
263: (y, x)
264: register Lisp_Object y, x;
265: {
266: double d = extract_float (y);
267:
268: if (NILP (x))
269: IN_FLOAT (d = atan (d), "atan", y);
270: else
271: {
272: double d2 = extract_float (x);
273:
274: IN_FLOAT2 (d = atan2 (d, d2), "atan", y, x);
275: }
276: return make_float (d);
277: }
278:
279: DEFUN ("cos", Fcos, Scos, 1, 1, 0,
280: doc: )
281: (arg)
282: register Lisp_Object arg;
283: {
284: double d = extract_float (arg);
285: IN_FLOAT (d = cos (d), "cos", arg);
286: return make_float (d);
287: }
288:
289: DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
290: doc: )
291: (arg)
292: register Lisp_Object arg;
293: {
294: double d = extract_float (arg);
295: IN_FLOAT (d = sin (d), "sin", arg);
296: return make_float (d);
297: }
298:
299: DEFUN ("tan", Ftan, Stan, 1, 1, 0,
300: doc: )
301: (arg)
302: register Lisp_Object arg;
303: {
304: double d = extract_float (arg);
305: double c = cos (d);
306: #ifdef FLOAT_CHECK_DOMAIN
307: if (c == 0.0)
308: domain_error ("tan", arg);
309: #endif
310: IN_FLOAT (d = sin (d) / c, "tan", arg);
311: return make_float (d);
312: }
313: ^L
314: #if 0
315:
316: DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
317: doc: )
318: (arg)
319: register Lisp_Object arg;
320: {
321: double d = extract_float (arg);
322: IN_FLOAT (d = j0 (d), "bessel-j0", arg);
323: return make_float (d);
324: }
325:
326: DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
327: doc: )
328: (arg)
329: register Lisp_Object arg;
330: {
331: double d = extract_float (arg);
332: IN_FLOAT (d = j1 (d), "bessel-j1", arg);
333: return make_float (d);
334: }
335:
336: DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
337: doc:
338: )
339: (n, arg)
340: register Lisp_Object n, arg;
341: {
342: int i1 = extract_float (n);
343: double f2 = extract_float (arg);
344:
345: IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
346: return make_float (f2);
347: }
348:
349: DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
350: doc: )
351: (arg)
352: register Lisp_Object arg;
353: {
354: double d = extract_float (arg);
355: IN_FLOAT (d = y0 (d), "bessel-y0", arg);
356: return make_float (d);
357: }
358:
359: DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
360: doc: )
361: (arg)
362: register Lisp_Object arg;
363: {
364: double d = extract_float (arg);
365: IN_FLOAT (d = y1 (d), "bessel-y0", arg);
366: return make_float (d);
367: }
368:
369: DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
370: doc:
371: )
372: (n, arg)
373: register Lisp_Object n, arg;
374: {
375: int i1 = extract_float (n);
376: double f2 = extract_float (arg);
377:
378: IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
379: return make_float (f2);
380: }
381:
382: #endif
383: ^L
384: #if 0
385:
386: DEFUN ("erf", Ferf, Serf, 1, 1, 0,
387: doc: )
388: (arg)
389: register Lisp_Object arg;
390: {
391: double d = extract_float (arg);
392: IN_FLOAT (d = erf (d), "erf", arg);
393: return make_float (d);
394: }
395:
396: DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
397: doc: )
398: (arg)
399: register Lisp_Object arg;
400: {
401: double d = extract_float (arg);
402: IN_FLOAT (d = erfc (d), "erfc", arg);
403: return make_float (d);
404: }
405:
406: DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
407: doc: )
408: (arg)
409: register Lisp_Object arg;
410: {
411: double d = extract_float (arg);
412: IN_FLOAT (d = lgamma (d), "log-gamma", arg);
413: return make_float (d);
414: }
415:
416: DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
417: doc: )
418: (arg)
419: register Lisp_Object arg;
420: {
421: double d = extract_float (arg);
422: #ifdef HAVE_CBRT
423: IN_FLOAT (d = cbrt (d), "cube-root", arg);
424: #else
425: if (d >= 0.0)
426: IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
427: else
428: IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
429: #endif
430: return make_float (d);
431: }
432:
433: #endif
434: ^L
435: DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
436: doc: )
437: (arg)
438: register Lisp_Object arg;
439: {
440: double d = extract_float (arg);
441: #ifdef FLOAT_CHECK_DOMAIN
442: if (d > 709.7827)
443: range_error ("exp", arg);
444: else if (d < -709.0)
445: return make_float (0.0);
446: else
447: #endif
448: IN_FLOAT (d = exp (d), "exp", arg);
449: return make_float (d);
450: }
451:
452: DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
453: doc: )
454: (arg1, arg2)
455: register Lisp_Object arg1, arg2;
456: {
457: double f1, f2;
458:
459: CHECK_NUMBER_OR_FLOAT (arg1);
460: CHECK_NUMBER_OR_FLOAT (arg2);
461: if (INTEGERP (arg1)
462: && INTEGERP (arg2)
463: && 0 <= XINT (arg2))
464: {
465: EMACS_INT acc, x, y;
466: Lisp_Object val;
467:
468: x = XINT (arg1);
469: y = XINT (arg2);
470: acc = 1;
471:
472: if (y < 0)
473: {
474: if (x == 1)
475: acc = 1;
476: else if (x == -1)
477: acc = (y & 1) ? -1 : 1;
478: else
479: acc = 0;
480: }
481: else
482: {
483: while (y > 0)
484: {
485: if (y & 1)
486: acc *= x;
487: x *= x;
488: y = (unsigned)y >> 1;
489: }
490: }
491: XSETINT (val, acc);
492: return val;
493: }
494: f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1);
495: f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2);
496:
497: if (f1 == 0.0 && f2 == 0.0)
498: f1 = 1.0;
499: #ifdef FLOAT_CHECK_DOMAIN
500: else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
501: domain_error2 ("expt", arg1, arg2);
502: #endif
503: IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2);
504: return make_float (f1);
505: }
506:
507: DEFUN ("log", Flog, Slog, 1, 2, 0,
508: doc:
509: )
510: (arg, base)
511: register Lisp_Object arg, base;
512: {
513: double d = extract_float (arg);
514:
515: #ifdef FLOAT_CHECK_DOMAIN
516: if (d <= 0.0)
517: domain_error2 ("log", arg, base);
518: #endif
519: if (NILP (base))
520: IN_FLOAT (d = log (d), "log", arg);
521: else
522: {
523: double b = extract_float (base);
524:
525: #ifdef FLOAT_CHECK_DOMAIN
526: if (b <= 0.0 || b == 1.0)
527: domain_error2 ("log", arg, base);
528: #endif
529: if (b == 10.0)
530: IN_FLOAT2 (d = log10 (d), "log", arg, base);
531: else
532: IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
533: }
534: return make_float (d);
535: }
536:
537: DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
538: doc: )
539: (arg)
540: register Lisp_Object arg;
541: {
542: double d = extract_float (arg);
543: #ifdef FLOAT_CHECK_DOMAIN
544: if (d <= 0.0)
545: domain_error ("log10", arg);
546: #endif
547: IN_FLOAT (d = log10 (d), "log10", arg);
548: return make_float (d);
549: }
550:
551: DEFUN ("sqrt",