Moved most remaining file functions to dlls/kernel.
[wine] / dlls / msvcrt / math.c
1 /*
2  * msvcrt.dll math functions
3  *
4  * Copyright 2000 Jon Griffiths
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This 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  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21
22 #include <stdio.h>
23 #define __USE_ISOC9X 1
24 #define __USE_ISOC99 1
25 #include <math.h>
26 #ifdef HAVE_IEEEFP_H
27 #include <ieeefp.h>
28 #endif
29
30 #include "msvcrt.h"
31 #include "msvcrt/errno.h"
32 #include "msvcrt/stdlib.h"
33 #include "msvcrt/math.h"
34 #include "msvcrt/float.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39
40 #ifndef HAVE_FINITE
41 #ifndef finite /* Could be a macro */
42 #ifdef isfinite
43 #define finite(x) isfinite(x)
44 #else
45 #define finite(x) (!isnan(x)) /* At least catch some cases */
46 #endif
47 #endif
48 #endif
49
50 #ifndef signbit
51 #define signbit(x) 0
52 #endif
53
54 typedef int (*MSVCRT_matherr_func)(struct MSVCRT__exception *);
55
56 static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
57
58 #if defined(__GNUC__) && defined(__i386__)
59
60 #define FPU_DOUBLE(var) double var; \
61   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
62 #define FPU_DOUBLES(var1,var2) double var1,var2; \
63   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
64   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
65
66 /*********************************************************************
67  *              _CIacos (MSVCRT.@)
68  */
69 double _CIacos(void)
70 {
71   FPU_DOUBLE(x);
72   if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
73   return acos(x);
74 }
75
76 /*********************************************************************
77  *              _CIasin (MSVCRT.@)
78  */
79 double _CIasin(void)
80 {
81   FPU_DOUBLE(x);
82   if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
83   return asin(x);
84 }
85
86 /*********************************************************************
87  *              _CIatan (MSVCRT.@)
88  */
89 double _CIatan(void)
90 {
91   FPU_DOUBLE(x);
92   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
93   return atan(x);
94 }
95
96 /*********************************************************************
97  *              _CIatan2 (MSVCRT.@)
98  */
99 double _CIatan2(void)
100 {
101   FPU_DOUBLES(x,y);
102   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
103   return atan2(x,y);
104 }
105
106 /*********************************************************************
107  *              _CIcos (MSVCRT.@)
108  */
109 double _CIcos(void)
110 {
111   FPU_DOUBLE(x);
112   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
113   return cos(x);
114 }
115
116 /*********************************************************************
117  *              _CIcosh (MSVCRT.@)
118  */
119 double _CIcosh(void)
120 {
121   FPU_DOUBLE(x);
122   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
123   return cosh(x);
124 }
125
126 /*********************************************************************
127  *              _CIexp (MSVCRT.@)
128  */
129 double _CIexp(void)
130 {
131   FPU_DOUBLE(x);
132   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
133   return exp(x);
134 }
135
136 /*********************************************************************
137  *              _CIfmod (MSVCRT.@)
138  */
139 double _CIfmod(void)
140 {
141   FPU_DOUBLES(x,y);
142   if (!finite(x) || !finite(y)) *MSVCRT__errno() = MSVCRT_EDOM;
143   return fmod(x,y);
144 }
145
146 /*********************************************************************
147  *              _CIlog (MSVCRT.@)
148  */
149 double _CIlog(void)
150 {
151   FPU_DOUBLE(x);
152   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
153   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
154   return log(x);
155 }
156
157 /*********************************************************************
158  *              _CIlog10 (MSVCRT.@)
159  */
160 double _CIlog10(void)
161 {
162   FPU_DOUBLE(x);
163   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
164   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
165   return log10(x);
166 }
167
168 /*********************************************************************
169  *              _CIpow (MSVCRT.@)
170  */
171 double _CIpow(void)
172 {
173   double z;
174   FPU_DOUBLES(x,y);
175   /* FIXME: If x < 0 and y is not integral, set EDOM */
176   z = pow(x,y);
177   if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
178   return z;
179 }
180
181 /*********************************************************************
182  *              _CIsin (MSVCRT.@)
183  */
184 double _CIsin(void)
185 {
186   FPU_DOUBLE(x);
187   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
188   return sin(x);
189 }
190
191 /*********************************************************************
192  *              _CIsinh (MSVCRT.@)
193  */
194 double _CIsinh(void)
195 {
196   FPU_DOUBLE(x);
197   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
198   return sinh(x);
199 }
200
201 /*********************************************************************
202  *              _CIsqrt (MSVCRT.@)
203  */
204 double _CIsqrt(void)
205 {
206   FPU_DOUBLE(x);
207   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
208   return sqrt(x);
209 }
210
211 /*********************************************************************
212  *              _CItan (MSVCRT.@)
213  */
214 double _CItan(void)
215 {
216   FPU_DOUBLE(x);
217   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
218   return tan(x);
219 }
220
221 /*********************************************************************
222  *              _CItanh (MSVCRT.@)
223  */
224 double _CItanh(void)
225 {
226   FPU_DOUBLE(x);
227   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
228   return tanh(x);
229 }
230
231 #else /* defined(__GNUC__) && defined(__i386__) */
232
233 /* The above cannot be called on non x86 platforms, stub them for linking */
234
235 #define IX86_ONLY(func) double func(void) { return 0.0; }
236
237 IX86_ONLY(_CIacos)
238 IX86_ONLY(_CIasin)
239 IX86_ONLY(_CIatan)
240 IX86_ONLY(_CIatan2)
241 IX86_ONLY(_CIcos)
242 IX86_ONLY(_CIcosh)
243 IX86_ONLY(_CIexp)
244 IX86_ONLY(_CIfmod)
245 IX86_ONLY(_CIlog)
246 IX86_ONLY(_CIlog10)
247 IX86_ONLY(_CIpow)
248 IX86_ONLY(_CIsin)
249 IX86_ONLY(_CIsinh)
250 IX86_ONLY(_CIsqrt)
251 IX86_ONLY(_CItan)
252 IX86_ONLY(_CItanh)
253
254 #endif /* defined(__GNUC__) && defined(__i386__) */
255
256 /*********************************************************************
257  *              _fpclass (MSVCRT.@)
258  */
259 int _fpclass(double num)
260 {
261 #if defined(HAVE_FPCLASS) || defined(fpclass)
262   switch (fpclass( num ))
263   {
264 #ifdef FP_SNAN
265   case FP_SNAN:  return _FPCLASS_SNAN;
266 #endif
267 #ifdef FP_QNAN
268   case FP_QNAN:  return _FPCLASS_QNAN;
269 #endif
270 #ifdef FP_NINF
271   case FP_NINF:  return _FPCLASS_NINF;
272 #endif
273 #ifdef FP_PINF
274   case FP_PINF:  return _FPCLASS_PINF;
275 #endif
276 #ifdef FP_NDENORM
277   case FP_NDENORM: return _FPCLASS_ND;
278 #endif
279 #ifdef FP_PDENORM
280   case FP_PDENORM: return _FPCLASS_PD;
281 #endif
282 #ifdef FP_NZERO
283   case FP_NZERO: return _FPCLASS_NZ;
284 #endif
285 #ifdef FP_PZERO
286   case FP_PZERO: return _FPCLASS_PZ;
287 #endif
288 #ifdef FP_NNORM
289   case FP_NNORM: return _FPCLASS_NN;
290 #endif
291 #ifdef FP_PNORM
292   case FP_PNORM: return _FPCLASS_PN;
293 #endif
294   }
295   return _FPCLASS_PN;
296 #elif defined (fpclassify)
297   switch (fpclassify( num ))
298   {
299   case FP_NAN: return _FPCLASS_QNAN;
300   case FP_INFINITE: return signbit(num) ? _FPCLASS_NINF : _FPCLASS_PINF;
301   case FP_SUBNORMAL: return signbit(num) ?_FPCLASS_ND : _FPCLASS_PD;
302   case FP_ZERO: return signbit(num) ? _FPCLASS_NZ : _FPCLASS_PZ;
303   }
304   return signbit(num) ? _FPCLASS_NN : _FPCLASS_PN;
305 #else
306   if (!finite(num))
307     return _FPCLASS_QNAN;
308   return num == 0.0 ? _FPCLASS_PZ : (num < 0 ? _FPCLASS_NN : _FPCLASS_PN);
309 #endif
310 }
311
312 /*********************************************************************
313  *              _rotl (MSVCRT.@)
314  */
315 unsigned int _rotl(unsigned int num, int shift)
316 {
317   shift &= 31;
318   return (num << shift) | (num >> (32-shift));
319 }
320
321 /*********************************************************************
322  *              _logb (MSVCRT.@)
323  */
324 double _logb(double num)
325 {
326   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
327   return logb(num);
328 }
329
330 /*********************************************************************
331  *              _lrotl (MSVCRT.@)
332  */
333 unsigned long _lrotl(unsigned long num, int shift)
334 {
335   shift &= 0x1f;
336   return (num << shift) | (num >> (32-shift));
337 }
338
339 /*********************************************************************
340  *              _lrotr (MSVCRT.@)
341  */
342 unsigned long _lrotr(unsigned long num, int shift)
343 {
344   shift &= 0x1f;
345   return (num >> shift) | (num << (32-shift));
346 }
347
348 /*********************************************************************
349  *              _rotr (MSVCRT.@)
350  */
351 unsigned int _rotr(unsigned int num, int shift)
352 {
353     shift &= 0x1f;
354     return (num >> shift) | (num << (32-shift));
355 }
356
357 /*********************************************************************
358  *              _scalb (MSVCRT.@)
359  */
360 double _scalb(double num, long power)
361 {
362   /* Note - Can't forward directly as libc expects y as double */
363   double dblpower = (double)power;
364   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
365   return scalb(num, dblpower);
366 }
367
368 /*********************************************************************
369  *              _matherr (MSVCRT.@)
370  */
371 int MSVCRT__matherr(struct MSVCRT__exception *e)
372 {
373   if (e)
374     TRACE("(%p = %d, %s, %g %g %g)\n",e, e->type, e->name, e->arg1, e->arg2,
375           e->retval);
376   else
377     TRACE("(null)\n");
378   if (MSVCRT_default_matherr_func)
379     return MSVCRT_default_matherr_func(e);
380   ERR(":Unhandled math error!\n");
381   return 0;
382 }
383
384 /*********************************************************************
385  *              __setusermatherr (MSVCRT.@)
386  */
387 void MSVCRT___setusermatherr(MSVCRT_matherr_func func)
388 {
389   MSVCRT_default_matherr_func = func;
390   TRACE(":new matherr handler %p\n", func);
391 }
392
393 /**********************************************************************
394  *              _statusfp (MSVCRT.@)
395  */
396 unsigned int _statusfp(void)
397 {
398    unsigned int retVal = 0;
399 #if defined(__GNUC__) && defined(__i386__)
400   unsigned int fpword;
401
402   __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
403   if (fpword & 0x1)  retVal |= _SW_INVALID;
404   if (fpword & 0x2)  retVal |= _SW_DENORMAL;
405   if (fpword & 0x4)  retVal |= _SW_ZERODIVIDE;
406   if (fpword & 0x8)  retVal |= _SW_OVERFLOW;
407   if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
408   if (fpword & 0x20) retVal |= _SW_INEXACT;
409 #else
410   FIXME(":Not implemented!\n");
411 #endif
412   return retVal;
413 }
414
415 /*********************************************************************
416  *              _clearfp (MSVCRT.@)
417  */
418 unsigned int _clearfp(void)
419 {
420   unsigned int retVal = _statusfp();
421 #if defined(__GNUC__) && defined(__i386__)
422   __asm__ __volatile__( "fnclex" );
423 #else
424   FIXME(":Not Implemented\n");
425 #endif
426   return retVal;
427 }
428
429 /*********************************************************************
430  *              __fpecode (MSVCRT.@)
431  */
432 int *__fpecode(void)
433 {
434     return &msvcrt_get_thread_data()->fpecode;
435 }
436
437 /*********************************************************************
438  *              ldexp (MSVCRT.@)
439  */
440 double MSVCRT_ldexp(double num, long exp)
441 {
442   double z = ldexp(num,exp);
443
444   if (!finite(z))
445     *MSVCRT__errno() = MSVCRT_ERANGE;
446   else if (z == 0 && signbit(z))
447     z = 0.0; /* Convert -0 -> +0 */
448   return z;
449 }
450
451 /*********************************************************************
452  *              _cabs (MSVCRT.@)
453  */
454 double MSVCRT__cabs(struct MSVCRT__complex num)
455 {
456   return sqrt(num.x * num.x + num.y * num.y);
457 }
458
459 /*********************************************************************
460  *              _chgsign (MSVCRT.@)
461  */
462 double _chgsign(double num)
463 {
464   /* FIXME: +-infinity,Nan not tested */
465   return -num;
466 }
467
468 /*********************************************************************
469  *              _control87 (MSVCRT.@)
470  */
471 unsigned int _control87(unsigned int newval, unsigned int mask)
472 {
473 #if defined(__GNUC__) && defined(__i386__)
474   unsigned int fpword = 0;
475   unsigned int flags = 0;
476
477   TRACE("(%08x, %08x): Called\n", newval, mask);
478
479   /* Get fp control word */
480   __asm__ __volatile__( "fstcw %0" : "=m" (fpword) : );
481
482   TRACE("Control word before : %08x\n", fpword);
483
484   /* Convert into mask constants */
485   if (fpword & 0x1)  flags |= _EM_INVALID;
486   if (fpword & 0x2)  flags |= _EM_DENORMAL;
487   if (fpword & 0x4)  flags |= _EM_ZERODIVIDE;
488   if (fpword & 0x8)  flags |= _EM_OVERFLOW;
489   if (fpword & 0x10) flags |= _EM_UNDERFLOW;
490   if (fpword & 0x20) flags |= _EM_INEXACT;
491   switch(fpword & 0xC00) {
492   case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
493   case 0x800: flags |= _RC_UP; break;
494   case 0x400: flags |= _RC_DOWN; break;
495   }
496   switch(fpword & 0x300) {
497   case 0x0:   flags |= _PC_24; break;
498   case 0x200: flags |= _PC_53; break;
499   case 0x300: flags |= _PC_64; break;
500   }
501   if (fpword & 0x1000) flags |= _IC_AFFINE;
502
503   /* Mask with parameters */
504   flags = (flags & ~mask) | (newval & mask);
505
506   /* Convert (masked) value back to fp word */
507   fpword = 0;
508   if (flags & _EM_INVALID)    fpword |= 0x1;
509   if (flags & _EM_DENORMAL)   fpword |= 0x2;
510   if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
511   if (flags & _EM_OVERFLOW)   fpword |= 0x8;
512   if (flags & _EM_UNDERFLOW)  fpword |= 0x10;
513   if (flags & _EM_INEXACT)    fpword |= 0x20;
514   switch(flags & (_RC_UP | _RC_DOWN)) {
515   case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
516   case _RC_UP:          fpword |= 0x800; break;
517   case _RC_DOWN:        fpword |= 0x400; break;
518   }
519   switch (flags & (_PC_24 | _PC_53)) {
520   case _PC_64: fpword |= 0x300; break;
521   case _PC_53: fpword |= 0x200; break;
522   case _PC_24: fpword |= 0x0; break;
523   }
524   if (flags & _IC_AFFINE) fpword |= 0x1000;
525
526   TRACE("Control word after  : %08x\n", fpword);
527
528   /* Put fp control word */
529   __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
530
531   return flags;
532 #else
533   FIXME(":Not Implemented!\n");
534   return 0;
535 #endif
536 }
537
538 /*********************************************************************
539  *              _controlfp (MSVCRT.@)
540  */
541 unsigned int _controlfp(unsigned int newval, unsigned int mask)
542 {
543 #ifdef __i386__
544   return _control87( newval, mask & ~_EM_DENORMAL );
545 #else
546   FIXME(":Not Implemented!\n");
547   return 0;
548 #endif
549 }
550
551 /*********************************************************************
552  *              _copysign (MSVCRT.@)
553  */
554 double _copysign(double num, double sign)
555 {
556   /* FIXME: Behaviour for Nan/Inf? */
557   if (sign < 0.0)
558     return num < 0.0 ? num : -num;
559   return num < 0.0 ? -num : num;
560 }
561
562 /*********************************************************************
563  *              _finite (MSVCRT.@)
564  */
565 int  _finite(double num)
566 {
567   return (finite(num)?1:0); /* See comment for _isnan() */
568 }
569
570 /*********************************************************************
571  *              _fpreset (MSVCRT.@)
572  */
573 void _fpreset(void)
574 {
575 #if defined(__GNUC__) && defined(__i386__)
576   __asm__ __volatile__( "fninit" );
577 #else
578   FIXME(":Not Implemented!\n");
579 #endif
580 }
581
582 /*********************************************************************
583  *              _isnan (MSVCRT.@)
584  */
585 INT  _isnan(double num)
586 {
587   /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
588    * Do the same, as the result may be used in calculations
589    */
590   return isnan(num) ? 1 : 0;
591 }
592
593 /*********************************************************************
594  *              _y0 (MSVCRT.@)
595  */
596 double _y0(double num)
597 {
598   double retval;
599   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
600   retval  = y0(num);
601   if (_fpclass(retval) == _FPCLASS_NINF)
602   {
603     *MSVCRT__errno() = MSVCRT_EDOM;
604     retval = sqrt(-1);
605   }
606   return retval;
607 }
608
609 /*********************************************************************
610  *              _y1 (MSVCRT.@)
611  */
612 double _y1(double num)
613 {
614   double retval;
615   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
616   retval  = y1(num);
617   if (_fpclass(retval) == _FPCLASS_NINF)
618   {
619     *MSVCRT__errno() = MSVCRT_EDOM;
620     retval = sqrt(-1);
621   }
622   return retval;
623 }
624
625 /*********************************************************************
626  *              _yn (MSVCRT.@)
627  */
628 double _yn(int order, double num)
629 {
630   double retval;
631   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
632   retval  = yn(order,num);
633   if (_fpclass(retval) == _FPCLASS_NINF)
634   {
635     *MSVCRT__errno() = MSVCRT_EDOM;
636     retval = sqrt(-1);
637   }
638   return retval;
639 }
640
641 /*********************************************************************
642  *              _nextafter (MSVCRT.@)
643  */
644 double _nextafter(double num, double next)
645 {
646   double retval;
647   if (!finite(num) || !finite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
648   retval = nextafter(num,next);
649   return retval;
650 }
651
652 /*********************************************************************
653  *              _ecvt (MSVCRT.@)
654  */
655 char *_ecvt( double number, int ndigits, int *decpt, int *sign )
656 {
657     MSVCRT_thread_data *data = msvcrt_get_thread_data();
658     char *dec;
659
660     if (!data->efcvt_buffer)
661         data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
662
663     snprintf(data->efcvt_buffer, 80, "%.*e", ndigits /* FIXME wrong */, number);
664     *sign = (number < 0);
665     dec = strchr(data->efcvt_buffer, '.');
666     *decpt = (dec) ? dec - data->efcvt_buffer : -1;
667     return data->efcvt_buffer;
668 }
669
670 /***********************************************************************
671  *              _fcvt  (MSVCRT.@)
672  */
673 char *_fcvt( double number, int ndigits, int *decpt, int *sign )
674 {
675     MSVCRT_thread_data *data = msvcrt_get_thread_data();
676     char *dec;
677
678     if (!data->efcvt_buffer)
679         data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
680
681     snprintf(data->efcvt_buffer, 80, "%.*e", ndigits, number);
682     *sign = (number < 0);
683     dec = strchr(data->efcvt_buffer, '.');
684     *decpt = (dec) ? dec - data->efcvt_buffer : -1;
685     return data->efcvt_buffer;
686 }
687
688 /***********************************************************************
689  *              _gcvt  (MSVCRT.@)
690  *
691  * FIXME: uses both E and F.
692  */
693 char *_gcvt( double number, int ndigit, char *buff )
694 {
695     sprintf(buff, "%.*E", ndigit, number);
696     return buff;
697 }
698
699 #include <stdlib.h> /* div_t, ldiv_t */
700
701 /*********************************************************************
702  *              div (MSVCRT.@)
703  * VERSION
704  *      [i386] Windows binary compatible - returns the struct in eax/edx.
705  */
706 #ifdef __i386__
707 unsigned __int64 MSVCRT_div(int num, int denom)
708 {
709   div_t dt = div(num,denom);
710   return ((unsigned __int64)dt.rem << 32) | (unsigned int)dt.quot;
711 }
712 #else
713 /*********************************************************************
714  *              div (MSVCRT.@)
715  * VERSION
716  *      [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
717  */
718 MSVCRT_div_t MSVCRT_div(int num, int denom)
719 {
720   div_t dt = div(num,denom);
721   MSVCRT_div_t     ret;
722   ret.quot = dt.quot;
723   ret.rem = dt.rem;
724
725   return ret;
726
727 }
728 #endif /* ifdef __i386__ */
729
730
731 /*********************************************************************
732  *              ldiv (MSVCRT.@)
733  * VERSION
734  *      [i386] Windows binary compatible - returns the struct in eax/edx.
735  */
736 #ifdef __i386__
737 unsigned __int64 MSVCRT_ldiv(long num, long denom)
738 {
739   ldiv_t ldt = ldiv(num,denom);
740   return ((unsigned __int64)ldt.rem << 32) | (unsigned long)ldt.quot;
741 }
742 #else
743 /*********************************************************************
744  *              ldiv (MSVCRT.@)
745  * VERSION
746  *      [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
747  */
748 MSVCRT_ldiv_t MSVCRT_ldiv(long num, long denom)
749 {
750   ldiv_t result = ldiv(num,denom);
751
752   MSVCRT_ldiv_t ret;
753   ret.quot = result.quot;
754   ret.rem = result.rem;
755
756   return ret;
757 }
758 #endif /* ifdef __i386__ */
759
760 /***********************************************************************
761  *              _adj_fdiv_m16i (MSVCRT.@)
762  * FIXME
763  *    This function is likely to have the wrong number of arguments.
764  *
765  * NOTE
766  *    I _think_ this function is intended to work around the Pentium
767  *    fdiv bug.
768  */
769 void _adj_fdiv_m16i(void)
770 {
771   TRACE("(): stub\n");
772 }
773
774 /***********************************************************************
775  *              _adj_fdiv_m32 (MSVCRT.@)
776  * FIXME
777  *    This function is likely to have the wrong number of arguments.
778  *
779  * NOTE
780  *    I _think_ this function is intended to work around the Pentium
781  *    fdiv bug.
782  */
783 void _adj_fdiv_m32(void)
784 {
785   TRACE("(): stub\n");
786 }
787
788 /***********************************************************************
789  *              _adj_fdiv_m32i (MSVCRT.@)
790  * FIXME
791  *    This function is likely to have the wrong number of arguments.
792  *
793  * NOTE
794  *    I _think_ this function is intended to work around the Pentium
795  *    fdiv bug.
796  */
797 void _adj_fdiv_m32i(void)
798 {
799   TRACE("(): stub\n");
800 }
801
802 /***********************************************************************
803  *              _adj_fdiv_m64 (MSVCRT.@)
804  * FIXME
805  *    This function is likely to have the wrong number of arguments.
806  *
807  * NOTE
808  *    I _think_ this function is intended to work around the Pentium
809  *    fdiv bug.
810  */
811 void _adj_fdiv_m64(void)
812 {
813   TRACE("(): stub\n");
814 }
815
816 /***********************************************************************
817  *              _adj_fdiv_r (MSVCRT.@)
818  * FIXME
819  *    This function is likely to have the wrong number of arguments.
820  *
821  * NOTE
822  *    I _think_ this function is intended to work around the Pentium
823  *    fdiv bug.
824  */
825 void _adj_fdiv_r(void)
826 {
827   TRACE("(): stub\n");
828 }
829
830 /***********************************************************************
831  *              _adj_fdivr_m16i (MSVCRT.@)
832  * FIXME
833  *    This function is likely to have the wrong number of arguments.
834  *
835  * NOTE
836  *    I _think_ this function is intended to work around the Pentium
837  *    fdiv bug.
838  */
839 void _adj_fdivr_m16i(void)
840 {
841   TRACE("(): stub\n");
842 }
843
844 /***********************************************************************
845  *              _adj_fdivr_m32 (MSVCRT.@)
846  * FIXME
847  *    This function is likely to have the wrong number of arguments.
848  *
849  * NOTE
850  *    I _think_ this function is intended to work around the Pentium
851  *    fdiv bug.
852  */
853 void _adj_fdivr_m32(void)
854 {
855   TRACE("(): stub\n");
856 }
857
858 /***********************************************************************
859  *              _adj_fdivr_m32i (MSVCRT.@)
860  * FIXME
861  *    This function is likely to have the wrong number of arguments.
862  *
863  * NOTE
864  *    I _think_ this function is intended to work around the Pentium
865  *    fdiv bug.
866  */
867 void _adj_fdivr_m32i(void)
868 {
869   TRACE("(): stub\n");
870 }
871
872 /***********************************************************************
873  *              _adj_fdivr_m64 (MSVCRT.@)
874  * FIXME
875  *    This function is likely to have the wrong number of arguments.
876  *
877  * NOTE
878  *    I _think_ this function is intended to work around the Pentium
879  *    fdiv bug.
880  */
881 void _adj_fdivr_m64(void)
882 {
883   TRACE("(): stub\n");
884 }
885
886 /***********************************************************************
887  *              _adj_fpatan (MSVCRT.@)
888  * FIXME
889  *    This function is likely to have the wrong number of arguments.
890  *
891  * NOTE
892  *    I _think_ this function is intended to work around the Pentium
893  *    fdiv bug.
894  */
895 void _adj_fpatan(void)
896 {
897   TRACE("(): stub\n");
898 }
899
900 /***********************************************************************
901  *              _adj_fprem (MSVCRT.@)
902  * FIXME
903  *    This function is likely to have the wrong number of arguments.
904  *
905  * NOTE
906  *    I _think_ this function is intended to work around the Pentium
907  *    fdiv bug.
908  */
909 void _adj_fprem(void)
910 {
911   TRACE("(): stub\n");
912 }
913
914 /***********************************************************************
915  *              _adj_fprem1 (MSVCRT.@)
916  * FIXME
917  *    This function is likely to have the wrong number of arguments.
918  *
919  * NOTE
920  *    I _think_ this function is intended to work around the Pentium
921  *    fdiv bug.
922  */
923 void _adj_fprem1(void)
924 {
925   TRACE("(): stub\n");
926 }
927
928 /***********************************************************************
929  *              _adj_fptan (MSVCRT.@)
930  * FIXME
931  *    This function is likely to have the wrong number of arguments.
932  *
933  * NOTE
934  *    I _think_ this function is intended to work around the Pentium
935  *    fdiv bug.
936  */
937 void _adj_fptan(void)
938 {
939   TRACE("(): stub\n");
940 }
941
942 /***********************************************************************
943  *              _adjust_fdiv (MSVCRT.@)
944  * FIXME
945  *    I _think_ this function should be a variable indicating whether
946  *    Pentium fdiv bug safe code should be used.
947  */
948 void _adjust_fdiv(void)
949 {
950   TRACE("(): stub\n");
951 }
952
953 /***********************************************************************
954  *              _safe_fdiv (MSVCRT.@)
955  * FIXME
956  *    This function is likely to have the wrong number of arguments.
957  *
958  * NOTE
959  *    I _think_ this function is intended to work around the Pentium
960  *    fdiv bug.
961  */
962 void _safe_fdiv(void)
963 {
964   TRACE("(): stub\n");
965 }
966
967 /***********************************************************************
968  *              _safe_fdivr (MSVCRT.@)
969  * FIXME
970  *    This function is likely to have the wrong number of arguments.
971  *
972  * NOTE
973  *    I _think_ this function is intended to work around the Pentium
974  *    fdiv bug.
975  */
976 void _safe_fdivr(void)
977 {
978   TRACE("(): stub\n");
979 }
980
981 /***********************************************************************
982  *              _safe_fprem (MSVCRT.@)
983  * FIXME
984  *    This function is likely to have the wrong number of arguments.
985  *
986  * NOTE
987  *    I _think_ this function is intended to work around the Pentium
988  *    fdiv bug.
989  */
990 void _safe_fprem(void)
991 {
992   TRACE("(): stub\n");
993 }
994
995 /***********************************************************************
996  *              _safe_fprem1 (MSVCRT.@)
997  *
998  * FIXME
999  *    This function is likely to have the wrong number of arguments.
1000  *
1001  * NOTE
1002  *    I _think_ this function is intended to work around the Pentium
1003  *    fdiv bug.
1004  */
1005 void _safe_fprem1(void)
1006 {
1007   TRACE("(): stub\n");
1008 }