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