|
|
1.1 root 1: /******************************************************************\
2: * *
1.1.1.3 ! root 3: * <math-68881.h> last modified: 23 May 1992. *
1.1 root 4: * *
5: * Copyright (C) 1989 by Matthew Self. *
6: * You may freely distribute verbatim copies of this software *
7: * provided that this copyright notice is retained in all copies. *
8: * You may distribute modifications to this software under the *
9: * conditions above if you also clearly note such modifications *
10: * with their author and date. *
11: * *
12: * Note: errno is not set to EDOM when domain errors occur for *
13: * most of these functions. Rather, it is assumed that the *
14: * 68881's OPERR exception will be enabled and handled *
15: * appropriately by the operating system. Similarly, overflow *
16: * and underflow do not set errno to ERANGE. *
17: * *
18: * Send bugs to Matthew Self ([email protected]). *
19: * *
20: \******************************************************************/
21:
1.1.1.3 ! root 22: /* If you find this in GCC,
! 23: please send bug reports to [email protected]. */
! 24:
1.1 root 25: /* Changed by Richard Stallman: % inserted before a #.
26: New function `hypot' added.
27: Nans written in hex to avoid 0rnan.
1.1.1.3 ! root 28: May 1992, use %! for fpcr register. Break lines before function names.
1.1 root 29: December 1989, add parens around `&' in pow.
30: November 1990, added alternate definition of HUGE_VAL for Sun. */
31:
32: #include <errno.h>
33:
34: #ifndef HUGE_VAL
35: #ifdef __sun__
36: /* The Sun assembler fails to handle the hex constant in the usual defn. */
37: #define HUGE_VAL \
38: ({ \
39: static union { int i[2]; double d; } u = { {0x7ff00000, 0} }; \
40: u.d; \
41: })
42: #else
43: #define HUGE_VAL \
44: ({ \
45: double huge_val; \
46: \
47: __asm ("fmove%.d %#0x7ff0000000000000,%0" /* Infinity */ \
48: : "=f" (huge_val) \
49: : /* no inputs */); \
50: huge_val; \
51: })
52: #endif
53: #endif
54:
1.1.1.3 ! root 55: __inline static const double
! 56: sin (double x)
1.1 root 57: {
58: double value;
59:
60: __asm ("fsin%.x %1,%0"
61: : "=f" (value)
62: : "f" (x));
63: return value;
64: }
65:
1.1.1.3 ! root 66: __inline static const double
! 67: cos (double x)
1.1 root 68: {
69: double value;
70:
71: __asm ("fcos%.x %1,%0"
72: : "=f" (value)
73: : "f" (x));
74: return value;
75: }
76:
1.1.1.3 ! root 77: __inline static const double
! 78: tan (double x)
1.1 root 79: {
80: double value;
81:
82: __asm ("ftan%.x %1,%0"
83: : "=f" (value)
84: : "f" (x));
85: return value;
86: }
87:
1.1.1.3 ! root 88: __inline static const double
! 89: asin (double x)
1.1 root 90: {
91: double value;
92:
93: __asm ("fasin%.x %1,%0"
94: : "=f" (value)
95: : "f" (x));
96: return value;
97: }
98:
1.1.1.3 ! root 99: __inline static const double
! 100: acos (double x)
1.1 root 101: {
102: double value;
103:
104: __asm ("facos%.x %1,%0"
105: : "=f" (value)
106: : "f" (x));
107: return value;
108: }
109:
1.1.1.3 ! root 110: __inline static const double
! 111: atan (double x)
1.1 root 112: {
113: double value;
114:
115: __asm ("fatan%.x %1,%0"
116: : "=f" (value)
117: : "f" (x));
118: return value;
119: }
120:
1.1.1.3 ! root 121: __inline static const double
! 122: atan2 (double y, double x)
1.1 root 123: {
124: double pi, pi_over_2;
125:
126: __asm ("fmovecr%.x %#0,%0" /* extended precision pi */
127: : "=f" (pi)
128: : /* no inputs */ );
129: __asm ("fscale%.b %#-1,%0" /* no loss of accuracy */
130: : "=f" (pi_over_2)
131: : "0" (pi));
132: if (x > 0)
133: {
134: if (y > 0)
135: {
136: if (x > y)
137: return atan (y / x);
138: else
139: return pi_over_2 - atan (x / y);
140: }
141: else
142: {
143: if (x > -y)
144: return atan (y / x);
145: else
146: return - pi_over_2 - atan (x / y);
147: }
148: }
149: else
150: {
151: if (y > 0)
152: {
153: if (-x > y)
154: return pi + atan (y / x);
155: else
156: return pi_over_2 - atan (x / y);
157: }
158: else
159: {
160: if (-x > -y)
161: return - pi + atan (y / x);
162: else if (y < 0)
163: return - pi_over_2 - atan (x / y);
164: else
165: {
166: double value;
167:
168: errno = EDOM;
169: __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */
170: : "=f" (value)
171: : /* no inputs */);
172: return value;
173: }
174: }
175: }
176: }
177:
1.1.1.3 ! root 178: __inline static const double
! 179: sinh (double x)
1.1 root 180: {
181: double value;
182:
183: __asm ("fsinh%.x %1,%0"
184: : "=f" (value)
185: : "f" (x));
186: return value;
187: }
188:
1.1.1.3 ! root 189: __inline static const double
! 190: cosh (double x)
1.1 root 191: {
192: double value;
193:
194: __asm ("fcosh%.x %1,%0"
195: : "=f" (value)
196: : "f" (x));
197: return value;
198: }
199:
1.1.1.3 ! root 200: __inline static const double
! 201: tanh (double x)
1.1 root 202: {
203: double value;
204:
205: __asm ("ftanh%.x %1,%0"
206: : "=f" (value)
207: : "f" (x));
208: return value;
209: }
210:
1.1.1.3 ! root 211: __inline static const double
! 212: atanh (double x)
1.1 root 213: {
214: double value;
215:
216: __asm ("fatanh%.x %1,%0"
217: : "=f" (value)
218: : "f" (x));
219: return value;
220: }
221:
1.1.1.3 ! root 222: __inline static const double
! 223: exp (double x)
1.1 root 224: {
225: double value;
226:
227: __asm ("fetox%.x %1,%0"
228: : "=f" (value)
229: : "f" (x));
230: return value;
231: }
232:
1.1.1.3 ! root 233: __inline static const double
! 234: expm1 (double x)
1.1 root 235: {
236: double value;
237:
238: __asm ("fetoxm1%.x %1,%0"
239: : "=f" (value)
240: : "f" (x));
241: return value;
242: }
243:
1.1.1.3 ! root 244: __inline static const double
! 245: log (double x)
1.1 root 246: {
247: double value;
248:
249: __asm ("flogn%.x %1,%0"
250: : "=f" (value)
251: : "f" (x));
252: return value;
253: }
254:
1.1.1.3 ! root 255: __inline static const double
! 256: log1p (double x)
1.1 root 257: {
258: double value;
259:
260: __asm ("flognp1%.x %1,%0"
261: : "=f" (value)
262: : "f" (x));
263: return value;
264: }
265:
1.1.1.3 ! root 266: __inline static const double
! 267: log10 (double x)
1.1 root 268: {
269: double value;
270:
271: __asm ("flog10%.x %1,%0"
272: : "=f" (value)
273: : "f" (x));
274: return value;
275: }
276:
1.1.1.3 ! root 277: __inline static const double
! 278: sqrt (double x)
1.1 root 279: {
280: double value;
281:
282: __asm ("fsqrt%.x %1,%0"
283: : "=f" (value)
284: : "f" (x));
285: return value;
286: }
287:
1.1.1.3 ! root 288: __inline static const double
! 289: hypot (const double x, const double y)
1.1 root 290: {
291: return sqrt (x*x + y*y);
292: }
293:
1.1.1.3 ! root 294: __inline static const double
! 295: pow (const double x, const double y)
1.1 root 296: {
297: if (x > 0)
298: return exp (y * log (x));
299: else if (x == 0)
300: {
301: if (y > 0)
302: return 0.0;
303: else
304: {
305: double value;
306:
307: errno = EDOM;
1.1.1.2 root 308: __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */
1.1 root 309: : "=f" (value)
310: : /* no inputs */);
311: return value;
312: }
313: }
314: else
315: {
316: double temp;
317:
318: __asm ("fintrz%.x %1,%0"
319: : "=f" (temp) /* integer-valued float */
320: : "f" (y));
321: if (y == temp)
322: {
323: int i = (int) y;
324:
1.1.1.2 root 325: if ((i & 1) == 0) /* even */
1.1 root 326: return exp (y * log (-x));
327: else
328: return - exp (y * log (-x));
329: }
330: else
331: {
332: double value;
333:
334: errno = EDOM;
335: __asm ("fmove%.d %#0x7fffffffffffffff,%0" /* quiet NaN */
336: : "=f" (value)
337: : /* no inputs */);
338: return value;
339: }
340: }
341: }
342:
1.1.1.3 ! root 343: __inline static const double
! 344: fabs (double x)
1.1 root 345: {
346: double value;
347:
348: __asm ("fabs%.x %1,%0"
349: : "=f" (value)
350: : "f" (x));
351: return value;
352: }
353:
1.1.1.3 ! root 354: __inline static const double
! 355: ceil (double x)
1.1 root 356: {
357: int rounding_mode, round_up;
358: double value;
359:
1.1.1.3 ! root 360: __asm volatile ("fmove%.l %!,%0"
1.1 root 361: : "=dm" (rounding_mode)
362: : /* no inputs */ );
363: round_up = rounding_mode | 0x30;
1.1.1.3 ! root 364: __asm volatile ("fmove%.l %0,%!"
1.1 root 365: : /* no outputs */
366: : "dmi" (round_up));
367: __asm volatile ("fint%.x %1,%0"
368: : "=f" (value)
369: : "f" (x));
1.1.1.3 ! root 370: __asm volatile ("fmove%.l %0,%!"
1.1 root 371: : /* no outputs */
372: : "dmi" (rounding_mode));
373: return value;
374: }
375:
1.1.1.3 ! root 376: __inline static const double
! 377: floor (double x)
1.1 root 378: {
379: int rounding_mode, round_down;
380: double value;
381:
1.1.1.3 ! root 382: __asm volatile ("fmove%.l %!,%0"
1.1 root 383: : "=dm" (rounding_mode)
384: : /* no inputs */ );
385: round_down = (rounding_mode & ~0x10)
386: | 0x20;
1.1.1.3 ! root 387: __asm volatile ("fmove%.l %0,%!"
1.1 root 388: : /* no outputs */
389: : "dmi" (round_down));
390: __asm volatile ("fint%.x %1,%0"
391: : "=f" (value)
392: : "f" (x));
1.1.1.3 ! root 393: __asm volatile ("fmove%.l %0,%!"
1.1 root 394: : /* no outputs */
395: : "dmi" (rounding_mode));
396: return value;
397: }
398:
1.1.1.3 ! root 399: __inline static const double
! 400: rint (double x)
1.1 root 401: {
402: int rounding_mode, round_nearest;
403: double value;
404:
1.1.1.3 ! root 405: __asm volatile ("fmove%.l %!,%0"
1.1 root 406: : "=dm" (rounding_mode)
407: : /* no inputs */ );
408: round_nearest = rounding_mode & ~0x30;
1.1.1.3 ! root 409: __asm volatile ("fmove%.l %0,%!"
1.1 root 410: : /* no outputs */
411: : "dmi" (round_nearest));
412: __asm volatile ("fint%.x %1,%0"
413: : "=f" (value)
414: : "f" (x));
1.1.1.3 ! root 415: __asm volatile ("fmove%.l %0,%!"
1.1 root 416: : /* no outputs */
417: : "dmi" (rounding_mode));
418: return value;
419: }
420:
1.1.1.3 ! root 421: __inline static const double
! 422: fmod (double x, double y)
1.1 root 423: {
424: double value;
425:
426: __asm ("fmod%.x %2,%0"
427: : "=f" (value)
428: : "0" (x),
429: "f" (y));
430: return value;
431: }
432:
1.1.1.3 ! root 433: __inline static const double
! 434: drem (double x, double y)
1.1 root 435: {
436: double value;
437:
438: __asm ("frem%.x %2,%0"
439: : "=f" (value)
440: : "0" (x),
441: "f" (y));
442: return value;
443: }
444:
1.1.1.3 ! root 445: __inline static const double
! 446: scalb (double x, int n)
1.1 root 447: {
448: double value;
449:
450: __asm ("fscale%.l %2,%0"
451: : "=f" (value)
452: : "0" (x),
453: "dmi" (n));
454: return value;
455: }
456:
1.1.1.3 ! root 457: __inline static double
! 458: logb (double x)
1.1 root 459: {
460: double exponent;
461:
462: __asm ("fgetexp%.x %1,%0"
463: : "=f" (exponent)
464: : "f" (x));
465: return exponent;
466: }
467:
1.1.1.3 ! root 468: __inline static const double
! 469: ldexp (double x, int n)
1.1 root 470: {
471: double value;
472:
473: __asm ("fscale%.l %2,%0"
474: : "=f" (value)
475: : "0" (x),
476: "dmi" (n));
477: return value;
478: }
479:
1.1.1.3 ! root 480: __inline static double
! 481: frexp (double x, int *exp)
1.1 root 482: {
483: double float_exponent;
484: int int_exponent;
485: double mantissa;
486:
487: __asm ("fgetexp%.x %1,%0"
488: : "=f" (float_exponent) /* integer-valued float */
489: : "f" (x));
490: int_exponent = (int) float_exponent;
491: __asm ("fgetman%.x %1,%0"
492: : "=f" (mantissa) /* 1.0 <= mantissa < 2.0 */
493: : "f" (x));
494: if (mantissa != 0)
495: {
496: __asm ("fscale%.b %#-1,%0"
497: : "=f" (mantissa) /* mantissa /= 2.0 */
498: : "0" (mantissa));
499: int_exponent += 1;
500: }
501: *exp = int_exponent;
502: return mantissa;
503: }
504:
1.1.1.3 ! root 505: __inline static double
! 506: modf (double x, double *ip)
1.1 root 507: {
508: double temp;
509:
510: __asm ("fintrz%.x %1,%0"
511: : "=f" (temp) /* integer-valued float */
512: : "f" (x));
513: *ip = temp;
514: return x - temp;
515: }
516:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.