d2d1: Implement d2d_radial_gradient_brush_SetCenter().
[wine.git] / dlls / msvcrt / math.c
blob60ce4e659f5f2b038fc5f2555d047a64f0b84f90
1 /*
2 * msvcrt.dll math functions
4 * Copyright 2000 Jon Griffiths
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.
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.
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
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdio.h>
24 #define __USE_ISOC9X 1
25 #define __USE_ISOC99 1
26 #include <math.h>
27 #ifdef HAVE_IEEEFP_H
28 #include <ieeefp.h>
29 #endif
31 #include "msvcrt.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
37 #ifndef HAVE_FINITEF
38 #define finitef(x) isfinite(x)
39 #endif
41 #ifndef HAVE_ISNANF
42 #ifdef HAVE_ISNAN
43 #define isnanf(x) isnan(x)
44 #else
45 #define isnanf(x) 0
46 #endif
47 #endif
49 /* FIXME: Does not work with -NAN and -0. */
50 #ifndef signbit
51 #define signbit(x) ((x) < 0)
52 #endif
54 #define _DOMAIN 1 /* domain error in argument */
55 #define _SING 2 /* singularity */
56 #define _OVERFLOW 3 /* range overflow */
57 #define _UNDERFLOW 4 /* range underflow */
59 typedef int (CDECL *MSVCRT_matherr_func)(struct MSVCRT__exception *);
60 typedef double LDOUBLE; /* long double is just a double */
62 static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
64 static BOOL sse2_supported;
65 static BOOL sse2_enabled;
67 void msvcrt_init_math(void)
69 sse2_supported = sse2_enabled = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE );
72 /*********************************************************************
73 * _matherr (MSVCRT.@)
75 int CDECL MSVCRT__matherr(struct MSVCRT__exception *e)
77 int ret;
79 if (e)
80 TRACE("(%p = {%d, \"%s\", %g, %g, %g})\n", e, e->type, e->name, e->arg1, e->arg2, e->retval);
81 else
82 TRACE("(null)\n");
84 if (MSVCRT_default_matherr_func)
86 ret = MSVCRT_default_matherr_func(e);
87 if (ret) return ret;
90 switch (e->type)
92 case _DOMAIN:
93 *MSVCRT__errno() = MSVCRT_EDOM;
94 break;
95 case _SING:
96 case _OVERFLOW:
97 *MSVCRT__errno() = MSVCRT_ERANGE;
98 break;
99 case _UNDERFLOW:
100 /* don't set errno */
101 break;
102 default:
103 ERR("Unhandled math error!\n");
106 return 0;
109 /*********************************************************************
110 * __setusermatherr (MSVCRT.@)
112 void CDECL MSVCRT___setusermatherr(MSVCRT_matherr_func func)
114 MSVCRT_default_matherr_func = func;
115 TRACE("new matherr handler %p\n", func);
118 static inline void math_error(int type, const char *name, double arg1, double arg2, double retval)
120 struct MSVCRT__exception exception = {type, (char *)name, arg1, arg2, retval};
121 MSVCRT__matherr(&exception);
124 /*********************************************************************
125 * _set_SSE2_enable (MSVCRT.@)
127 int CDECL MSVCRT__set_SSE2_enable(int flag)
129 sse2_enabled = flag && sse2_supported;
130 return sse2_enabled;
133 #ifdef _WIN64
134 /*********************************************************************
135 * _set_FMA3_enable (MSVCR120.@)
137 int CDECL MSVCRT__set_FMA3_enable(int flag)
139 FIXME("(%x) stub\n", flag);
140 return 0;
142 #endif
144 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || _MSVCR_VER>=120
146 /*********************************************************************
147 * _chgsignf (MSVCRT.@)
149 float CDECL MSVCRT__chgsignf( float num )
151 /* FIXME: +-infinity,Nan not tested */
152 return -num;
155 /*********************************************************************
156 * _copysignf (MSVCRT.@)
158 float CDECL MSVCRT__copysignf( float num, float sign )
160 if (signbit(sign))
161 return signbit(num) ? num : -num;
162 return signbit(num) ? -num : num;
165 /*********************************************************************
166 * _nextafterf (MSVCRT.@)
168 float CDECL MSVCRT__nextafterf( float num, float next )
170 if (!finitef(num) || !finitef(next)) *MSVCRT__errno() = MSVCRT_EDOM;
171 return nextafterf( num, next );
174 #endif
175 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
177 /*********************************************************************
178 * _finitef (MSVCRT.@)
180 int CDECL MSVCRT__finitef( float num )
182 return finitef(num) != 0; /* See comment for _isnan() */
185 /*********************************************************************
186 * _isnanf (MSVCRT.@)
188 INT CDECL MSVCRT__isnanf( float num )
190 /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
191 * Do the same, as the result may be used in calculations
193 return isnanf(num) != 0;
196 /*********************************************************************
197 * _logbf (MSVCRT.@)
199 float CDECL MSVCRT__logbf( float num )
201 float ret = logbf(num);
202 if (isnanf(num)) math_error(_DOMAIN, "_logbf", num, 0, ret);
203 else if (!num) math_error(_SING, "_logbf", num, 0, ret);
204 return ret;
207 /*********************************************************************
208 * MSVCRT_acosf (MSVCRT.@)
210 float CDECL MSVCRT_acosf( float x )
212 /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
213 * asin() uses a similar construction. This is bad because as x gets nearer to
214 * 1 the error in the expression "1 - x^2" can get relatively large due to
215 * cancellation. The sqrt() makes things worse. A safer way to calculate
216 * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
217 float ret = atan2f(sqrtf((1 - x) * (1 + x)), x);
218 if (x < -1.0 || x > 1.0 || !finitef(x)) math_error(_DOMAIN, "acosf", x, 0, ret);
219 return ret;
222 /*********************************************************************
223 * MSVCRT_asinf (MSVCRT.@)
225 float CDECL MSVCRT_asinf( float x )
227 float ret = atan2f(x, sqrtf((1 - x) * (1 + x)));
228 if (x < -1.0 || x > 1.0 || !finitef(x)) math_error(_DOMAIN, "asinf", x, 0, ret);
229 return ret;
232 /*********************************************************************
233 * MSVCRT_atanf (MSVCRT.@)
235 float CDECL MSVCRT_atanf( float x )
237 float ret = atanf(x);
238 if (!finitef(x)) math_error(_DOMAIN, "atanf", x, 0, ret);
239 return ret;
242 /*********************************************************************
243 * MSVCRT_atan2f (MSVCRT.@)
245 float CDECL MSVCRT_atan2f( float x, float y )
247 float ret = atan2f(x, y);
248 if (isnanf(x)) math_error(_DOMAIN, "atan2f", x, y, ret);
249 return ret;
252 /*********************************************************************
253 * MSVCRT_cosf (MSVCRT.@)
255 float CDECL MSVCRT_cosf( float x )
257 float ret = cosf(x);
258 if (!finitef(x)) math_error(_DOMAIN, "cosf", x, 0, ret);
259 return ret;
262 /*********************************************************************
263 * MSVCRT_coshf (MSVCRT.@)
265 float CDECL MSVCRT_coshf( float x )
267 float ret = coshf(x);
268 if (isnanf(x)) math_error(_DOMAIN, "coshf", x, 0, ret);
269 return ret;
272 /*********************************************************************
273 * MSVCRT_expf (MSVCRT.@)
275 float CDECL MSVCRT_expf( float x )
277 float ret = expf(x);
278 if (isnanf(x)) math_error(_DOMAIN, "expf", x, 0, ret);
279 else if (finitef(x) && !ret) math_error(_UNDERFLOW, "expf", x, 0, ret);
280 else if (finitef(x) && !finitef(ret)) math_error(_OVERFLOW, "expf", x, 0, ret);
281 return ret;
284 /*********************************************************************
285 * MSVCRT_fmodf (MSVCRT.@)
287 float CDECL MSVCRT_fmodf( float x, float y )
289 float ret = fmodf(x, y);
290 if (!finitef(x) || !finitef(y)) math_error(_DOMAIN, "fmodf", x, 0, ret);
291 return ret;
294 /*********************************************************************
295 * MSVCRT_logf (MSVCRT.@)
297 float CDECL MSVCRT_logf( float x )
299 float ret = logf(x);
300 if (x < 0.0) math_error(_DOMAIN, "logf", x, 0, ret);
301 else if (x == 0.0) math_error(_SING, "logf", x, 0, ret);
302 return ret;
305 /*********************************************************************
306 * MSVCRT_log10f (MSVCRT.@)
308 float CDECL MSVCRT_log10f( float x )
310 float ret = log10f(x);
311 if (x < 0.0) math_error(_DOMAIN, "log10f", x, 0, ret);
312 else if (x == 0.0) math_error(_SING, "log10f", x, 0, ret);
313 return ret;
316 /*********************************************************************
317 * MSVCRT_powf (MSVCRT.@)
319 float CDECL MSVCRT_powf( float x, float y )
321 float z = powf(x,y);
322 if (x < 0 && y != floorf(y)) math_error(_DOMAIN, "powf", x, y, z);
323 else if (!x && finitef(y) && y < 0) math_error(_SING, "powf", x, y, z);
324 else if (finitef(x) && finitef(y) && !finitef(z)) math_error(_OVERFLOW, "powf", x, y, z);
325 else if (x && finitef(x) && finitef(y) && !z) math_error(_UNDERFLOW, "powf", x, y, z);
326 return z;
329 /*********************************************************************
330 * MSVCRT_sinf (MSVCRT.@)
332 float CDECL MSVCRT_sinf( float x )
334 float ret = sinf(x);
335 if (!finitef(x)) math_error(_DOMAIN, "sinf", x, 0, ret);
336 return ret;
339 /*********************************************************************
340 * MSVCRT_sinhf (MSVCRT.@)
342 float CDECL MSVCRT_sinhf( float x )
344 float ret = sinhf(x);
345 if (isnanf(x)) math_error(_DOMAIN, "sinhf", x, 0, ret);
346 return ret;
349 /*********************************************************************
350 * MSVCRT_sqrtf (MSVCRT.@)
352 float CDECL MSVCRT_sqrtf( float x )
354 float ret = sqrtf(x);
355 if (x < 0.0) math_error(_DOMAIN, "sqrtf", x, 0, ret);
356 return ret;
359 /*********************************************************************
360 * MSVCRT_tanf (MSVCRT.@)
362 float CDECL MSVCRT_tanf( float x )
364 float ret = tanf(x);
365 if (!finitef(x)) math_error(_DOMAIN, "tanf", x, 0, ret);
366 return ret;
369 /*********************************************************************
370 * MSVCRT_tanhf (MSVCRT.@)
372 float CDECL MSVCRT_tanhf( float x )
374 float ret = tanhf(x);
375 if (!finitef(x)) math_error(_DOMAIN, "tanhf", x, 0, ret);
376 return ret;
379 /*********************************************************************
380 * ceilf (MSVCRT.@)
382 float CDECL MSVCRT_ceilf( float x )
384 return ceilf(x);
387 /*********************************************************************
388 * fabsf (MSVCRT.@)
390 float CDECL MSVCRT_fabsf( float x )
392 return fabsf(x);
395 /*********************************************************************
396 * floorf (MSVCRT.@)
398 float CDECL MSVCRT_floorf( float x )
400 return floorf(x);
403 /*********************************************************************
404 * frexpf (MSVCRT.@)
406 float CDECL MSVCRT_frexpf( float x, int *exp )
408 return frexpf( x, exp );
411 /*********************************************************************
412 * modff (MSVCRT.@)
414 float CDECL MSVCRT_modff( float x, float *iptr )
416 return modff( x, iptr );
419 #endif
421 /*********************************************************************
422 * MSVCRT_acos (MSVCRT.@)
424 double CDECL MSVCRT_acos( double x )
426 /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
427 * asin() uses a similar construction. This is bad because as x gets nearer to
428 * 1 the error in the expression "1 - x^2" can get relatively large due to
429 * cancellation. The sqrt() makes things worse. A safer way to calculate
430 * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
431 double ret = atan2(sqrt((1 - x) * (1 + x)), x);
432 if (x < -1.0 || x > 1.0 || !isfinite(x)) math_error(_DOMAIN, "acos", x, 0, ret);
433 return ret;
436 /*********************************************************************
437 * MSVCRT_asin (MSVCRT.@)
439 double CDECL MSVCRT_asin( double x )
441 double ret = atan2(x, sqrt((1 - x) * (1 + x)));
442 if (x < -1.0 || x > 1.0 || !isfinite(x)) math_error(_DOMAIN, "asin", x, 0, ret);
443 return ret;
446 /*********************************************************************
447 * MSVCRT_atan (MSVCRT.@)
449 double CDECL MSVCRT_atan( double x )
451 double ret = atan(x);
452 if (isnan(x)) math_error(_DOMAIN, "atan", x, 0, ret);
453 return ret;
456 /*********************************************************************
457 * MSVCRT_atan2 (MSVCRT.@)
459 double CDECL MSVCRT_atan2( double x, double y )
461 double ret = atan2(x, y);
462 if (isnan(x)) math_error(_DOMAIN, "atan2", x, y, ret);
463 return ret;
466 /*********************************************************************
467 * MSVCRT_cos (MSVCRT.@)
469 double CDECL MSVCRT_cos( double x )
471 double ret = cos(x);
472 if (!isfinite(x)) math_error(_DOMAIN, "cos", x, 0, ret);
473 return ret;
476 /*********************************************************************
477 * MSVCRT_cosh (MSVCRT.@)
479 double CDECL MSVCRT_cosh( double x )
481 double ret = cosh(x);
482 if (isnan(x)) math_error(_DOMAIN, "cosh", x, 0, ret);
483 return ret;
486 /*********************************************************************
487 * MSVCRT_exp (MSVCRT.@)
489 double CDECL MSVCRT_exp( double x )
491 double ret = exp(x);
492 if (isnan(x)) math_error(_DOMAIN, "exp", x, 0, ret);
493 else if (isfinite(x) && !ret) math_error(_UNDERFLOW, "exp", x, 0, ret);
494 else if (isfinite(x) && !isfinite(ret)) math_error(_OVERFLOW, "exp", x, 0, ret);
495 return ret;
498 /*********************************************************************
499 * MSVCRT_fmod (MSVCRT.@)
501 double CDECL MSVCRT_fmod( double x, double y )
503 double ret = fmod(x, y);
504 if (!isfinite(x) || !isfinite(y)) math_error(_DOMAIN, "fmod", x, y, ret);
505 return ret;
508 /*********************************************************************
509 * MSVCRT_log (MSVCRT.@)
511 double CDECL MSVCRT_log( double x )
513 double ret = log(x);
514 if (x < 0.0) math_error(_DOMAIN, "log", x, 0, ret);
515 else if (x == 0.0) math_error(_SING, "log", x, 0, ret);
516 return ret;
519 /*********************************************************************
520 * MSVCRT_log10 (MSVCRT.@)
522 double CDECL MSVCRT_log10( double x )
524 double ret = log10(x);
525 if (x < 0.0) math_error(_DOMAIN, "log10", x, 0, ret);
526 else if (x == 0.0) math_error(_SING, "log10", x, 0, ret);
527 return ret;
530 /*********************************************************************
531 * MSVCRT_pow (MSVCRT.@)
533 double CDECL MSVCRT_pow( double x, double y )
535 double z = pow(x,y);
536 if (x < 0 && y != floor(y)) math_error(_DOMAIN, "pow", x, y, z);
537 else if (!x && isfinite(y) && y < 0) math_error(_SING, "pow", x, y, z);
538 else if (isfinite(x) && isfinite(y) && !isfinite(z)) math_error(_OVERFLOW, "pow", x, y, z);
539 else if (x && isfinite(x) && isfinite(y) && !z) math_error(_UNDERFLOW, "pow", x, y, z);
540 return z;
543 /*********************************************************************
544 * MSVCRT_sin (MSVCRT.@)
546 double CDECL MSVCRT_sin( double x )
548 double ret = sin(x);
549 if (!isfinite(x)) math_error(_DOMAIN, "sin", x, 0, ret);
550 return ret;
553 /*********************************************************************
554 * MSVCRT_sinh (MSVCRT.@)
556 double CDECL MSVCRT_sinh( double x )
558 double ret = sinh(x);
559 if (isnan(x)) math_error(_DOMAIN, "sinh", x, 0, ret);
560 return ret;
563 /*********************************************************************
564 * MSVCRT_sqrt (MSVCRT.@)
566 double CDECL MSVCRT_sqrt( double x )
568 double ret = sqrt(x);
569 if (x < 0.0) math_error(_DOMAIN, "sqrt", x, 0, ret);
570 return ret;
573 /*********************************************************************
574 * MSVCRT_tan (MSVCRT.@)
576 double CDECL MSVCRT_tan( double x )
578 double ret = tan(x);
579 if (!isfinite(x)) math_error(_DOMAIN, "tan", x, 0, ret);
580 return ret;
583 /*********************************************************************
584 * MSVCRT_tanh (MSVCRT.@)
586 double CDECL MSVCRT_tanh( double x )
588 double ret = tanh(x);
589 if (isnan(x)) math_error(_DOMAIN, "tanh", x, 0, ret);
590 return ret;
594 #if defined(__GNUC__) && defined(__i386__)
596 #define FPU_DOUBLE(var) double var; \
597 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
598 #define FPU_DOUBLES(var1,var2) double var1,var2; \
599 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
600 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
602 /*********************************************************************
603 * _CIacos (MSVCRT.@)
605 double CDECL _CIacos(void)
607 FPU_DOUBLE(x);
608 return MSVCRT_acos(x);
611 /*********************************************************************
612 * _CIasin (MSVCRT.@)
614 double CDECL _CIasin(void)
616 FPU_DOUBLE(x);
617 return MSVCRT_asin(x);
620 /*********************************************************************
621 * _CIatan (MSVCRT.@)
623 double CDECL _CIatan(void)
625 FPU_DOUBLE(x);
626 return MSVCRT_atan(x);
629 /*********************************************************************
630 * _CIatan2 (MSVCRT.@)
632 double CDECL _CIatan2(void)
634 FPU_DOUBLES(x,y);
635 return MSVCRT_atan2(x,y);
638 /*********************************************************************
639 * _CIcos (MSVCRT.@)
641 double CDECL _CIcos(void)
643 FPU_DOUBLE(x);
644 return MSVCRT_cos(x);
647 /*********************************************************************
648 * _CIcosh (MSVCRT.@)
650 double CDECL _CIcosh(void)
652 FPU_DOUBLE(x);
653 return MSVCRT_cosh(x);
656 /*********************************************************************
657 * _CIexp (MSVCRT.@)
659 double CDECL _CIexp(void)
661 FPU_DOUBLE(x);
662 return MSVCRT_exp(x);
665 /*********************************************************************
666 * _CIfmod (MSVCRT.@)
668 double CDECL _CIfmod(void)
670 FPU_DOUBLES(x,y);
671 return MSVCRT_fmod(x,y);
674 /*********************************************************************
675 * _CIlog (MSVCRT.@)
677 double CDECL _CIlog(void)
679 FPU_DOUBLE(x);
680 return MSVCRT_log(x);
683 /*********************************************************************
684 * _CIlog10 (MSVCRT.@)
686 double CDECL _CIlog10(void)
688 FPU_DOUBLE(x);
689 return MSVCRT_log10(x);
692 /*********************************************************************
693 * _CIpow (MSVCRT.@)
695 double CDECL _CIpow(void)
697 FPU_DOUBLES(x,y);
698 return MSVCRT_pow(x,y);
701 /*********************************************************************
702 * _CIsin (MSVCRT.@)
704 double CDECL _CIsin(void)
706 FPU_DOUBLE(x);
707 return MSVCRT_sin(x);
710 /*********************************************************************
711 * _CIsinh (MSVCRT.@)
713 double CDECL _CIsinh(void)
715 FPU_DOUBLE(x);
716 return MSVCRT_sinh(x);
719 /*********************************************************************
720 * _CIsqrt (MSVCRT.@)
722 double CDECL _CIsqrt(void)
724 FPU_DOUBLE(x);
725 return MSVCRT_sqrt(x);
728 /*********************************************************************
729 * _CItan (MSVCRT.@)
731 double CDECL _CItan(void)
733 FPU_DOUBLE(x);
734 return MSVCRT_tan(x);
737 /*********************************************************************
738 * _CItanh (MSVCRT.@)
740 double CDECL _CItanh(void)
742 FPU_DOUBLE(x);
743 return MSVCRT_tanh(x);
746 /*********************************************************************
747 * _ftol (MSVCRT.@)
749 LONGLONG CDECL MSVCRT__ftol(void)
751 FPU_DOUBLE(x);
752 return (LONGLONG)x;
755 #endif /* defined(__GNUC__) && defined(__i386__) */
757 /*********************************************************************
758 * _fpclass (MSVCRT.@)
760 int CDECL MSVCRT__fpclass(double num)
762 #if defined(HAVE_FPCLASS) || defined(fpclass)
763 switch (fpclass( num ))
765 case FP_SNAN: return MSVCRT__FPCLASS_SNAN;
766 case FP_QNAN: return MSVCRT__FPCLASS_QNAN;
767 case FP_NINF: return MSVCRT__FPCLASS_NINF;
768 case FP_PINF: return MSVCRT__FPCLASS_PINF;
769 case FP_NDENORM: return MSVCRT__FPCLASS_ND;
770 case FP_PDENORM: return MSVCRT__FPCLASS_PD;
771 case FP_NZERO: return MSVCRT__FPCLASS_NZ;
772 case FP_PZERO: return MSVCRT__FPCLASS_PZ;
773 case FP_NNORM: return MSVCRT__FPCLASS_NN;
774 case FP_PNORM: return MSVCRT__FPCLASS_PN;
775 default: return MSVCRT__FPCLASS_PN;
777 #elif defined (fpclassify)
778 switch (fpclassify( num ))
780 case FP_NAN: return MSVCRT__FPCLASS_QNAN;
781 case FP_INFINITE: return signbit(num) ? MSVCRT__FPCLASS_NINF : MSVCRT__FPCLASS_PINF;
782 case FP_SUBNORMAL: return signbit(num) ?MSVCRT__FPCLASS_ND : MSVCRT__FPCLASS_PD;
783 case FP_ZERO: return signbit(num) ? MSVCRT__FPCLASS_NZ : MSVCRT__FPCLASS_PZ;
785 return signbit(num) ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN;
786 #else
787 if (!isfinite(num))
788 return MSVCRT__FPCLASS_QNAN;
789 return num == 0.0 ? MSVCRT__FPCLASS_PZ : (num < 0 ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN);
790 #endif
793 /*********************************************************************
794 * _rotl (MSVCRT.@)
796 unsigned int CDECL _rotl(unsigned int num, int shift)
798 shift &= 31;
799 return (num << shift) | (num >> (32-shift));
802 /*********************************************************************
803 * _lrotl (MSVCRT.@)
805 MSVCRT_ulong CDECL MSVCRT__lrotl(MSVCRT_ulong num, int shift)
807 shift &= 0x1f;
808 return (num << shift) | (num >> (32-shift));
811 /*********************************************************************
812 * _lrotr (MSVCRT.@)
814 MSVCRT_ulong CDECL MSVCRT__lrotr(MSVCRT_ulong num, int shift)
816 shift &= 0x1f;
817 return (num >> shift) | (num << (32-shift));
820 /*********************************************************************
821 * _rotr (MSVCRT.@)
823 unsigned int CDECL _rotr(unsigned int num, int shift)
825 shift &= 0x1f;
826 return (num >> shift) | (num << (32-shift));
829 /*********************************************************************
830 * _rotl64 (MSVCRT.@)
832 unsigned __int64 CDECL _rotl64(unsigned __int64 num, int shift)
834 shift &= 63;
835 return (num << shift) | (num >> (64-shift));
838 /*********************************************************************
839 * _rotr64 (MSVCRT.@)
841 unsigned __int64 CDECL _rotr64(unsigned __int64 num, int shift)
843 shift &= 63;
844 return (num >> shift) | (num << (64-shift));
847 /*********************************************************************
848 * abs (MSVCRT.@)
850 int CDECL MSVCRT_abs( int n )
852 return n >= 0 ? n : -n;
855 /*********************************************************************
856 * labs (MSVCRT.@)
858 MSVCRT_long CDECL MSVCRT_labs( MSVCRT_long n )
860 return n >= 0 ? n : -n;
863 /*********************************************************************
864 * llabs (MSVCRT.@)
866 MSVCRT_longlong CDECL MSVCRT_llabs( MSVCRT_longlong n )
868 return n >= 0 ? n : -n;
871 /*********************************************************************
872 * _abs64 (MSVCRT.@)
874 __int64 CDECL _abs64( __int64 n )
876 return n >= 0 ? n : -n;
879 /*********************************************************************
880 * _logb (MSVCRT.@)
882 double CDECL MSVCRT__logb(double num)
884 double ret = logb(num);
885 if (isnan(num)) math_error(_DOMAIN, "_logb", num, 0, ret);
886 else if (!num) math_error(_SING, "_logb", num, 0, ret);
887 return ret;
890 /*********************************************************************
891 * _hypot (MSVCRT.@)
893 double CDECL _hypot(double x, double y)
895 /* FIXME: errno handling */
896 return hypot( x, y );
899 /*********************************************************************
900 * _hypotf (MSVCRT.@)
902 float CDECL MSVCRT__hypotf(float x, float y)
904 /* FIXME: errno handling */
905 return hypotf( x, y );
908 /*********************************************************************
909 * ceil (MSVCRT.@)
911 double CDECL MSVCRT_ceil( double x )
913 return ceil(x);
916 /*********************************************************************
917 * floor (MSVCRT.@)
919 double CDECL MSVCRT_floor( double x )
921 return floor(x);
924 /*********************************************************************
925 * fabs (MSVCRT.@)
927 double CDECL MSVCRT_fabs( double x )
929 return fabs(x);
932 /*********************************************************************
933 * frexp (MSVCRT.@)
935 double CDECL MSVCRT_frexp( double x, int *exp )
937 return frexp( x, exp );
940 /*********************************************************************
941 * modf (MSVCRT.@)
943 double CDECL MSVCRT_modf( double x, double *iptr )
945 return modf( x, iptr );
948 /**********************************************************************
949 * _statusfp2 (MSVCRT.@)
951 * Not exported by native msvcrt, added in msvcr80.
953 #if defined(__i386__) || defined(__x86_64__)
954 void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
956 #ifdef __GNUC__
957 unsigned int flags;
958 unsigned long fpword;
960 if (x86_sw)
962 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) );
963 flags = 0;
964 if (fpword & 0x1) flags |= MSVCRT__SW_INVALID;
965 if (fpword & 0x2) flags |= MSVCRT__SW_DENORMAL;
966 if (fpword & 0x4) flags |= MSVCRT__SW_ZERODIVIDE;
967 if (fpword & 0x8) flags |= MSVCRT__SW_OVERFLOW;
968 if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
969 if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
970 *x86_sw = flags;
973 if (!sse2_sw) return;
975 if (sse2_supported)
977 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
978 flags = 0;
979 if (fpword & 0x1) flags |= MSVCRT__SW_INVALID;
980 if (fpword & 0x2) flags |= MSVCRT__SW_DENORMAL;
981 if (fpword & 0x4) flags |= MSVCRT__SW_ZERODIVIDE;
982 if (fpword & 0x8) flags |= MSVCRT__SW_OVERFLOW;
983 if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
984 if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
985 *sse2_sw = flags;
987 else *sse2_sw = 0;
988 #else
989 FIXME( "not implemented\n" );
990 #endif
992 #endif
994 /**********************************************************************
995 * _statusfp (MSVCRT.@)
997 unsigned int CDECL _statusfp(void)
999 #if defined(__i386__) || defined(__x86_64__)
1000 unsigned int x86_sw, sse2_sw;
1002 _statusfp2( &x86_sw, &sse2_sw );
1003 /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
1004 return x86_sw | sse2_sw;
1005 #else
1006 FIXME( "not implemented\n" );
1007 return 0;
1008 #endif
1011 /*********************************************************************
1012 * _clearfp (MSVCRT.@)
1014 unsigned int CDECL _clearfp(void)
1016 unsigned int flags = 0;
1017 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1018 unsigned long fpword;
1020 __asm__ __volatile__( "fnstsw %0; fnclex" : "=m" (fpword) );
1021 if (fpword & 0x1) flags |= MSVCRT__SW_INVALID;
1022 if (fpword & 0x2) flags |= MSVCRT__SW_DENORMAL;
1023 if (fpword & 0x4) flags |= MSVCRT__SW_ZERODIVIDE;
1024 if (fpword & 0x8) flags |= MSVCRT__SW_OVERFLOW;
1025 if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
1026 if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
1028 if (sse2_supported)
1030 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
1031 if (fpword & 0x1) flags |= MSVCRT__SW_INVALID;
1032 if (fpword & 0x2) flags |= MSVCRT__SW_DENORMAL;
1033 if (fpword & 0x4) flags |= MSVCRT__SW_ZERODIVIDE;
1034 if (fpword & 0x8) flags |= MSVCRT__SW_OVERFLOW;
1035 if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
1036 if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
1037 fpword &= ~0x3f;
1038 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
1040 #else
1041 FIXME( "not implemented\n" );
1042 #endif
1043 return flags;
1046 /*********************************************************************
1047 * __fpecode (MSVCRT.@)
1049 int * CDECL __fpecode(void)
1051 return &msvcrt_get_thread_data()->fpecode;
1054 /*********************************************************************
1055 * ldexp (MSVCRT.@)
1057 double CDECL MSVCRT_ldexp(double num, MSVCRT_long exp)
1059 double z = ldexp(num,exp);
1061 if (isfinite(num) && !isfinite(z))
1062 math_error(_OVERFLOW, "ldexp", num, exp, z);
1063 else if (isfinite(num) && !z)
1064 math_error(_UNDERFLOW, "ldexp", num, exp, z);
1065 else if (z == 0 && signbit(z))
1066 z = 0.0; /* Convert -0 -> +0 */
1067 return z;
1070 /*********************************************************************
1071 * _cabs (MSVCRT.@)
1073 double CDECL MSVCRT__cabs(struct MSVCRT__complex num)
1075 return sqrt(num.x * num.x + num.y * num.y);
1078 /*********************************************************************
1079 * _chgsign (MSVCRT.@)
1081 double CDECL MSVCRT__chgsign(double num)
1083 /* FIXME: +-infinity,Nan not tested */
1084 return -num;
1087 /*********************************************************************
1088 * __control87_2 (MSVCRT.@)
1090 * Not exported by native msvcrt, added in msvcr80.
1092 #if defined(__i386__) || defined(__x86_64__)
1093 int CDECL __control87_2( unsigned int newval, unsigned int mask,
1094 unsigned int *x86_cw, unsigned int *sse2_cw )
1096 #ifdef __GNUC__
1097 unsigned long fpword;
1098 unsigned int flags;
1100 if (x86_cw)
1102 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
1104 /* Convert into mask constants */
1105 flags = 0;
1106 if (fpword & 0x1) flags |= MSVCRT__EM_INVALID;
1107 if (fpword & 0x2) flags |= MSVCRT__EM_DENORMAL;
1108 if (fpword & 0x4) flags |= MSVCRT__EM_ZERODIVIDE;
1109 if (fpword & 0x8) flags |= MSVCRT__EM_OVERFLOW;
1110 if (fpword & 0x10) flags |= MSVCRT__EM_UNDERFLOW;
1111 if (fpword & 0x20) flags |= MSVCRT__EM_INEXACT;
1112 switch (fpword & 0xc00)
1114 case 0xc00: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
1115 case 0x800: flags |= MSVCRT__RC_UP; break;
1116 case 0x400: flags |= MSVCRT__RC_DOWN; break;
1118 switch (fpword & 0x300)
1120 case 0x0: flags |= MSVCRT__PC_24; break;
1121 case 0x200: flags |= MSVCRT__PC_53; break;
1122 case 0x300: flags |= MSVCRT__PC_64; break;
1124 if (fpword & 0x1000) flags |= MSVCRT__IC_AFFINE;
1126 TRACE( "x86 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
1127 if (mask)
1129 flags = (flags & ~mask) | (newval & mask);
1131 /* Convert (masked) value back to fp word */
1132 fpword = 0;
1133 if (flags & MSVCRT__EM_INVALID) fpword |= 0x1;
1134 if (flags & MSVCRT__EM_DENORMAL) fpword |= 0x2;
1135 if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x4;
1136 if (flags & MSVCRT__EM_OVERFLOW) fpword |= 0x8;
1137 if (flags & MSVCRT__EM_UNDERFLOW) fpword |= 0x10;
1138 if (flags & MSVCRT__EM_INEXACT) fpword |= 0x20;
1139 switch (flags & MSVCRT__MCW_RC)
1141 case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0xc00; break;
1142 case MSVCRT__RC_UP: fpword |= 0x800; break;
1143 case MSVCRT__RC_DOWN: fpword |= 0x400; break;
1145 switch (flags & MSVCRT__MCW_PC)
1147 case MSVCRT__PC_64: fpword |= 0x300; break;
1148 case MSVCRT__PC_53: fpword |= 0x200; break;
1149 case MSVCRT__PC_24: fpword |= 0x0; break;
1151 if (flags & MSVCRT__IC_AFFINE) fpword |= 0x1000;
1153 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1155 *x86_cw = flags;
1158 if (!sse2_cw) return 1;
1160 if (sse2_supported)
1162 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
1164 /* Convert into mask constants */
1165 flags = 0;
1166 if (fpword & 0x80) flags |= MSVCRT__EM_INVALID;
1167 if (fpword & 0x100) flags |= MSVCRT__EM_DENORMAL;
1168 if (fpword & 0x200) flags |= MSVCRT__EM_ZERODIVIDE;
1169 if (fpword & 0x400) flags |= MSVCRT__EM_OVERFLOW;
1170 if (fpword & 0x800) flags |= MSVCRT__EM_UNDERFLOW;
1171 if (fpword & 0x1000) flags |= MSVCRT__EM_INEXACT;
1172 switch (fpword & 0x6000)
1174 case 0x6000: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
1175 case 0x4000: flags |= MSVCRT__RC_UP; break;
1176 case 0x2000: flags |= MSVCRT__RC_DOWN; break;
1178 switch (fpword & 0x8040)
1180 case 0x0040: flags |= MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
1181 case 0x8000: flags |= MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
1182 case 0x8040: flags |= MSVCRT__DN_FLUSH; break;
1185 TRACE( "sse2 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
1186 if (mask)
1188 flags = (flags & ~mask) | (newval & mask);
1190 /* Convert (masked) value back to fp word */
1191 fpword = 0;
1192 if (flags & MSVCRT__EM_INVALID) fpword |= 0x80;
1193 if (flags & MSVCRT__EM_DENORMAL) fpword |= 0x100;
1194 if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
1195 if (flags & MSVCRT__EM_OVERFLOW) fpword |= 0x400;
1196 if (flags & MSVCRT__EM_UNDERFLOW) fpword |= 0x800;
1197 if (flags & MSVCRT__EM_INEXACT) fpword |= 0x1000;
1198 switch (flags & MSVCRT__MCW_RC)
1200 case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0x6000; break;
1201 case MSVCRT__RC_UP: fpword |= 0x4000; break;
1202 case MSVCRT__RC_DOWN: fpword |= 0x2000; break;
1204 switch (flags & MSVCRT__MCW_DN)
1206 case MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
1207 case MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
1208 case MSVCRT__DN_FLUSH: fpword |= 0x8040; break;
1210 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
1212 *sse2_cw = flags;
1214 else *sse2_cw = 0;
1216 return 1;
1217 #else
1218 FIXME( "not implemented\n" );
1219 return 0;
1220 #endif
1222 #endif
1224 /*********************************************************************
1225 * _control87 (MSVCRT.@)
1227 unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
1229 #if defined(__i386__) || defined(__x86_64__)
1230 unsigned int x86_cw, sse2_cw;
1232 __control87_2( newval, mask, &x86_cw, &sse2_cw );
1234 if ((x86_cw ^ sse2_cw) & (MSVCRT__MCW_EM | MSVCRT__MCW_RC)) x86_cw |= MSVCRT__EM_AMBIGUOUS;
1235 return x86_cw;
1236 #else
1237 FIXME( "not implemented\n" );
1238 return 0;
1239 #endif
1242 /*********************************************************************
1243 * _controlfp (MSVCRT.@)
1245 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
1247 return _control87( newval, mask & ~MSVCRT__EM_DENORMAL );
1250 /*********************************************************************
1251 * _set_controlfp (MSVCRT.@)
1253 void CDECL _set_controlfp( unsigned int newval, unsigned int mask )
1255 _controlfp( newval, mask );
1258 /*********************************************************************
1259 * _controlfp_s (MSVCRT.@)
1261 int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
1263 static const unsigned int all_flags = (MSVCRT__MCW_EM | MSVCRT__MCW_IC | MSVCRT__MCW_RC |
1264 MSVCRT__MCW_PC | MSVCRT__MCW_DN);
1265 unsigned int val;
1267 if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
1269 if (cur) *cur = _controlfp( 0, 0 ); /* retrieve it anyway */
1270 return MSVCRT_EINVAL;
1272 val = _controlfp( newval, mask );
1273 if (cur) *cur = val;
1274 return 0;
1277 /*********************************************************************
1278 * fegetenv (MSVCR120.@)
1280 int CDECL MSVCRT_fegetenv(MSVCRT_fenv_t *env)
1282 env->control = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW |
1283 MSVCRT__EM_OVERFLOW | MSVCRT__EM_ZERODIVIDE | MSVCRT__EM_INVALID);
1284 env->status = _statusfp();
1285 return 0;
1288 /*********************************************************************
1289 * __fpe_flt_rounds (UCRTBASE.@)
1291 int CDECL __fpe_flt_rounds(void)
1293 unsigned int fpc = _controlfp(0, 0) & MSVCRT__RC_CHOP;
1295 TRACE("()\n");
1297 switch(fpc) {
1298 case MSVCRT__RC_CHOP: return 0;
1299 case MSVCRT__RC_NEAR: return 1;
1300 #ifdef _WIN64
1301 case MSVCRT__RC_UP: return 3;
1302 default: return 2;
1303 #else
1304 case MSVCRT__RC_UP: return 2;
1305 default: return 3;
1306 #endif
1310 /*********************************************************************
1311 * fegetround (MSVCR120.@)
1313 int CDECL MSVCRT_fegetround(void)
1315 return _controlfp(0, 0) & MSVCRT__RC_CHOP;
1318 /*********************************************************************
1319 * fesetround (MSVCR120.@)
1321 int CDECL MSVCRT_fesetround(int round_mode)
1323 if (round_mode & (~MSVCRT__RC_CHOP))
1324 return 1;
1325 _controlfp(round_mode, MSVCRT__RC_CHOP);
1326 return 0;
1329 /*********************************************************************
1330 * _copysign (MSVCRT.@)
1332 double CDECL MSVCRT__copysign(double num, double sign)
1334 if (signbit(sign))
1335 return signbit(num) ? num : -num;
1336 return signbit(num) ? -num : num;
1339 /*********************************************************************
1340 * _finite (MSVCRT.@)
1342 int CDECL MSVCRT__finite(double num)
1344 return isfinite(num) != 0; /* See comment for _isnan() */
1347 /*********************************************************************
1348 * _fpreset (MSVCRT.@)
1350 void CDECL _fpreset(void)
1352 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1353 const unsigned int x86_cw = 0x27f;
1354 __asm__ __volatile__( "fninit; fldcw %0" : : "m" (x86_cw) );
1355 if (sse2_supported)
1357 const unsigned long sse2_cw = 0x1f80;
1358 __asm__ __volatile__( "ldmxcsr %0" : : "m" (sse2_cw) );
1360 #else
1361 FIXME( "not implemented\n" );
1362 #endif
1365 /*********************************************************************
1366 * fesetenv (MSVCR120.@)
1368 int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
1370 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1371 struct {
1372 WORD control_word;
1373 WORD unused1;
1374 WORD status_word;
1375 WORD unused2;
1376 WORD tag_word;
1377 WORD unused3;
1378 DWORD instruction_pointer;
1379 WORD code_segment;
1380 WORD unused4;
1381 DWORD operand_addr;
1382 WORD data_segment;
1383 WORD unused5;
1384 } fenv;
1386 TRACE( "(%p)\n", env );
1388 if (!env->control && !env->status) {
1389 _fpreset();
1390 return 0;
1393 __asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
1395 fenv.control_word &= ~0x3d;
1396 if (env->control & MSVCRT__EM_INVALID) fenv.control_word |= 0x1;
1397 if (env->control & MSVCRT__EM_ZERODIVIDE) fenv.control_word |= 0x4;
1398 if (env->control & MSVCRT__EM_OVERFLOW) fenv.control_word |= 0x8;
1399 if (env->control & MSVCRT__EM_UNDERFLOW) fenv.control_word |= 0x10;
1400 if (env->control & MSVCRT__EM_INEXACT) fenv.control_word |= 0x20;
1402 fenv.status_word &= ~0x3d;
1403 if (env->status & MSVCRT__SW_INVALID) fenv.status_word |= 0x1;
1404 if (env->status & MSVCRT__SW_ZERODIVIDE) fenv.status_word |= 0x4;
1405 if (env->status & MSVCRT__SW_OVERFLOW) fenv.status_word |= 0x8;
1406 if (env->status & MSVCRT__SW_UNDERFLOW) fenv.status_word |= 0x10;
1407 if (env->status & MSVCRT__SW_INEXACT) fenv.status_word |= 0x20;
1409 __asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)",
1410 "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
1412 if (sse2_supported)
1414 DWORD fpword;
1416 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
1417 fpword &= ~0x1e80;
1418 if (env->control & MSVCRT__EM_INVALID) fpword |= 0x80;
1419 if (env->control & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
1420 if (env->control & MSVCRT__EM_OVERFLOW) fpword |= 0x400;
1421 if (env->control & MSVCRT__EM_UNDERFLOW) fpword |= 0x800;
1422 if (env->control & MSVCRT__EM_INEXACT) fpword |= 0x1000;
1423 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
1426 return 0;
1427 #else
1428 FIXME( "not implemented\n" );
1429 #endif
1430 return 1;
1433 /*********************************************************************
1434 * _isnan (MSVCRT.@)
1436 INT CDECL MSVCRT__isnan(double num)
1438 /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
1439 * Do the same, as the result may be used in calculations
1441 return isnan(num) != 0;
1444 /*********************************************************************
1445 * _j0 (MSVCRT.@)
1447 double CDECL MSVCRT__j0(double num)
1449 /* FIXME: errno handling */
1450 return j0(num);
1453 /*********************************************************************
1454 * _j1 (MSVCRT.@)
1456 double CDECL MSVCRT__j1(double num)
1458 /* FIXME: errno handling */
1459 return j1(num);
1462 /*********************************************************************
1463 * _jn (MSVCRT.@)
1465 double CDECL MSVCRT__jn(int n, double num)
1467 /* FIXME: errno handling */
1468 return jn(n, num);
1471 /*********************************************************************
1472 * _y0 (MSVCRT.@)
1474 double CDECL MSVCRT__y0(double num)
1476 double retval;
1477 if (!isfinite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1478 retval = y0(num);
1479 if (MSVCRT__fpclass(retval) == MSVCRT__FPCLASS_NINF)
1481 *MSVCRT__errno() = MSVCRT_EDOM;
1482 retval = sqrt(-1);
1484 return retval;
1487 /*********************************************************************
1488 * _y1 (MSVCRT.@)
1490 double CDECL MSVCRT__y1(double num)
1492 double retval;
1493 if (!isfinite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1494 retval = y1(num);
1495 if (MSVCRT__fpclass(retval) == MSVCRT__FPCLASS_NINF)
1497 *MSVCRT__errno() = MSVCRT_EDOM;
1498 retval = sqrt(-1);
1500 return retval;
1503 /*********************************************************************
1504 * _yn (MSVCRT.@)
1506 double CDECL MSVCRT__yn(int order, double num)
1508 double retval;
1509 if (!isfinite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
1510 retval = yn(order,num);
1511 if (MSVCRT__fpclass(retval) == MSVCRT__FPCLASS_NINF)
1513 *MSVCRT__errno() = MSVCRT_EDOM;
1514 retval = sqrt(-1);
1516 return retval;
1519 /*********************************************************************
1520 * _nearbyint (MSVCRT.@)
1522 double CDECL MSVCRT_nearbyint(double num)
1524 #ifdef HAVE_NEARBYINT
1525 return nearbyint(num);
1526 #else
1527 return num >= 0 ? floor(num + 0.5) : ceil(num - 0.5);
1528 #endif
1531 /*********************************************************************
1532 * _nearbyintf (MSVCRT.@)
1534 float CDECL MSVCRT_nearbyintf(float num)
1536 #ifdef HAVE_NEARBYINTF
1537 return nearbyintf(num);
1538 #else
1539 return MSVCRT_nearbyint(num);
1540 #endif
1543 /*********************************************************************
1544 * _nextafter (MSVCRT.@)
1546 double CDECL MSVCRT__nextafter(double num, double next)
1548 double retval;
1549 if (!isfinite(num) || !isfinite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
1550 retval = nextafter(num,next);
1551 return retval;
1554 /*********************************************************************
1555 * _ecvt (MSVCRT.@)
1557 char * CDECL MSVCRT__ecvt( double number, int ndigits, int *decpt, int *sign )
1559 int prec, len;
1560 thread_data_t *data = msvcrt_get_thread_data();
1561 /* FIXME: check better for overflow (native supports over 300 chars) */
1562 ndigits = min( ndigits, 80 - 7); /* 7 : space for dec point, 1 for "e",
1563 * 4 for exponent and one for
1564 * terminating '\0' */
1565 if (!data->efcvt_buffer)
1566 data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
1568 if( number < 0) {
1569 *sign = TRUE;
1570 number = -number;
1571 } else
1572 *sign = FALSE;
1573 /* handle cases with zero ndigits or less */
1574 prec = ndigits;
1575 if( prec < 1) prec = 2;
1576 len = snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number);
1577 /* take the decimal "point away */
1578 if( prec != 1)
1579 memmove( data->efcvt_buffer + 1, data->efcvt_buffer + 2, len - 1 );
1580 /* take the exponential "e" out */
1581 data->efcvt_buffer[ prec] = '\0';
1582 /* read the exponent */
1583 sscanf( data->efcvt_buffer + prec + 1, "%d", decpt);
1584 (*decpt)++;
1585 /* adjust for some border cases */
1586 if( data->efcvt_buffer[0] == '0')/* value is zero */
1587 *decpt = 0;
1588 /* handle cases with zero ndigits or less */
1589 if( ndigits < 1){
1590 if( data->efcvt_buffer[ 0] >= '5')
1591 (*decpt)++;
1592 data->efcvt_buffer[ 0] = '\0';
1594 TRACE("out=\"%s\"\n",data->efcvt_buffer);
1595 return data->efcvt_buffer;
1598 /*********************************************************************
1599 * _ecvt_s (MSVCRT.@)
1601 int CDECL MSVCRT__ecvt_s( char *buffer, MSVCRT_size_t length, double number, int ndigits, int *decpt, int *sign )
1603 int prec, len;
1604 char *result;
1605 const char infret[] = "1#INF";
1607 if (!MSVCRT_CHECK_PMT(buffer != NULL)) return MSVCRT_EINVAL;
1608 if (!MSVCRT_CHECK_PMT(decpt != NULL)) return MSVCRT_EINVAL;
1609 if (!MSVCRT_CHECK_PMT(sign != NULL)) return MSVCRT_EINVAL;
1610 if (!MSVCRT_CHECK_PMT_ERR( length > 2, MSVCRT_ERANGE )) return MSVCRT_ERANGE;
1611 if (!MSVCRT_CHECK_PMT_ERR(ndigits < (int)length - 1, MSVCRT_ERANGE )) return MSVCRT_ERANGE;
1613 /* special case - inf */
1614 if(number == HUGE_VAL || number == -HUGE_VAL)
1616 memset(buffer, '0', ndigits);
1617 memcpy(buffer, infret, min(ndigits, sizeof(infret) - 1 ) );
1618 buffer[ndigits] = '\0';
1619 (*decpt) = 1;
1620 if(number == -HUGE_VAL)
1621 (*sign) = 1;
1622 else
1623 (*sign) = 0;
1624 return 0;
1626 /* handle cases with zero ndigits or less */
1627 prec = ndigits;
1628 if( prec < 1) prec = 2;
1629 result = MSVCRT_malloc(prec + 7);
1631 if( number < 0) {
1632 *sign = TRUE;
1633 number = -number;
1634 } else
1635 *sign = FALSE;
1636 len = snprintf(result, prec + 7, "%.*le", prec - 1, number);
1637 /* take the decimal "point away */
1638 if( prec != 1)
1639 memmove( result + 1, result + 2, len - 1 );
1640 /* take the exponential "e" out */
1641 result[ prec] = '\0';
1642 /* read the exponent */
1643 sscanf( result + prec + 1, "%d", decpt);
1644 (*decpt)++;
1645 /* adjust for some border cases */
1646 if( result[0] == '0')/* value is zero */
1647 *decpt = 0;
1648 /* handle cases with zero ndigits or less */
1649 if( ndigits < 1){
1650 if( result[ 0] >= '5')
1651 (*decpt)++;
1652 result[ 0] = '\0';
1654 memcpy( buffer, result, max(ndigits + 1, 1) );
1655 MSVCRT_free( result );
1656 return 0;
1659 /***********************************************************************
1660 * _fcvt (MSVCRT.@)
1662 char * CDECL MSVCRT__fcvt( double number, int ndigits, int *decpt, int *sign )
1664 thread_data_t *data = msvcrt_get_thread_data();
1665 int stop, dec1, dec2;
1666 char *ptr1, *ptr2, *first;
1667 char buf[80]; /* ought to be enough */
1669 if (!data->efcvt_buffer)
1670 data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
1672 if (number < 0)
1674 *sign = 1;
1675 number = -number;
1676 } else *sign = 0;
1678 stop = snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1679 ptr1 = buf;
1680 ptr2 = data->efcvt_buffer;
1681 first = NULL;
1682 dec1 = 0;
1683 dec2 = 0;
1685 /* For numbers below the requested resolution, work out where
1686 the decimal point will be rather than finding it in the string */
1687 if (number < 1.0 && number > 0.0) {
1688 dec2 = log10(number + 1e-10);
1689 if (-dec2 <= ndigits) dec2 = 0;
1692 /* If requested digits is zero or less, we will need to truncate
1693 * the returned string */
1694 if (ndigits < 1) {
1695 stop += ndigits;
1698 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1699 while (*ptr1 != '\0' && *ptr1 != '.') {
1700 if (!first) first = ptr2;
1701 if ((ptr1 - buf) < stop) {
1702 *ptr2++ = *ptr1++;
1703 } else {
1704 ptr1++;
1706 dec1++;
1709 if (ndigits > 0) {
1710 ptr1++;
1711 if (!first) {
1712 while (*ptr1 == '0') { /* Process leading zeroes */
1713 *ptr2++ = *ptr1++;
1714 dec1--;
1717 while (*ptr1 != '\0') {
1718 if (!first) first = ptr2;
1719 *ptr2++ = *ptr1++;
1723 *ptr2 = '\0';
1725 /* We never found a non-zero digit, then our number is either
1726 * smaller than the requested precision, or 0.0 */
1727 if (!first) {
1728 if (number > 0.0) {
1729 first = ptr2;
1730 } else {
1731 first = data->efcvt_buffer;
1732 dec1 = 0;
1736 *decpt = dec2 ? dec2 : dec1;
1737 return first;
1740 /***********************************************************************
1741 * _fcvt_s (MSVCRT.@)
1743 int CDECL MSVCRT__fcvt_s(char* outbuffer, MSVCRT_size_t size, double number, int ndigits, int *decpt, int *sign)
1745 int stop, dec1, dec2;
1746 char *ptr1, *ptr2, *first;
1747 char buf[80]; /* ought to be enough */
1749 if (!outbuffer || !decpt || !sign || size == 0)
1751 *MSVCRT__errno() = MSVCRT_EINVAL;
1752 return MSVCRT_EINVAL;
1755 if (number < 0)
1757 *sign = 1;
1758 number = -number;
1759 } else *sign = 0;
1761 stop = snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1762 ptr1 = buf;
1763 ptr2 = outbuffer;
1764 first = NULL;
1765 dec1 = 0;
1766 dec2 = 0;
1768 /* For numbers below the requested resolution, work out where
1769 the decimal point will be rather than finding it in the string */
1770 if (number < 1.0 && number > 0.0) {
1771 dec2 = log10(number + 1e-10);
1772 if (-dec2 <= ndigits) dec2 = 0;
1775 /* If requested digits is zero or less, we will need to truncate
1776 * the returned string */
1777 if (ndigits < 1) {
1778 stop += ndigits;
1781 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1782 while (*ptr1 != '\0' && *ptr1 != '.') {
1783 if (!first) first = ptr2;
1784 if ((ptr1 - buf) < stop) {
1785 if (size > 1) {
1786 *ptr2++ = *ptr1++;
1787 size--;
1789 } else {
1790 ptr1++;
1792 dec1++;
1795 if (ndigits > 0) {
1796 ptr1++;
1797 if (!first) {
1798 while (*ptr1 == '0') { /* Process leading zeroes */
1799 if (number == 0.0 && size > 1) {
1800 *ptr2++ = '0';
1801 size--;
1803 ptr1++;
1804 dec1--;
1807 while (*ptr1 != '\0') {
1808 if (!first) first = ptr2;
1809 if (size > 1) {
1810 *ptr2++ = *ptr1++;
1811 size--;
1816 *ptr2 = '\0';
1818 /* We never found a non-zero digit, then our number is either
1819 * smaller than the requested precision, or 0.0 */
1820 if (!first && (number <= 0.0))
1821 dec1 = 0;
1823 *decpt = dec2 ? dec2 : dec1;
1824 return 0;
1827 /***********************************************************************
1828 * _gcvt (MSVCRT.@)
1830 char * CDECL MSVCRT__gcvt( double number, int ndigit, char *buff )
1832 if(!buff) {
1833 *MSVCRT__errno() = MSVCRT_EINVAL;
1834 return NULL;
1837 if(ndigit < 0) {
1838 *MSVCRT__errno() = MSVCRT_ERANGE;
1839 return NULL;
1842 MSVCRT_sprintf(buff, "%.*g", ndigit, number);
1843 return buff;
1846 /***********************************************************************
1847 * _gcvt_s (MSVCRT.@)
1849 int CDECL MSVCRT__gcvt_s(char *buff, MSVCRT_size_t size, double number, int digits)
1851 int len;
1853 if(!buff) {
1854 *MSVCRT__errno() = MSVCRT_EINVAL;
1855 return MSVCRT_EINVAL;
1858 if( digits<0 || digits>=size) {
1859 if(size)
1860 buff[0] = '\0';
1862 *MSVCRT__errno() = MSVCRT_ERANGE;
1863 return MSVCRT_ERANGE;
1866 len = MSVCRT__scprintf("%.*g", digits, number);
1867 if(len > size) {
1868 buff[0] = '\0';
1869 *MSVCRT__errno() = MSVCRT_ERANGE;
1870 return MSVCRT_ERANGE;
1873 MSVCRT_sprintf(buff, "%.*g", digits, number);
1874 return 0;
1877 #include <stdlib.h> /* div_t, ldiv_t */
1879 /*********************************************************************
1880 * div (MSVCRT.@)
1881 * VERSION
1882 * [i386] Windows binary compatible - returns the struct in eax/edx.
1884 #ifdef __i386__
1885 unsigned __int64 CDECL MSVCRT_div(int num, int denom)
1887 div_t dt = div(num,denom);
1888 return ((unsigned __int64)dt.rem << 32) | (unsigned int)dt.quot;
1890 #else
1891 /*********************************************************************
1892 * div (MSVCRT.@)
1893 * VERSION
1894 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1896 MSVCRT_div_t CDECL MSVCRT_div(int num, int denom)
1898 div_t dt = div(num,denom);
1899 MSVCRT_div_t ret;
1900 ret.quot = dt.quot;
1901 ret.rem = dt.rem;
1903 return ret;
1906 #endif /* ifdef __i386__ */
1909 /*********************************************************************
1910 * ldiv (MSVCRT.@)
1911 * VERSION
1912 * [i386] Windows binary compatible - returns the struct in eax/edx.
1914 #ifdef __i386__
1915 unsigned __int64 CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
1917 ldiv_t ldt = ldiv(num,denom);
1918 return ((unsigned __int64)ldt.rem << 32) | (MSVCRT_ulong)ldt.quot;
1920 #else
1921 /*********************************************************************
1922 * ldiv (MSVCRT.@)
1923 * VERSION
1924 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1926 MSVCRT_ldiv_t CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
1928 ldiv_t result = ldiv(num,denom);
1930 MSVCRT_ldiv_t ret;
1931 ret.quot = result.quot;
1932 ret.rem = result.rem;
1934 return ret;
1936 #endif /* ifdef __i386__ */
1938 /*********************************************************************
1939 * lldiv (MSVCRT.@)
1941 MSVCRT_lldiv_t CDECL MSVCRT_lldiv(MSVCRT_longlong num, MSVCRT_longlong denom)
1943 MSVCRT_lldiv_t ret;
1945 ret.quot = num / denom;
1946 ret.rem = num % denom;
1948 return ret;
1951 #ifdef __i386__
1953 /*********************************************************************
1954 * _adjust_fdiv (MSVCRT.@)
1955 * Used by the MSVC compiler to work around the Pentium FDIV bug.
1957 int MSVCRT__adjust_fdiv = 0;
1959 /***********************************************************************
1960 * _adj_fdiv_m16i (MSVCRT.@)
1962 * NOTE
1963 * I _think_ this function is intended to work around the Pentium
1964 * fdiv bug.
1966 void __stdcall _adj_fdiv_m16i( short arg )
1968 TRACE("(): stub\n");
1971 /***********************************************************************
1972 * _adj_fdiv_m32 (MSVCRT.@)
1974 * NOTE
1975 * I _think_ this function is intended to work around the Pentium
1976 * fdiv bug.
1978 void __stdcall _adj_fdiv_m32( unsigned int arg )
1980 TRACE("(): stub\n");
1983 /***********************************************************************
1984 * _adj_fdiv_m32i (MSVCRT.@)
1986 * NOTE
1987 * I _think_ this function is intended to work around the Pentium
1988 * fdiv bug.
1990 void __stdcall _adj_fdiv_m32i( int arg )
1992 TRACE("(): stub\n");
1995 /***********************************************************************
1996 * _adj_fdiv_m64 (MSVCRT.@)
1998 * NOTE
1999 * I _think_ this function is intended to work around the Pentium
2000 * fdiv bug.
2002 void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
2004 TRACE("(): stub\n");
2007 /***********************************************************************
2008 * _adj_fdiv_r (MSVCRT.@)
2009 * FIXME
2010 * This function is likely to have the wrong number of arguments.
2012 * NOTE
2013 * I _think_ this function is intended to work around the Pentium
2014 * fdiv bug.
2016 void _adj_fdiv_r(void)
2018 TRACE("(): stub\n");
2021 /***********************************************************************
2022 * _adj_fdivr_m16i (MSVCRT.@)
2024 * NOTE
2025 * I _think_ this function is intended to work around the Pentium
2026 * fdiv bug.
2028 void __stdcall _adj_fdivr_m16i( short arg )
2030 TRACE("(): stub\n");
2033 /***********************************************************************
2034 * _adj_fdivr_m32 (MSVCRT.@)
2036 * NOTE
2037 * I _think_ this function is intended to work around the Pentium
2038 * fdiv bug.
2040 void __stdcall _adj_fdivr_m32( unsigned int arg )
2042 TRACE("(): stub\n");
2045 /***********************************************************************
2046 * _adj_fdivr_m32i (MSVCRT.@)
2048 * NOTE
2049 * I _think_ this function is intended to work around the Pentium
2050 * fdiv bug.
2052 void __stdcall _adj_fdivr_m32i( int arg )
2054 TRACE("(): stub\n");
2057 /***********************************************************************
2058 * _adj_fdivr_m64 (MSVCRT.@)
2060 * NOTE
2061 * I _think_ this function is intended to work around the Pentium
2062 * fdiv bug.
2064 void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
2066 TRACE("(): stub\n");
2069 /***********************************************************************
2070 * _adj_fpatan (MSVCRT.@)
2071 * FIXME
2072 * This function is likely to have the wrong number of arguments.
2074 * NOTE
2075 * I _think_ this function is intended to work around the Pentium
2076 * fdiv bug.
2078 void _adj_fpatan(void)
2080 TRACE("(): stub\n");
2083 /***********************************************************************
2084 * _adj_fprem (MSVCRT.@)
2085 * FIXME
2086 * This function is likely to have the wrong number of arguments.
2088 * NOTE
2089 * I _think_ this function is intended to work around the Pentium
2090 * fdiv bug.
2092 void _adj_fprem(void)
2094 TRACE("(): stub\n");
2097 /***********************************************************************
2098 * _adj_fprem1 (MSVCRT.@)
2099 * FIXME
2100 * This function is likely to have the wrong number of arguments.
2102 * NOTE
2103 * I _think_ this function is intended to work around the Pentium
2104 * fdiv bug.
2106 void _adj_fprem1(void)
2108 TRACE("(): stub\n");
2111 /***********************************************************************
2112 * _adj_fptan (MSVCRT.@)
2113 * FIXME
2114 * This function is likely to have the wrong number of arguments.
2116 * NOTE
2117 * I _think_ this function is intended to work around the Pentium
2118 * fdiv bug.
2120 void _adj_fptan(void)
2122 TRACE("(): stub\n");
2125 /***********************************************************************
2126 * _safe_fdiv (MSVCRT.@)
2127 * FIXME
2128 * This function is likely to have the wrong number of arguments.
2130 * NOTE
2131 * I _think_ this function is intended to work around the Pentium
2132 * fdiv bug.
2134 void _safe_fdiv(void)
2136 TRACE("(): stub\n");
2139 /***********************************************************************
2140 * _safe_fdivr (MSVCRT.@)
2141 * FIXME
2142 * This function is likely to have the wrong number of arguments.
2144 * NOTE
2145 * I _think_ this function is intended to work around the Pentium
2146 * fdiv bug.
2148 void _safe_fdivr(void)
2150 TRACE("(): stub\n");
2153 /***********************************************************************
2154 * _safe_fprem (MSVCRT.@)
2155 * FIXME
2156 * This function is likely to have the wrong number of arguments.
2158 * NOTE
2159 * I _think_ this function is intended to work around the Pentium
2160 * fdiv bug.
2162 void _safe_fprem(void)
2164 TRACE("(): stub\n");
2167 /***********************************************************************
2168 * _safe_fprem1 (MSVCRT.@)
2170 * FIXME
2171 * This function is likely to have the wrong number of arguments.
2173 * NOTE
2174 * I _think_ this function is intended to work around the Pentium
2175 * fdiv bug.
2177 void _safe_fprem1(void)
2179 TRACE("(): stub\n");
2182 /***********************************************************************
2183 * __libm_sse2_acos (MSVCRT.@)
2185 void __cdecl MSVCRT___libm_sse2_acos(void)
2187 double d;
2188 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2189 d = acos( d );
2190 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2193 /***********************************************************************
2194 * __libm_sse2_acosf (MSVCRT.@)
2196 void __cdecl MSVCRT___libm_sse2_acosf(void)
2198 float f;
2199 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2200 f = acosf( f );
2201 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2204 /***********************************************************************
2205 * __libm_sse2_asin (MSVCRT.@)
2207 void __cdecl MSVCRT___libm_sse2_asin(void)
2209 double d;
2210 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2211 d = asin( d );
2212 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2215 /***********************************************************************
2216 * __libm_sse2_asinf (MSVCRT.@)
2218 void __cdecl MSVCRT___libm_sse2_asinf(void)
2220 float f;
2221 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2222 f = asinf( f );
2223 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2226 /***********************************************************************
2227 * __libm_sse2_atan (MSVCRT.@)
2229 void __cdecl MSVCRT___libm_sse2_atan(void)
2231 double d;
2232 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2233 d = atan( d );
2234 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2237 /***********************************************************************
2238 * __libm_sse2_atan2 (MSVCRT.@)
2240 void __cdecl MSVCRT___libm_sse2_atan2(void)
2242 double d1, d2;
2243 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
2244 d1 = atan2( d1, d2 );
2245 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
2248 /***********************************************************************
2249 * __libm_sse2_atanf (MSVCRT.@)
2251 void __cdecl MSVCRT___libm_sse2_atanf(void)
2253 float f;
2254 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2255 f = atanf( f );
2256 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2259 /***********************************************************************
2260 * __libm_sse2_cos (MSVCRT.@)
2262 void __cdecl MSVCRT___libm_sse2_cos(void)
2264 double d;
2265 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2266 d = cos( d );
2267 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2270 /***********************************************************************
2271 * __libm_sse2_cosf (MSVCRT.@)
2273 void __cdecl MSVCRT___libm_sse2_cosf(void)
2275 float f;
2276 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2277 f = cosf( f );
2278 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2281 /***********************************************************************
2282 * __libm_sse2_exp (MSVCRT.@)
2284 void __cdecl MSVCRT___libm_sse2_exp(void)
2286 double d;
2287 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2288 d = exp( d );
2289 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2292 /***********************************************************************
2293 * __libm_sse2_expf (MSVCRT.@)
2295 void __cdecl MSVCRT___libm_sse2_expf(void)
2297 float f;
2298 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2299 f = expf( f );
2300 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2303 /***********************************************************************
2304 * __libm_sse2_log (MSVCRT.@)
2306 void __cdecl MSVCRT___libm_sse2_log(void)
2308 double d;
2309 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2310 d = log( d );
2311 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2314 /***********************************************************************
2315 * __libm_sse2_log10 (MSVCRT.@)
2317 void __cdecl MSVCRT___libm_sse2_log10(void)
2319 double d;
2320 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2321 d = log10( d );
2322 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2325 /***********************************************************************
2326 * __libm_sse2_log10f (MSVCRT.@)
2328 void __cdecl MSVCRT___libm_sse2_log10f(void)
2330 float f;
2331 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2332 f = log10f( f );
2333 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2336 /***********************************************************************
2337 * __libm_sse2_logf (MSVCRT.@)
2339 void __cdecl MSVCRT___libm_sse2_logf(void)
2341 float f;
2342 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2343 f = logf( f );
2344 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2347 /***********************************************************************
2348 * __libm_sse2_pow (MSVCRT.@)
2350 void __cdecl MSVCRT___libm_sse2_pow(void)
2352 double d1, d2;
2353 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
2354 d1 = pow( d1, d2 );
2355 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
2358 /***********************************************************************
2359 * __libm_sse2_powf (MSVCRT.@)
2361 void __cdecl MSVCRT___libm_sse2_powf(void)
2363 float f1, f2;
2364 __asm__ __volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1), "=g" (f2) );
2365 f1 = powf( f1, f2 );
2366 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f1) );
2369 /***********************************************************************
2370 * __libm_sse2_sin (MSVCRT.@)
2372 void __cdecl MSVCRT___libm_sse2_sin(void)
2374 double d;
2375 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2376 d = sin( d );
2377 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2380 /***********************************************************************
2381 * __libm_sse2_sinf (MSVCRT.@)
2383 void __cdecl MSVCRT___libm_sse2_sinf(void)
2385 float f;
2386 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2387 f = sinf( f );
2388 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2391 /***********************************************************************
2392 * __libm_sse2_tan (MSVCRT.@)
2394 void __cdecl MSVCRT___libm_sse2_tan(void)
2396 double d;
2397 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2398 d = tan( d );
2399 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2402 /***********************************************************************
2403 * __libm_sse2_tanf (MSVCRT.@)
2405 void __cdecl MSVCRT___libm_sse2_tanf(void)
2407 float f;
2408 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2409 f = tanf( f );
2410 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2413 /***********************************************************************
2414 * __libm_sse2_sqrt_precise (MSVCR110.@)
2416 void __cdecl MSVCRT___libm_sse2_sqrt_precise(void)
2418 double d;
2419 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2420 d = sqrt( d );
2421 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2424 #endif /* __i386__ */
2426 /*********************************************************************
2427 * cbrt (MSVCR120.@)
2429 double CDECL MSVCR120_cbrt(double x)
2431 #ifdef HAVE_CBRT
2432 return cbrt(x);
2433 #else
2434 return x < 0 ? -pow(-x, 1.0 / 3.0) : pow(x, 1.0 / 3.0);
2435 #endif
2438 /*********************************************************************
2439 * cbrtf (MSVCR120.@)
2441 float CDECL MSVCR120_cbrtf(float x)
2443 #ifdef HAVE_CBRTF
2444 return cbrtf(x);
2445 #else
2446 return MSVCR120_cbrt(x);
2447 #endif
2450 /*********************************************************************
2451 * cbrtl (MSVCR120.@)
2453 LDOUBLE CDECL MSVCR120_cbrtl(LDOUBLE x)
2455 return MSVCR120_cbrt(x);
2458 /*********************************************************************
2459 * exp2 (MSVCR120.@)
2461 double CDECL MSVCR120_exp2(double x)
2463 #ifdef HAVE_EXP2
2464 double ret = exp2(x);
2465 #else
2466 double ret = pow(2, x);
2467 #endif
2468 if (isfinite(x) && !isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
2469 return ret;
2472 /*********************************************************************
2473 * exp2f (MSVCR120.@)
2475 float CDECL MSVCR120_exp2f(float x)
2477 #ifdef HAVE_EXP2F
2478 float ret = exp2f(x);
2479 if (finitef(x) && !finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
2480 return ret;
2481 #else
2482 return MSVCR120_exp2(x);
2483 #endif
2486 /*********************************************************************
2487 * exp2l (MSVCR120.@)
2489 LDOUBLE CDECL MSVCR120_exp2l(LDOUBLE x)
2491 return MSVCR120_exp2(x);
2494 /*********************************************************************
2495 * expm1 (MSVCR120.@)
2497 double CDECL MSVCR120_expm1(double x)
2499 #ifdef HAVE_EXPM1
2500 double ret = expm1(x);
2501 #else
2502 double ret = exp(x) - 1;
2503 #endif
2504 if (isfinite(x) && !isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
2505 return ret;
2508 /*********************************************************************
2509 * expm1f (MSVCR120.@)
2511 float CDECL MSVCR120_expm1f(float x)
2513 #ifdef HAVE_EXPM1F
2514 float ret = expm1f(x);
2515 #else
2516 float ret = exp(x) - 1;
2517 #endif
2518 if (finitef(x) && !finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
2519 return ret;
2522 /*********************************************************************
2523 * expm1l (MSVCR120.@)
2525 LDOUBLE CDECL MSVCR120_expm1l(LDOUBLE x)
2527 return MSVCR120_expm1(x);
2530 /*********************************************************************
2531 * log1p (MSVCR120.@)
2533 double CDECL MSVCR120_log1p(double x)
2535 if (x < -1) *MSVCRT__errno() = MSVCRT_EDOM;
2536 else if (x == -1) *MSVCRT__errno() = MSVCRT_ERANGE;
2537 #ifdef HAVE_LOG1P
2538 return log1p(x);
2539 #else
2540 return log(1 + x);
2541 #endif
2544 /*********************************************************************
2545 * log1pf (MSVCR120.@)
2547 float CDECL MSVCR120_log1pf(float x)
2549 if (x < -1) *MSVCRT__errno() = MSVCRT_EDOM;
2550 else if (x == -1) *MSVCRT__errno() = MSVCRT_ERANGE;
2551 #ifdef HAVE_LOG1PF
2552 return log1pf(x);
2553 #else
2554 return log(1 + x);
2555 #endif
2558 /*********************************************************************
2559 * log1pl (MSVCR120.@)
2561 LDOUBLE CDECL MSVCR120_log1pl(LDOUBLE x)
2563 return MSVCR120_log1p(x);
2566 /*********************************************************************
2567 * log2 (MSVCR120.@)
2569 double CDECL MSVCR120_log2(double x)
2571 if (x < 0) *MSVCRT__errno() = MSVCRT_EDOM;
2572 else if (x == 0) *MSVCRT__errno() = MSVCRT_ERANGE;
2573 #ifdef HAVE_LOG2
2574 return log2(x);
2575 #else
2576 return log(x) / log(2);
2577 #endif
2580 /*********************************************************************
2581 * log2f (MSVCR120.@)
2583 float CDECL MSVCR120_log2f(float x)
2585 #ifdef HAVE_LOG2F
2586 if (x < 0) *MSVCRT__errno() = MSVCRT_EDOM;
2587 else if (x == 0) *MSVCRT__errno() = MSVCRT_ERANGE;
2588 return log2f(x);
2589 #else
2590 return MSVCR120_log2(x);
2591 #endif
2594 /*********************************************************************
2595 * log2l (MSVCR120.@)
2597 LDOUBLE CDECL MSVCR120_log2l(LDOUBLE x)
2599 return MSVCR120_log2(x);
2602 /*********************************************************************
2603 * rint (MSVCR120.@)
2605 double CDECL MSVCR120_rint(double x)
2607 #ifdef HAVE_RINT
2608 return rint(x);
2609 #else
2610 return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5);
2611 #endif
2614 /*********************************************************************
2615 * rintf (MSVCR120.@)
2617 float CDECL MSVCR120_rintf(float x)
2619 #ifdef HAVE_RINTF
2620 return rintf(x);
2621 #else
2622 return MSVCR120_rint(x);
2623 #endif
2626 /*********************************************************************
2627 * rintl (MSVCR120.@)
2629 LDOUBLE CDECL MSVCR120_rintl(LDOUBLE x)
2631 return MSVCR120_rint(x);
2634 /*********************************************************************
2635 * lrint (MSVCR120.@)
2637 MSVCRT_long CDECL MSVCR120_lrint(double x)
2639 #ifdef HAVE_LRINT
2640 return lrint(x);
2641 #else
2642 return MSVCR120_rint(x);
2643 #endif
2646 /*********************************************************************
2647 * lrintf (MSVCR120.@)
2649 MSVCRT_long CDECL MSVCR120_lrintf(float x)
2651 #ifdef HAVE_LRINTF
2652 return lrintf(x);
2653 #else
2654 return MSVCR120_lrint(x);
2655 #endif
2658 /*********************************************************************
2659 * lrintl (MSVCR120.@)
2661 MSVCRT_long CDECL MSVCR120_lrintl(LDOUBLE x)
2663 return MSVCR120_lrint(x);
2666 /*********************************************************************
2667 * llrint (MSVCR120.@)
2669 MSVCRT_longlong CDECL MSVCR120_llrint(double x)
2671 #ifdef HAVE_LLRINT
2672 return llrint(x);
2673 #else
2674 return MSVCR120_rint(x);
2675 #endif
2678 /*********************************************************************
2679 * llrintf (MSVCR120.@)
2681 MSVCRT_longlong CDECL MSVCR120_llrintf(float x)
2683 #ifdef HAVE_LLRINTF
2684 return llrintf(x);
2685 #else
2686 return MSVCR120_llrint(x);
2687 #endif
2690 /*********************************************************************
2691 * rintl (MSVCR120.@)
2693 MSVCRT_longlong CDECL MSVCR120_llrintl(LDOUBLE x)
2695 return MSVCR120_llrint(x);
2698 /*********************************************************************
2699 * round (MSVCR120.@)
2701 double CDECL MSVCR120_round(double x)
2703 #ifdef HAVE_ROUND
2704 return round(x);
2705 #else
2706 return MSVCR120_rint(x);
2707 #endif
2710 /*********************************************************************
2711 * roundf (MSVCR120.@)
2713 float CDECL MSVCR120_roundf(float x)
2715 #ifdef HAVE_ROUNDF
2716 return roundf(x);
2717 #else
2718 return MSVCR120_round(x);
2719 #endif
2722 /*********************************************************************
2723 * roundl (MSVCR120.@)
2725 LDOUBLE CDECL MSVCR120_roundl(LDOUBLE x)
2727 return MSVCR120_round(x);
2730 /*********************************************************************
2731 * lround (MSVCR120.@)
2733 MSVCRT_long CDECL MSVCR120_lround(double x)
2735 #ifdef HAVE_LROUND
2736 return lround(x);
2737 #else
2738 return MSVCR120_round(x);
2739 #endif
2742 /*********************************************************************
2743 * lroundf (MSVCR120.@)
2745 MSVCRT_long CDECL MSVCR120_lroundf(float x)
2747 #ifdef HAVE_LROUNDF
2748 return lroundf(x);
2749 #else
2750 return MSVCR120_lround(x);
2751 #endif
2754 /*********************************************************************
2755 * lroundl (MSVCR120.@)
2757 MSVCRT_long CDECL MSVCR120_lroundl(LDOUBLE x)
2759 return MSVCR120_lround(x);
2762 /*********************************************************************
2763 * llround (MSVCR120.@)
2765 MSVCRT_longlong CDECL MSVCR120_llround(double x)
2767 #ifdef HAVE_LLROUND
2768 return llround(x);
2769 #else
2770 return MSVCR120_round(x);
2771 #endif
2774 /*********************************************************************
2775 * llroundf (MSVCR120.@)
2777 MSVCRT_longlong CDECL MSVCR120_llroundf(float x)
2779 #ifdef HAVE_LLROUNDF
2780 return llroundf(x);
2781 #else
2782 return MSVCR120_llround(x);
2783 #endif
2786 /*********************************************************************
2787 * roundl (MSVCR120.@)
2789 MSVCRT_longlong CDECL MSVCR120_llroundl(LDOUBLE x)
2791 return MSVCR120_llround(x);
2794 /*********************************************************************
2795 * trunc (MSVCR120.@)
2797 double CDECL MSVCR120_trunc(double x)
2799 #ifdef HAVE_TRUNC
2800 return trunc(x);
2801 #else
2802 return (x > 0) ? floor(x) : ceil(x);
2803 #endif
2806 /*********************************************************************
2807 * truncf (MSVCR120.@)
2809 float CDECL MSVCR120_truncf(float x)
2811 #ifdef HAVE_TRUNCF
2812 return truncf(x);
2813 #else
2814 return MSVCR120_trunc(x);
2815 #endif
2818 /*********************************************************************
2819 * truncl (MSVCR120.@)
2821 LDOUBLE CDECL MSVCR120_truncl(LDOUBLE x)
2823 return MSVCR120_trunc(x);
2826 /*********************************************************************
2827 * _dclass (MSVCR120.@)
2829 short CDECL MSVCR120__dclass(double x)
2831 switch (MSVCRT__fpclass(x)) {
2832 case MSVCRT__FPCLASS_QNAN:
2833 case MSVCRT__FPCLASS_SNAN:
2834 return MSVCRT_FP_NAN;
2835 case MSVCRT__FPCLASS_NINF:
2836 case MSVCRT__FPCLASS_PINF:
2837 return MSVCRT_FP_INFINITE;
2838 case MSVCRT__FPCLASS_ND:
2839 case MSVCRT__FPCLASS_PD:
2840 return MSVCRT_FP_SUBNORMAL;
2841 case MSVCRT__FPCLASS_NN:
2842 case MSVCRT__FPCLASS_PN:
2843 default:
2844 return MSVCRT_FP_NORMAL;
2845 case MSVCRT__FPCLASS_NZ:
2846 case MSVCRT__FPCLASS_PZ:
2847 return MSVCRT_FP_ZERO;
2851 /*********************************************************************
2852 * _fdclass (MSVCR120.@)
2854 short CDECL MSVCR120__fdclass(float x)
2856 return MSVCR120__dclass(x);
2859 /*********************************************************************
2860 * _ldclass (MSVCR120.@)
2862 short CDECL MSVCR120__ldclass(LDOUBLE x)
2864 return MSVCR120__dclass(x);
2867 /*********************************************************************
2868 * _dtest (MSVCR120.@)
2870 short CDECL MSVCR120__dtest(double *x)
2872 return MSVCR120__dclass(*x);
2875 /*********************************************************************
2876 * _fdtest (MSVCR120.@)
2878 short CDECL MSVCR120__fdtest(float *x)
2880 return MSVCR120__dclass(*x);
2883 /*********************************************************************
2884 * _ldtest (MSVCR120.@)
2886 short CDECL MSVCR120__ldtest(LDOUBLE *x)
2888 return MSVCR120__dclass(*x);
2891 /*********************************************************************
2892 * erf (MSVCR120.@)
2894 double CDECL MSVCR120_erf(double x)
2896 #ifdef HAVE_ERF
2897 return erf(x);
2898 #else
2899 /* Abramowitz and Stegun approximation, maximum error: 1.5*10^-7 */
2900 double t, y;
2901 int sign = signbit(x);
2903 if (sign) x = -x;
2904 t = 1 / (1 + 0.3275911 * x);
2905 y = ((((1.061405429*t - 1.453152027)*t + 1.421413741)*t - 0.284496736)*t + 0.254829592)*t;
2906 y = 1.0 - y*exp(-x*x);
2907 return sign ? -y : y;
2908 #endif
2911 /*********************************************************************
2912 * erff (MSVCR120.@)
2914 float CDECL MSVCR120_erff(float x)
2916 #ifdef HAVE_ERFF
2917 return erff(x);
2918 #else
2919 return MSVCR120_erf(x);
2920 #endif
2923 /*********************************************************************
2924 * erfl (MSVCR120.@)
2926 LDOUBLE CDECL MSVCR120_erfl(LDOUBLE x)
2928 return MSVCR120_erf(x);
2931 /*********************************************************************
2932 * erfc (MSVCR120.@)
2934 double CDECL MSVCR120_erfc(double x)
2936 #ifdef HAVE_ERFC
2937 return erfc(x);
2938 #else
2939 return 1 - MSVCR120_erf(x);
2940 #endif
2943 /*********************************************************************
2944 * erfcf (MSVCR120.@)
2946 float CDECL MSVCR120_erfcf(float x)
2948 #ifdef HAVE_ERFCF
2949 return erfcf(x);
2950 #else
2951 return MSVCR120_erfc(x);
2952 #endif
2955 /*********************************************************************
2956 * erfcl (MSVCR120.@)
2958 LDOUBLE CDECL MSVCR120_erfcl(LDOUBLE x)
2960 return MSVCR120_erfc(x);
2963 /*********************************************************************
2964 * fmaxf (MSVCR120.@)
2966 float CDECL MSVCR120_fmaxf(float x, float y)
2968 if(isnanf(x))
2969 return y;
2970 if(isnanf(y))
2971 return x;
2972 if(x==0 && y==0)
2973 return signbit(x) ? y : x;
2974 return x<y ? y : x;
2977 /*********************************************************************
2978 * fmax (MSVCR120.@)
2980 double CDECL MSVCR120_fmax(double x, double y)
2982 if(isnan(x))
2983 return y;
2984 if(isnan(y))
2985 return x;
2986 if(x==0 && y==0)
2987 return signbit(x) ? y : x;
2988 return x<y ? y : x;
2991 /*********************************************************************
2992 * _fdsign (MSVCR120.@)
2994 int CDECL MSVCR120__fdsign(float x)
2996 return signbit(x) ? 0x8000 : 0;
2999 /*********************************************************************
3000 * _dsign (MSVCR120.@)
3002 int CDECL MSVCR120__dsign(double x)
3004 return signbit(x) ? 0x8000 : 0;
3008 /*********************************************************************
3009 * _dpcomp (MSVCR120.@)
3011 int CDECL MSVCR120__dpcomp(double x, double y)
3013 if(isnan(x) || isnan(y))
3014 return 0;
3016 if(x == y) return 2;
3017 return x < y ? 1 : 4;
3020 /*********************************************************************
3021 * _fdpcomp (MSVCR120.@)
3023 int CDECL MSVCR120__fdpcomp(float x, float y)
3025 return MSVCR120__dpcomp(x, y);
3028 /*********************************************************************
3029 * fminf (MSVCR120.@)
3031 float CDECL MSVCR120_fminf(float x, float y)
3033 if(isnanf(x))
3034 return y;
3035 if(isnanf(y))
3036 return x;
3037 if(x==0 && y==0)
3038 return signbit(x) ? x : y;
3039 return x<y ? x : y;
3042 /*********************************************************************
3043 * fmin (MSVCR120.@)
3045 double CDECL MSVCR120_fmin(double x, double y)
3047 if(isnan(x))
3048 return y;
3049 if(isnan(y))
3050 return x;
3051 if(x==0 && y==0)
3052 return signbit(x) ? x : y;
3053 return x<y ? x : y;
3056 /*********************************************************************
3057 * asinh (MSVCR120.@)
3059 double CDECL MSVCR120_asinh(double x)
3061 #ifdef HAVE_ASINH
3062 return asinh(x);
3063 #else
3064 if (!isfinite(x*x+1)) return log(2) + log(x);
3065 return log(x + sqrt(x*x+1));
3066 #endif
3069 /*********************************************************************
3070 * asinhf (MSVCR120.@)
3072 float CDECL MSVCR120_asinhf(float x)
3074 #ifdef HAVE_ASINHF
3075 return asinhf(x);
3076 #else
3077 return MSVCR120_asinh(x);
3078 #endif
3081 /*********************************************************************
3082 * asinhl (MSVCR120.@)
3084 LDOUBLE CDECL MSVCR120_asinhl(LDOUBLE x)
3086 return MSVCR120_asinh(x);
3089 /*********************************************************************
3090 * acosh (MSVCR120.@)
3092 double CDECL MSVCR120_acosh(double x)
3094 if (x < 1) *MSVCRT__errno() = MSVCRT_EDOM;
3096 #ifdef HAVE_ACOSH
3097 return acosh(x);
3098 #else
3099 if (x < 1) {
3100 MSVCRT_fenv_t env;
3102 MSVCRT_fegetenv(&env);
3103 env.status |= MSVCRT__SW_INVALID;
3104 MSVCRT_fesetenv(&env);
3105 return NAN;
3107 if (!isfinite(x*x)) return log(2) + log(x);
3108 return log(x + sqrt(x*x-1));
3109 #endif
3112 /*********************************************************************
3113 * acoshf (MSVCR120.@)
3115 float CDECL MSVCR120_acoshf(float x)
3117 #ifdef HAVE_ACOSHF
3118 if (x < 1) *MSVCRT__errno() = MSVCRT_EDOM;
3120 return acoshf(x);
3121 #else
3122 return MSVCR120_acosh(x);
3123 #endif
3126 /*********************************************************************
3127 * acoshl (MSVCR120.@)
3129 LDOUBLE CDECL MSVCR120_acoshl(LDOUBLE x)
3131 return MSVCR120_acosh(x);
3134 /*********************************************************************
3135 * atanh (MSVCR120.@)
3137 double CDECL MSVCR120_atanh(double x)
3139 double ret;
3141 if (x > 1 || x < -1) {
3142 MSVCRT_fenv_t env;
3144 *MSVCRT__errno() = MSVCRT_EDOM;
3146 /* on Linux atanh returns -NAN in this case */
3147 MSVCRT_fegetenv(&env);
3148 env.status |= MSVCRT__SW_INVALID;
3149 MSVCRT_fesetenv(&env);
3150 return NAN;
3153 #ifdef HAVE_ATANH
3154 ret = atanh(x);
3155 #else
3156 if (-1e-6 < x && x < 1e-6) ret = x + x*x*x/3;
3157 else ret = (log(1+x) - log(1-x)) / 2;
3158 #endif
3160 if (!isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
3161 return ret;
3164 /*********************************************************************
3165 * atanhf (MSVCR120.@)
3167 float CDECL MSVCR120_atanhf(float x)
3169 #ifdef HAVE_ATANHF
3170 float ret;
3172 if (x > 1 || x < -1) {
3173 MSVCRT_fenv_t env;
3175 *MSVCRT__errno() = MSVCRT_EDOM;
3177 MSVCRT_fegetenv(&env);
3178 env.status |= MSVCRT__SW_INVALID;
3179 MSVCRT_fesetenv(&env);
3180 return NAN;
3183 ret = atanhf(x);
3185 if (!finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
3186 return ret;
3187 #else
3188 return MSVCR120_atanh(x);
3189 #endif
3192 /*********************************************************************
3193 * atanhl (MSVCR120.@)
3195 LDOUBLE CDECL MSVCR120_atanhl(LDOUBLE x)
3197 return MSVCR120_atanh(x);
3200 /*********************************************************************
3201 * _scalb (MSVCRT.@)
3202 * scalbn (MSVCR120.@)
3203 * scalbln (MSVCR120.@)
3205 double CDECL MSVCRT__scalb(double num, MSVCRT_long power)
3207 return MSVCRT_ldexp(num, power);
3210 /*********************************************************************
3211 * _scalbf (MSVCRT.@)
3212 * scalbnf (MSVCR120.@)
3213 * scalblnf (MSVCR120.@)
3215 float CDECL MSVCRT__scalbf(float num, MSVCRT_long power)
3217 return MSVCRT_ldexp(num, power);
3220 /*********************************************************************
3221 * scalbnl (MSVCR120.@)
3222 * scalblnl (MSVCR120.@)
3224 LDOUBLE CDECL MSVCR120_scalbnl(LDOUBLE num, MSVCRT_long power)
3226 return MSVCRT__scalb(num, power);
3229 /*********************************************************************
3230 * remainder (MSVCR120.@)
3232 double CDECL MSVCR120_remainder(double x, double y)
3234 #ifdef HAVE_REMAINDER
3235 /* this matches 64-bit Windows. 32-bit Windows is slightly different */
3236 if(!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
3237 if(isnan(y) || y==0.0) *MSVCRT__errno() = MSVCRT_EDOM;
3238 return remainder(x, y);
3239 #else
3240 FIXME( "not implemented\n" );
3241 return 0.0;
3242 #endif
3245 /*********************************************************************
3246 * remainderf (MSVCR120.@)
3248 float CDECL MSVCR120_remainderf(float x, float y)
3250 #ifdef HAVE_REMAINDERF
3251 /* this matches 64-bit Windows. 32-bit Windows is slightly different */
3252 if(!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
3253 if(isnanf(y) || y==0.0f) *MSVCRT__errno() = MSVCRT_EDOM;
3254 return remainderf(x, y);
3255 #else
3256 FIXME( "not implemented\n" );
3257 return 0.0f;
3258 #endif
3261 /*********************************************************************
3262 * remainderl (MSVCR120.@)
3264 LDOUBLE CDECL MSVCR120_remainderl(LDOUBLE x, LDOUBLE y)
3266 return MSVCR120_remainder(x, y);
3269 /*********************************************************************
3270 * lgamma (MSVCR120.@)
3272 double CDECL MSVCR120_lgamma(double x)
3274 #ifdef HAVE_LGAMMA
3275 return lgamma(x);
3276 #else
3277 FIXME( "not implemented\n" );
3278 return 0.0;
3279 #endif
3282 /*********************************************************************
3283 * lgammaf (MSVCR120.@)
3285 float CDECL MSVCR120_lgammaf(float x)
3287 #ifdef HAVE_LGAMMAF
3288 return lgammaf(x);
3289 #else
3290 FIXME( "not implemented\n" );
3291 return 0.0f;
3292 #endif
3295 /*********************************************************************
3296 * lgammal (MSVCR120.@)
3298 LDOUBLE CDECL MSVCR120_lgammal(LDOUBLE x)
3300 return MSVCR120_lgamma(x);
3303 /*********************************************************************
3304 * nan (MSVCR120.@)
3306 double CDECL MSVCR120_nan(const char *tagp)
3308 /* Windows ignores input (MSDN) */
3309 return NAN;
3312 /*********************************************************************
3313 * nanf (MSVCR120.@)
3315 float CDECL MSVCR120_nanf(const char *tagp)
3317 return NAN;
3320 /*********************************************************************
3321 * _except1 (MSVCR120.@)
3322 * TODO:
3323 * - find meaning of ignored cw and operation bits
3324 * - unk parameter
3326 double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res, DWORD cw, void *unk)
3328 ULONG_PTR exception_arg;
3329 DWORD exception = 0;
3330 MSVCRT_fenv_t env;
3331 DWORD fpword = 0;
3332 WORD operation;
3334 TRACE("(%x %x %lf %lf %x %p)\n", fpe, op, arg, res, cw, unk);
3336 #ifdef _WIN64
3337 cw = ((cw >> 7) & 0x3f) | ((cw >> 3) & 0xc00);
3338 #endif
3339 operation = op << 5;
3340 exception_arg = (ULONG_PTR)&operation;
3342 MSVCRT_fegetenv(&env);
3344 if (fpe & 0x1) { /* overflow */
3345 if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) {
3346 /* 32-bit version also sets SW_INEXACT here */
3347 env.status |= MSVCRT__SW_OVERFLOW;
3348 if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
3349 res = signbit(res) ? -INFINITY : INFINITY;
3350 } else {
3351 exception = EXCEPTION_FLT_OVERFLOW;
3353 } else if (fpe & 0x2) { /* underflow */
3354 if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) {
3355 env.status |= MSVCRT__SW_UNDERFLOW;
3356 if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
3357 res = signbit(res) ? -0.0 : 0.0;
3358 } else {
3359 exception = EXCEPTION_FLT_UNDERFLOW;
3361 } else if (fpe & 0x4) { /* zerodivide */
3362 if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) {
3363 env.status |= MSVCRT__SW_ZERODIVIDE;
3364 if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
3365 } else {
3366 exception = EXCEPTION_FLT_DIVIDE_BY_ZERO;
3368 } else if (fpe & 0x8) { /* invalid */
3369 if (fpe == 0x8 && (cw & 0x1)) {
3370 env.status |= MSVCRT__SW_INVALID;
3371 } else {
3372 exception = EXCEPTION_FLT_INVALID_OPERATION;
3374 } else if (fpe & 0x10) { /* inexact */
3375 if (fpe == 0x10 && (cw & 0x20)) {
3376 env.status |= MSVCRT__SW_INEXACT;
3377 } else {
3378 exception = EXCEPTION_FLT_INEXACT_RESULT;
3382 if (exception)
3383 env.status = 0;
3384 MSVCRT_fesetenv(&env);
3385 if (exception)
3386 RaiseException(exception, 0, 1, &exception_arg);
3388 if (cw & 0x1) fpword |= MSVCRT__EM_INVALID;
3389 if (cw & 0x2) fpword |= MSVCRT__EM_DENORMAL;
3390 if (cw & 0x4) fpword |= MSVCRT__EM_ZERODIVIDE;
3391 if (cw & 0x8) fpword |= MSVCRT__EM_OVERFLOW;
3392 if (cw & 0x10) fpword |= MSVCRT__EM_UNDERFLOW;
3393 if (cw & 0x20) fpword |= MSVCRT__EM_INEXACT;
3394 switch (cw & 0xc00)
3396 case 0xc00: fpword |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
3397 case 0x800: fpword |= MSVCRT__RC_UP; break;
3398 case 0x400: fpword |= MSVCRT__RC_DOWN; break;
3400 switch (cw & 0x300)
3402 case 0x0: fpword |= MSVCRT__PC_24; break;
3403 case 0x200: fpword |= MSVCRT__PC_53; break;
3404 case 0x300: fpword |= MSVCRT__PC_64; break;
3406 if (cw & 0x1000) fpword |= MSVCRT__IC_AFFINE;
3407 _control87(fpword, 0xffffffff);
3409 return res;