1/* Test double on x86. */
2
3/* { dg-do run } */
4/* { dg-options -O2 } */
5
6extern void abort (void);
7
8static __inline  double
9mypow (double __x, double __y)
10{
11  register double __value, __exponent;
12  long __p = (long) __y;
13  if (__y == (double) __p)
14    {
15      double __r = 1.0;
16      if (__p == 0)
17	return 1.0;
18      if (__p < 0)
19	{
20	  __p = -__p;
21	  __x = 1.0 / __x;
22	}
23      while (1)
24	{
25	  if (__p & 1)
26	    __r *= __x;
27	  __p >>= 1;
28	  if (__p == 0)
29	    return __r;
30	  __x *= __x;
31	}
32    }
33  __asm __volatile__
34    ("fmul	%%st(1),%%st\n\t"	/* y * log2(x) */
35     "fst	%%st(1)\n\t"
36     "frndint\n\t"			/* int(y * log2(x)) */
37     "fxch  %%st(1)\n\t"
38     "fsub	%%st(1),%%st\n\t"	/* fract(y * log2(x)) */
39     "f2xm1\n\t"			/* 2^(fract(y * log2(x))) - 1 */
40     : "=t" (__value), "=u" (__exponent) :  "0" (__x), "1" (__y));
41  __value += 1.0;
42  __asm __volatile__
43    ("fscale"
44     : "=t" (__value) : "0" (__value), "u" (__exponent));
45  return __value;
46}
47
48const double E1 = 2.71828182845904523536028747135;
49
50double fact (double x)
51{
52  double corr;
53  corr = 1.0;
54  return corr * mypow(x/E1, x);
55}
56
57int main ()
58{
59  double y, z;
60
61  y = fact (46.2);
62  z = mypow (46.2/E1, 46.2);
63
64#if 0
65  printf ("%26.19e, %26.19e\n", y, z);
66#endif
67
68  if (y > z)
69    y -= z;
70  else
71    y = z - y;
72
73  y /= z;
74  if (y > 0.1)
75    abort ();
76
77  return 0;
78}
79