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 */ |
---|