:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / misc / 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 #include <windows.h>
22 #include <stdlib.h>
23
24 double atan (double __x);
25 double atan2 (double __y, double __x);
26 double ceil (double __x);
27 double cos (double __x);
28 double fabs (double __x);
29 double floor (double __x);
30 long _ftol (double fl);
31 double log (double __x);
32 double __log2 (double __x);
33 double pow (double __x, double __y);
34 double sin (double __x);
35 double sqrt (double __x);
36 double tan (double __x);
37 div_t div(int num, int denom);
38 int mod(int num, int denom);
39
40 double atan (double __x)
41 {
42   register double __value;
43   __asm __volatile__
44     ("fld1\n\t"
45      "fpatan"
46      : "=t" (__value) : "0" (__x));
47
48   return __value;
49 }
50
51 double atan2 (double __y, double __x)
52 {
53   register double __value;
54   __asm __volatile__
55     ("fpatan\n\t"
56      "fld %%st(0)"
57      : "=t" (__value) : "0" (__x), "u" (__y));
58
59   return __value;
60 }
61
62 double ceil (double __x)
63 {
64   register double __value;
65   __volatile unsigned short int __cw, __cwtmp;
66
67   __asm __volatile ("fnstcw %0" : "=m" (__cw));
68   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
69   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
70   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
71   __asm __volatile ("fldcw %0" : : "m" (__cw));
72
73   return __value;
74 }
75
76 double cos (double __x)
77 {
78   register double __value;
79   __asm __volatile__
80     ("fcos"
81      : "=t" (__value): "0" (__x));
82
83   return __value;
84 }
85
86 double fabs (double __x)
87 {
88   register double __value;
89   __asm __volatile__
90     ("fabs"
91      : "=t" (__value) : "0" (__x));
92
93   return __value;
94 }
95
96 double floor (double __x)
97 {
98   register double __value;
99   __volatile unsigned short int __cw, __cwtmp;
100
101   __asm __volatile ("fnstcw %0" : "=m" (__cw));
102   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
103   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
104   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
105   __asm __volatile ("fldcw %0" : : "m" (__cw));
106
107   return __value;
108 }
109
110 long _ftol (double fl)
111 {
112   return (long)fl;
113 }
114
115 double log (double __x)
116 {
117   register double __value;
118   __asm __volatile__
119     ("fldln2\n\t"
120      "fxch\n\t"
121      "fyl2x"
122      : "=t" (__value) : "0" (__x));
123
124   return __value;
125 }
126
127 double __log2 (double __x)
128 {
129   register double __value;
130   __asm __volatile__
131     ("fld1\n\t"
132      "fxch\n\t"
133      "fyl2x"
134      : "=t" (__value) : "0" (__x));
135
136   return __value;
137 }
138
139 double pow (double __x, double __y)
140 {
141   register double __value, __exponent;
142   long __p = (long) __y;
143
144   if (__x == 0.0 && __y > 0.0)
145     return 0.0;
146   if (__y == (double) __p)
147     {
148       double __r = 1.0;
149       if (__p == 0)
150         return 1.0;
151       if (__p < 0)
152         {
153           __p = -__p;
154           __x = 1.0 / __x;
155         }
156       while (1)
157         {
158           if (__p & 1)
159             __r *= __x;
160           __p >>= 1;
161           if (__p == 0)
162             return __r;
163           __x *= __x;
164         }
165       /* NOTREACHED */
166     }
167   __asm __volatile__
168     ("fmul      %%st(1)         # y * log2(x)\n\t"
169      "fst       %%st(1)\n\t"
170      "frndint                   # int(y * log2(x))\n\t"
171      "fxch\n\t"
172      "fsub      %%st(1)         # fract(y * log2(x))\n\t"
173      "f2xm1                     # 2^(fract(y * log2(x))) - 1\n\t"
174      : "=t" (__value), "=u" (__exponent) :  "0" (__log2 (__x)), "1" (__y));
175   __value += 1.0;
176   __asm __volatile__
177     ("fscale"
178      : "=t" (__value) : "0" (__value), "u" (__exponent));
179
180   return __value;
181 }
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 double sqrt (double __x)
194 {
195   register double __value;
196   __asm __volatile__
197     ("fsqrt"
198      : "=t" (__value) : "0" (__x));
199
200   return __value;
201 }
202
203 double tan (double __x)
204 {
205   register double __value;
206   register double __value2 __attribute__ ((unused));
207   __asm __volatile__
208     ("fptan"
209      : "=t" (__value2), "=u" (__value) : "0" (__x));
210
211   return __value;
212 }
213
214 div_t div(int num, int denom)
215 {
216   div_t r;
217   if (num > 0 && denom < 0) {
218     num = -num;
219     denom = -denom;
220   }
221   r.quot = num / denom;
222   r.rem = num % denom;
223   if (num < 0 && denom > 0)
224   {
225     if (r.rem > 0)
226     {
227       r.quot++;
228       r.rem -= denom;
229     }
230   }
231   return r;
232 }
233
234 int mod(int num, int denom)
235 {
236   div_t dvt = div(num, denom);
237   return dvt.rem;
238 }
239
240 //FIXME! Is there a better algorithm. like FT_MulDiv
241 INT STDCALL EngMulDiv(
242              INT nMultiplicand,
243              INT nMultiplier,
244              INT nDivisor)
245 {
246 #if SIZEOF_LONG_LONG >= 8
247     long long ret;
248
249     if (!nDivisor) return -1;
250
251     /* We want to deal with a positive divisor to simplify the logic. */
252     if (nDivisor < 0)
253     {
254       nMultiplicand = - nMultiplicand;
255       nDivisor = -nDivisor;
256     }
257
258     /* If the result is positive, we "add" to round. else, we subtract to round. */
259     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
260          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
261       ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
262     else
263       ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
264
265     if ((ret > 2147483647) || (ret < -2147483647)) return -1;
266     return ret;
267 #else
268     if (!nDivisor) return -1;
269
270     /* We want to deal with a positive divisor to simplify the logic. */
271     if (nDivisor < 0)
272     {
273       nMultiplicand = - nMultiplicand;
274       nDivisor = -nDivisor;
275     }
276
277     /* If the result is positive, we "add" to round. else, we subtract to round. */
278     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
279          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
280       return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
281
282     return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
283
284 #endif
285 }