user32/tests: Remove unneeded assignment (LLVM/Clang).
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
35
36 #ifndef HAVE_FINITE
37 #ifndef finite /* Could be a macro */
38 #ifdef isfinite
39 #define finite(x) isfinite(x)
40 #else
41 #define finite(x) (!isnan(x)) /* At least catch some cases */
42 #endif
43 #endif
44 #endif
45
46 #ifndef signbit
47 #define signbit(x) 0
48 #endif
49
50 typedef int (CDECL *MSVCRT_matherr_func)(struct MSVCRT__exception *);
51
52 static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
53
54 static BOOL sse2_supported;
55 static BOOL sse2_enabled;
56
57 void msvcrt_init_math(void)
58 {
59     sse2_supported = sse2_enabled = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE );
60 }
61
62 /*********************************************************************
63  *      _set_SSE2_enable (MSVCRT.@)
64  */
65 int CDECL MSVCRT__set_SSE2_enable(int flag)
66 {
67     sse2_enabled = flag && sse2_supported;
68     return sse2_enabled;
69 }
70
71 #ifdef __x86_64__
72
73 /*********************************************************************
74  *      MSVCRT_acosf (MSVCRT.@)
75  */
76 float CDECL MSVCRT_acosf( float x )
77 {
78   if (x < -1.0 || x > 1.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
79   /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
80    * asin() uses a similar construction. This is bad because as x gets nearer to
81    * 1 the error in the expression "1 - x^2" can get relatively large due to
82    * cancellation. The sqrt() makes things worse. A safer way to calculate
83    * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
84   return atan2f(sqrtf((1 - x) * (1 + x)), x);
85 }
86
87 /*********************************************************************
88  *      MSVCRT_asinf (MSVCRT.@)
89  */
90 float CDECL MSVCRT_asinf( float x )
91 {
92   if (x < -1.0 || x > 1.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
93   return atan2f(x, sqrtf((1 - x) * (1 + x)));
94 }
95
96 /*********************************************************************
97  *      MSVCRT_atanf (MSVCRT.@)
98  */
99 float CDECL MSVCRT_atanf( float x )
100 {
101   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
102   return atanf(x);
103 }
104
105 /*********************************************************************
106  *              MSVCRT_atan2f (MSVCRT.@)
107  */
108 float CDECL MSVCRT_atan2f( float x, float y )
109 {
110   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
111   return atan2f(x,y);
112 }
113
114 /*********************************************************************
115  *      MSVCRT_cosf (MSVCRT.@)
116  */
117 float CDECL MSVCRT_cosf( float x )
118 {
119   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
120   return cosf(x);
121 }
122
123 /*********************************************************************
124  *      MSVCRT_coshf (MSVCRT.@)
125  */
126 float CDECL MSVCRT_coshf( float x )
127 {
128   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
129   return coshf(x);
130 }
131
132 /*********************************************************************
133  *      MSVCRT_expf (MSVCRT.@)
134  */
135 float CDECL MSVCRT_expf( float x )
136 {
137   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
138   return expf(x);
139 }
140
141 /*********************************************************************
142  *      MSVCRT_fmodf (MSVCRT.@)
143  */
144 float CDECL MSVCRT_fmodf( float x, float y )
145 {
146   if (!finitef(x) || !finitef(y)) *MSVCRT__errno() = MSVCRT_EDOM;
147   return fmodf(x,y);
148 }
149
150 /*********************************************************************
151  *      MSVCRT_logf (MSVCRT.@)
152  */
153 float CDECL MSVCRT_logf( float x)
154 {
155   if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
156   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
157   return logf(x);
158 }
159
160 /*********************************************************************
161  *      MSVCRT_log10f (MSVCRT.@)
162  */
163 float CDECL MSVCRT_log10f( float x )
164 {
165   if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
166   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
167   return log10f(x);
168 }
169
170 /*********************************************************************
171  *      MSVCRT_powf (MSVCRT.@)
172  */
173 float CDECL MSVCRT_powf( float x, float y )
174 {
175   /* FIXME: If x < 0 and y is not integral, set EDOM */
176   float z = powf(x,y);
177   if (!finitef(z)) *MSVCRT__errno() = MSVCRT_EDOM;
178   return z;
179 }
180
181 /*********************************************************************
182  *      MSVCRT_sinf (MSVCRT.@)
183  */
184 float CDECL MSVCRT_sinf( float x )
185 {
186   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
187   return sinf(x);
188 }
189
190 /*********************************************************************
191  *      MSVCRT_sinhf (MSVCRT.@)
192  */
193 float CDECL MSVCRT_sinhf( float x )
194 {
195   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
196   return sinhf(x);
197 }
198
199 /*********************************************************************
200  *      MSVCRT_sqrtf (MSVCRT.@)
201  */
202 float CDECL MSVCRT_sqrtf( float x )
203 {
204   if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
205   return sqrtf(x);
206 }
207
208 /*********************************************************************
209  *      MSVCRT_tanf (MSVCRT.@)
210  */
211 float CDECL MSVCRT_tanf( float x )
212 {
213   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
214   return tanf(x);
215 }
216
217 /*********************************************************************
218  *      MSVCRT_tanhf (MSVCRT.@)
219  */
220 float CDECL MSVCRT_tanhf( float x )
221 {
222   if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
223   return tanhf(x);
224 }
225
226 /*********************************************************************
227  *      ceilf (MSVCRT.@)
228  */
229 float CDECL MSVCRT_ceilf( float x )
230 {
231   return ceilf(x);
232 }
233
234 /*********************************************************************
235  *      floorf (MSVCRT.@)
236  */
237 float CDECL MSVCRT_floorf( float x )
238 {
239   return floorf(x);
240 }
241
242 /*********************************************************************
243  *      frexpf (MSVCRT.@)
244  */
245 float CDECL MSVCRT_frexpf( float x, int *exp )
246 {
247   return frexpf( x, exp );
248 }
249
250 /*********************************************************************
251  *      _scalbf (MSVCRT.@)
252  */
253 float CDECL MSVCRT__scalbf(float num, MSVCRT_long power)
254 {
255   if (!finitef(num)) *MSVCRT__errno() = MSVCRT_EDOM;
256   return ldexpf(num, power);
257 }
258
259 /*********************************************************************
260  *      modff (MSVCRT.@)
261  */
262 double CDECL MSVCRT_modff( float x, float *iptr )
263 {
264   return modff( x, iptr );
265 }
266
267 #endif
268
269 /*********************************************************************
270  *              MSVCRT_acos (MSVCRT.@)
271  */
272 double CDECL MSVCRT_acos( double x )
273 {
274   if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
275   /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
276    * asin() uses a similar construction. This is bad because as x gets nearer to
277    * 1 the error in the expression "1 - x^2" can get relatively large due to
278    * cancellation. The sqrt() makes things worse. A safer way to calculate
279    * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
280   return atan2(sqrt((1 - x) * (1 + x)), x);
281 }
282
283 /*********************************************************************
284  *              MSVCRT_asin (MSVCRT.@)
285  */
286 double CDECL MSVCRT_asin( double x )
287 {
288   if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
289   return atan2(x, sqrt((1 - x) * (1 + x)));
290 }
291
292 /*********************************************************************
293  *              MSVCRT_atan (MSVCRT.@)
294  */
295 double CDECL MSVCRT_atan( double x )
296 {
297   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
298   return atan(x);
299 }
300
301 /*********************************************************************
302  *              MSVCRT_atan2 (MSVCRT.@)
303  */
304 double CDECL MSVCRT_atan2( double x, double y )
305 {
306   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
307   return atan2(x,y);
308 }
309
310 /*********************************************************************
311  *              MSVCRT_cos (MSVCRT.@)
312  */
313 double CDECL MSVCRT_cos( double x )
314 {
315   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
316   return cos(x);
317 }
318
319 /*********************************************************************
320  *              MSVCRT_cosh (MSVCRT.@)
321  */
322 double CDECL MSVCRT_cosh( double x )
323 {
324   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
325   return cosh(x);
326 }
327
328 /*********************************************************************
329  *              MSVCRT_exp (MSVCRT.@)
330  */
331 double CDECL MSVCRT_exp( double x )
332 {
333   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
334   return exp(x);
335 }
336
337 /*********************************************************************
338  *              MSVCRT_fmod (MSVCRT.@)
339  */
340 double CDECL MSVCRT_fmod( double x, double y )
341 {
342   if (!finite(x) || !finite(y)) *MSVCRT__errno() = MSVCRT_EDOM;
343   return fmod(x,y);
344 }
345
346 /*********************************************************************
347  *              MSVCRT_log (MSVCRT.@)
348  */
349 double CDECL MSVCRT_log( double x)
350 {
351   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
352   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
353   return log(x);
354 }
355
356 /*********************************************************************
357  *              MSVCRT_log10 (MSVCRT.@)
358  */
359 double CDECL MSVCRT_log10( double x )
360 {
361   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
362   if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
363   return log10(x);
364 }
365
366 /*********************************************************************
367  *              MSVCRT_pow (MSVCRT.@)
368  */
369 double CDECL MSVCRT_pow( double x, double y )
370 {
371   /* FIXME: If x < 0 and y is not integral, set EDOM */
372   double z = pow(x,y);
373   if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
374   return z;
375 }
376
377 /*********************************************************************
378  *              MSVCRT_sin (MSVCRT.@)
379  */
380 double CDECL MSVCRT_sin( double x )
381 {
382   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
383   return sin(x);
384 }
385
386 /*********************************************************************
387  *              MSVCRT_sinh (MSVCRT.@)
388  */
389 double CDECL MSVCRT_sinh( double x )
390 {
391   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
392   return sinh(x);
393 }
394
395 /*********************************************************************
396  *              MSVCRT_sqrt (MSVCRT.@)
397  */
398 double CDECL MSVCRT_sqrt( double x )
399 {
400   if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
401   return sqrt(x);
402 }
403
404 /*********************************************************************
405  *              MSVCRT_tan (MSVCRT.@)
406  */
407 double CDECL MSVCRT_tan( double x )
408 {
409   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
410   return tan(x);
411 }
412
413 /*********************************************************************
414  *              MSVCRT_tanh (MSVCRT.@)
415  */
416 double CDECL MSVCRT_tanh( double x )
417 {
418   if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
419   return tanh(x);
420 }
421
422
423 #if defined(__GNUC__) && defined(__i386__)
424
425 #define FPU_DOUBLE(var) double var; \
426   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
427 #define FPU_DOUBLES(var1,var2) double var1,var2; \
428   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
429   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
430
431 /*********************************************************************
432  *              _CIacos (MSVCRT.@)
433  */
434 double CDECL _CIacos(void)
435 {
436   FPU_DOUBLE(x);
437   return MSVCRT_acos(x);
438 }
439
440 /*********************************************************************
441  *              _CIasin (MSVCRT.@)
442  */
443 double CDECL _CIasin(void)
444 {
445   FPU_DOUBLE(x);
446   return MSVCRT_asin(x);
447 }
448
449 /*********************************************************************
450  *              _CIatan (MSVCRT.@)
451  */
452 double CDECL _CIatan(void)
453 {
454   FPU_DOUBLE(x);
455   return MSVCRT_atan(x);
456 }
457
458 /*********************************************************************
459  *              _CIatan2 (MSVCRT.@)
460  */
461 double CDECL _CIatan2(void)
462 {
463   FPU_DOUBLES(x,y);
464   return MSVCRT_atan2(x,y);
465 }
466
467 /*********************************************************************
468  *              _CIcos (MSVCRT.@)
469  */
470 double CDECL _CIcos(void)
471 {
472   FPU_DOUBLE(x);
473   return MSVCRT_cos(x);
474 }
475
476 /*********************************************************************
477  *              _CIcosh (MSVCRT.@)
478  */
479 double CDECL _CIcosh(void)
480 {
481   FPU_DOUBLE(x);
482   return MSVCRT_cosh(x);
483 }
484
485 /*********************************************************************
486  *              _CIexp (MSVCRT.@)
487  */
488 double CDECL _CIexp(void)
489 {
490   FPU_DOUBLE(x);
491   return MSVCRT_exp(x);
492 }
493
494 /*********************************************************************
495  *              _CIfmod (MSVCRT.@)
496  */
497 double CDECL _CIfmod(void)
498 {
499   FPU_DOUBLES(x,y);
500   return MSVCRT_fmod(x,y);
501 }
502
503 /*********************************************************************
504  *              _CIlog (MSVCRT.@)
505  */
506 double CDECL _CIlog(void)
507 {
508   FPU_DOUBLE(x);
509   return MSVCRT_log(x);
510 }
511
512 /*********************************************************************
513  *              _CIlog10 (MSVCRT.@)
514  */
515 double CDECL _CIlog10(void)
516 {
517   FPU_DOUBLE(x);
518   return MSVCRT_log10(x);
519 }
520
521 /*********************************************************************
522  *              _CIpow (MSVCRT.@)
523  */
524 double CDECL _CIpow(void)
525 {
526   FPU_DOUBLES(x,y);
527   return MSVCRT_pow(x,y);
528 }
529
530 /*********************************************************************
531  *              _CIsin (MSVCRT.@)
532  */
533 double CDECL _CIsin(void)
534 {
535   FPU_DOUBLE(x);
536   return MSVCRT_sin(x);
537 }
538
539 /*********************************************************************
540  *              _CIsinh (MSVCRT.@)
541  */
542 double CDECL _CIsinh(void)
543 {
544   FPU_DOUBLE(x);
545   return MSVCRT_sinh(x);
546 }
547
548 /*********************************************************************
549  *              _CIsqrt (MSVCRT.@)
550  */
551 double CDECL _CIsqrt(void)
552 {
553   FPU_DOUBLE(x);
554   return MSVCRT_sqrt(x);
555 }
556
557 /*********************************************************************
558  *              _CItan (MSVCRT.@)
559  */
560 double CDECL _CItan(void)
561 {
562   FPU_DOUBLE(x);
563   return MSVCRT_tan(x);
564 }
565
566 /*********************************************************************
567  *              _CItanh (MSVCRT.@)
568  */
569 double CDECL _CItanh(void)
570 {
571   FPU_DOUBLE(x);
572   return MSVCRT_tanh(x);
573 }
574
575 #endif /* defined(__GNUC__) && defined(__i386__) */
576
577 /*********************************************************************
578  *              _fpclass (MSVCRT.@)
579  */
580 int CDECL _fpclass(double num)
581 {
582 #if defined(HAVE_FPCLASS) || defined(fpclass)
583   switch (fpclass( num ))
584   {
585 #ifdef FP_SNAN
586   case FP_SNAN:  return MSVCRT__FPCLASS_SNAN;
587 #endif
588 #ifdef FP_QNAN
589   case FP_QNAN:  return MSVCRT__FPCLASS_QNAN;
590 #endif
591 #ifdef FP_NINF
592   case FP_NINF:  return MSVCRT__FPCLASS_NINF;
593 #endif
594 #ifdef FP_PINF
595   case FP_PINF:  return MSVCRT__FPCLASS_PINF;
596 #endif
597 #ifdef FP_NDENORM
598   case FP_NDENORM: return MSVCRT__FPCLASS_ND;
599 #endif
600 #ifdef FP_PDENORM
601   case FP_PDENORM: return MSVCRT__FPCLASS_PD;
602 #endif
603 #ifdef FP_NZERO
604   case FP_NZERO: return MSVCRT__FPCLASS_NZ;
605 #endif
606 #ifdef FP_PZERO
607   case FP_PZERO: return MSVCRT__FPCLASS_PZ;
608 #endif
609 #ifdef FP_NNORM
610   case FP_NNORM: return MSVCRT__FPCLASS_NN;
611 #endif
612 #ifdef FP_PNORM
613   case FP_PNORM: return MSVCRT__FPCLASS_PN;
614 #endif
615   default: return MSVCRT__FPCLASS_PN;
616   }
617 #elif defined (fpclassify)
618   switch (fpclassify( num ))
619   {
620   case FP_NAN: return MSVCRT__FPCLASS_QNAN;
621   case FP_INFINITE: return signbit(num) ? MSVCRT__FPCLASS_NINF : MSVCRT__FPCLASS_PINF;
622   case FP_SUBNORMAL: return signbit(num) ?MSVCRT__FPCLASS_ND : MSVCRT__FPCLASS_PD;
623   case FP_ZERO: return signbit(num) ? MSVCRT__FPCLASS_NZ : MSVCRT__FPCLASS_PZ;
624   }
625   return signbit(num) ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN;
626 #else
627   if (!finite(num))
628     return MSVCRT__FPCLASS_QNAN;
629   return num == 0.0 ? MSVCRT__FPCLASS_PZ : (num < 0 ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN);
630 #endif
631 }
632
633 /*********************************************************************
634  *              _rotl (MSVCRT.@)
635  */
636 unsigned int CDECL _rotl(unsigned int num, int shift)
637 {
638   shift &= 31;
639   return (num << shift) | (num >> (32-shift));
640 }
641
642 /*********************************************************************
643  *              _logb (MSVCRT.@)
644  */
645 double CDECL _logb(double num)
646 {
647   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
648   return logb(num);
649 }
650
651 /*********************************************************************
652  *              _lrotl (MSVCRT.@)
653  */
654 MSVCRT_ulong CDECL MSVCRT__lrotl(MSVCRT_ulong num, int shift)
655 {
656   shift &= 0x1f;
657   return (num << shift) | (num >> (32-shift));
658 }
659
660 /*********************************************************************
661  *              _lrotr (MSVCRT.@)
662  */
663 MSVCRT_ulong CDECL MSVCRT__lrotr(MSVCRT_ulong num, int shift)
664 {
665   shift &= 0x1f;
666   return (num >> shift) | (num << (32-shift));
667 }
668
669 /*********************************************************************
670  *              _rotr (MSVCRT.@)
671  */
672 unsigned int CDECL _rotr(unsigned int num, int shift)
673 {
674     shift &= 0x1f;
675     return (num >> shift) | (num << (32-shift));
676 }
677
678 /*********************************************************************
679  *              _scalb (MSVCRT.@)
680  */
681 double CDECL MSVCRT__scalb(double num, MSVCRT_long power)
682 {
683   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
684   return ldexp(num, power);
685 }
686
687 /*********************************************************************
688  *              _hypot (MSVCRT.@)
689  */
690 double CDECL _hypot(double x, double y)
691 {
692   /* FIXME: errno handling */
693   return hypot( x, y );
694 }
695
696 /*********************************************************************
697  *      _hypotf (MSVCRT.@)
698  */
699 float CDECL _hypotf(float x, float y)
700 {
701   /* FIXME: errno handling */
702   return hypotf( x, y );
703 }
704
705 /*********************************************************************
706  *              ceil (MSVCRT.@)
707  */
708 double CDECL MSVCRT_ceil( double x )
709 {
710   return ceil(x);
711 }
712
713 /*********************************************************************
714  *              floor (MSVCRT.@)
715  */
716 double CDECL MSVCRT_floor( double x )
717 {
718   return floor(x);
719 }
720
721 /*********************************************************************
722  *              fabs (MSVCRT.@)
723  */
724 double CDECL MSVCRT_fabs( double x )
725 {
726   return fabs(x);
727 }
728
729 /*********************************************************************
730  *              frexp (MSVCRT.@)
731  */
732 double CDECL MSVCRT_frexp( double x, int *exp )
733 {
734   return frexp( x, exp );
735 }
736
737 /*********************************************************************
738  *              modf (MSVCRT.@)
739  */
740 double CDECL MSVCRT_modf( double x, double *iptr )
741 {
742   return modf( x, iptr );
743 }
744
745 /*********************************************************************
746  *              _matherr (MSVCRT.@)
747  */
748 int CDECL MSVCRT__matherr(struct MSVCRT__exception *e)
749 {
750   if (e)
751     TRACE("(%p = %d, %s, %g %g %g)\n",e, e->type, e->name, e->arg1, e->arg2,
752           e->retval);
753   else
754     TRACE("(null)\n");
755   if (MSVCRT_default_matherr_func)
756     return MSVCRT_default_matherr_func(e);
757   ERR(":Unhandled math error!\n");
758   return 0;
759 }
760
761 /*********************************************************************
762  *              __setusermatherr (MSVCRT.@)
763  */
764 void CDECL MSVCRT___setusermatherr(MSVCRT_matherr_func func)
765 {
766   MSVCRT_default_matherr_func = func;
767   TRACE(":new matherr handler %p\n", func);
768 }
769
770 /**********************************************************************
771  *              _statusfp2 (MSVCRT.@)
772  *
773  * Not exported by native msvcrt, added in msvcr80.
774  */
775 #if defined(__i386__) || defined(__x86_64__)
776 void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
777 {
778 #ifdef __GNUC__
779     unsigned int flags;
780     unsigned long fpword;
781
782     if (x86_sw)
783     {
784         __asm__ __volatile__( "fstsw %0" : "=m" (fpword) );
785         flags = 0;
786         if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
787         if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
788         if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
789         if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
790         if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
791         if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
792         *x86_sw = flags;
793     }
794
795     if (!sse2_sw) return;
796
797     if (sse2_supported)
798     {
799         __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
800         flags = 0;
801         if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
802         if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
803         if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
804         if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
805         if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
806         if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
807         *sse2_sw = flags;
808     }
809     else *sse2_sw = 0;
810 #else
811     FIXME( "not implemented\n" );
812 #endif
813 }
814 #endif
815
816 /**********************************************************************
817  *              _statusfp (MSVCRT.@)
818  */
819 unsigned int CDECL _statusfp(void)
820 {
821 #if defined(__i386__) || defined(__x86_64__)
822     unsigned int x86_sw, sse2_sw;
823
824     _statusfp2( &x86_sw, &sse2_sw );
825     /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
826     return x86_sw | sse2_sw;
827 #else
828     FIXME( "not implemented\n" );
829     return 0;
830 #endif
831 }
832
833 /*********************************************************************
834  *              _clearfp (MSVCRT.@)
835  */
836 unsigned int CDECL _clearfp(void)
837 {
838     unsigned int flags = 0;
839 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
840     unsigned long fpword;
841
842     __asm__ __volatile__( "fnstsw %0; fnclex" : "=m" (fpword) );
843     if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
844     if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
845     if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
846     if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
847     if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
848     if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
849
850     if (sse2_supported)
851     {
852         __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
853         if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
854         if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
855         if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
856         if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
857         if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
858         if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
859         fpword &= ~0x3f;
860         __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
861     }
862 #else
863     FIXME( "not implemented\n" );
864 #endif
865     return flags;
866 }
867
868 /*********************************************************************
869  *              __fpecode (MSVCRT.@)
870  */
871 int * CDECL __fpecode(void)
872 {
873     return &msvcrt_get_thread_data()->fpecode;
874 }
875
876 /*********************************************************************
877  *              ldexp (MSVCRT.@)
878  */
879 double CDECL MSVCRT_ldexp(double num, MSVCRT_long exp)
880 {
881   double z = ldexp(num,exp);
882
883   if (!finite(z))
884     *MSVCRT__errno() = MSVCRT_ERANGE;
885   else if (z == 0 && signbit(z))
886     z = 0.0; /* Convert -0 -> +0 */
887   return z;
888 }
889
890 /*********************************************************************
891  *              _cabs (MSVCRT.@)
892  */
893 double CDECL MSVCRT__cabs(struct MSVCRT__complex num)
894 {
895   return sqrt(num.x * num.x + num.y * num.y);
896 }
897
898 /*********************************************************************
899  *              _chgsign (MSVCRT.@)
900  */
901 double CDECL _chgsign(double num)
902 {
903   /* FIXME: +-infinity,Nan not tested */
904   return -num;
905 }
906
907 /*********************************************************************
908  *              __control87_2 (MSVCRT.@)
909  *
910  * Not exported by native msvcrt, added in msvcr80.
911  */
912 #if defined(__i386__) || defined(__x86_64__)
913 int CDECL __control87_2( unsigned int newval, unsigned int mask,
914                          unsigned int *x86_cw, unsigned int *sse2_cw )
915 {
916 #ifdef __GNUC__
917     unsigned long fpword;
918     unsigned int flags;
919
920     if (x86_cw)
921     {
922         __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
923
924         /* Convert into mask constants */
925         flags = 0;
926         if (fpword & 0x1)  flags |= MSVCRT__EM_INVALID;
927         if (fpword & 0x2)  flags |= MSVCRT__EM_DENORMAL;
928         if (fpword & 0x4)  flags |= MSVCRT__EM_ZERODIVIDE;
929         if (fpword & 0x8)  flags |= MSVCRT__EM_OVERFLOW;
930         if (fpword & 0x10) flags |= MSVCRT__EM_UNDERFLOW;
931         if (fpword & 0x20) flags |= MSVCRT__EM_INEXACT;
932         switch (fpword & 0xc00)
933         {
934         case 0xc00: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
935         case 0x800: flags |= MSVCRT__RC_UP; break;
936         case 0x400: flags |= MSVCRT__RC_DOWN; break;
937         }
938         switch (fpword & 0x300)
939         {
940         case 0x0:   flags |= MSVCRT__PC_24; break;
941         case 0x200: flags |= MSVCRT__PC_53; break;
942         case 0x300: flags |= MSVCRT__PC_64; break;
943         }
944         if (fpword & 0x1000) flags |= MSVCRT__IC_AFFINE;
945
946         TRACE( "x86 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
947         if (mask)
948         {
949             flags = (flags & ~mask) | (newval & mask);
950
951             /* Convert (masked) value back to fp word */
952             fpword = 0;
953             if (flags & MSVCRT__EM_INVALID)    fpword |= 0x1;
954             if (flags & MSVCRT__EM_DENORMAL)   fpword |= 0x2;
955             if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x4;
956             if (flags & MSVCRT__EM_OVERFLOW)   fpword |= 0x8;
957             if (flags & MSVCRT__EM_UNDERFLOW)  fpword |= 0x10;
958             if (flags & MSVCRT__EM_INEXACT)    fpword |= 0x20;
959             switch (flags & MSVCRT__MCW_RC)
960             {
961             case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0xc00; break;
962             case MSVCRT__RC_UP:                 fpword |= 0x800; break;
963             case MSVCRT__RC_DOWN:               fpword |= 0x400; break;
964             }
965             switch (flags & MSVCRT__MCW_PC)
966             {
967             case MSVCRT__PC_64: fpword |= 0x300; break;
968             case MSVCRT__PC_53: fpword |= 0x200; break;
969             case MSVCRT__PC_24: fpword |= 0x0; break;
970             }
971             if (flags & MSVCRT__IC_AFFINE) fpword |= 0x1000;
972
973             __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
974         }
975         *x86_cw = flags;
976     }
977
978     if (!sse2_cw) return 1;
979
980     if (sse2_supported)
981     {
982         __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
983
984         /* Convert into mask constants */
985         flags = 0;
986         if (fpword & 0x80)   flags |= MSVCRT__EM_INVALID;
987         if (fpword & 0x100)  flags |= MSVCRT__EM_DENORMAL;
988         if (fpword & 0x200)  flags |= MSVCRT__EM_ZERODIVIDE;
989         if (fpword & 0x400)  flags |= MSVCRT__EM_OVERFLOW;
990         if (fpword & 0x800)  flags |= MSVCRT__EM_UNDERFLOW;
991         if (fpword & 0x1000) flags |= MSVCRT__EM_INEXACT;
992         switch (fpword & 0x6000)
993         {
994         case 0x6000: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
995         case 0x4000: flags |= MSVCRT__RC_UP; break;
996         case 0x2000: flags |= MSVCRT__RC_DOWN; break;
997         }
998         switch (fpword & 0x8040)
999         {
1000         case 0x0040: flags |= MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
1001         case 0x8000: flags |= MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
1002         case 0x8040: flags |= MSVCRT__DN_FLUSH; break;
1003         }
1004
1005         TRACE( "sse2 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
1006         if (mask)
1007         {
1008             flags = (flags & ~mask) | (newval & mask);
1009
1010             /* Convert (masked) value back to fp word */
1011             fpword = 0;
1012             if (flags & MSVCRT__EM_INVALID)    fpword |= 0x80;
1013             if (flags & MSVCRT__EM_DENORMAL)   fpword |= 0x100;
1014             if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
1015             if (flags & MSVCRT__EM_OVERFLOW)   fpword |= 0x400;
1016             if (flags & MSVCRT__EM_UNDERFLOW)  fpword |= 0x800;
1017             if (flags & MSVCRT__EM_INEXACT)    fpword |= 0x1000;
1018             switch (flags & MSVCRT__MCW_RC)
1019             {
1020             case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0x6000; break;
1021             case MSVCRT__RC_UP:                 fpword |= 0x4000; break;
1022             case MSVCRT__RC_DOWN:               fpword |= 0x2000; break;
1023             }
1024             switch (flags & MSVCRT__MCW_DN)
1025             {
1026             case MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
1027             case MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
1028             case MSVCRT__DN_FLUSH:                       fpword |= 0x8040; break;
1029             }
1030             __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
1031         }
1032         *sse2_cw = flags;
1033     }
1034     else *sse2_cw = 0;
1035
1036     return 1;
1037 #else
1038     FIXME( "not implemented\n" );
1039     return 0;
1040 #endif
1041 }
1042 #endif
1043
1044 /*********************************************************************
1045  *              _control87 (MSVCRT.@)
1046  */
1047 unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
1048 {
1049 #if defined(__i386__) || defined(__x86_64__)
1050     unsigned int x86_cw, sse2_cw;
1051
1052     __control87_2( newval, mask, &x86_cw, &sse2_cw );
1053
1054     if ((x86_cw ^ sse2_cw) & (MSVCRT__MCW_EM | MSVCRT__MCW_RC)) x86_cw |= MSVCRT__EM_AMBIGUOUS;
1055     return x86_cw;
1056 #else
1057     FIXME( "not implemented\n" );
1058     return 0;
1059 #endif
1060 }
1061
1062 /*********************************************************************
1063  *              _controlfp (MSVCRT.@)
1064  */
1065 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
1066 {
1067   return _control87( newval, mask & ~MSVCRT__EM_DENORMAL );
1068 }
1069
1070 /*********************************************************************
1071  *              _set_controlfp (MSVCRT.@)
1072  */
1073 void CDECL _set_controlfp( unsigned int newval, unsigned int mask )
1074 {
1075     _controlfp( newval, mask );
1076 }
1077
1078 /*********************************************************************
1079  *              _controlfp_s (MSVCRT.@)
1080  */
1081 int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
1082 {
1083     static const unsigned int all_flags = (MSVCRT__MCW_EM | MSVCRT__MCW_IC | MSVCRT__MCW_RC |
1084                                            MSVCRT__MCW_PC | MSVCRT__MCW_DN);
1085     unsigned int val;
1086
1087     if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
1088     {
1089         if (cur) *cur = _controlfp( 0, 0 );  /* retrieve it anyway */
1090         *MSVCRT__errno() = MSVCRT_EINVAL;
1091         return MSVCRT_EINVAL;
1092     }
1093     val = _controlfp( newval, mask );
1094     if (cur) *cur = val;
1095     return 0;
1096 }
1097
1098 /*********************************************************************
1099  *              _copysign (MSVCRT.@)
1100  */
1101 double CDECL _copysign(double num, double sign)
1102 {
1103   /* FIXME: Behaviour for Nan/Inf? */
1104   if (sign < 0.0)
1105     return num < 0.0 ? num : -num;
1106   return num < 0.0 ? -num : num;
1107 }
1108
1109 /*********************************************************************
1110  *              _finite (MSVCRT.@)
1111  */
1112 int CDECL _finite(double num)
1113 {
1114   return (finite(num)?1:0); /* See comment for _isnan() */
1115 }
1116
1117 /*********************************************************************
1118  *              _fpreset (MSVCRT.@)
1119  */
1120 void CDECL _fpreset(void)
1121 {
1122 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1123     const unsigned int x86_cw = 0x27f;
1124     __asm__ __volatile__( "fninit; fldcw %0" : : "m" (x86_cw) );
1125     if (sse2_supported)
1126     {
1127         const unsigned long sse2_cw = 0x1f80;
1128         __asm__ __volatile__( "ldmxcsr %0" : : "m" (sse2_cw) );
1129     }
1130 #else
1131     FIXME( "not implemented\n" );
1132 #endif
1133 }
1134
1135 /*********************************************************************
1136  *              _isnan (MSVCRT.@)
1137  */
1138 INT CDECL _isnan(double num)
1139 {
1140   /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
1141    * Do the same, as the result may be used in calculations
1142    */
1143   return isnan(num) ? 1 : 0;
1144 }
1145
1146 /*********************************************************************
1147  *              _j0 (MSVCRT.@)
1148  */
1149 double CDECL _j0(double num)
1150 {
1151   /* FIXME: errno handling */
1152   return j0(num);
1153 }
1154
1155 /*********************************************************************
1156  *              _j1 (MSVCRT.@)
1157  */
1158 double CDECL _j1(double num)
1159 {
1160   /* FIXME: errno handling */
1161   return j1(num);
1162 }
1163
1164 /*********************************************************************
1165  *              jn (MSVCRT.@)
1166  */
1167 double CDECL _jn(int n, double num)
1168 {
1169   /* FIXME: errno handling */
1170   return jn(n, num);
1171 }
1172
1173 /*********************************************************************
1174  *              _y0 (MSVCRT.@)
1175  */
1176 double CDECL _y0(double num)
1177 {
1178   double retval;
1179   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1180   retval  = y0(num);
1181   if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
1182   {
1183     *MSVCRT__errno() = MSVCRT_EDOM;
1184     retval = sqrt(-1);
1185   }
1186   return retval;
1187 }
1188
1189 /*********************************************************************
1190  *              _y1 (MSVCRT.@)
1191  */
1192 double CDECL _y1(double num)
1193 {
1194   double retval;
1195   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1196   retval  = y1(num);
1197   if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
1198   {
1199     *MSVCRT__errno() = MSVCRT_EDOM;
1200     retval = sqrt(-1);
1201   }
1202   return retval;
1203 }
1204
1205 /*********************************************************************
1206  *              _yn (MSVCRT.@)
1207  */
1208 double CDECL _yn(int order, double num)
1209 {
1210   double retval;
1211   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1212   retval  = yn(order,num);
1213   if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
1214   {
1215     *MSVCRT__errno() = MSVCRT_EDOM;
1216     retval = sqrt(-1);
1217   }
1218   return retval;
1219 }
1220
1221 /*********************************************************************
1222  *              _nextafter (MSVCRT.@)
1223  */
1224 double CDECL _nextafter(double num, double next)
1225 {
1226   double retval;
1227   if (!finite(num) || !finite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
1228   retval = nextafter(num,next);
1229   return retval;
1230 }
1231
1232 /*********************************************************************
1233  *              _ecvt (MSVCRT.@)
1234  */
1235 char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign )
1236 {
1237     int prec, len;
1238     thread_data_t *data = msvcrt_get_thread_data();
1239     /* FIXME: check better for overflow (native supports over 300 chars's) */
1240     ndigits = min( ndigits, 80 - 7); /* 7 : space for dec point, 1 for "e",
1241                                       * 4 for exponent and one for
1242                                       * terminating '\0' */
1243     if (!data->efcvt_buffer)
1244         data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
1245
1246     if( number < 0) {
1247         *sign = TRUE;
1248         number = -number;
1249     } else
1250         *sign = FALSE;
1251     /* handle cases with zero ndigits or less */
1252     prec = ndigits;
1253     if( prec < 1) prec = 2;
1254     len = snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number);
1255     /* take the decimal "point away */
1256     if( prec != 1)
1257         memmove( data->efcvt_buffer + 1, data->efcvt_buffer + 2, len - 1 );
1258     /* take the exponential "e" out */
1259     data->efcvt_buffer[ prec] = '\0';
1260     /* read the exponent */
1261     sscanf( data->efcvt_buffer + prec + 1, "%d", decpt);
1262     (*decpt)++;
1263     /* adjust for some border cases */
1264     if( data->efcvt_buffer[0] == '0')/* value is zero */
1265         *decpt = 0;
1266     /* handle cases with zero ndigits or less */
1267     if( ndigits < 1){
1268         if( data->efcvt_buffer[ 0] >= '5')
1269             (*decpt)++;
1270         data->efcvt_buffer[ 0] = '\0';
1271     }
1272     TRACE("out=\"%s\"\n",data->efcvt_buffer);
1273     return data->efcvt_buffer;
1274 }
1275
1276 /*********************************************************************
1277  *              _ecvt_s (MSVCRT.@)
1278  */
1279 int CDECL _ecvt_s( char *buffer, MSVCRT_size_t length, double number, int ndigits, int *decpt, int *sign )
1280 {
1281     int prec, len;
1282     char *result;
1283     const char infret[] = "1#INF";
1284
1285     if(!MSVCRT_CHECK_PMT(buffer != NULL) || !MSVCRT_CHECK_PMT(decpt != NULL) || !MSVCRT_CHECK_PMT(sign != NULL))
1286     {
1287         *MSVCRT__errno() = MSVCRT_EINVAL;
1288         return MSVCRT_EINVAL;
1289     }
1290     if(!MSVCRT_CHECK_PMT(length > 2) || !MSVCRT_CHECK_PMT(ndigits < (int)length - 1))
1291     {
1292         *MSVCRT__errno() = MSVCRT_ERANGE;
1293         return MSVCRT_ERANGE;
1294     }
1295
1296     /* special case - inf */
1297     if(number == HUGE_VAL || number == -HUGE_VAL)
1298     {
1299         memset(buffer, '0', ndigits);
1300         memcpy(buffer, infret, min(ndigits, sizeof(infret) - 1 ) );
1301         buffer[ndigits] = '\0';
1302         (*decpt) = 1;
1303         if(number == -HUGE_VAL)
1304             (*sign) = 1;
1305         else
1306             (*sign) = 0;
1307         return 0;
1308     }
1309     result = (char*)MSVCRT_malloc(max(ndigits + 7, 7));
1310
1311     if( number < 0) {
1312         *sign = TRUE;
1313         number = -number;
1314     } else
1315         *sign = FALSE;
1316     /* handle cases with zero ndigits or less */
1317     prec = ndigits;
1318     if( prec < 1) prec = 2;
1319     len = snprintf(result, 80, "%.*le", prec - 1, number);
1320     /* take the decimal "point away */
1321     if( prec != 1)
1322         memmove( result + 1, result + 2, len - 1 );
1323     /* take the exponential "e" out */
1324     result[ prec] = '\0';
1325     /* read the exponent */
1326     sscanf( result + prec + 1, "%d", decpt);
1327     (*decpt)++;
1328     /* adjust for some border cases */
1329     if( result[0] == '0')/* value is zero */
1330         *decpt = 0;
1331     /* handle cases with zero ndigits or less */
1332     if( ndigits < 1){
1333         if( result[ 0] >= '5')
1334             (*decpt)++;
1335         result[ 0] = '\0';
1336     }
1337     memcpy( buffer, result, max(ndigits + 1, 1) );
1338     MSVCRT_free( result );
1339     return 0;
1340 }
1341
1342 /***********************************************************************
1343  *              _fcvt  (MSVCRT.@)
1344  */
1345 char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
1346 {
1347     thread_data_t *data = msvcrt_get_thread_data();
1348     int stop, dec1, dec2;
1349     char *ptr1, *ptr2, *first;
1350     char buf[80]; /* ought to be enough */
1351
1352     if (!data->efcvt_buffer)
1353         data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
1354
1355     if (number < 0)
1356     {
1357         *sign = 1;
1358         number = -number;
1359     } else *sign = 0;
1360
1361     snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1362     ptr1 = buf;
1363     ptr2 = data->efcvt_buffer;
1364     first = NULL;
1365     dec1 = 0;
1366     dec2 = 0;
1367
1368     /* For numbers below the requested resolution, work out where
1369        the decimal point will be rather than finding it in the string */
1370     if (number < 1.0 && number > 0.0) {
1371         dec2 = log10(number + 1e-10);
1372         if (-dec2 <= ndigits) dec2 = 0;
1373     }
1374
1375     /* If requested digits is zero or less, we will need to truncate
1376      * the returned string */
1377     if (ndigits < 1) {
1378         stop = strlen(buf) + ndigits;
1379     } else {
1380         stop = strlen(buf);
1381     }
1382
1383     while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1384     while (*ptr1 != '\0' && *ptr1 != '.') {
1385         if (!first) first = ptr2;
1386         if ((ptr1 - buf) < stop) {
1387             *ptr2++ = *ptr1++;
1388         } else {
1389             ptr1++;
1390         }
1391         dec1++;
1392     }
1393
1394     if (ndigits > 0) {
1395         ptr1++;
1396         if (!first) {
1397             while (*ptr1 == '0') { /* Process leading zeroes */
1398                 *ptr2++ = *ptr1++;
1399                 dec1--;
1400             }
1401         }
1402         while (*ptr1 != '\0') {
1403             if (!first) first = ptr2;
1404             *ptr2++ = *ptr1++;
1405         }
1406     }
1407
1408     *ptr2 = '\0';
1409
1410     /* We never found a non-zero digit, then our number is either
1411      * smaller than the requested precision, or 0.0 */
1412     if (!first) {
1413         if (number > 0.0) {
1414             first = ptr2;
1415         } else {
1416             first = data->efcvt_buffer;
1417             dec1 = 0;
1418         }
1419     }
1420
1421     *decpt = dec2 ? dec2 : dec1;
1422     return first;
1423 }
1424
1425 /***********************************************************************
1426  *              _fcvt_s  (MSVCRT.@)
1427  */
1428 int CDECL _fcvt_s(char* outbuffer, MSVCRT_size_t size, double number, int ndigits, int *decpt, int *sign)
1429 {
1430     int stop, dec1, dec2;
1431     char *ptr1, *ptr2, *first;
1432     char buf[80]; /* ought to be enough */
1433
1434     if (!outbuffer || !decpt || !sign || size == 0)
1435     {
1436         *MSVCRT__errno() = MSVCRT_EINVAL;
1437         return MSVCRT_EINVAL;
1438     }
1439
1440     if (number < 0)
1441     {
1442         *sign = 1;
1443         number = -number;
1444     } else *sign = 0;
1445
1446     snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1447     ptr1 = buf;
1448     ptr2 = outbuffer;
1449     first = NULL;
1450     dec1 = 0;
1451     dec2 = 0;
1452
1453     /* For numbers below the requested resolution, work out where
1454        the decimal point will be rather than finding it in the string */
1455     if (number < 1.0 && number > 0.0) {
1456         dec2 = log10(number + 1e-10);
1457         if (-dec2 <= ndigits) dec2 = 0;
1458     }
1459
1460     /* If requested digits is zero or less, we will need to truncate
1461      * the returned string */
1462     if (ndigits < 1) {
1463         stop = strlen(buf) + ndigits;
1464     } else {
1465         stop = strlen(buf);
1466     }
1467
1468     while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1469     while (*ptr1 != '\0' && *ptr1 != '.') {
1470         if (!first) first = ptr2;
1471         if ((ptr1 - buf) < stop) {
1472             if (size > 1) {
1473                 *ptr2++ = *ptr1++;
1474                 size--;
1475             }
1476         } else {
1477             ptr1++;
1478         }
1479         dec1++;
1480     }
1481
1482     if (ndigits > 0) {
1483         ptr1++;
1484         if (!first) {
1485             while (*ptr1 == '0') { /* Process leading zeroes */
1486                 if (number == 0.0 && size > 1) {
1487                     *ptr2++ = '0';
1488                     size--;
1489                 }
1490                 ptr1++;
1491                 dec1--;
1492             }
1493         }
1494         while (*ptr1 != '\0') {
1495             if (!first) first = ptr2;
1496             if (size > 1) {
1497                 *ptr2++ = *ptr1++;
1498                 size--;
1499             }
1500         }
1501     }
1502
1503     *ptr2 = '\0';
1504
1505     /* We never found a non-zero digit, then our number is either
1506      * smaller than the requested precision, or 0.0 */
1507     if (!first && (number <= 0.0))
1508         dec1 = 0;
1509
1510     *decpt = dec2 ? dec2 : dec1;
1511     return 0;
1512 }
1513
1514 /***********************************************************************
1515  *              _gcvt  (MSVCRT.@)
1516  */
1517 char * CDECL _gcvt( double number, int ndigit, char *buff )
1518 {
1519     if(!buff) {
1520         *MSVCRT__errno() = MSVCRT_EINVAL;
1521         return NULL;
1522     }
1523
1524     if(ndigit < 0) {
1525         *MSVCRT__errno() = MSVCRT_ERANGE;
1526         return NULL;
1527     }
1528
1529     MSVCRT_sprintf(buff, "%.*g", ndigit, number);
1530     return buff;
1531 }
1532
1533 /***********************************************************************
1534  *              _gcvt_s  (MSVCRT.@)
1535  */
1536 int CDECL _gcvt_s(char *buff, MSVCRT_size_t size, double number, int digits)
1537 {
1538     int len;
1539
1540     if(!buff) {
1541         *MSVCRT__errno() = MSVCRT_EINVAL;
1542         return MSVCRT_EINVAL;
1543     }
1544
1545     if( digits<0 || digits>=size) {
1546         if(size)
1547             buff[0] = '\0';
1548
1549         *MSVCRT__errno() = MSVCRT_ERANGE;
1550         return MSVCRT_ERANGE;
1551     }
1552
1553     len = MSVCRT__scprintf("%.*g", digits, number);
1554     if(len > size) {
1555         buff[0] = '\0';
1556         *MSVCRT__errno() = MSVCRT_ERANGE;
1557         return MSVCRT_ERANGE;
1558     }
1559
1560     MSVCRT_sprintf(buff, "%.*g", digits, number);
1561     return 0;
1562 }
1563
1564 #include <stdlib.h> /* div_t, ldiv_t */
1565
1566 /*********************************************************************
1567  *              div (MSVCRT.@)
1568  * VERSION
1569  *      [i386] Windows binary compatible - returns the struct in eax/edx.
1570  */
1571 #ifdef __i386__
1572 unsigned __int64 CDECL MSVCRT_div(int num, int denom)
1573 {
1574   div_t dt = div(num,denom);
1575   return ((unsigned __int64)dt.rem << 32) | (unsigned int)dt.quot;
1576 }
1577 #else
1578 /*********************************************************************
1579  *              div (MSVCRT.@)
1580  * VERSION
1581  *      [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1582  */
1583 MSVCRT_div_t CDECL MSVCRT_div(int num, int denom)
1584 {
1585   div_t dt = div(num,denom);
1586   MSVCRT_div_t     ret;
1587   ret.quot = dt.quot;
1588   ret.rem = dt.rem;
1589
1590   return ret;
1591
1592 }
1593 #endif /* ifdef __i386__ */
1594
1595
1596 /*********************************************************************
1597  *              ldiv (MSVCRT.@)
1598  * VERSION
1599  *      [i386] Windows binary compatible - returns the struct in eax/edx.
1600  */
1601 #ifdef __i386__
1602 unsigned __int64 CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
1603 {
1604   ldiv_t ldt = ldiv(num,denom);
1605   return ((unsigned __int64)ldt.rem << 32) | (MSVCRT_ulong)ldt.quot;
1606 }
1607 #else
1608 /*********************************************************************
1609  *              ldiv (MSVCRT.@)
1610  * VERSION
1611  *      [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1612  */
1613 MSVCRT_ldiv_t CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
1614 {
1615   ldiv_t result = ldiv(num,denom);
1616
1617   MSVCRT_ldiv_t ret;
1618   ret.quot = result.quot;
1619   ret.rem = result.rem;
1620
1621   return ret;
1622 }
1623 #endif /* ifdef __i386__ */
1624
1625 #ifdef __i386__
1626
1627 /*********************************************************************
1628  *              _adjust_fdiv (MSVCRT.@)
1629  * Used by the MSVC compiler to work around the Pentium FDIV bug.
1630  */
1631 int MSVCRT__adjust_fdiv = 0;
1632
1633 /***********************************************************************
1634  *              _adj_fdiv_m16i (MSVCRT.@)
1635  *
1636  * NOTE
1637  *    I _think_ this function is intended to work around the Pentium
1638  *    fdiv bug.
1639  */
1640 void __stdcall _adj_fdiv_m16i( short arg )
1641 {
1642   TRACE("(): stub\n");
1643 }
1644
1645 /***********************************************************************
1646  *              _adj_fdiv_m32 (MSVCRT.@)
1647  *
1648  * NOTE
1649  *    I _think_ this function is intended to work around the Pentium
1650  *    fdiv bug.
1651  */
1652 void __stdcall _adj_fdiv_m32( unsigned int arg )
1653 {
1654   TRACE("(): stub\n");
1655 }
1656
1657 /***********************************************************************
1658  *              _adj_fdiv_m32i (MSVCRT.@)
1659  *
1660  * NOTE
1661  *    I _think_ this function is intended to work around the Pentium
1662  *    fdiv bug.
1663  */
1664 void __stdcall _adj_fdiv_m32i( int arg )
1665 {
1666   TRACE("(): stub\n");
1667 }
1668
1669 /***********************************************************************
1670  *              _adj_fdiv_m64 (MSVCRT.@)
1671  *
1672  * NOTE
1673  *    I _think_ this function is intended to work around the Pentium
1674  *    fdiv bug.
1675  */
1676 void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
1677 {
1678   TRACE("(): stub\n");
1679 }
1680
1681 /***********************************************************************
1682  *              _adj_fdiv_r (MSVCRT.@)
1683  * FIXME
1684  *    This function is likely to have the wrong number of arguments.
1685  *
1686  * NOTE
1687  *    I _think_ this function is intended to work around the Pentium
1688  *    fdiv bug.
1689  */
1690 void _adj_fdiv_r(void)
1691 {
1692   TRACE("(): stub\n");
1693 }
1694
1695 /***********************************************************************
1696  *              _adj_fdivr_m16i (MSVCRT.@)
1697  *
1698  * NOTE
1699  *    I _think_ this function is intended to work around the Pentium
1700  *    fdiv bug.
1701  */
1702 void __stdcall _adj_fdivr_m16i( short arg )
1703 {
1704   TRACE("(): stub\n");
1705 }
1706
1707 /***********************************************************************
1708  *              _adj_fdivr_m32 (MSVCRT.@)
1709  *
1710  * NOTE
1711  *    I _think_ this function is intended to work around the Pentium
1712  *    fdiv bug.
1713  */
1714 void __stdcall _adj_fdivr_m32( unsigned int arg )
1715 {
1716   TRACE("(): stub\n");
1717 }
1718
1719 /***********************************************************************
1720  *              _adj_fdivr_m32i (MSVCRT.@)
1721  *
1722  * NOTE
1723  *    I _think_ this function is intended to work around the Pentium
1724  *    fdiv bug.
1725  */
1726 void __stdcall _adj_fdivr_m32i( int arg )
1727 {
1728   TRACE("(): stub\n");
1729 }
1730
1731 /***********************************************************************
1732  *              _adj_fdivr_m64 (MSVCRT.@)
1733  *
1734  * NOTE
1735  *    I _think_ this function is intended to work around the Pentium
1736  *    fdiv bug.
1737  */
1738 void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
1739 {
1740   TRACE("(): stub\n");
1741 }
1742
1743 /***********************************************************************
1744  *              _adj_fpatan (MSVCRT.@)
1745  * FIXME
1746  *    This function is likely to have the wrong number of arguments.
1747  *
1748  * NOTE
1749  *    I _think_ this function is intended to work around the Pentium
1750  *    fdiv bug.
1751  */
1752 void _adj_fpatan(void)
1753 {
1754   TRACE("(): stub\n");
1755 }
1756
1757 /***********************************************************************
1758  *              _adj_fprem (MSVCRT.@)
1759  * FIXME
1760  *    This function is likely to have the wrong number of arguments.
1761  *
1762  * NOTE
1763  *    I _think_ this function is intended to work around the Pentium
1764  *    fdiv bug.
1765  */
1766 void _adj_fprem(void)
1767 {
1768   TRACE("(): stub\n");
1769 }
1770
1771 /***********************************************************************
1772  *              _adj_fprem1 (MSVCRT.@)
1773  * FIXME
1774  *    This function is likely to have the wrong number of arguments.
1775  *
1776  * NOTE
1777  *    I _think_ this function is intended to work around the Pentium
1778  *    fdiv bug.
1779  */
1780 void _adj_fprem1(void)
1781 {
1782   TRACE("(): stub\n");
1783 }
1784
1785 /***********************************************************************
1786  *              _adj_fptan (MSVCRT.@)
1787  * FIXME
1788  *    This function is likely to have the wrong number of arguments.
1789  *
1790  * NOTE
1791  *    I _think_ this function is intended to work around the Pentium
1792  *    fdiv bug.
1793  */
1794 void _adj_fptan(void)
1795 {
1796   TRACE("(): stub\n");
1797 }
1798
1799 /***********************************************************************
1800  *              _safe_fdiv (MSVCRT.@)
1801  * FIXME
1802  *    This function is likely to have the wrong number of arguments.
1803  *
1804  * NOTE
1805  *    I _think_ this function is intended to work around the Pentium
1806  *    fdiv bug.
1807  */
1808 void _safe_fdiv(void)
1809 {
1810   TRACE("(): stub\n");
1811 }
1812
1813 /***********************************************************************
1814  *              _safe_fdivr (MSVCRT.@)
1815  * FIXME
1816  *    This function is likely to have the wrong number of arguments.
1817  *
1818  * NOTE
1819  *    I _think_ this function is intended to work around the Pentium
1820  *    fdiv bug.
1821  */
1822 void _safe_fdivr(void)
1823 {
1824   TRACE("(): stub\n");
1825 }
1826
1827 /***********************************************************************
1828  *              _safe_fprem (MSVCRT.@)
1829  * FIXME
1830  *    This function is likely to have the wrong number of arguments.
1831  *
1832  * NOTE
1833  *    I _think_ this function is intended to work around the Pentium
1834  *    fdiv bug.
1835  */
1836 void _safe_fprem(void)
1837 {
1838   TRACE("(): stub\n");
1839 }
1840
1841 /***********************************************************************
1842  *              _safe_fprem1 (MSVCRT.@)
1843  *
1844  * FIXME
1845  *    This function is likely to have the wrong number of arguments.
1846  *
1847  * NOTE
1848  *    I _think_ this function is intended to work around the Pentium
1849  *    fdiv bug.
1850  */
1851 void _safe_fprem1(void)
1852 {
1853   TRACE("(): stub\n");
1854 }
1855
1856 /***********************************************************************
1857  *              __libm_sse2_acos   (MSVCRT.@)
1858  */
1859 void __cdecl __libm_sse2_acos(void)
1860 {
1861     double d;
1862     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1863     d = acos( d );
1864     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1865 }
1866
1867 /***********************************************************************
1868  *              __libm_sse2_acosf   (MSVCRT.@)
1869  */
1870 void __cdecl __libm_sse2_acosf(void)
1871 {
1872     float f;
1873     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
1874     f = acosf( f );
1875     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
1876 }
1877
1878 /***********************************************************************
1879  *              __libm_sse2_asin   (MSVCRT.@)
1880  */
1881 void __cdecl __libm_sse2_asin(void)
1882 {
1883     double d;
1884     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1885     d = asin( d );
1886     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1887 }
1888
1889 /***********************************************************************
1890  *              __libm_sse2_asinf   (MSVCRT.@)
1891  */
1892 void __cdecl __libm_sse2_asinf(void)
1893 {
1894     float f;
1895     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
1896     f = asinf( f );
1897     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
1898 }
1899
1900 /***********************************************************************
1901  *              __libm_sse2_atan   (MSVCRT.@)
1902  */
1903 void __cdecl __libm_sse2_atan(void)
1904 {
1905     double d;
1906     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1907     d = atan( d );
1908     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1909 }
1910
1911 /***********************************************************************
1912  *              __libm_sse2_atan2   (MSVCRT.@)
1913  */
1914 void __cdecl __libm_sse2_atan2(void)
1915 {
1916     double d1, d2;
1917     __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
1918     d1 = atan2( d1, d2 );
1919     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
1920 }
1921
1922 /***********************************************************************
1923  *              __libm_sse2_atanf   (MSVCRT.@)
1924  */
1925 void __cdecl __libm_sse2_atanf(void)
1926 {
1927     float f;
1928     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
1929     f = atanf( f );
1930     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
1931 }
1932
1933 /***********************************************************************
1934  *              __libm_sse2_cos   (MSVCRT.@)
1935  */
1936 void __cdecl __libm_sse2_cos(void)
1937 {
1938     double d;
1939     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1940     d = cos( d );
1941     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1942 }
1943
1944 /***********************************************************************
1945  *              __libm_sse2_cosf   (MSVCRT.@)
1946  */
1947 void __cdecl __libm_sse2_cosf(void)
1948 {
1949     float f;
1950     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
1951     f = cosf( f );
1952     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
1953 }
1954
1955 /***********************************************************************
1956  *              __libm_sse2_exp   (MSVCRT.@)
1957  */
1958 void __cdecl __libm_sse2_exp(void)
1959 {
1960     double d;
1961     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1962     d = exp( d );
1963     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1964 }
1965
1966 /***********************************************************************
1967  *              __libm_sse2_expf   (MSVCRT.@)
1968  */
1969 void __cdecl __libm_sse2_expf(void)
1970 {
1971     float f;
1972     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
1973     f = expf( f );
1974     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
1975 }
1976
1977 /***********************************************************************
1978  *              __libm_sse2_log   (MSVCRT.@)
1979  */
1980 void __cdecl __libm_sse2_log(void)
1981 {
1982     double d;
1983     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1984     d = log( d );
1985     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1986 }
1987
1988 /***********************************************************************
1989  *              __libm_sse2_log10   (MSVCRT.@)
1990  */
1991 void __cdecl __libm_sse2_log10(void)
1992 {
1993     double d;
1994     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
1995     d = log10( d );
1996     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
1997 }
1998
1999 /***********************************************************************
2000  *              __libm_sse2_log10f   (MSVCRT.@)
2001  */
2002 void __cdecl __libm_sse2_log10f(void)
2003 {
2004     float f;
2005     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2006     f = log10f( f );
2007     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2008 }
2009
2010 /***********************************************************************
2011  *              __libm_sse2_logf   (MSVCRT.@)
2012  */
2013 void __cdecl __libm_sse2_logf(void)
2014 {
2015     float f;
2016     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2017     f = logf( f );
2018     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2019 }
2020
2021 /***********************************************************************
2022  *              __libm_sse2_pow   (MSVCRT.@)
2023  */
2024 void __cdecl __libm_sse2_pow(void)
2025 {
2026     double d1, d2;
2027     __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
2028     d1 = pow( d1, d2 );
2029     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
2030 }
2031
2032 /***********************************************************************
2033  *              __libm_sse2_powf   (MSVCRT.@)
2034  */
2035 void __cdecl __libm_sse2_powf(void)
2036 {
2037     float f1, f2;
2038     __asm__ __volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1), "=g" (f2) );
2039     f1 = powf( f1, f2 );
2040     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f1) );
2041 }
2042
2043 /***********************************************************************
2044  *              __libm_sse2_sin   (MSVCRT.@)
2045  */
2046 void __cdecl __libm_sse2_sin(void)
2047 {
2048     double d;
2049     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2050     d = sin( d );
2051     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2052 }
2053
2054 /***********************************************************************
2055  *              __libm_sse2_sinf   (MSVCRT.@)
2056  */
2057 void __cdecl __libm_sse2_sinf(void)
2058 {
2059     float f;
2060     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2061     f = sinf( f );
2062     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2063 }
2064
2065 /***********************************************************************
2066  *              __libm_sse2_tan   (MSVCRT.@)
2067  */
2068 void __cdecl __libm_sse2_tan(void)
2069 {
2070     double d;
2071     __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2072     d = tan( d );
2073     __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2074 }
2075
2076 /***********************************************************************
2077  *              __libm_sse2_tanf   (MSVCRT.@)
2078  */
2079 void __cdecl __libm_sse2_tanf(void)
2080 {
2081     float f;
2082     __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2083     f = tanf( f );
2084     __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2085 }
2086
2087 #endif  /* __i386__ */