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