1186681Sed/******************************************************************\
2186681Sed*								   *
3186681Sed*  <math-68881.h>		last modified: 23 May 1992.	   *
4186681Sed*								   *
5186681Sed*  Copyright (C) 1989 by Matthew Self.				   *
6186681Sed*  You may freely distribute verbatim copies of this software	   *
7186681Sed*  provided that this copyright notice is retained in all copies.  *
8186681Sed*  You may distribute modifications to this software under the     *
9186681Sed*  conditions above if you also clearly note such modifications    *
10186681Sed*  with their author and date.			   	     	   *
11186681Sed*								   *
12186681Sed*  Note:  errno is not set to EDOM when domain errors occur for    *
13186681Sed*  most of these functions.  Rather, it is assumed that the	   *
14186681Sed*  68881's OPERR exception will be enabled and handled		   *
15186681Sed*  appropriately by the	operating system.  Similarly, overflow	   *
16186681Sed*  and underflow do not set errno to ERANGE.			   *
17186681Sed*								   *
18186681Sed*  Send bugs to Matthew Self (self@bayes.arc.nasa.gov).		   *
19186681Sed*								   *
20186681Sed\******************************************************************/
21186681Sed
22186681Sed/* This file is NOT a part of GCC, just distributed with it.  */
23186681Sed
24186681Sed/* If you find this in GCC,
25186681Sed   please send bug reports to bug-gcc@prep.ai.mit.edu.  */
26186681Sed
27186681Sed/* Changed by Richard Stallman:
28186681Sed   May 1993, add conditional to prevent multiple inclusion.
29186681Sed   % inserted before a #.
30186681Sed   New function `hypot' added.
31186681Sed   Nans written in hex to avoid 0rnan.
32186681Sed   May 1992, use %! for fpcr register.  Break lines before function names.
33186681Sed   December 1989, add parens around `&' in pow.
34187562Sed   November 1990, added alternate definition of HUGE_VAL for Sun.  */
35186681Sed
36186681Sed/* Changed by Jim Wilson:
37186681Sed   September 1993, Use #undef before HUGE_VAL instead of #ifdef/#endif.  */
38186681Sed
39186681Sed/* Changed by Ian Lance Taylor:
40186681Sed   September 1994, use extern inline instead of static inline.  */
41186681Sed
42186681Sed#ifndef __math_68881
43186681Sed#define __math_68881
44186681Sed
45186681Sed#include <errno.h>
46186681Sed
47186681Sed#undef HUGE_VAL
48186681Sed#ifdef __sun__
49186681Sed/* The Sun assembler fails to handle the hex constant in the usual defn.  */
50186681Sed#define HUGE_VAL							\
51186681Sed({									\
52186681Sed  static union { int i[2]; double d; } u = { {0x7ff00000, 0} };		\
53186681Sed  u.d;									\
54186681Sed})
55186681Sed#else
56186681Sed#define HUGE_VAL							\
57186681Sed({									\
58186681Sed  double huge_val;							\
59186681Sed									\
60186681Sed  __asm ("fmove%.d %#0x7ff0000000000000,%0"	/* Infinity */		\
61186681Sed	 : "=f" (huge_val)						\
62186681Sed	 : /* no inputs */);						\
63186681Sed  huge_val;								\
64186681Sed})
65186681Sed#endif
66186681Sed
67186681Sed__inline extern double
68186681Sedsin (double x)
69186681Sed{
70186681Sed  double value;
71186681Sed
72186681Sed  __asm ("fsin%.x %1,%0"
73186681Sed	 : "=f" (value)
74187469Sed	 : "f" (x));
75186681Sed  return value;
76186681Sed}
77186681Sed
78186681Sed__inline extern double
79186681Sedcos (double x)
80186681Sed{
81186681Sed  double value;
82186681Sed
83187562Sed  __asm ("fcos%.x %1,%0"
84187562Sed	 : "=f" (value)
85186681Sed	 : "f" (x));
86186681Sed  return value;
87186681Sed}
88186681Sed
89186681Sed__inline extern double
90186681Sedtan (double x)
91186681Sed{
92186681Sed  double value;
93187562Sed
94187562Sed  __asm ("ftan%.x %1,%0"
95187562Sed	 : "=f" (value)
96187562Sed	 : "f" (x));
97187562Sed  return value;
98187562Sed}
99187562Sed
100187562Sed__inline extern double
101187562Sedasin (double x)
102187562Sed{
103187562Sed  double value;
104187562Sed
105187562Sed  __asm ("fasin%.x %1,%0"
106187562Sed	 : "=f" (value)
107187562Sed	 : "f" (x));
108186681Sed  return value;
109186681Sed}
110186681Sed
111186681Sed__inline extern double
112186681Sedacos (double x)
113186681Sed{
114186681Sed  double value;
115186681Sed
116196786Sed  __asm ("facos%.x %1,%0"
117196786Sed	 : "=f" (value)
118186681Sed	 : "f" (x));
119197522Sed  return value;
120197522Sed}
121187562Sed
122186681Sed__inline extern double
123186681Sedatan (double x)
124186681Sed{
125186681Sed  double value;
126186681Sed
127186681Sed  __asm ("fatan%.x %1,%0"
128186681Sed	 : "=f" (value)
129186681Sed	 : "f" (x));
130186681Sed  return value;
131186681Sed}
132186681Sed
133186681Sed__inline extern double
134186681Sedatan2 (double y, double x)
135186681Sed{
136186681Sed  double pi, pi_over_2;
137186681Sed
138186681Sed  __asm ("fmovecr%.x %#0,%0"		/* extended precision pi */
139186681Sed	 : "=f" (pi)
140186681Sed	 : /* no inputs */ );
141186681Sed  __asm ("fscale%.b %#-1,%0"		/* no loss of accuracy */
142186681Sed	 : "=f" (pi_over_2)
143186681Sed	 : "0" (pi));
144186681Sed  if (x > 0)
145186681Sed    {
146186681Sed      if (y > 0)
147186681Sed	{
148186681Sed	  if (x > y)
149186681Sed	    return atan (y / x);
150186681Sed	  else
151186681Sed	    return pi_over_2 - atan (x / y);
152186681Sed	}
153186681Sed      else
154186681Sed	{
155186681Sed	  if (x > -y)
156186681Sed	    return atan (y / x);
157186681Sed	  else
158186681Sed	    return - pi_over_2 - atan (x / y);
159186681Sed	}
160186681Sed    }
161186681Sed  else
162186681Sed    {
163186681Sed      if (y < 0)
164186681Sed	{
165186681Sed	  if (-x > -y)
166186681Sed	    return - pi + atan (y / x);
167186681Sed	  else
168186681Sed	    return - pi_over_2 - atan (x / y);
169186681Sed	}
170186681Sed      else
171186681Sed	{
172186681Sed	  if (-x > y)
173186681Sed	    return pi + atan (y / x);
174186681Sed	  else if (y > 0)
175186681Sed	    return pi_over_2 - atan (x / y);
176186681Sed	  else
177186681Sed	    {
178186681Sed	      double value;
179186681Sed
180186681Sed	      errno = EDOM;
181186681Sed	      __asm ("fmove%.d %#0x7fffffffffffffff,%0" 	/* quiet NaN */
182186681Sed		     : "=f" (value)
183186681Sed		     : /* no inputs */);
184186681Sed	      return value;
185186681Sed	    }
186186681Sed	}
187186681Sed    }
188186681Sed}
189186681Sed
190186681Sed__inline extern double
191186681Sedsinh (double x)
192186681Sed{
193186681Sed  double value;
194186681Sed
195186681Sed  __asm ("fsinh%.x %1,%0"
196186681Sed	 : "=f" (value)
197186681Sed	 : "f" (x));
198186681Sed  return value;
199186681Sed}
200186681Sed
201186681Sed__inline extern double
202186681Sedcosh (double x)
203186681Sed{
204186681Sed  double value;
205186681Sed
206186681Sed  __asm ("fcosh%.x %1,%0"
207186681Sed	 : "=f" (value)
208186681Sed	 : "f" (x));
209186681Sed  return value;
210186681Sed}
211186681Sed
212186681Sed__inline extern double
213186681Sedtanh (double x)
214186681Sed{
215186681Sed  double value;
216186681Sed
217186681Sed  __asm ("ftanh%.x %1,%0"
218186681Sed	 : "=f" (value)
219186681Sed	 : "f" (x));
220186681Sed  return value;
221186681Sed}
222186681Sed
223186681Sed__inline extern double
224186681Sedatanh (double x)
225186681Sed{
226186681Sed  double value;
227186681Sed
228186681Sed  __asm ("fatanh%.x %1,%0"
229186681Sed	 : "=f" (value)
230193940Sed	 : "f" (x));
231186681Sed  return value;
232186681Sed}
233186681Sed
234186681Sed__inline extern double
235186681Sedexp (double x)
236186681Sed{
237186681Sed  double value;
238186681Sed
239186681Sed  __asm ("fetox%.x %1,%0"
240186681Sed	 : "=f" (value)
241186681Sed	 : "f" (x));
242186681Sed  return value;
243186681Sed}
244186681Sed
245186681Sed__inline extern double
246186681Sedexpm1 (double x)
247186681Sed{
248186681Sed  double value;
249186681Sed
250186681Sed  __asm ("fetoxm1%.x %1,%0"
251186681Sed	 : "=f" (value)
252186681Sed	 : "f" (x));
253186681Sed  return value;
254186681Sed}
255186681Sed
256186681Sed__inline extern double
257186681Sedlog (double x)
258186681Sed{
259186681Sed  double value;
260186681Sed
261186681Sed  __asm ("flogn%.x %1,%0"
262186681Sed	 : "=f" (value)
263186681Sed	 : "f" (x));
264186681Sed  return value;
265186681Sed}
266186681Sed
267186681Sed__inline extern double
268186681Sedlog1p (double x)
269186681Sed{
270186681Sed  double value;
271186681Sed
272186681Sed  __asm ("flognp1%.x %1,%0"
273186681Sed	 : "=f" (value)
274186681Sed	 : "f" (x));
275186681Sed  return value;
276186681Sed}
277186681Sed
278186681Sed__inline extern double
279186681Sedlog10 (double x)
280186681Sed{
281186681Sed  double value;
282186681Sed
283186681Sed  __asm ("flog10%.x %1,%0"
284187562Sed	 : "=f" (value)
285187562Sed	 : "f" (x));
286187562Sed  return value;
287187562Sed}
288186681Sed
289186681Sed__inline extern double
290187562Sedsqrt (double x)
291187562Sed{
292186681Sed  double value;
293186681Sed
294186681Sed  __asm ("fsqrt%.x %1,%0"
295186681Sed	 : "=f" (value)
296186681Sed	 : "f" (x));
297186681Sed  return value;
298186681Sed}
299186681Sed
300187367Sed__inline extern double
301186681Sedhypot (double x, double y)
302186681Sed{
303186681Sed  return sqrt (x*x + y*y);
304186681Sed}
305186681Sed
306186681Sed__inline extern double
307186681Sedpow (double x, double y)
308186681Sed{
309186681Sed  if (x > 0)
310186681Sed    return exp (y * log (x));
311186681Sed  else if (x == 0)
312186681Sed    {
313186681Sed      if (y > 0)
314186681Sed	return 0.0;
315186681Sed      else
316187469Sed	{
317186681Sed	  double value;
318186681Sed
319186681Sed	  errno = EDOM;
320186681Sed	  __asm ("fmove%.d %#0x7fffffffffffffff,%0"		/* quiet NaN */
321186681Sed		 : "=f" (value)
322186681Sed		 : /* no inputs */);
323186681Sed	  return value;
324186681Sed	}
325186681Sed    }
326186681Sed  else
327186681Sed    {
328186681Sed      double temp;
329186681Sed
330186681Sed      __asm ("fintrz%.x %1,%0"
331186681Sed	     : "=f" (temp)			/* integer-valued float */
332186681Sed	     : "f" (y));
333186681Sed      if (y == temp)
334186681Sed        {
335186681Sed	  int i = (int) y;
336186681Sed
337186681Sed	  if ((i & 1) == 0)			/* even */
338186681Sed	    return exp (y * log (-x));
339186681Sed	  else
340186681Sed	    return - exp (y * log (-x));
341186681Sed        }
342186681Sed      else
343186681Sed        {
344186681Sed	  double value;
345186681Sed
346186681Sed	  errno = EDOM;
347186681Sed	  __asm ("fmove%.d %#0x7fffffffffffffff,%0"		/* quiet NaN */
348186681Sed		 : "=f" (value)
349186681Sed		 : /* no inputs */);
350186681Sed	  return value;
351186681Sed        }
352186681Sed    }
353186681Sed}
354186681Sed
355__inline extern double
356fabs (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
367ceil (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
389floor (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
412rint (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
434fmod (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
446drem (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
458scalb (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
470logb (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
481ldexp (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
493frexp (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
518modf (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 */
530