update for HEAD-2003091401
[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 /*
47  * @implemented
48  */
49 double ceil (double __x)
50 {
51   register double __value;
52   __volatile unsigned short int __cw, __cwtmp;
53
54   __asm __volatile ("fnstcw %0" : "=m" (__cw));
55   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
56   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
57   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
58   __asm __volatile ("fldcw %0" : : "m" (__cw));
59
60   return __value;
61 }
62
63 /*
64  * @implemented
65  */
66 double cos (double __x)
67 {
68   register double __value;
69   __asm __volatile__
70     ("fcos"
71      : "=t" (__value): "0" (__x));
72
73   return __value;
74 }
75
76 /*
77  * @implemented
78  */
79 double fabs (double __x)
80 {
81   register double __value;
82   __asm __volatile__
83     ("fabs"
84      : "=t" (__value) : "0" (__x));
85
86   return __value;
87 }
88
89 /*
90  * @implemented
91  */
92 double floor (double __x)
93 {
94   register double __value;
95   __volatile unsigned short int __cw, __cwtmp;
96
97   __asm __volatile ("fnstcw %0" : "=m" (__cw));
98   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
99   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
100   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
101   __asm __volatile ("fldcw %0" : : "m" (__cw));
102
103   return __value;
104 }
105
106 /*
107  * @implemented
108  */
109 double log (double __x)
110 {
111   register double __value;
112   __asm __volatile__
113     ("fldln2\n\t"
114      "fxch\n\t"
115      "fyl2x"
116      : "=t" (__value) : "0" (__x));
117
118   return __value;
119 }
120
121 double __log2 (double __x)
122 {
123   register double __value;
124   __asm __volatile__
125     ("fld1\n\t"
126      "fxch\n\t"
127      "fyl2x"
128      : "=t" (__value) : "0" (__x));
129
130   return __value;
131 }
132
133 /*
134  * @implemented
135  */
136 double pow (double __x, double __y)
137 {
138   register double __value, __exponent;
139   long __p = (long) __y;
140
141   if (__x == 0.0 && __y > 0.0)
142     return 0.0;
143   if (__y == (double) __p)
144     {
145       double __r = 1.0;
146       if (__p == 0)
147         return 1.0;
148       if (__p < 0)
149         {
150           __p = -__p;
151           __x = 1.0 / __x;
152         }
153       while (1)
154         {
155           if (__p & 1)
156             __r *= __x;
157           __p >>= 1;
158           if (__p == 0)
159             return __r;
160           __x *= __x;
161         }
162       /* NOTREACHED */
163     }
164   __asm __volatile__
165     ("fmul      %%st(1)         # y * log2(x)\n\t"
166      "fst       %%st(1)\n\t"
167      "frndint                   # int(y * log2(x))\n\t"
168      "fxch\n\t"
169      "fsub      %%st(1)         # fract(y * log2(x))\n\t"
170      "f2xm1                     # 2^(fract(y * log2(x))) - 1\n\t"
171      : "=t" (__value), "=u" (__exponent) :  "0" (__log2 (__x)), "1" (__y));
172   __value += 1.0;
173   __asm __volatile__
174     ("fscale"
175      : "=t" (__value) : "0" (__value), "u" (__exponent));
176
177   return __value;
178 }
179
180 /*
181  * @implemented
182  */
183 double sin (double __x)
184 {
185   register double __value;
186   __asm __volatile__
187     ("fsin"
188      : "=t" (__value) : "0" (__x));
189
190   return __value;
191 }
192
193 /*
194  * @implemented
195  */
196 double sqrt (double __x)
197 {
198   register double __value;
199   __asm __volatile__
200     ("fsqrt"
201      : "=t" (__value) : "0" (__x));
202
203   return __value;
204 }
205
206 /*
207  * @implemented
208  */
209 double tan (double __x)
210 {
211   register double __value;
212   register double __value2 __attribute__ ((unused));
213   __asm __volatile__
214     ("fptan"
215      : "=t" (__value2), "=u" (__value) : "0" (__x));
216
217   return __value;
218 }