This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / lib / ntdll / rtl / math.c
1 /* Math functions for i387.
2    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by John C. Bowman <bowman@ipp-garching.mpg.de>, 1995.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21
22 double atan (double __x);
23 double ceil (double __x);
24 double cos (double __x);
25 double fabs (double __x);
26 double floor (double __x);
27 double log (double __x);
28 double __log2 (double __x);
29 double pow (double __x, double __y);
30 double sin (double __x);
31 double sqrt (double __x);
32 double tan (double __x);
33
34
35 double atan (double __x)
36 {
37   register double __value;
38   __asm __volatile__
39     ("fld1\n\t"
40      "fpatan"
41      : "=t" (__value) : "0" (__x));
42
43   return __value;
44 }
45
46 double ceil (double __x)
47 {
48   register double __value;
49   __volatile unsigned short int __cw, __cwtmp;
50
51   __asm __volatile ("fnstcw %0" : "=m" (__cw));
52   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
53   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
54   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
55   __asm __volatile ("fldcw %0" : : "m" (__cw));
56
57   return __value;
58 }
59
60 double cos (double __x)
61 {
62   register double __value;
63   __asm __volatile__
64     ("fcos"
65      : "=t" (__value): "0" (__x));
66
67   return __value;
68 }
69
70 double fabs (double __x)
71 {
72   register double __value;
73   __asm __volatile__
74     ("fabs"
75      : "=t" (__value) : "0" (__x));
76
77   return __value;
78 }
79
80 double floor (double __x)
81 {
82   register double __value;
83   __volatile unsigned short int __cw, __cwtmp;
84
85   __asm __volatile ("fnstcw %0" : "=m" (__cw));
86   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
87   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
88   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
89   __asm __volatile ("fldcw %0" : : "m" (__cw));
90
91   return __value;
92 }
93
94 double log (double __x)
95 {
96   register double __value;
97   __asm __volatile__
98     ("fldln2\n\t"
99      "fxch\n\t"
100      "fyl2x"
101      : "=t" (__value) : "0" (__x));
102
103   return __value;
104 }
105
106 double __log2 (double __x)
107 {
108   register double __value;
109   __asm __volatile__
110     ("fld1\n\t"
111      "fxch\n\t"
112      "fyl2x"
113      : "=t" (__value) : "0" (__x));
114
115   return __value;
116 }
117
118 double pow (double __x, double __y)
119 {
120   register double __value, __exponent;
121   long __p = (long) __y;
122
123   if (__x == 0.0 && __y > 0.0)
124     return 0.0;
125   if (__y == (double) __p)
126     {
127       double __r = 1.0;
128       if (__p == 0)
129         return 1.0;
130       if (__p < 0)
131         {
132           __p = -__p;
133           __x = 1.0 / __x;
134         }
135       while (1)
136         {
137           if (__p & 1)
138             __r *= __x;
139           __p >>= 1;
140           if (__p == 0)
141             return __r;
142           __x *= __x;
143         }
144       /* NOTREACHED */
145     }
146   __asm __volatile__
147     ("fmul      %%st(1)         # y * log2(x)\n\t"
148      "fst       %%st(1)\n\t"
149      "frndint                   # int(y * log2(x))\n\t"
150      "fxch\n\t"
151      "fsub      %%st(1)         # fract(y * log2(x))\n\t"
152      "f2xm1                     # 2^(fract(y * log2(x))) - 1\n\t"
153      : "=t" (__value), "=u" (__exponent) :  "0" (__log2 (__x)), "1" (__y));
154   __value += 1.0;
155   __asm __volatile__
156     ("fscale"
157      : "=t" (__value) : "0" (__value), "u" (__exponent));
158
159   return __value;
160 }
161
162 double sin (double __x)
163 {
164   register double __value;
165   __asm __volatile__
166     ("fsin"
167      : "=t" (__value) : "0" (__x));
168
169   return __value;
170 }
171
172 double sqrt (double __x)
173 {
174   register double __value;
175   __asm __volatile__
176     ("fsqrt"
177      : "=t" (__value) : "0" (__x));
178
179   return __value;
180 }
181
182 double tan (double __x)
183 {
184   register double __value;
185   register double __value2 __attribute__ ((unused));
186   __asm __volatile__
187     ("fptan"
188      : "=t" (__value2), "=u" (__value) : "0" (__x));
189
190   return __value;
191 }