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